diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 485a76e8b0f..00000000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,18 +0,0 @@ -[env] -# Enforce native_blockifier linking with pypy3.9. -PYO3_PYTHON = "/usr/local/bin/pypy3.9" -# Increase Rust stack size. -# This should be large enough for `MAX_ENTRY_POINT_RECURSION_DEPTH` recursive entry point calls. -RUST_MIN_STACK = "4194304" # 4 MiB - -[target.x86_64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", - ] - -[target.aarch64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] diff --git a/.clippy.toml b/.clippy.toml deleted file mode 100644 index ada6ea9b7e7..00000000000 --- a/.clippy.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Place configuration for clippy lints here, when applicable (lints that can be configured -# state so in clippy's documentation). -# Note: only lint configurations can be placed here, lints must be placed in `.cargo/config.toml`. diff --git a/.github/.codecov.yml b/.github/.codecov.yml deleted file mode 100644 index c88b947e165..00000000000 --- a/.github/.codecov.yml +++ /dev/null @@ -1,16 +0,0 @@ -ignore: - - "crates/**/*test*.rs" -coverage: - status: - project: - default: - target: auto # set the target coverage to the value of the parent commit - threshold: 0% # pct of drop in coverage that is still considered as success - informational: true # if true does not fail the CI is coverage is bellow the target value - only_pulls: true # run only on PRs - patch: - default: - target: 100% - threshold: 0% - informational: true - only_pulls: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index e9e6c51b4df..00000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,177 +0,0 @@ -name: CI - -on: - push: - branches: - - main - - main-v[0-9].** - tags: - - v[0-9].** - - pull_request: - types: - - opened - - reopened - - synchronize - - auto_merge_enabled - - edited - -jobs: - commitlint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install commitlint - run: npm install --global @commitlint/cli @commitlint/config-conventional - - - name: Validate PR commits with commitlint - if: github.event_name == 'pull_request' && !(contains(github.event.pull_request.title, '/merge-main') || contains(github.event.pull_request.title, '/merge main')) - env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: commitlint --from "$BASE_SHA" --to "$HEAD_SHA" --verbose - - - name: Validate PR title with commitlint - if: github.event_name != 'merge_group' && github.event_name != 'push' && !(contains(github.event.pull_request.title, '/merge-main') || contains(github.event.pull_request.title, '/merge main')) - env: - TITLE: ${{ github.event.pull_request.title }} - run: echo "$TITLE" | commitlint --verbose - - format: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - components: rustfmt - toolchain: nightly-2024-04-29 - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - run: scripts/rust_fmt.sh --check - - clippy: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - with: - components: clippy - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - # Setup pypy and link to the location expected by .cargo/config.toml. - - uses: actions/setup-python@v5 - id: setup-pypy - with: - python-version: 'pypy3.9' - - run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9 - - env: - LD_LIBRARY_PATH: ${{ steps.setup-pypy.outputs.pythonLocation }}/bin - run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV - - - run: scripts/clippy.sh - - featureless-build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - run: cargo build -p blockifier - - run: cargo test -p blockifier - - run-python-tests: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - run: | - python -m pip install --upgrade pip - pip install pytest - - run: pytest scripts/merge_paths_test.py - - run-tests: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - # Setup pypy and link to the location expected by .cargo/config.toml. - - uses: actions/setup-python@v5 - id: setup-pypy - with: - python-version: 'pypy3.9' - - run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9 - - env: - LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin - run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV - - - run: cargo test - - run: cargo test --features concurrency - - native-blockifier-artifacts-push: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - - name: Build native blockifier - run: ./build_native_blockifier.sh - - # Commit hash on pull request event would be the head commit of the branch. - - name: Get commit hash prefix for PR update - if: ${{ github.event_name == 'pull_request' }} - env: - COMMIT_SHA: ${{ github.event.pull_request.head.sha }} - run: echo "SHORT_HASH=${COMMIT_SHA:0:7}" >> $GITHUB_ENV - - # On push event (to main, for example) we should take the commit post-push. - - name: Get commit hash prefix for merge - if: ${{ github.event_name != 'pull_request' }} - env: - COMMIT_SHA: ${{ github.event.after }} - run: echo "SHORT_HASH=${COMMIT_SHA:0:7}" >> $GITHUB_ENV - - # Rename is required; see https://pyo3.rs/v0.19.2/building_and_distribution#manual-builds. - - name: Rename shared object - run: | - mv \ - target/release/libnative_blockifier.so \ - target/release/native_blockifier.pypy39-pp73-x86_64-linux-gnu.so - - - name: Authenticate with GCS - uses: "google-github-actions/auth@v2" - with: - credentials_json: ${{ secrets.SA_NATIVE_BLOCKIFIER_ARTIFACTS_BUCKET_WRITER_ACCESS_KEY }} - - - name: Upload binary to GCP - id: upload_file - uses: "google-github-actions/upload-cloud-storage@v2" - with: - path: "target/release/native_blockifier.pypy39-pp73-x86_64-linux-gnu.so" - destination: "native_blockifier_artifacts/${{ env.SHORT_HASH }}/release/" - - # Keep the name 'udeps' to match original action name, so we don't need to define specific branch - # rules on Github for specific version branches. - udeps: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run Machete (detect unused dependencies) - uses: bnjbvr/cargo-machete@main diff --git a/.github/workflows/compiled_cairo.yml b/.github/workflows/compiled_cairo.yml deleted file mode 100644 index 847eb30b791..00000000000 --- a/.github/workflows/compiled_cairo.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: CI - -on: - push: - branches: - - main - tags: - - v[0-9].** - - pull_request: - types: - - opened - - reopened - - synchronize - paths: - - 'crates/blockifier/feature_contracts/cairo0/**' - -jobs: - verify_cairo_file_dependencies: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - # Setup pypy and link to the location expected by .cargo/config.toml. - - uses: actions/setup-python@v5 - id: setup-pypy - with: - python-version: 'pypy3.9' - - run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9 - - env: - LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin - run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV - - - run: - pip install -r crates/blockifier/tests/requirements.txt; - cargo test verify_feature_contracts -- --include-ignored diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index a92b63bfeba..00000000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Coverage - -on: [pull_request, push] - -jobs: - coverage: - runs-on: ubuntu-20.04 - env: - CARGO_TERM_COLOR: always - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - # Setup pypy and link to the location expected by .cargo/config.toml. - - uses: actions/setup-python@v5 - id: setup-pypy - with: - python-version: 'pypy3.9' - - run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9 - - env: - LD_LIBRARY_PATH: ${{ steps.setup-pypy.outputs.pythonLocation }}/bin - run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV - - - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov - # - name: Generate code coverage - # run: cargo llvm-cov --codecov --output-path codecov.json - # env: - # SEED: 0 - # - name: Upload coverage to Codecov - # uses: codecov/codecov-action@v3 - # with: - # token: ${{ secrets.CODECOV_TOKEN }} - # verbose: true - # fail_ci_if_error: true diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml deleted file mode 100644 index 0b42eeb4d0d..00000000000 --- a/.github/workflows/post-merge.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: post-merge - -on: - pull_request: - types: - - closed -jobs: - if_merged: - if: github.event.pull_request.merged == true - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v0-rust-ubuntu-20.04" - - # Setup pypy and link to the location expected by .cargo/config.toml. - - uses: actions/setup-python@v5 - id: setup-pypy - with: - python-version: 'pypy3.9' - - run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9 - - env: - LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin - run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV - - - run: | - pip install -r crates/blockifier/tests/requirements.txt - cargo test -- --include-ignored diff --git a/.github/workflows/verify-deps.yml b/.github/workflows/verify-deps.yml deleted file mode 100644 index 5e11b67b97e..00000000000 --- a/.github/workflows/verify-deps.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Nightly Latest Dependencies Check - -on: - schedule: - - cron: '0 0 * * *' # Runs at 00:00 UTC every day - -jobs: - latest_deps: - name: Latest Dependencies - runs-on: ubuntu-20.04 - continue-on-error: true - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - name: Update Dependencies - run: cargo update --verbose - - name: Build - run: cargo build --verbose - - name: Test - run: cargo test --verbose diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e21a6d42309..00000000000 --- a/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.egg-info -/data -/logs -build -dist -target -*/.vscode/* -*.DS_Store - -tmp_venv/* - diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 060d8ae1ac4..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "editor.tokenColorCustomizations": { - "textMateRules": [ - { - "scope": "googletest.failed", - "settings": { - "foreground": "#f00" - } - }, - { - "scope": "googletest.passed", - "settings": { - "foreground": "#0f0" - } - }, - { - "scope": "googletest.run", - "settings": { - "foreground": "#0f0" - } - } - ] - } -} diff --git a/BUILD b/BUILD deleted file mode 100644 index 0410bd87b6b..00000000000 --- a/BUILD +++ /dev/null @@ -1,2 +0,0 @@ -# Export the built artifact to allow local builds. -exports_files(["target/release/libnative_blockifier.so"]) diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index c78c59f4c8d..00000000000 --- a/Cargo.lock +++ /dev/null @@ -1,4435 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anstream" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" - -[[package]] -name = "anstyle-parse" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", - "itertools 0.10.5", - "num-traits 0.2.19", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", - "derivative", - "digest", - "itertools 0.10.5", - "num-bigint", - "num-traits 0.2.19", - "paste", - "rustc_version", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits 0.2.19", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-poly" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", -] - -[[package]] -name = "ark-secp256k1" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02e954eaeb4ddb29613fee20840c2bbc85ca4396d53e33837e11905363c5f2" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-secp256r1" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3975a01b0a6e3eae0f72ec7ca8598a6620fc72fa5981f6f5cca33b7cd788f633" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-serialize-derive", - "ark-std", - "digest", - "num-bigint", -] - -[[package]] -name = "ark-serialize-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits 0.2.19", - "rand", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bincode" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" -dependencies = [ - "serde", -] - -[[package]] -name = "bindgen" -version = "0.66.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" -dependencies = [ - "bitflags 2.4.1", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.66", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blockifier" -version = "0.8.0-rc.1" -dependencies = [ - "anyhow", - "ark-ec", - "ark-ff", - "ark-secp256k1", - "ark-secp256r1", - "assert_matches", - "cached", - "cairo-lang-casm", - "cairo-lang-runner", - "cairo-lang-starknet-classes", - "cairo-lang-utils", - "cairo-vm", - "criterion", - "derive_more", - "glob", - "indexmap 2.2.6", - "itertools 0.10.5", - "keccak", - "log", - "num-bigint", - "num-integer", - "num-rational", - "num-traits 0.2.19", - "once_cell", - "paste", - "phf", - "pretty_assertions", - "rand", - "regex", - "rstest", - "serde", - "serde_json", - "sha2", - "sha3", - "starknet-types-core", - "starknet_api", - "strum", - "strum_macros 0.24.3", - "test-case", - "thiserror", - "tikv-jemallocator", -] - -[[package]] -name = "bstr" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "cached" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b195e4fbc4b6862bbd065b991a34750399c119797efff72492f28a5864de8700" -dependencies = [ - "async-trait", - "cached_proc_macro", - "cached_proc_macro_types", - "futures", - "hashbrown 0.13.2", - "instant", - "once_cell", - "thiserror", - "tokio", -] - -[[package]] -name = "cached_proc_macro" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b48814962d2fd604c50d2b9433c2a41a0ab567779ee2c02f7fba6eca1221f082" -dependencies = [ - "cached_proc_macro_types", - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cached_proc_macro_types" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" - -[[package]] -name = "cairo-lang-casm" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5abf875e93f696e783412d3f2a7c6f66e94e07c30b01559380b4d0707dc0050e" -dependencies = [ - "cairo-lang-utils", - "indoc 2.0.5", - "num-bigint", - "num-traits 0.2.19", - "parity-scale-codec", - "serde", -] - -[[package]] -name = "cairo-lang-compiler" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f135e1768e199e88b04f824e34b9411ff49fc31970e77cbf5c6f448170441d18" -dependencies = [ - "anyhow", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-lowering", - "cairo-lang-parser", - "cairo-lang-project", - "cairo-lang-semantic", - "cairo-lang-sierra", - "cairo-lang-sierra-generator", - "cairo-lang-syntax", - "cairo-lang-utils", - "indoc 2.0.5", - "salsa", - "smol_str", - "thiserror", -] - -[[package]] -name = "cairo-lang-debug" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e2bf0a6caf1e54938bc67ca082cbeb5385969784bfb1109c187ca9dc5e1806" -dependencies = [ - "cairo-lang-utils", -] - -[[package]] -name = "cairo-lang-defs" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65bb0e855afeb88d11585605f836bd0cd444375b234103e87342df2c91aba1b" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-parser", - "cairo-lang-syntax", - "cairo-lang-utils", - "itertools 0.12.1", - "salsa", - "smol_str", -] - -[[package]] -name = "cairo-lang-diagnostics" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab96083f60a077d300d0b89bd4b9c31731c95f5db355a11c4657ee25f3acc198" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-filesystem", - "cairo-lang-utils", - "itertools 0.12.1", -] - -[[package]] -name = "cairo-lang-eq-solver" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf2aaa50fa5b15070b2bf02c60a62f917f9aa1ff6dedf5a2627ecafe8e33cfa" -dependencies = [ - "cairo-lang-utils", - "good_lp", -] - -[[package]] -name = "cairo-lang-filesystem" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8094bcf7e44204c2fc2f10760e7e2e5769a6267cba5d8a303c0331dd480d5663" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-utils", - "path-clean", - "salsa", - "serde", - "smol_str", -] - -[[package]] -name = "cairo-lang-formatter" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a1d92f1163b3b0e22e6392d22f7a275b9e64ab453f32b8b62bb1aeedbe73e04" -dependencies = [ - "anyhow", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-parser", - "cairo-lang-syntax", - "cairo-lang-utils", - "diffy", - "ignore", - "itertools 0.12.1", - "salsa", - "serde", - "smol_str", - "thiserror", -] - -[[package]] -name = "cairo-lang-lowering" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb629a773c07c2863717d1711fd3ecc17807c1fc094bb90cccac56061056a4" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-parser", - "cairo-lang-proc-macros", - "cairo-lang-semantic", - "cairo-lang-syntax", - "cairo-lang-utils", - "id-arena", - "itertools 0.12.1", - "log", - "num-bigint", - "num-traits 0.2.19", - "once_cell", - "salsa", - "smol_str", -] - -[[package]] -name = "cairo-lang-parser" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7b1d7af8e1bff971b8b9bbce796650a57de93dfb092bc0c17c2f85d915de6e" -dependencies = [ - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-syntax", - "cairo-lang-syntax-codegen", - "cairo-lang-utils", - "colored", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "salsa", - "smol_str", - "unescaper", -] - -[[package]] -name = "cairo-lang-plugins" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eccf06d643d155a72057dc93c40cf34dabe11e8c629dbf3111c528a3d750a66" -dependencies = [ - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-parser", - "cairo-lang-syntax", - "cairo-lang-utils", - "indent", - "indoc 2.0.5", - "itertools 0.12.1", - "salsa", - "smol_str", -] - -[[package]] -name = "cairo-lang-proc-macros" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa10434f9ce0828e8d77f3a13ae2f878da453345b14d54a66de3e196c0e4674" -dependencies = [ - "cairo-lang-debug", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "cairo-lang-project" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4882d2263fb7c95dbab0c3b5578d8c0e2417fd680df8cc61aa50321b6a5a40d" -dependencies = [ - "cairo-lang-filesystem", - "cairo-lang-utils", - "serde", - "smol_str", - "thiserror", - "toml", -] - -[[package]] -name = "cairo-lang-runner" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ab7b0e0640adaed21b9d9b9b94b3edf7f7ab95514b1dd40c679317a33dabea" -dependencies = [ - "ark-ff", - "ark-secp256k1", - "ark-secp256r1", - "cairo-lang-casm", - "cairo-lang-lowering", - "cairo-lang-sierra", - "cairo-lang-sierra-ap-change", - "cairo-lang-sierra-generator", - "cairo-lang-sierra-to-casm", - "cairo-lang-sierra-type-size", - "cairo-lang-starknet", - "cairo-lang-utils", - "cairo-vm", - "itertools 0.12.1", - "keccak", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "rand", - "sha2", - "smol_str", - "starknet-types-core", - "thiserror", -] - -[[package]] -name = "cairo-lang-semantic" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba49614f98322e1ccda33265f8193f66cbd88eff23b0deb94db981aa0666650" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-parser", - "cairo-lang-plugins", - "cairo-lang-proc-macros", - "cairo-lang-syntax", - "cairo-lang-test-utils", - "cairo-lang-utils", - "id-arena", - "indoc 2.0.5", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "once_cell", - "salsa", - "smol_str", - "toml", -] - -[[package]] -name = "cairo-lang-sierra" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a41d56c6afebdbe2c5ffb4e216f60b07391c29c91fccf0a60790817f49ba68" -dependencies = [ - "anyhow", - "cairo-lang-utils", - "const-fnv1a-hash", - "convert_case 0.6.0", - "derivative", - "itertools 0.12.1", - "lalrpop", - "lalrpop-util", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "once_cell", - "regex", - "salsa", - "serde", - "serde_json", - "sha3", - "smol_str", - "starknet-types-core", - "thiserror", -] - -[[package]] -name = "cairo-lang-sierra-ap-change" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667050b93db661ebce0b33c92ce44abffebde37c5645e4761722ad3c49a1c34f" -dependencies = [ - "cairo-lang-eq-solver", - "cairo-lang-sierra", - "cairo-lang-sierra-type-size", - "cairo-lang-utils", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "thiserror", -] - -[[package]] -name = "cairo-lang-sierra-gas" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27fcbf81e8ed4efe7e9c30bbdfa8074b9af01a5e16154999dd9527baba27f1fb" -dependencies = [ - "cairo-lang-eq-solver", - "cairo-lang-sierra", - "cairo-lang-sierra-type-size", - "cairo-lang-utils", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "thiserror", -] - -[[package]] -name = "cairo-lang-sierra-generator" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058c05d10913a130fb21964f0bf1a37b05eafcf2f50a73cd4aa3e11da7e4cfc7" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-lowering", - "cairo-lang-parser", - "cairo-lang-semantic", - "cairo-lang-sierra", - "cairo-lang-syntax", - "cairo-lang-utils", - "itertools 0.12.1", - "num-traits 0.2.19", - "once_cell", - "salsa", - "serde", - "serde_json", - "smol_str", -] - -[[package]] -name = "cairo-lang-sierra-to-casm" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8607cc5cf16f3a930ad4b3799e986b0ca36ada2c0da1dd6bd2ef35cbb1eb9e74" -dependencies = [ - "assert_matches", - "cairo-lang-casm", - "cairo-lang-sierra", - "cairo-lang-sierra-ap-change", - "cairo-lang-sierra-gas", - "cairo-lang-sierra-type-size", - "cairo-lang-utils", - "indoc 2.0.5", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "starknet-types-core", - "thiserror", -] - -[[package]] -name = "cairo-lang-sierra-type-size" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224624b1e279b3eea7693680f577335e66e6dd5fbfbd2576f4a7d0b5d697f61d" -dependencies = [ - "cairo-lang-sierra", - "cairo-lang-utils", -] - -[[package]] -name = "cairo-lang-starknet" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a54ebea4ea990a33a2158ecdf46ffb3cb1af8fff6a79c3dd310c6a9ed43e82" -dependencies = [ - "anyhow", - "cairo-lang-compiler", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-lowering", - "cairo-lang-plugins", - "cairo-lang-semantic", - "cairo-lang-sierra", - "cairo-lang-sierra-generator", - "cairo-lang-starknet-classes", - "cairo-lang-syntax", - "cairo-lang-utils", - "const_format", - "indent", - "indoc 2.0.5", - "itertools 0.12.1", - "once_cell", - "serde", - "serde_json", - "smol_str", - "starknet-types-core", - "thiserror", -] - -[[package]] -name = "cairo-lang-starknet-classes" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb66ae799e1963318e1bab782848f53797787c396dfd590be539f3f12d56ac4" -dependencies = [ - "cairo-lang-casm", - "cairo-lang-sierra", - "cairo-lang-sierra-to-casm", - "cairo-lang-utils", - "convert_case 0.6.0", - "itertools 0.12.1", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "once_cell", - "serde", - "serde_json", - "sha3", - "smol_str", - "starknet-types-core", - "thiserror", -] - -[[package]] -name = "cairo-lang-syntax" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e673dc1058a8639c094a330a701e8902cbd34defe659a3d95bcf6c3f3de249d" -dependencies = [ - "cairo-lang-debug", - "cairo-lang-filesystem", - "cairo-lang-utils", - "num-bigint", - "num-traits 0.2.19", - "salsa", - "smol_str", - "unescaper", -] - -[[package]] -name = "cairo-lang-syntax-codegen" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0dd466dbac4263573b81b83e22534285da30a4e7c15b888407fbb33d8accb9" -dependencies = [ - "genco", - "xshell", -] - -[[package]] -name = "cairo-lang-test-utils" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09431da22acc1cf081b1802b73ff484bdc75ca1cd5ad6fa9b84fba8753b2e08f" -dependencies = [ - "cairo-lang-formatter", - "cairo-lang-utils", - "colored", - "log", - "pretty_assertions", -] - -[[package]] -name = "cairo-lang-utils" -version = "2.7.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97498c08958be8d569c16982cac431d785adc3effdfa6d0775c65aec578dfd91" -dependencies = [ - "hashbrown 0.14.5", - "indexmap 2.2.6", - "itertools 0.12.1", - "num-bigint", - "num-traits 0.2.19", - "parity-scale-codec", - "schemars", - "serde", -] - -[[package]] -name = "cairo-vm" -version = "1.0.0-rc5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e09134ea1e0be6c1fbd330f0945df0512fa70944fd0b3ecc2f74a6008f01e9da" -dependencies = [ - "anyhow", - "bincode", - "bitvec", - "generic-array", - "hashbrown 0.14.5", - "hex", - "keccak", - "lazy_static", - "nom", - "num-bigint", - "num-integer", - "num-prime", - "num-traits 0.2.19", - "rand", - "rust_decimal", - "serde", - "serde_json", - "sha2", - "sha3", - "starknet-crypto 0.6.2", - "starknet-types-core", - "thiserror-no-std", - "zip", -] - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags 1.3.2", - "textwrap", - "unicode-width", -] - -[[package]] -name = "clap" -version = "4.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim 0.11.1", -] - -[[package]] -name = "clap_lex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - -[[package]] -name = "const-fnv1a-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" - -[[package]] -name = "const_format" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap 2.34.0", - "criterion-plot", - "csv", - "itertools 0.10.5", - "lazy_static", - "num-traits 0.2.19", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "csv" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "diffy" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e616e59155c92257e84970156f506287853355f58cd4a6eb167385722c32b790" -dependencies = [ - "nu-ansi-term", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dyn-clone" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "ena" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" -dependencies = [ - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "genco" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d7af598790738fee616426e669360fa361273b1b9c9b7f30c92fa627605cad" -dependencies = [ - "genco-macros", - "relative-path", - "smallvec", -] - -[[package]] -name = "genco-macros" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4cf186fea4af17825116f72932fe52cce9a13bae39ff63b4dc0cfdb3fb4bde1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "globset" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax 0.8.2", -] - -[[package]] -name = "good_lp" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3198bd13dea84c76a64621d6ee8ee26a4960a9a0d538eca95ca8f1320a469ac9" -dependencies = [ - "fnv", - "minilp", -] - -[[package]] -name = "half" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.7", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash 0.8.7", - "allocator-api2", - "serde", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "human_bytes" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f255a4535024abf7640cb288260811fc14794f62b063652ed349f9a6c2348e" - -[[package]] -name = "id-arena" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - -[[package]] -name = "ignore" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indent" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1a0777d972970f204fdf8ef319f1f4f8459131636d7e3c96c5d59570d0fa6" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "indoc" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" - -[[package]] -name = "indoc" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "integer-encoding" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" - -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi 0.3.3", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lalrpop" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" -dependencies = [ - "ascii-canvas", - "bit-set", - "diff", - "ena", - "is-terminal", - "itertools 0.10.5", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax 0.7.5", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "lambdaworks-crypto" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb5d4f22241504f7c7b8d2c3a7d7835d7c07117f10bff2a7d96a9ef6ef217c3" -dependencies = [ - "lambdaworks-math", - "serde", - "sha2", - "sha3", -] - -[[package]] -name = "lambdaworks-math" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "358e172628e713b80a530a59654154bfc45783a6ed70ea284839800cebdf8f97" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets 0.52.0", -] - -[[package]] -name = "libmdbx" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0bee397dc9a7003e7bd34fffc1dc2d4c4fdc96530a0c439a5f98c9402bc7bf" -dependencies = [ - "bitflags 2.4.1", - "byteorder", - "derive_more", - "indexmap 1.9.3", - "libc", - "lifetimed-bytes", - "mdbx-sys", - "parking_lot 0.12.1", - "thiserror", -] - -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall 0.4.1", -] - -[[package]] -name = "lifetimed-bytes" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c970c8ea4c7b023a41cfa4af4c785a16694604c2f2a3b0d1f20a9bcb73fa550" -dependencies = [ - "bytes", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "lru" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" -dependencies = [ - "hashbrown 0.12.3", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "matrixmultiply" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" -dependencies = [ - "rawpointer", -] - -[[package]] -name = "mdbx-sys" -version = "0.12.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a329f8d655fb646cc9511c00886eefcddb6ef131869ef2d4b02c24c66825ac" -dependencies = [ - "bindgen", - "cc", - "libc", -] - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "memmap2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metrics" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" -dependencies = [ - "ahash 0.8.7", - "metrics-macros", - "portable-atomic", -] - -[[package]] -name = "metrics-macros" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "minilp" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" -dependencies = [ - "log", - "sprs", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "native_blockifier" -version = "0.8.0-rc.1" -dependencies = [ - "blockifier", - "cached", - "cairo-lang-starknet-classes", - "cairo-vm", - "indexmap 2.2.6", - "log", - "num-bigint", - "papyrus_storage", - "pretty_assertions", - "pyo3", - "pyo3-log", - "serde", - "serde_json", - "starknet-types-core", - "starknet_api", - "tempfile", - "thiserror", -] - -[[package]] -name = "ndarray" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits 0.2.19", - "rawpointer", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" -dependencies = [ - "num-integer", - "num-traits 0.2.19", - "rand", - "serde", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits 0.2.19", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "num-modular" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits 0.2.19", -] - -[[package]] -name = "num-prime" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4e3bc495f6e95bc15a6c0c55ac00421504a5a43d09e3cc455d1fea7015581d" -dependencies = [ - "bitvec", - "either", - "lru", - "num-bigint", - "num-integer", - "num-modular", - "num-traits 0.2.19", - "rand", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "serde", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "papyrus_common" -version = "0.4.0-dev.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "253c374b2174d98425fdd5e2e0a1bfd9b9f880a37c45149926ff02548ca6fa56" -dependencies = [ - "bitvec", - "cairo-lang-starknet-classes", - "hex", - "indexmap 2.2.6", - "itertools 0.10.5", - "lazy_static", - "rand", - "serde", - "serde_json", - "sha3", - "starknet-crypto 0.5.2", - "starknet-types-core", - "starknet_api", - "thiserror", -] - -[[package]] -name = "papyrus_config" -version = "0.4.0-dev.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681c77c3036aa865206d874c5fbaa264713f22bfd0ef518c7881a1954fc3a045" -dependencies = [ - "clap 4.5.4", - "itertools 0.10.5", - "serde", - "serde_json", - "strum_macros 0.25.3", - "thiserror", - "validator", -] - -[[package]] -name = "papyrus_proc_macros" -version = "0.4.0-dev.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80ae7c26b3754c405b911a45d9304c10feebf237b6b91b3c3c0fc31cbad9692f" -dependencies = [ - "quote", - "syn 2.0.66", -] - -[[package]] -name = "papyrus_storage" -version = "0.4.0-dev.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92bd277d8c0f980cb9da4584b01cd43213309ed0d5dc73a627b24080fab89845" -dependencies = [ - "byteorder", - "cairo-lang-casm", - "cairo-lang-starknet-classes", - "cairo-lang-utils", - "human_bytes", - "indexmap 2.2.6", - "integer-encoding", - "libmdbx", - "memmap2", - "metrics", - "num-bigint", - "page_size", - "papyrus_common", - "papyrus_config", - "papyrus_proc_macros", - "parity-scale-codec", - "primitive-types", - "serde", - "serde_json", - "starknet-types-core", - "starknet_api", - "tempfile", - "thiserror", - "tracing", - "validator", - "zstd 0.13.1", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.9", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "path-clean" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.2.6", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits 0.2.19", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "portable-atomic" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "pretty_assertions" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" -dependencies = [ - "diff", - "yansi", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-serde", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.0", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pyo3" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "indoc 1.0.9", - "libc", - "memoffset", - "num-bigint", - "parking_lot 0.12.1", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-log" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09c2b349b6538d8a73d436ca606dab6ce0aaab4dad9e6b7bdd57a4f556c3bc3" -dependencies = [ - "arc-swap", - "log", - "pyo3", -] - -[[package]] -name = "pyo3-macros" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "relative-path" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "rstest" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de1bb486a691878cd320c2f0d319ba91eeaa2e894066d8b5f8f117c000e9d962" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290ca1a1c8ca7edb7c3283bd44dc35dd54fdec6253a3912e201ba1072018fca8" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", - "unicode-ident", -] - -[[package]] -name = "rust_decimal" -version = "1.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" -dependencies = [ - "arrayvec", - "num-traits 0.2.19", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "salsa" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403" -dependencies = [ - "crossbeam-utils", - "indexmap 1.9.3", - "lock_api", - "log", - "oorandom", - "parking_lot 0.11.2", - "rustc-hash", - "salsa-macros", - "smallvec", -] - -[[package]] -name = "salsa-macros" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3904a4ba0a9d0211816177fd34b04c7095443f8cdacd11175064fe541c8fe2" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schemars" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" -dependencies = [ - "dyn-clone", - "indexmap 1.9.3", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.66", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" - -[[package]] -name = "serde" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "serde_json" -version = "1.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" -dependencies = [ - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "smol_str" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" -dependencies = [ - "serde", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "sprs" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" -dependencies = [ - "ndarray", - "num-complex", - "num-traits 0.1.43", -] - -[[package]] -name = "starknet-crypto" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f2175b0b3fc24ff2ec6dc07f5a720498994effca7e78b11a6e1c1bd02cad52" -dependencies = [ - "crypto-bigint", - "hex", - "hmac", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "rfc6979", - "sha2", - "starknet-crypto-codegen", - "starknet-curve 0.3.0", - "starknet-ff", - "zeroize", -] - -[[package]] -name = "starknet-crypto" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e2c30c01e8eb0fc913c4ee3cf676389fffc1d1182bfe5bb9670e4e72e968064" -dependencies = [ - "crypto-bigint", - "hex", - "hmac", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "rfc6979", - "sha2", - "starknet-crypto-codegen", - "starknet-curve 0.4.2", - "starknet-ff", - "zeroize", -] - -[[package]] -name = "starknet-crypto-codegen" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" -dependencies = [ - "starknet-curve 0.4.2", - "starknet-ff", - "syn 2.0.66", -] - -[[package]] -name = "starknet-curve" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252610baff59e4c4332ce3569f7469c5d3f9b415a2240d698fb238b2b4fc0942" -dependencies = [ - "starknet-ff", -] - -[[package]] -name = "starknet-curve" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c383518bb312751e4be80f53e8644034aa99a0afb29d7ac41b89a997db875b" -dependencies = [ - "starknet-ff", -] - -[[package]] -name = "starknet-ff" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abf1b44ec5b18d87c1ae5f54590ca9d0699ef4dd5b2ffa66fc97f24613ec585" -dependencies = [ - "ark-ff", - "crypto-bigint", - "getrandom", - "hex", -] - -[[package]] -name = "starknet-types-core" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6bacf0ba19bc721e518bc4bf389ff13daa8a7c5db5fd320600473b8aa9fcbd" -dependencies = [ - "lambdaworks-crypto", - "lambdaworks-math", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "serde", -] - -[[package]] -name = "starknet_api" -version = "0.13.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a80f50db7439ceb65de759fcbadb1695c82aec82126b2313413632e40d4eec" -dependencies = [ - "bitvec", - "cairo-lang-starknet-classes", - "derive_more", - "hex", - "indexmap 2.2.6", - "itertools 0.12.1", - "once_cell", - "primitive-types", - "serde", - "serde_json", - "sha3", - "starknet-crypto 0.5.2", - "starknet-types-core", - "strum", - "strum_macros 0.24.3", - "thiserror", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared 0.10.0", - "precomputed-hash", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.66", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "test-case" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0" -dependencies = [ - "test-case-macros", -] - -[[package]] -name = "test-case-macros" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26" -dependencies = [ - "cfg-if", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "thiserror-impl-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e6318948b519ba6dc2b442a6d0b904ebfb8d411a3ad3e07843615a72249758" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "thiserror-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ad459d94dd517257cc96add8a43190ee620011bb6e6cdc82dafd97dfafafea" -dependencies = [ - "thiserror-impl-no-std", -] - -[[package]] -name = "tikv-jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" -dependencies = [ - "backtrace", - "parking_lot 0.12.1", - "pin-project-lite", - "tokio-macros", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "toml" -version = "0.8.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.13", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.31", -] - -[[package]] -name = "toml_edit" -version = "0.22.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" -dependencies = [ - "indexmap 2.2.6", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.9", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unescaper" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f0f68e58d297ba8b22b8b5a96a87b863ba6bb46aaf51e19a4b02c5a6dd5b7f" -dependencies = [ - "thiserror", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unindent" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "validator" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d6937c33ec6039d8071bcf72933146b5bbe378d645d8fa59bdadabfc2a249" -dependencies = [ - "idna 0.2.3", - "lazy_static", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", - "validator_types", -] - -[[package]] -name = "validator_derive" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286b4497f270f59276a89ae0ad109d5f8f18c69b613e3fb22b61201aadb0c4d" -dependencies = [ - "if_chain", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "validator_types", -] - -[[package]] -name = "validator_types" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9680608df133af2c1ddd5eaf1ddce91d60d61b6bc51494ef326458365a470a" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.66", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winnow" -version = "0.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6" -dependencies = [ - "memchr", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xshell" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437" -dependencies = [ - "xshell-macros", -] - -[[package]] -name = "xshell-macros" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852" - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" -dependencies = [ - "zstd-safe 7.1.0", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 1066dabdf1a..00000000000 --- a/Cargo.toml +++ /dev/null @@ -1,70 +0,0 @@ -[workspace] -# Using version 2 to avoid unifying features. For more info, read: -# https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2 -resolver = "2" - -members = ["crates/blockifier", "crates/native_blockifier"] - -[workspace.package] -version = "0.8.0-rc.1" -edition = "2021" -repository = "https://github.com/starkware-libs/blockifier/" -license = "Apache-2.0" -license-file = "LICENSE" - -[workspace.dependencies] -anyhow = "1.0.0" -ark-ec = "0.4.2" -ark-ff = "0.4.0-alpha.7" -ark-secp256k1 = "0.4.0" -ark-secp256r1 = "0.4.0" -assert_matches = "1.5.0" -cached = "0.44.0" -cairo-lang-casm = "2.7.0-rc.3" -cairo-lang-runner = "2.7.0-rc.3" -cairo-lang-starknet-classes = "2.7.0-rc.3" -cairo-lang-utils = "2.7.0-rc.3" -cairo-vm = "1.0.0-rc5" -criterion = "0.3" -derive_more = "0.99.17" -glob = "0.3.1" -indexmap = "2.1.0" -itertools = "0.10.3" -keccak = "0.1.3" -log = "0.4" -num-bigint = "0.4" -num-integer = "0.1.45" -num-rational = { version = "0.4", features = ["serde"] } -num-traits = "0.2" -once_cell = "1.19.0" -papyrus_storage = "0.4.0-dev.4" -paste = "1.0.15" -phf = { version = "0.11", features = ["macros"] } -pretty_assertions = "1.2.1" -pyo3 = "0.19.1" -pyo3-log = "0.8.1" -rand = "0.8" -regex = "1.10.4" -rstest = "0.17.0" -serde = "1.0.184" -serde_json = "1.0.81" -sha2 = "0.10.8" -sha3 = "0.10.6" -starknet-types-core = { version = "0.1.5", features = ["hash", "prime-bigint"] } -starknet_api = "0.13.0-rc.0" -strum = "0.24.1" -strum_macros = "0.24.3" -tempfile = "3.7.0" -test-case = "2.2.2" -thiserror = "1.0.37" -tikv-jemallocator = "0.5.4" - -[workspace.lints.rust] -future-incompatible = "deny" -nonstandard-style = "deny" -rust-2018-idioms = "deny" -unused = "deny" -warnings = "deny" - -[workspace.lints.clippy] -as_conversions = "deny" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e6d9a8d4ee6..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM ubuntu:20.04 - -RUN apt update && apt -y install \ - build-essential \ - clang \ - curl \ - python3-dev - -ENV RUSTUP_HOME=/opt/rust -ENV CARGO_HOME=/opt/rust -ENV PATH=$PATH:/opt/rust/bin - -COPY scripts/install_build_tools.sh . -RUN bash install_build_tools.sh diff --git a/README.md b/README.md deleted file mode 100644 index 110fa3be730..00000000000 --- a/README.md +++ /dev/null @@ -1,66 +0,0 @@ -
-

Blockifier

-
- Report a Bug - · - Request a Feature - · - Ask a Question -
- -
-
- -[![GitHub Workflow Status](https://github.com/starkware-libs/blockifier/actions/workflows/post-merge.yml/badge.svg)](https://github.com/starkware-libs/blockifier/actions/workflows/post-merge.yml) -[![codecov](https://codecov.io/gh/starkware-libs/blockifier/branch/main/graph/badge.svg?token=Z5MXY45MR5)](https://codecov.io/gh/starkware-libs/blockifier) - -
- -
-Table of Contents - -- [About](#about) -- [Roadmap](#roadmap) -- [Support](#support) -- [Security](#security) -- [License](#license) - -
- ---- - -## About - -Blockifier is a Rust implementation of the component in the Starknet sequencer that executes transactions, and is in charge of creating state diffs and blocks. - -## Roadmap - -The Blockifier is a step towards a decentralized sequencer client for Starknet, allowing anyone to run one. -We'll add more milestones to this table once we finish the first one, where we blockify transactions sequentially, including all existing functionality. - -| name | status | -| -------------------------------------------------------------------------------------------------------------------------------------- | :----: | -| Add the ability to execute a block and output a state diff. | ✅ | -| Integrate with the existing Starknet Sequencer by replacing its current transaction-blockifying component, which is written in Python. | ⏳ | -| Implement optimistic concurrency of transaction execution. | | -| Extend the Blockifier into a full Starknet sequencer, written in Rust, replacing the one currently in use. | | - -## Support - -Reach out to the maintainer at one of the following places: - -- [GitHub Discussions](https://github.com/starkware-libs/blockifier/discussions) -- Contact options listed on [this GitHub profile](https://github.com/starkware-libs) - -## Security - -Blockifier follows good security practices, but 100% security cannot be assured. -Blockifier is provided **"as is"** without any **warranty**. Use at your own risk. - -_For more information and to report security issues, please refer to our [security documentation](docs/SECURITY.md)._ - -## License - -This project is licensed under the **Apache 2.0 license**. - -See [LICENSE](LICENSE) for more information. diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/build_native_blockifier.sh b/build_native_blockifier.sh deleted file mode 100755 index 3c3879485e1..00000000000 --- a/build_native_blockifier.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/env bash -set -e - -docker_image_name=blockifier-ci -docker build . -t ${docker_image_name} - -docker run \ - --rm \ - --net host \ - -e CARGO_HOME=${HOME}/.cargo \ - -u $UID \ - -v /tmp:/tmp \ - -v "${HOME}:${HOME}" \ - --workdir ${PWD} \ - ${docker_image_name} \ - cargo build --release -p native_blockifier --features "testing" diff --git a/commitlint.config.js b/commitlint.config.js deleted file mode 100644 index 910cc673cd6..00000000000 --- a/commitlint.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const Configuration = { - /* - * Resolve and load @commitlint/config-conventional from node_modules. - * Referenced packages must be installed. - * See [the README](https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/config-conventional/README.md) - * for applied rules. - */ - extends: ['@commitlint/config-conventional'], - /* - * Resolve and load conventional-changelog-atom from node_modules. - * Referenced packages must be installed - */ - // parserPreset: 'conventional-changelog-atom', - /* - * Resolve and load @commitlint/format from node_modules. - * Referenced package must be installed - */ - formatter: '@commitlint/format', - /* - * Any rules defined here will override rules from @commitlint/config-conventional - */ - rules: { - 'scope-enum': [2, 'always', [ - 'concurrency', - 'execution', - 'fee', - 'native_blockifier', - 'state', - 'transaction', - ]], - }, - /* - * Functions that return true if commitlint should ignore the given message. - */ - ignores: [(commit) => commit === ''], - /* - * Whether commitlint uses the default ignore rules. - */ - defaultIgnores: true, - /* - * Custom URL to show upon failure - */ - helpUrl: - 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint', - /* - * Custom prompt configs, not used currently. - */ - prompt: { - messages: {}, - questions: { - type: { - description: 'please input type:', - }, - }, - }, -}; - -module.exports = Configuration; diff --git a/crates/committer/Cargo.toml b/crates/committer/Cargo.toml new file mode 100644 index 00000000000..aed76d8e4b2 --- /dev/null +++ b/crates/committer/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "committer" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Computes and manages Starknet state." + +[lints] +workspace = true + +[features] +testing = [] + +[dev-dependencies] +pretty_assertions.workspace = true +rand.workspace = true +rstest.workspace = true + +[dependencies] +async-recursion.workspace = true +derive_more.workspace = true +ethnum.workspace = true +hex.workspace = true +log.workspace = true +rand.workspace = true +serde.workspace = true +serde_json.workspace = true +starknet-types-core.workspace = true +strum.workspace = true +strum_macros.workspace = true +thiserror.workspace = true +tokio.workspace = true + +# Optional dependencies required for tests and the testing feature. +# See [here](https://github.com/bnjbvr/cargo-machete/issues/128). +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/crates/committer/src/block_committer.rs b/crates/committer/src/block_committer.rs new file mode 100644 index 00000000000..3a8d642348d --- /dev/null +++ b/crates/committer/src/block_committer.rs @@ -0,0 +1,3 @@ +pub mod commit; +pub mod errors; +pub mod input; diff --git a/crates/committer/src/block_committer/commit.rs b/crates/committer/src/block_committer/commit.rs new file mode 100644 index 00000000000..a3d2cec8aa3 --- /dev/null +++ b/crates/committer/src/block_committer/commit.rs @@ -0,0 +1,148 @@ +use log::warn; +use std::collections::HashMap; + +use crate::block_committer::errors::BlockCommitmentError; +use crate::block_committer::input::Config; +use crate::block_committer::input::ConfigImpl; +use crate::block_committer::input::ContractAddress; +use crate::block_committer::input::Input; +use crate::block_committer::input::StateDiff; +use crate::patricia_merkle_tree::filled_tree::forest::FilledForest; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::original_skeleton_tree::skeleton_forest::ForestSortedIndices; +use crate::patricia_merkle_tree::original_skeleton_tree::skeleton_forest::OriginalSkeletonForest; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunctionImpl; +use crate::patricia_merkle_tree::updated_skeleton_tree::skeleton_forest::UpdatedSkeletonForest; +use crate::storage::map_storage::MapStorage; + +type BlockCommitmentResult = Result; + +pub async fn commit_block(input: Input) -> BlockCommitmentResult { + let (mut storage_tries_indices, mut contracts_trie_indices, mut classes_trie_indices) = + get_all_modified_indices(&input.state_diff); + let forest_sorted_indices = ForestSortedIndices { + storage_tries_sorted_indices: storage_tries_indices + .iter_mut() + .map(|(address, indices)| (*address, SortedLeafIndices::new(indices))) + .collect(), + contracts_trie_sorted_indices: SortedLeafIndices::new(&mut contracts_trie_indices), + classes_trie_sorted_indices: SortedLeafIndices::new(&mut classes_trie_indices), + }; + let actual_storage_updates = input.state_diff.actual_storage_updates(); + let actual_classes_updates = input.state_diff.actual_classes_updates(); + let (mut original_forest, original_contracts_trie_leaves) = OriginalSkeletonForest::create( + MapStorage::from(input.storage), + input.contracts_trie_root_hash, + input.classes_trie_root_hash, + &actual_storage_updates, + &actual_classes_updates, + &forest_sorted_indices, + &input.config, + )?; + + if input.config.warn_on_trivial_modifications() { + check_trivial_nonce_and_class_hash_updates( + &original_contracts_trie_leaves, + &input.state_diff.address_to_class_hash, + &input.state_diff.address_to_nonce, + ); + } + + let updated_forest = UpdatedSkeletonForest::create( + &mut original_forest, + &input.state_diff.skeleton_classes_updates(), + &input.state_diff.skeleton_storage_updates(), + &original_contracts_trie_leaves, + &input.state_diff.address_to_class_hash, + &input.state_diff.address_to_nonce, + )?; + + Ok(FilledForest::create::( + updated_forest, + actual_storage_updates, + actual_classes_updates, + &original_contracts_trie_leaves, + &input.state_diff.address_to_class_hash, + &input.state_diff.address_to_nonce, + ) + .await?) +} + +/// Compares the previous state's nonce and class hash with the given in the state diff. +/// In case of trivial update, logs out a warning for trivial state diff update. +fn check_trivial_nonce_and_class_hash_updates( + original_contracts_trie_leaves: &HashMap, + address_to_class_hash: &HashMap, + address_to_nonce: &HashMap, +) { + for (address, nonce) in address_to_nonce.iter() { + if original_contracts_trie_leaves + .get(&NodeIndex::from_contract_address(address)) + .is_some_and(|previous_contract_state| previous_contract_state.nonce == *nonce) + { + warn!( + "Encountered a trivial nonce update of contract {:?}", + address + ) + } + } + + for (address, class_hash) in address_to_class_hash.iter() { + if original_contracts_trie_leaves + .get(&NodeIndex::from_contract_address(address)) + .is_some_and(|previous_contract_state| { + previous_contract_state.class_hash == *class_hash + }) + { + warn!( + "Encountered a trivial class hash update of contract {:?}", + address + ) + } + } +} + +type StorageTriesIndices = HashMap>; +type ContractsTrieIndices = Vec; +type ClassesTrieIndices = Vec; + +/// Returns all modified indices in the given state diff. +pub(crate) fn get_all_modified_indices( + state_diff: &StateDiff, +) -> ( + StorageTriesIndices, + ContractsTrieIndices, + ClassesTrieIndices, +) { + let accessed_addresses = state_diff.accessed_addresses(); + let contracts_trie_indices: Vec = accessed_addresses + .iter() + .map(|address| NodeIndex::from_contract_address(address)) + .collect(); + let classes_trie_indices: Vec = state_diff + .class_hash_to_compiled_class_hash + .keys() + .map(NodeIndex::from_class_hash) + .collect(); + let storage_tries_indices: HashMap> = accessed_addresses + .iter() + .map(|address| { + let indices: Vec = match state_diff.storage_updates.get(address) { + Some(updates) => updates + .keys() + .map(NodeIndex::from_starknet_storage_key) + .collect(), + None => Vec::new(), + }; + (**address, indices) + }) + .collect(); + ( + storage_tries_indices, + contracts_trie_indices, + classes_trie_indices, + ) +} diff --git a/crates/committer/src/block_committer/errors.rs b/crates/committer/src/block_committer/errors.rs new file mode 100644 index 00000000000..f2c7d4d2ae1 --- /dev/null +++ b/crates/committer/src/block_committer/errors.rs @@ -0,0 +1,9 @@ +use thiserror::Error; + +use crate::forest_errors::ForestError; + +#[derive(Debug, Error)] +pub enum BlockCommitmentError { + #[error(transparent)] + ForestError(#[from] ForestError), +} diff --git a/crates/committer/src/block_committer/input.rs b/crates/committer/src/block_committer/input.rs new file mode 100644 index 00000000000..10f6f630fc1 --- /dev/null +++ b/crates/committer/src/block_committer/input.rs @@ -0,0 +1,150 @@ +use log::LevelFilter; + +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::{LeafModifications, SkeletonLeaf}; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::storage::storage_trait::{StorageKey, StorageValue}; +use std::collections::{HashMap, HashSet}; +use std::fmt::Debug; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +// TODO(Nimrod, 1/6/2025): Use the ContractAddress defined in starknet-types-core when available. +pub struct ContractAddress(pub Felt); + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +// TODO(Nimrod, 1/6/2025): Use the StarknetStorageValue defined in starknet-types-core when available. +pub struct StarknetStorageKey(pub Felt); + +#[derive(Clone, Copy, Default, Debug, Eq, PartialEq)] +pub struct StarknetStorageValue(pub Felt); + +#[derive(Debug, Default, Eq, PartialEq)] +pub struct StateDiff { + pub address_to_class_hash: HashMap, + pub address_to_nonce: HashMap, + pub class_hash_to_compiled_class_hash: HashMap, + pub storage_updates: + HashMap>, +} + +/// Trait contains all optional configurations of the committer. +pub trait Config: Debug + Eq + PartialEq { + /// Indicates whether a warning should be given in case of a trivial state update. + /// If the configuration is set, it requires that the storage will contain the original data for + /// the modified leaves. Otherwise, it is not required. + fn warn_on_trivial_modifications(&self) -> bool; + + /// Indicates from which log level output should be printed out to console. + fn logger_level(&self) -> LevelFilter; +} + +#[derive(Debug, Eq, PartialEq)] +pub struct ConfigImpl { + warn_on_trivial_modifications: bool, + log_level: LevelFilter, +} + +impl Config for ConfigImpl { + fn warn_on_trivial_modifications(&self) -> bool { + self.warn_on_trivial_modifications + } + + fn logger_level(&self) -> LevelFilter { + self.log_level + } +} + +impl ConfigImpl { + pub fn new(warn_on_trivial_modifications: bool, log_level: LevelFilter) -> Self { + Self { + warn_on_trivial_modifications, + log_level, + } + } +} + +#[derive(Debug, Eq, PartialEq)] +pub struct Input { + pub storage: HashMap, + /// All relevant information for the state diff commitment. + pub state_diff: StateDiff, + pub contracts_trie_root_hash: HashOutput, + pub classes_trie_root_hash: HashOutput, + pub config: C, +} + +impl StateDiff { + pub(crate) fn accessed_addresses(&self) -> HashSet<&ContractAddress> { + HashSet::from_iter( + self.address_to_class_hash + .keys() + .chain(self.address_to_nonce.keys()) + .chain(self.storage_updates.keys()), + ) + } + + /// For each modified contract calculates it's actual storage updates. + pub(crate) fn skeleton_storage_updates( + &self, + ) -> HashMap> { + self.accessed_addresses() + .iter() + .map(|address| { + let updates = match self.storage_updates.get(address) { + Some(inner_updates) => inner_updates + .iter() + .map(|(key, value)| { + ( + NodeIndex::from_starknet_storage_key(key), + SkeletonLeaf::from(value.0), + ) + }) + .collect(), + None => HashMap::new(), + }; + (**address, updates) + }) + .collect() + } + + pub(crate) fn skeleton_classes_updates(&self) -> LeafModifications { + self.class_hash_to_compiled_class_hash + .iter() + .map(|(class_hash, compiled_class_hash)| { + ( + NodeIndex::from_class_hash(class_hash), + SkeletonLeaf::from(compiled_class_hash.0), + ) + }) + .collect() + } + + pub(crate) fn actual_storage_updates( + &self, + ) -> HashMap> { + self.accessed_addresses() + .iter() + .map(|address| { + let updates = match self.storage_updates.get(address) { + Some(inner_updates) => inner_updates + .iter() + .map(|(key, value)| (NodeIndex::from_starknet_storage_key(key), *value)) + .collect(), + None => HashMap::new(), + }; + (**address, updates) + }) + .collect() + } + + pub(crate) fn actual_classes_updates(&self) -> LeafModifications { + self.class_hash_to_compiled_class_hash + .iter() + .map(|(class_hash, compiled_class_hash)| { + (NodeIndex::from_class_hash(class_hash), *compiled_class_hash) + }) + .collect() + } +} diff --git a/crates/committer/src/felt.rs b/crates/committer/src/felt.rs new file mode 100644 index 00000000000..85b9b1e970e --- /dev/null +++ b/crates/committer/src/felt.rs @@ -0,0 +1,130 @@ +use core::fmt; +use ethnum::U256; +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::{Felt as StarknetTypesFelt, FromStrError}; + +#[derive( + Eq, + PartialEq, + Clone, + Copy, + Default, + Hash, + derive_more::Add, + derive_more::Sub, + PartialOrd, + Ord, + Serialize, + Deserialize, +)] +pub struct Felt(pub StarknetTypesFelt); + +#[macro_export] +macro_rules! impl_from_hex_for_felt_wrapper { + ($wrapper:ty) => { + impl $wrapper { + pub(crate) fn from_hex(hex_string: &str) -> Result { + Ok(Self(Felt::from_hex(hex_string)?)) + } + } + }; +} + +#[macro_export] +macro_rules! impl_from { + ($to:ty, $from:ty, $($other_from: ty),+) => { + $crate::impl_from!($to, $from); + $crate::impl_from!($to $(, $other_from)*); + }; + ($to:ty, $from:ty) => { + impl From<$from> for $to { + fn from(value: $from) -> Self { + Self(value.into()) + } + } + }; +} +impl_from!(Felt, StarknetTypesFelt, u128, u8); + +impl From for StarknetTypesFelt { + fn from(felt: Felt) -> Self { + felt.0 + } +} + +impl From<&Felt> for U256 { + fn from(felt: &Felt) -> Self { + U256::from_be_bytes(felt.to_bytes_be()) + } +} + +impl std::ops::Mul for Felt { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + Self(self.0 * rhs.0) + } +} + +impl fmt::Debug for Felt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", U256::from(self)) + } +} + +impl Felt { + pub const ZERO: Felt = Felt(StarknetTypesFelt::ZERO); + #[allow(dead_code)] + pub(crate) const ONE: Felt = Felt(StarknetTypesFelt::ONE); + #[allow(dead_code)] + pub(crate) const TWO: Felt = Felt(StarknetTypesFelt::TWO); + #[allow(dead_code)] + pub(crate) const THREE: Felt = Felt(StarknetTypesFelt::THREE); + pub const MAX: Felt = Felt(StarknetTypesFelt::MAX); + + pub fn from_bytes_be_slice(bytes: &[u8]) -> Self { + Self(StarknetTypesFelt::from_bytes_be_slice(bytes)) + } + + /// Raises `self` to the power of `exponent`. + #[allow(dead_code)] + pub(crate) fn pow(&self, exponent: impl Into) -> Self { + Self(self.0.pow(exponent.into())) + } + + #[allow(dead_code)] + pub(crate) fn bits(&self) -> u8 { + self.0 + .bits() + .try_into() + // Should not fail as it takes less than 252 bits to represent a felt. + .expect("Unexpected error occurred when extracting bits of a Felt.") + } + + pub fn from_bytes_be(bytes: &[u8; 32]) -> Self { + StarknetTypesFelt::from_bytes_be(bytes).into() + } + + pub fn to_bytes_be(self) -> [u8; 32] { + self.0.to_bytes_be() + } + + /// Parse a hex-encoded number into `Felt`. + pub fn from_hex(hex_string: &str) -> Result { + Ok(StarknetTypesFelt::from_hex(hex_string)?.into()) + } + + pub fn to_hex(&self) -> String { + self.0.to_hex_string() + } + + // Convert to a 64-character hexadecimal string without the "0x" prefix. + pub fn to_fixed_hex_string(&self) -> String { + // Zero-pad the remaining string + self.0 + .to_fixed_hex_string() + .strip_prefix("0x") + .unwrap_or("0") + .to_string() + } +} diff --git a/crates/committer/src/forest_errors.rs b/crates/committer/src/forest_errors.rs new file mode 100644 index 00000000000..168ccad0edd --- /dev/null +++ b/crates/committer/src/forest_errors.rs @@ -0,0 +1,35 @@ +use crate::block_committer::input::ContractAddress; +use crate::patricia_merkle_tree::filled_tree::errors::{ + ClassesTrieError, ContractsTrieError, StorageTrieError, +}; +use crate::patricia_merkle_tree::original_skeleton_tree::errors::OriginalSkeletonTreeError; +use crate::patricia_merkle_tree::updated_skeleton_tree::errors::UpdatedSkeletonTreeError; + +use thiserror::Error; +use tokio::task::JoinError; + +pub(crate) type ForestResult = Result; + +#[derive(Debug, Error)] +pub enum ForestError { + #[error(transparent)] + OriginalSkeleton(#[from] OriginalSkeletonTreeError), + #[error(transparent)] + UpdatedSkeleton(#[from] UpdatedSkeletonTreeError), + #[error(transparent)] + ClassesTrie(#[from] ClassesTrieError), + #[error(transparent)] + StorageTrie(#[from] StorageTrieError), + #[error(transparent)] + ContractsTrie(#[from] ContractsTrieError), + #[error("Missing input: Couldn't find the storage trie's current state of address {0:?}")] + MissingContractCurrentState(ContractAddress), + #[error("Can't build storage trie's updated skeleton, because there is no original skeleton at address {0:?}")] + MissingOriginalSkeleton(ContractAddress), + #[error("Can't fill storage trie, because there is no updated skeleton at address {0:?}")] + MissingUpdatedSkeleton(ContractAddress), + #[error("Can't build storage trie, because there are no sorted leaf indices of the contract at address {0:?}")] + MissingSortedLeafIndices(ContractAddress), + #[error(transparent)] + JoinError(#[from] JoinError), +} diff --git a/crates/committer/src/hash.rs b/crates/committer/src/hash.rs new file mode 100644 index 00000000000..37201a3cbb8 --- /dev/null +++ b/crates/committer/src/hash.rs @@ -0,0 +1 @@ +pub mod hash_trait; diff --git a/crates/committer/src/hash/hash_trait.rs b/crates/committer/src/hash/hash_trait.rs new file mode 100644 index 00000000000..43dc4f2ed61 --- /dev/null +++ b/crates/committer/src/hash/hash_trait.rs @@ -0,0 +1,13 @@ +use starknet_types_core::felt::FromStrError; + +use crate::{felt::Felt, impl_from_hex_for_felt_wrapper}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct HashOutput(pub Felt); + +impl HashOutput { + pub(crate) const ZERO: HashOutput = HashOutput(Felt::ZERO); + pub(crate) const ROOT_OF_EMPTY_TREE: HashOutput = Self::ZERO; +} + +impl_from_hex_for_felt_wrapper!(HashOutput); diff --git a/crates/committer/src/lib.rs b/crates/committer/src/lib.rs new file mode 100644 index 00000000000..d87fb198189 --- /dev/null +++ b/crates/committer/src/lib.rs @@ -0,0 +1,6 @@ +pub mod block_committer; +pub mod felt; +pub mod forest_errors; +pub mod hash; +pub mod patricia_merkle_tree; +pub mod storage; diff --git a/crates/committer/src/patricia_merkle_tree.rs b/crates/committer/src/patricia_merkle_tree.rs new file mode 100644 index 00000000000..b3c5c9ad7ee --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree.rs @@ -0,0 +1,12 @@ +pub mod errors; +pub mod filled_tree; +pub mod node_data; +pub mod original_skeleton_tree; +pub mod types; +pub mod updated_skeleton_tree; + +#[cfg(test)] +pub mod internal_test_utils; + +#[cfg(any(feature = "testing", test))] +pub mod external_test_utils; diff --git a/crates/committer/src/patricia_merkle_tree/errors.rs b/crates/committer/src/patricia_merkle_tree/errors.rs new file mode 100644 index 00000000000..e157db8934b --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/errors.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum TypesError { + #[error("Failed to convert type {from:?} to {to}. Reason: {reason}.")] + ConversionError { + from: T, + to: &'static str, + reason: &'static str, + }, +} diff --git a/crates/committer/src/patricia_merkle_tree/external_test_utils.rs b/crates/committer/src/patricia_merkle_tree/external_test_utils.rs new file mode 100644 index 00000000000..ca7472c324c --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/external_test_utils.rs @@ -0,0 +1,128 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use ethnum::U256; +use serde_json::json; + +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::errors::TypesError; +use crate::storage::map_storage::MapStorage; +use rand::Rng; + +use super::filled_tree::tree::{FilledTree, StorageTrie}; +use super::node_data::leaf::{Leaf, LeafModifications, SkeletonLeaf}; +use super::original_skeleton_tree::config::OriginalSkeletonStorageTrieConfig; +use super::original_skeleton_tree::tree::{OriginalSkeletonTree, OriginalSkeletonTreeImpl}; +use super::types::{NodeIndex, SortedLeafIndices}; +use super::updated_skeleton_tree::hash_function::TreeHashFunctionImpl; +use super::updated_skeleton_tree::tree::{UpdatedSkeletonTree, UpdatedSkeletonTreeImpl}; + +impl TryFrom<&U256> for Felt { + type Error = TypesError; + fn try_from(value: &U256) -> Result { + if *value > U256::from(&Felt::MAX) { + return Err(TypesError::ConversionError { + from: *value, + to: "Felt", + reason: "value is bigger than felt::max", + }); + } + Ok(Self::from_bytes_be(&value.to_be_bytes())) + } +} + +/// Generates a random U256 number between low and high (exclusive). +/// Panics if low > high +pub fn get_random_u256(rng: &mut R, low: U256, high: U256) -> U256 { + assert!(low < high); + let high_of_low = low.high(); + let high_of_high = high.high(); + + let delta = high - low; + if delta <= u128::MAX { + let delta = u128::try_from(delta).expect("Failed to convert delta to u128"); + return low + rng.gen_range(0..delta); + } + + // Randomize the high 128 bits in the extracted range, and the low 128 bits in their entire + // domain until the result is in range. + // As high-low>u128::MAX, the expected number of samples until the loops breaks is bound from + // above by 3 (as either: + // 1. high_of_high > high_of_low + 1, and there is a 1/3 chance to get a valid result for high + // bits in (high_of_low, high_of_high). + // 2. high_of_high == high_of_low + 1, and every possible low 128 bits value is valid either + // when the high bits equal high_of_high, or when they equal high_of_low). + let mut randomize = || { + U256::from_words( + rng.gen_range(*high_of_low..=*high_of_high), + rng.gen_range(0..=u128::MAX), + ) + }; + let mut result = randomize(); + while result < low || result >= high { + result = randomize(); + } + result +} + +pub async fn tree_computation_flow( + leaf_modifications: Arc>, + storage: &MapStorage, + root_hash: HashOutput, +) -> StorageTrie { + let config = OriginalSkeletonStorageTrieConfig::new(&leaf_modifications, false); + let mut sorted_leaf_indices: Vec = leaf_modifications.keys().copied().collect(); + let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices); + let mut original_skeleton = + OriginalSkeletonTreeImpl::create(storage, root_hash, sorted_leaf_indices, &config) + .expect("Failed to create the original skeleton tree"); + + let updated_skeleton: UpdatedSkeletonTreeImpl = UpdatedSkeletonTree::create( + &mut original_skeleton, + &leaf_modifications + .iter() + .map(|(index, data)| { + ( + *index, + match data.is_empty() { + true => SkeletonLeaf::Zero, + false => SkeletonLeaf::NonZero, + }, + ) + }) + .collect(), + ) + .expect("Failed to create the updated skeleton tree"); + + StorageTrie::create::(updated_skeleton.into(), leaf_modifications) + .await + .expect("Failed to create the filled tree") +} + +pub async fn single_tree_flow_test( + leaf_modifications: LeafModifications, + storage: MapStorage, + root_hash: HashOutput, +) -> String { + // Move from leaf number to actual index. + let leaf_modifications = leaf_modifications + .into_iter() + .map(|(k, v)| (NodeIndex::FIRST_LEAF + k, v)) + .collect::>(); + + let filled_tree = + tree_computation_flow(Arc::new(leaf_modifications), &storage, root_hash).await; + + let hash_result = filled_tree.get_root_hash(); + + let mut result_map = HashMap::new(); + // Serialize the hash result. + let json_hash = &json!(hash_result.0.to_hex()); + result_map.insert("root_hash", json_hash); + // Serlialize the storage modifications. + let json_storage = &json!(filled_tree.serialize()); + result_map.insert("storage_changes", json_storage); + serde_json::to_string(&result_map).expect("serialization failed") +} diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree.rs b/crates/committer/src/patricia_merkle_tree/filled_tree.rs new file mode 100644 index 00000000000..4357d7f2fb4 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree.rs @@ -0,0 +1,5 @@ +pub mod errors; +pub mod forest; +pub mod node; +pub mod node_serde; +pub mod tree; diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/errors.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/errors.rs new file mode 100644 index 00000000000..073a2d37b2b --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/errors.rs @@ -0,0 +1,38 @@ +use tokio::task::JoinError; + +use crate::block_committer::input::StarknetStorageValue; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::filled_tree::node::FilledNode; +use crate::patricia_merkle_tree::node_data::errors::LeafError; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::updated_skeleton_tree::errors::UpdatedSkeletonTreeError; +use crate::patricia_merkle_tree::{node_data::leaf::Leaf, types::NodeIndex}; + +#[derive(thiserror::Error, Debug)] +pub enum FilledTreeError { + #[error("Deleted leaf at index {0:?} appears in the updated skeleton tree.")] + DeletedLeafInSkeleton(NodeIndex), + #[error("Double update at node {index:?}. Existing value: {existing_value:?}.")] + DoubleUpdate { + index: NodeIndex, + existing_value: Box>, + }, + #[error(transparent)] + Leaf(#[from] LeafError), + #[error("Missing node at index {0:?}.")] + MissingNode(NodeIndex), + #[error("Missing root.")] + MissingRoot, + #[error("Poisoned lock: {0}.")] + PoisonedLock(String), + #[error(transparent)] + SerializeError(#[from] serde_json::Error), + #[error(transparent)] + UpdatedSkeletonError(#[from] UpdatedSkeletonTreeError), + #[error(transparent)] + JoinError(#[from] JoinError), +} + +pub type StorageTrieError = FilledTreeError; +pub type ClassesTrieError = FilledTreeError; +pub type ContractsTrieError = FilledTreeError; diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/forest.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/forest.rs new file mode 100644 index 00000000000..cadbe2a70d0 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/forest.rs @@ -0,0 +1,130 @@ +use crate::block_committer::input::{ContractAddress, StarknetStorageValue}; +use crate::forest_errors::{ForestError, ForestResult}; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, Nonce}; +use crate::patricia_merkle_tree::filled_tree::tree::FilledTree; +use crate::patricia_merkle_tree::filled_tree::tree::{ + ClassesTrie, ContractsTrie, StorageTrie, StorageTrieMap, +}; +use crate::patricia_merkle_tree::node_data::leaf::{ContractState, LeafModifications}; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::ForestHashFunction; +use crate::patricia_merkle_tree::updated_skeleton_tree::skeleton_forest::UpdatedSkeletonForest; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; +use crate::storage::storage_trait::Storage; + +use std::collections::HashMap; +use std::sync::Arc; +use tokio::task::JoinSet; + +pub struct FilledForest { + pub storage_tries: StorageTrieMap, + pub contracts_trie: ContractsTrie, + pub classes_trie: ClassesTrie, +} + +impl FilledForest { + pub fn write_to_storage(&self, storage: &mut impl Storage) { + // Serialize all trees to one hash map. + let new_db_objects = self + .storage_tries + .values() + .flat_map(|tree| tree.serialize().into_iter()) + .chain(self.contracts_trie.serialize()) + .chain(self.classes_trie.serialize()) + .collect(); + + // Store the new hash map + storage.mset(new_db_objects); + } + + pub fn get_contract_root_hash(&self) -> HashOutput { + self.contracts_trie.get_root_hash() + } + + pub fn get_compiled_class_root_hash(&self) -> HashOutput { + self.classes_trie.get_root_hash() + } + + pub(crate) async fn create( + mut updated_forest: UpdatedSkeletonForest, + storage_updates: HashMap>, + classes_updates: LeafModifications, + original_contracts_trie_leaves: &HashMap, + address_to_class_hash: &HashMap, + address_to_nonce: &HashMap, + ) -> ForestResult { + let classes_trie_task = tokio::spawn(ClassesTrie::create::( + Arc::new(updated_forest.classes_trie), + Arc::new(classes_updates), + )); + let mut contracts_trie_modifications = HashMap::new(); + let mut filled_storage_tries = HashMap::new(); + let mut contracts_state_tasks = JoinSet::new(); + + for (address, inner_updates) in storage_updates { + let updated_storage_trie = updated_forest + .storage_tries + .remove(&address) + .ok_or(ForestError::MissingUpdatedSkeleton(address))?; + + let original_contract_state = original_contracts_trie_leaves + .get(&NodeIndex::from_contract_address(&address)) + .ok_or(ForestError::MissingContractCurrentState(address))?; + contracts_state_tasks.spawn(Self::new_contract_state::( + address, + *(address_to_nonce + .get(&address) + .unwrap_or(&original_contract_state.nonce)), + *(address_to_class_hash + .get(&address) + .unwrap_or(&original_contract_state.class_hash)), + updated_storage_trie, + inner_updates, + )); + } + + while let Some(result) = contracts_state_tasks.join_next().await { + let (address, new_contract_state, filled_storage_trie) = result??; + contracts_trie_modifications.insert( + NodeIndex::from_contract_address(&address), + new_contract_state, + ); + filled_storage_tries.insert(address, filled_storage_trie); + } + + let contracts_trie_task = tokio::spawn(ContractsTrie::create::( + Arc::new(updated_forest.contracts_trie), + Arc::new(contracts_trie_modifications), + )); + + Ok(Self { + storage_tries: filled_storage_tries, + contracts_trie: contracts_trie_task.await??, + classes_trie: classes_trie_task.await??, + }) + } + + async fn new_contract_state( + contract_address: ContractAddress, + new_nonce: Nonce, + new_class_hash: ClassHash, + updated_storage_trie: UpdatedSkeletonTreeImpl, + inner_updates: LeafModifications, + ) -> ForestResult<(ContractAddress, ContractState, StorageTrie)> { + let filled_storage_trie = + StorageTrie::create::(Arc::new(updated_storage_trie), Arc::new(inner_updates)) + .await?; + let new_root_hash = filled_storage_trie.get_root_hash(); + Ok(( + contract_address, + ContractState { + nonce: new_nonce, + storage_root_hash: new_root_hash, + class_hash: new_class_hash, + }, + filled_storage_trie, + )) + } +} diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/node.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/node.rs new file mode 100644 index 00000000000..116209c5580 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/node.rs @@ -0,0 +1,30 @@ +use starknet_types_core::felt::FromStrError; + +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::impl_from_hex_for_felt_wrapper; +use crate::patricia_merkle_tree::node_data::inner_node::NodeData; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; + +// TODO(Nimrod, 1/6/2024): Use the ClassHash defined in starknet-types-core when available. + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct ClassHash(pub Felt); + +impl_from_hex_for_felt_wrapper!(ClassHash); +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct Nonce(pub Felt); + +impl_from_hex_for_felt_wrapper!(Nonce); + +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct CompiledClassHash(pub Felt); + +impl_from_hex_for_felt_wrapper!(CompiledClassHash); + +#[derive(Clone, Debug, PartialEq, Eq)] +/// A node in a Patricia-Merkle tree which was modified during an update. +pub struct FilledNode { + pub hash: HashOutput, + pub data: NodeData, +} diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/node_serde.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/node_serde.rs new file mode 100644 index 00000000000..9f631daaf71 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/node_serde.rs @@ -0,0 +1,143 @@ +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::FilledNode; +use crate::patricia_merkle_tree::node_data::inner_node::{ + BinaryData, EdgeData, EdgePathLength, NodeData, PathToBottom, +}; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; +use crate::storage::db_object::DBObject; +use crate::storage::errors::DeserializationError; +use crate::storage::storage_trait::{StarknetPrefix, StorageKey, StorageValue}; +use ethnum::U256; +use serde::{Deserialize, Serialize}; + +// Const describe the size of the serialized node. +pub(crate) const SERIALIZE_HASH_BYTES: usize = 32; +pub(crate) const BINARY_BYTES: usize = 2 * SERIALIZE_HASH_BYTES; +pub(crate) const EDGE_LENGTH_BYTES: usize = 1; +pub(crate) const EDGE_PATH_BYTES: usize = 32; +pub(crate) const EDGE_BYTES: usize = SERIALIZE_HASH_BYTES + EDGE_PATH_BYTES + EDGE_LENGTH_BYTES; +#[allow(dead_code)] +pub(crate) const STORAGE_LEAF_SIZE: usize = SERIALIZE_HASH_BYTES; + +/// Temporary struct to serialize the leaf CompiledClass. +/// Required to comply to existing storage layout. +#[derive(Serialize, Deserialize)] +pub(crate) struct LeafCompiledClassToSerialize { + pub(crate) compiled_class_hash: Felt, +} + +impl FilledNode { + pub fn suffix(&self) -> [u8; SERIALIZE_HASH_BYTES] { + self.hash.0.to_bytes_be() + } + + pub fn db_key(&self) -> StorageKey { + self.get_db_key(&self.suffix()) + } +} + +impl DBObject for FilledNode { + /// This method serializes the filled node into a byte vector, where: + /// - For binary nodes: Concatenates left and right hashes. + /// - For edge nodes: Concatenates bottom hash, path, and path length. + /// - For leaf nodes: use leaf.serialize() method. + fn serialize(&self) -> StorageValue { + match &self.data { + NodeData::Binary(BinaryData { + left_hash, + right_hash, + }) => { + // Serialize left and right hashes to byte arrays. + let left: [u8; SERIALIZE_HASH_BYTES] = left_hash.0.to_bytes_be(); + let right: [u8; SERIALIZE_HASH_BYTES] = right_hash.0.to_bytes_be(); + + // Concatenate left and right hashes. + let serialized = [left, right].concat(); + StorageValue(serialized) + } + + NodeData::Edge(EdgeData { + bottom_hash, + path_to_bottom, + }) => { + // Serialize bottom hash, path, and path length to byte arrays. + let bottom: [u8; SERIALIZE_HASH_BYTES] = bottom_hash.0.to_bytes_be(); + let path: [u8; SERIALIZE_HASH_BYTES] = + U256::from(&path_to_bottom.path).to_be_bytes(); + let length: [u8; 1] = u8::from(path_to_bottom.length).to_be_bytes(); + + // Concatenate bottom hash, path, and path length. + let serialized = [bottom.to_vec(), path.to_vec(), length.to_vec()].concat(); + StorageValue(serialized) + } + + NodeData::Leaf(leaf_data) => leaf_data.serialize(), + } + } + + fn get_prefix(&self) -> Vec { + match &self.data { + NodeData::Binary(_) | NodeData::Edge(_) => { + StarknetPrefix::InnerNode.to_storage_prefix() + } + NodeData::Leaf(leaf_data) => leaf_data.get_prefix(), + } + } +} + +impl FilledNode { + /// Deserializes filled nodes. + pub(crate) fn deserialize( + node_hash: HashOutput, + value: &StorageValue, + is_leaf: bool, + ) -> Result { + if is_leaf { + return Ok(Self { + hash: node_hash, + data: NodeData::Leaf(L::deserialize(value)?), + }); + } + + if value.0.len() == BINARY_BYTES { + Ok(Self { + hash: node_hash, + data: NodeData::Binary(BinaryData { + left_hash: HashOutput(Felt::from_bytes_be_slice( + &value.0[..SERIALIZE_HASH_BYTES], + )), + right_hash: HashOutput(Felt::from_bytes_be_slice( + &value.0[SERIALIZE_HASH_BYTES..], + )), + }), + }) + } else { + assert_eq!( + value.0.len(), + EDGE_BYTES, + "Unexpected inner node storage value length {}, expected to be {} or {}.", + value.0.len(), + EDGE_BYTES, + BINARY_BYTES + ); + Ok(Self { + hash: node_hash, + data: NodeData::Edge(EdgeData { + bottom_hash: HashOutput(Felt::from_bytes_be_slice( + &value.0[..SERIALIZE_HASH_BYTES], + )), + path_to_bottom: PathToBottom::new( + U256::from_be_bytes( + value.0[SERIALIZE_HASH_BYTES..SERIALIZE_HASH_BYTES + EDGE_PATH_BYTES] + .try_into() + .expect("Slice with incorrect length."), + ) + .into(), + EdgePathLength::new(value.0[EDGE_BYTES - 1])?, + )?, + }), + }) + } + } +} diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/tree.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/tree.rs new file mode 100644 index 00000000000..6bc032f48c6 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/tree.rs @@ -0,0 +1,260 @@ +use std::collections::HashMap; +use std::sync::Arc; +use std::sync::Mutex; + +use async_recursion::async_recursion; + +use crate::block_committer::input::ContractAddress; +use crate::block_committer::input::StarknetStorageValue; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::errors::FilledTreeError; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::filled_tree::node::FilledNode; +use crate::patricia_merkle_tree::node_data::inner_node::BinaryData; +use crate::patricia_merkle_tree::node_data::inner_node::EdgeData; +use crate::patricia_merkle_tree::node_data::inner_node::NodeData; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; +use crate::patricia_merkle_tree::node_data::leaf::LeafModifications; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunction; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTree; +use crate::storage::db_object::DBObject; +use crate::storage::storage_trait::StorageKey; +use crate::storage::storage_trait::StorageValue; + +#[cfg(test)] +#[path = "tree_test.rs"] +pub mod tree_test; + +pub(crate) type FilledTreeResult = Result>; +/// Consider a Patricia-Merkle Tree which has been updated with new leaves. +/// FilledTree consists of all nodes which were modified in the update, including their updated +/// data and hashes. +pub(crate) trait FilledTree: Sized { + /// Computes and returns the filled tree. + async fn create<'a, TH: TreeHashFunction + 'static>( + updated_skeleton: Arc + 'static>, + leaf_modifications: Arc>, + ) -> FilledTreeResult; + + /// Serializes the current state of the tree into a hashmap, + /// where each key-value pair corresponds + /// to a storage key and its serialized storage value. + fn serialize(&self) -> HashMap; + + fn get_root_hash(&self) -> HashOutput; +} + +#[derive(Debug, Eq, PartialEq)] +pub struct FilledTreeImpl { + pub tree_map: HashMap>, + pub root_hash: HashOutput, +} + +pub type StorageTrie = FilledTreeImpl; +pub type ClassesTrie = FilledTreeImpl; +pub type ContractsTrie = FilledTreeImpl; +pub type StorageTrieMap = HashMap; + +impl FilledTreeImpl { + fn initialize_with_placeholders<'a>( + updated_skeleton: &Arc>, + ) -> HashMap>>> { + let mut filled_tree_map = HashMap::new(); + for (index, node) in updated_skeleton.get_nodes() { + if !matches!(node, UpdatedSkeletonNode::UnmodifiedSubTree(_)) { + filled_tree_map.insert(index, Mutex::new(None)); + } + } + filled_tree_map + } + + pub(crate) fn get_all_nodes(&self) -> &HashMap> { + &self.tree_map + } + + /// Writes the hash and data to the output map. The writing is done in a thread-safe manner with + /// interior mutability to avoid thread contention. + fn write_to_output_map( + output_map: Arc>>>>, + index: NodeIndex, + hash: HashOutput, + data: NodeData, + ) -> FilledTreeResult<(), L> { + match output_map.get(&index) { + Some(node) => { + let mut node = node + .lock() + .map_err(|_| FilledTreeError::PoisonedLock("Cannot lock node.".to_owned()))?; + match node.take() { + Some(existing_node) => Err(FilledTreeError::DoubleUpdate { + index, + existing_value: Box::new(existing_node), + }), + None => { + *node = Some(FilledNode { hash, data }); + Ok(()) + } + } + } + None => Err(FilledTreeError::::MissingNode(index)), + } + } + + fn remove_arc_mutex_and_option( + hash_map_in: Arc>>>>, + ) -> FilledTreeResult>, L> { + let mut hash_map_out = HashMap::new(); + for (key, value) in hash_map_in.iter() { + let mut value = value + .lock() + .map_err(|_| FilledTreeError::::PoisonedLock("Cannot lock node.".to_owned()))?; + match value.take() { + Some(value) => { + hash_map_out.insert(*key, value); + } + None => return Err(FilledTreeError::::MissingNode(*key)), + } + } + Ok(hash_map_out) + } + + #[async_recursion] + async fn compute_filled_tree_rec<'a, TH>( + updated_skeleton: Arc + 'async_recursion + 'static>, + index: NodeIndex, + leaf_modifications: Arc>, + output_map: Arc>>>>, + ) -> FilledTreeResult + where + TH: TreeHashFunction + 'static, + { + let node = updated_skeleton.get_node(index)?; + match node { + UpdatedSkeletonNode::Binary => { + let left_index = index * 2.into(); + let right_index = left_index + NodeIndex::ROOT; + + let (left_hash, right_hash) = ( + tokio::spawn(Self::compute_filled_tree_rec::( + Arc::clone(&updated_skeleton), + left_index, + Arc::clone(&leaf_modifications), + Arc::clone(&output_map), + )), + tokio::spawn(Self::compute_filled_tree_rec::( + Arc::clone(&updated_skeleton), + right_index, + Arc::clone(&leaf_modifications), + Arc::clone(&output_map), + )), + ); + + let data = NodeData::Binary(BinaryData { + left_hash: left_hash.await??, + right_hash: right_hash.await??, + }); + + let hash_value = TH::compute_node_hash(&data); + Self::write_to_output_map(output_map, index, hash_value, data)?; + Ok(hash_value) + } + UpdatedSkeletonNode::Edge(path_to_bottom) => { + let bottom_node_index = NodeIndex::compute_bottom_index(index, path_to_bottom); + let bottom_hash = Self::compute_filled_tree_rec::( + Arc::clone(&updated_skeleton), + bottom_node_index, + leaf_modifications, + Arc::clone(&output_map), + ) + .await?; + let data = NodeData::Edge(EdgeData { + path_to_bottom: *path_to_bottom, + bottom_hash, + }); + let hash_value = TH::compute_node_hash(&data); + Self::write_to_output_map(output_map, index, hash_value, data)?; + Ok(hash_value) + } + UpdatedSkeletonNode::UnmodifiedSubTree(hash_result) => Ok(*hash_result), + UpdatedSkeletonNode::Leaf => { + let leaf_data = L::create(&index, leaf_modifications).await?; + if leaf_data.is_empty() { + return Err(FilledTreeError::::DeletedLeafInSkeleton(index)); + } + let node_data = NodeData::Leaf(leaf_data); + let hash_value = TH::compute_node_hash(&node_data); + Self::write_to_output_map(output_map, index, hash_value, node_data)?; + Ok(hash_value) + } + } + } + + fn create_unmodified<'a>( + updated_skeleton: &Arc>, + ) -> Result> { + let root_node = updated_skeleton.get_node(NodeIndex::ROOT)?; + let UpdatedSkeletonNode::UnmodifiedSubTree(root_hash) = root_node else { + panic!("A root of tree without modifications is expected to be a unmodified subtree.") + }; + Ok(Self { + tree_map: HashMap::new(), + root_hash: *root_hash, + }) + } + + fn create_empty() -> Self { + Self { + tree_map: HashMap::new(), + root_hash: HashOutput::ROOT_OF_EMPTY_TREE, + } + } +} + +impl FilledTree for FilledTreeImpl { + async fn create<'a, TH: TreeHashFunction + 'static>( + updated_skeleton: Arc + 'static>, + leaf_modifications: Arc>, + ) -> Result> { + // Compute the filled tree in two steps: + // 1. Create a map containing the tree structure without hash values. + // 2. Fill in the hash values. + if leaf_modifications.is_empty() { + return Self::create_unmodified(&updated_skeleton); + } + + if updated_skeleton.is_empty() { + return Ok(Self::create_empty()); + } + + let filled_tree_map = Arc::new(Self::initialize_with_placeholders(&updated_skeleton)); + let root_hash = Self::compute_filled_tree_rec::( + updated_skeleton, + NodeIndex::ROOT, + leaf_modifications, + Arc::clone(&filled_tree_map), + ) + .await?; + + // Create and return a new FilledTreeImpl from the hashmap. + Ok(FilledTreeImpl { + tree_map: Self::remove_arc_mutex_and_option(filled_tree_map)?, + root_hash, + }) + } + + fn serialize(&self) -> HashMap { + // This function iterates over each node in the tree, using the node's `db_key` as the hashmap key + // and the result of the node's `serialize` method as the value. + self.get_all_nodes() + .iter() + .map(|(_, node)| (node.db_key(), node.serialize())) + .collect() + } + + fn get_root_hash(&self) -> HashOutput { + self.root_hash + } +} diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs new file mode 100644 index 00000000000..26f61139ca0 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs @@ -0,0 +1,305 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::FilledNode; +use crate::patricia_merkle_tree::filled_tree::tree::{FilledTree, FilledTreeImpl}; +use crate::patricia_merkle_tree::internal_test_utils::{MockLeaf, OriginalSkeletonMockTrieConfig}; +use crate::patricia_merkle_tree::node_data::inner_node::{ + BinaryData, EdgeData, EdgePathLength, NodeData, PathToBottom, +}; +use crate::patricia_merkle_tree::node_data::leaf::SkeletonLeaf; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl; +use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices}; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunctionImpl; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::{ + UpdatedSkeletonNodeMap, UpdatedSkeletonTree, UpdatedSkeletonTreeImpl, +}; +use crate::storage::map_storage::MapStorage; + +#[tokio::test(flavor = "multi_thread")] +/// This test is a sanity test for computing the root hash of the patricia merkle tree with a single node that is a leaf with hash==1. +async fn test_filled_tree_sanity() { + let mut skeleton_tree: UpdatedSkeletonNodeMap = HashMap::new(); + let new_filled_leaf = MockLeaf(Felt::ONE); + let new_leaf_index = NodeIndex::ROOT; + skeleton_tree.insert(new_leaf_index, UpdatedSkeletonNode::Leaf); + let modifications = HashMap::from([(new_leaf_index, new_filled_leaf)]); + let updated_skeleton_tree = UpdatedSkeletonTreeImpl { skeleton_tree }; + let root_hash = FilledTreeImpl::create::( + Arc::new(updated_skeleton_tree), + Arc::new(modifications), + ) + .await + .unwrap() + .get_root_hash(); + assert_eq!(root_hash, HashOutput(Felt::ONE), "Root hash mismatch"); +} + +// TODO(Aner, 11/4/25): Add test with large patricia merkle tree. +// TOOD(Aner, 11/4/25): Add test with different leaf types. + +#[tokio::test(flavor = "multi_thread")] +/// This test is a small test for testing the root hash computation of the patricia merkle tree. +/// The tree structure & results were computed separately and tested for regression. +/// i=1: binary +/// / \ +/// i=2: edge i=3: edge +/// l=1, p=0 l=4, p=15 +/// / \ +/// i=4: binary \ +/// / \ \ +/// i=8: edge i=9: edge \ +/// l=2, p=3 l=2, p=0 \ +/// \ / \ +/// \ / \ +/// i=35: leaf i=36: leaf i=63: leaf +/// v=1 v=2 v=3 +async fn test_small_filled_tree() { + // Set up the updated skeleton tree. + let new_leaves = [(35, "0x1"), (36, "0x2"), (63, "0x3")]; + let nodes_in_skeleton_tree: Vec<(NodeIndex, UpdatedSkeletonNode)> = [ + create_binary_updated_skeleton_node_for_testing(1), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(2, 0, 1), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(3, 15, 4), + create_binary_updated_skeleton_node_for_testing(4), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(8, 3, 2), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(9, 0, 2), + ] + .into_iter() + .chain( + new_leaves + .iter() + .map(|(index, _)| create_leaf_updated_skeleton_node_for_testing(*index)), + ) + .collect(); + let skeleton_tree: UpdatedSkeletonNodeMap = nodes_in_skeleton_tree.into_iter().collect(); + + let updated_skeleton_tree = UpdatedSkeletonTreeImpl { skeleton_tree }; + let modifications = new_leaves + .iter() + .map(|(index, value)| { + ( + NodeIndex::from(*index), + MockLeaf(Felt::from_hex(value).unwrap()), + ) + }) + .collect(); + + // Compute the hash values. + let filled_tree = FilledTreeImpl::create::( + Arc::new(updated_skeleton_tree), + Arc::new(modifications), + ) + .await + .unwrap(); + let filled_tree_map = filled_tree.get_all_nodes(); + let root_hash = filled_tree.get_root_hash(); + + // The expected hash values were computed separately. + let expected_root_hash = HashOutput(Felt::from_hex("0x21").unwrap()); + let expected_filled_tree_map = HashMap::from([ + create_mock_binary_entry_for_testing(1, "0x21", "0xb", "0x16"), + create_mock_edge_entry_for_testing(2, "0xb", 0, 1, "0xa"), + create_mock_edge_entry_for_testing(3, "0x16", 15, 4, "0x3"), + create_mock_binary_entry_for_testing(4, "0xa", "0x6", "0x4"), + create_mock_edge_entry_for_testing(8, "0x6", 3, 2, "0x1"), + create_mock_edge_entry_for_testing(9, "0x4", 0, 2, "0x2"), + create_mock_leaf_entry_for_testing(35, "0x1"), + create_mock_leaf_entry_for_testing(36, "0x2"), + create_mock_leaf_entry_for_testing(63, "0x3"), + ]); + assert_eq!(filled_tree_map, &expected_filled_tree_map); + assert_eq!(root_hash, expected_root_hash, "Root hash mismatch"); +} + +#[tokio::test(flavor = "multi_thread")] +/// This test is a small test for testing the root hash computation of the patricia merkle tree +/// with unmodified nodes. The tree structure & results are a partial of test_small_filled_tree. +/// i=1: binary +/// / \ +/// i=2: edge i=3: unmodified +/// l=1, p=0 hash=0x3 +/// / +/// i=4: binary +/// / \ +/// i=8: edge i=9: unmodified +/// l=2, p=3 hash=0x4 +/// \ +/// \ +/// i=35: leaf +/// v=1 +async fn test_small_tree_with_unmodified_nodes() { + // Set up the updated skeleton tree. + let (new_leaf_index, new_leaf) = (35, "0x1"); + let nodes_in_skeleton_tree = [ + create_binary_updated_skeleton_node_for_testing(1), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(2, 0, 1), + create_unmodified_updated_skeleton_node_for_testing(3, "0x3"), + create_binary_updated_skeleton_node_for_testing(4), + create_path_to_bottom_edge_updated_skeleton_node_for_testing(8, 3, 2), + create_unmodified_updated_skeleton_node_for_testing(9, "0x4"), + create_leaf_updated_skeleton_node_for_testing(new_leaf_index), + ]; + let skeleton_tree: UpdatedSkeletonNodeMap = nodes_in_skeleton_tree.into_iter().collect(); + + let updated_skeleton_tree = UpdatedSkeletonTreeImpl { skeleton_tree }; + let modifications = HashMap::from([( + NodeIndex::from(new_leaf_index), + MockLeaf(Felt::from_hex(new_leaf).unwrap()), + )]); + + // Compute the hash values. + let filled_tree = FilledTreeImpl::create::( + Arc::new(updated_skeleton_tree), + Arc::new(modifications), + ) + .await + .unwrap(); + let filled_tree_map = filled_tree.get_all_nodes(); + let root_hash = filled_tree.get_root_hash(); + + // The expected hash values were computed separately. Note that the unmodified nodes are not + // computed in the filled tree, but the hash values are directly used. The hashes of unmodified + // nodes should not appear in the filled tree. + let expected_root_hash = HashOutput(Felt::from_hex("0xe").unwrap()); + let expected_filled_tree_map = HashMap::from([ + create_mock_binary_entry_for_testing(1, "0xe", "0xb", "0x3"), + create_mock_edge_entry_for_testing(2, "0b", 0, 1, "0xa"), + create_mock_binary_entry_for_testing(4, "0xa", "0x6", "0x4"), + create_mock_edge_entry_for_testing(8, "0x6", 3, 2, "0x1"), + create_mock_leaf_entry_for_testing(35, "0x1"), + ]); + assert_eq!(filled_tree_map, &expected_filled_tree_map); + assert_eq!(root_hash, expected_root_hash, "Root hash mismatch"); +} + +#[tokio::test(flavor = "multi_thread")] +/// Test that deleting a leaf that does not exist in the tree succeeds. +async fn test_delete_leaf_from_empty_tree() { + let storage_modifications: HashMap = + HashMap::from([(NodeIndex::FIRST_LEAF, MockLeaf(Felt::ZERO))]); + + let mut indices = [NodeIndex::FIRST_LEAF]; + // Create an empty original skeleton tree with a single leaf modified. + let mut original_skeleton_tree = OriginalSkeletonTreeImpl::create_impl( + &MapStorage { + storage: HashMap::new(), + }, + HashOutput::ROOT_OF_EMPTY_TREE, + SortedLeafIndices::new(&mut indices), + &OriginalSkeletonMockTrieConfig::new(&storage_modifications, false), + ) + .unwrap(); + + // Create an updated skeleton tree with a single leaf that is deleted. + let skeleton_modifications = HashMap::from([(NodeIndex::FIRST_LEAF, SkeletonLeaf::Zero)]); + + let updated_skeleton_tree = + UpdatedSkeletonTreeImpl::create(&mut original_skeleton_tree, &skeleton_modifications) + .unwrap(); + + let leaf_modifications = HashMap::from([(NodeIndex::FIRST_LEAF, MockLeaf(Felt::ZERO))]); + // Compute the filled tree. + let filled_tree = FilledTreeImpl::create::( + updated_skeleton_tree.into(), + leaf_modifications.into(), + ) + .await + .unwrap(); + + // The filled tree should be empty. + let filled_tree_map = filled_tree.get_all_nodes(); + assert!(filled_tree_map.is_empty()); + let root_hash = filled_tree.get_root_hash(); + assert!(root_hash == HashOutput::ROOT_OF_EMPTY_TREE); +} + +fn create_binary_updated_skeleton_node_for_testing( + index: u128, +) -> (NodeIndex, UpdatedSkeletonNode) { + (NodeIndex::from(index), UpdatedSkeletonNode::Binary) +} + +fn create_path_to_bottom_edge_updated_skeleton_node_for_testing( + index: u128, + path: u128, + length: u8, +) -> (NodeIndex, UpdatedSkeletonNode) { + ( + NodeIndex::from(index), + UpdatedSkeletonNode::Edge( + PathToBottom::new(path.into(), EdgePathLength::new(length).unwrap()).unwrap(), + ), + ) +} + +fn create_unmodified_updated_skeleton_node_for_testing( + index: u128, + hash: &str, +) -> (NodeIndex, UpdatedSkeletonNode) { + ( + NodeIndex::from(index), + UpdatedSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::from_hex(hash).unwrap())), + ) +} + +fn create_leaf_updated_skeleton_node_for_testing(index: u128) -> (NodeIndex, UpdatedSkeletonNode) { + (NodeIndex::from(index), UpdatedSkeletonNode::Leaf) +} + +fn create_mock_binary_entry_for_testing( + index: u128, + hash: &str, + left_hash: &str, + right_hash: &str, +) -> (NodeIndex, FilledNode) { + ( + NodeIndex::from(index), + FilledNode { + hash: HashOutput(Felt::from_hex(hash).unwrap()), + data: NodeData::Binary(BinaryData { + left_hash: HashOutput(Felt::from_hex(left_hash).unwrap()), + right_hash: HashOutput(Felt::from_hex(right_hash).unwrap()), + }), + }, + ) +} + +fn create_mock_edge_entry_for_testing( + index: u128, + hash: &str, + path: u128, + length: u8, + bottom_hash: &str, +) -> (NodeIndex, FilledNode) { + ( + NodeIndex::from(index), + FilledNode { + hash: HashOutput(Felt::from_hex(hash).unwrap()), + data: NodeData::Edge(EdgeData { + bottom_hash: HashOutput(Felt::from_hex(bottom_hash).unwrap()), + path_to_bottom: PathToBottom::new( + path.into(), + EdgePathLength::new(length).unwrap(), + ) + .unwrap(), + }), + }, + ) +} + +fn create_mock_leaf_entry_for_testing( + index: u128, + hash: &str, +) -> (NodeIndex, FilledNode) { + ( + NodeIndex::from(index), + FilledNode { + hash: HashOutput(Felt::from_hex(hash).unwrap()), + data: NodeData::Leaf(MockLeaf(Felt::from_hex(hash).unwrap())), + }, + ) +} diff --git a/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs b/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs new file mode 100644 index 00000000000..2cf06aaa030 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs @@ -0,0 +1,176 @@ +use std::sync::Arc; + +use crate::felt::Felt; +use crate::generate_trie_config; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::external_test_utils::get_random_u256; +use crate::patricia_merkle_tree::filled_tree::tree::FilledTreeImpl; +use crate::patricia_merkle_tree::node_data::errors::LeafResult; +use crate::patricia_merkle_tree::node_data::inner_node::NodeData; +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; +use crate::patricia_merkle_tree::node_data::leaf::SkeletonLeaf; +use crate::patricia_merkle_tree::node_data::leaf::{Leaf, LeafModifications}; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonTreeConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::errors::OriginalSkeletonTreeError; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeResult; +use crate::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight}; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::{ + HashFunction, TreeHashFunction, TreeHashFunctionImpl, +}; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; +use crate::storage::db_object::{DBObject, Deserializable}; +use crate::storage::storage_trait::StorageValue; +use ethnum::U256; +use rand::rngs::ThreadRng; +use rstest::{fixture, rstest}; + +#[derive(Debug, PartialEq, Clone, Copy, Default, Eq)] +pub(crate) struct MockLeaf(pub(crate) Felt); + +impl DBObject for MockLeaf { + fn serialize(&self) -> StorageValue { + StorageValue(self.0.to_bytes_be().to_vec()) + } + + fn get_prefix(&self) -> Vec { + vec![0] + } +} + +impl Deserializable for MockLeaf { + fn deserialize( + value: &StorageValue, + ) -> Result { + Ok(Self(Felt::from_bytes_be_slice(&value.0))) + } + + fn prefix() -> Vec { + vec![0] + } +} + +impl Leaf for MockLeaf { + fn is_empty(&self) -> bool { + self.0 == Felt::ZERO + } + + async fn create( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> LeafResult { + Self::from_modifications(index, leaf_modifications) + } +} + +impl TreeHashFunction for TreeHashFunctionImpl { + fn compute_leaf_hash(leaf_data: &MockLeaf) -> HashOutput { + HashOutput(leaf_data.0) + } + + fn compute_node_hash(node_data: &NodeData) -> HashOutput { + Self::compute_node_hash_with_inner_hash_function::(node_data) + } +} + +generate_trie_config!(OriginalSkeletonMockTrieConfig, MockLeaf); + +pub(crate) type MockTrie = FilledTreeImpl; + +struct MockHashFunction; + +impl HashFunction for MockHashFunction { + fn hash(left: &Felt, right: &Felt) -> HashOutput { + HashOutput(*left + *right) + } +} + +impl From for SkeletonLeaf { + fn from(value: u8) -> Self { + Self::from(Felt::from(value)) + } +} + +impl From<&str> for PathToBottom { + fn from(value: &str) -> Self { + Self::new( + U256::from_str_radix(value, 2) + .expect("Invalid binary string") + .into(), + EdgePathLength::new( + (value.len() - if value.starts_with('+') { 1 } else { 0 }) + .try_into() + .expect("String is too large"), + ) + .expect("Invalid length"), + ) + .expect("Illegal PathToBottom") + } +} + +#[fixture] +pub(crate) fn random() -> ThreadRng { + rand::thread_rng() +} + +impl NodeIndex { + /// Assumes self represents an index in a smaller tree height. Returns a node index represents + /// the same index in the starknet state tree as if the smaller tree was 'planted' at the lowest + /// leftmost node from the root. + pub(crate) fn from_subtree_index(subtree_index: Self, subtree_height: SubTreeHeight) -> Self { + let height_diff = SubTreeHeight::ACTUAL_HEIGHT.0 - subtree_height.0; + let offset = (NodeIndex::ROOT << height_diff) - 1.into(); + subtree_index + (offset << (subtree_index.bit_length() - 1)) + } +} + +pub(crate) fn small_tree_index_to_full(index: U256, height: SubTreeHeight) -> NodeIndex { + NodeIndex::from_subtree_index(NodeIndex::new(index), height) +} + +#[rstest] +#[should_panic] +#[case(U256::ZERO, U256::ZERO)] +#[case(U256::ZERO, U256::ONE)] +#[case(U256::ONE, U256::ONE << 128)] +#[case((U256::ONE<<128)-U256::ONE, U256::ONE << 128)] +#[case(U256::ONE<<128, (U256::ONE << 128)+U256::ONE)] +fn test_get_random_u256(mut random: ThreadRng, #[case] low: U256, #[case] high: U256) { + let r = get_random_u256(&mut random, low, high); + assert!(low <= r && r < high); +} + +/// Returns an UpdatedSkeleton instance initialized with the UpdatedSkeletonNodes immediately +/// derived from the leaf_modifications (as done in UpdatedSkeletonTreeImpl::finalize_bottom_layer). +pub(crate) fn get_initial_updated_skeleton( + original_skeleton: &[(NodeIndex, OriginalSkeletonNode)], + leaf_modifications: &[(NodeIndex, u8)], +) -> UpdatedSkeletonTreeImpl { + UpdatedSkeletonTreeImpl { + skeleton_tree: leaf_modifications + .iter() + .filter(|(_, leaf_val)| *leaf_val != 0) + .map(|(index, _)| (*index, UpdatedSkeletonNode::Leaf)) + .chain( + original_skeleton + .iter() + .filter_map(|(index, node)| match node { + OriginalSkeletonNode::UnmodifiedSubTree(hash) => { + Some((*index, UpdatedSkeletonNode::UnmodifiedSubTree(*hash))) + } + OriginalSkeletonNode::Binary | OriginalSkeletonNode::Edge(_) => None, + }), + ) + .collect(), + } +} + +pub(crate) fn as_fully_indexed( + subtree_height: u8, + indices: impl Iterator, +) -> Vec { + indices + .map(|index| small_tree_index_to_full(index, SubTreeHeight::new(subtree_height))) + .collect() +} diff --git a/crates/committer/src/patricia_merkle_tree/node_data.rs b/crates/committer/src/patricia_merkle_tree/node_data.rs new file mode 100644 index 00000000000..4e528cf888e --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data.rs @@ -0,0 +1,4 @@ +pub mod errors; +pub mod inner_node; +pub mod leaf; +pub mod leaf_serde; diff --git a/crates/committer/src/patricia_merkle_tree/node_data/errors.rs b/crates/committer/src/patricia_merkle_tree/node_data/errors.rs new file mode 100644 index 00000000000..4d1a729b38a --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/errors.rs @@ -0,0 +1,33 @@ +use std::fmt::Debug; +use thiserror::Error; + +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePath, EdgePathLength}; +use crate::patricia_merkle_tree::types::NodeIndex; + +#[derive(Debug, Error)] +pub enum PathToBottomError { + #[error("Tried to remove {n_edges:?} edges from a {length:?} length path.")] + RemoveEdgesError { + length: EdgePathLength, + n_edges: EdgePathLength, + }, + #[error("EdgePath {path:?} is too long for EdgePathLength {length:?}.")] + MismatchedLengthError { + path: EdgePath, + length: EdgePathLength, + }, +} + +#[derive(Debug, Error)] +pub enum EdgePathError { + #[error("Length {length:?} is not in range [0, EdgePathLength::MAX]")] + IllegalLength { length: u8 }, +} + +#[derive(Debug, Error)] +pub enum LeafError { + #[error("Missing modification data at index {0:?}.")] + MissingLeafModificationData(NodeIndex), +} + +pub type LeafResult = Result; diff --git a/crates/committer/src/patricia_merkle_tree/node_data/inner_node.rs b/crates/committer/src/patricia_merkle_tree/node_data/inner_node.rs new file mode 100644 index 00000000000..20f3357a3a9 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/inner_node.rs @@ -0,0 +1,177 @@ +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::node_data::errors::{EdgePathError, PathToBottomError}; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; +use crate::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight}; + +use ethnum::U256; +use strum_macros::{EnumDiscriminants, EnumIter}; + +#[cfg(test)] +#[path = "inner_node_tests.rs"] +pub mod inner_node_test; + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(any(test, feature = "testing"), derive(EnumDiscriminants))] +#[cfg_attr(any(test, feature = "testing"), strum_discriminants(derive(EnumIter)))] +// A Patricia-Merkle tree node's data, i.e., the pre-image of its hash. +pub enum NodeData { + Binary(BinaryData), + Edge(EdgeData), + Leaf(L), +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct BinaryData { + pub left_hash: HashOutput, + pub right_hash: HashOutput, +} + +// Wraps a U256. Maximal possible value is the longest path in a tree of height 251 (2 ^ 251 - 1). +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct EdgePath(pub U256); + +impl EdgePath { + pub const BITS: u8 = SubTreeHeight::ACTUAL_HEIGHT.0; + + /// [EdgePath] constant that represents the longest path (from some node) in a tree. + #[allow(clippy::as_conversions)] + pub const MAX: Self = Self(U256::from_words( + u128::MAX >> (U256::BITS - Self::BITS as u32), + u128::MAX, + )); +} + +impl From for EdgePath { + fn from(value: U256) -> Self { + assert!(value <= EdgePath::MAX.0, "Path {value:?} is too long."); + Self(value) + } +} + +impl From for EdgePath { + fn from(value: u128) -> Self { + Self(value.into()) + } +} + +impl From<&EdgePath> for Felt { + fn from(path: &EdgePath) -> Self { + Self::from_bytes_be(&path.0.to_be_bytes()) + } +} + +impl From<&EdgePath> for U256 { + fn from(path: &EdgePath) -> Self { + path.0 + } +} +#[derive( + Clone, Copy, Debug, Default, PartialOrd, derive_more::Add, derive_more::Sub, PartialEq, Eq, Hash, +)] +pub struct EdgePathLength(u8); + +impl EdgePathLength { + /// [EdgePathLength] constant that represents the longest path (from some node) in a tree. + pub const ONE: Self = Self(1); + pub const MAX: Self = Self(SubTreeHeight::ACTUAL_HEIGHT.0); + + pub fn new(length: u8) -> Result { + if length > Self::MAX.0 { + return Err(EdgePathError::IllegalLength { length }); + } + Ok(Self(length)) + } +} + +impl From for u8 { + fn from(value: EdgePathLength) -> Self { + value.0 + } +} + +impl From for Felt { + fn from(value: EdgePathLength) -> Self { + value.0.into() + } +} + +#[allow(clippy::manual_non_exhaustive)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct PathToBottom { + pub path: EdgePath, + pub length: EdgePathLength, + // Used to prevent direct instantiation, while allowing destructure of other fields. + _fake_field: (), +} + +type PathToBottomResult = Result; + +impl PathToBottom { + /// Creates a new [PathToBottom] instance. + // Asserts the path is not longer than the length. + pub fn new(path: EdgePath, length: EdgePathLength) -> PathToBottomResult { + let bit_length = U256::BITS - path.0.leading_zeros(); + if bit_length > u8::from(length).into() { + return Err(PathToBottomError::MismatchedLengthError { path, length }); + } + Ok(Self { + path, + length, + _fake_field: (), + }) + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct EdgeData { + pub bottom_hash: HashOutput, + pub path_to_bottom: PathToBottom, +} + +impl PathToBottom { + pub(crate) const LEFT_CHILD: Self = Self { + path: EdgePath(U256::ZERO), + length: EdgePathLength(1), + _fake_field: (), + }; + + pub(crate) const RIGHT_CHILD: Self = Self { + path: EdgePath(U256::ONE), + length: EdgePathLength(1), + _fake_field: (), + }; + + pub(crate) fn bottom_index(&self, root_index: NodeIndex) -> NodeIndex { + NodeIndex::compute_bottom_index(root_index, self) + } + + /// Returns true iff the first step on the path is to the left. + pub(crate) fn is_left_descendant(&self) -> bool { + self.path.0 >> (self.length.0 - 1) == 0 + } + + pub(crate) fn concat_paths(&self, other: Self) -> PathToBottom { + Self::new( + EdgePath::from((self.path.0 << other.length.0) + other.path.0), + self.length + other.length, + ) + .unwrap_or_else(|_| { + panic!("Concatenating paths {self:?} and {other:?} unexpectedly failed.") + }) + } + + /// Returns the path after removing the first steps (the edges from the path's origin node). + pub(crate) fn remove_first_edges(&self, n_edges: EdgePathLength) -> PathToBottomResult { + if self.length < n_edges { + return Err(PathToBottomError::RemoveEdgesError { + length: self.length, + n_edges, + }); + } + Self::new( + EdgePath(self.path.0 & ((U256::ONE << (self.length.0 - n_edges.0)) - 1)), + self.length - n_edges, + ) + } +} diff --git a/crates/committer/src/patricia_merkle_tree/node_data/inner_node_tests.rs b/crates/committer/src/patricia_merkle_tree/node_data/inner_node_tests.rs new file mode 100644 index 00000000000..2bbbd204758 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/inner_node_tests.rs @@ -0,0 +1,24 @@ +use ethnum::U256; +use rstest::rstest; + +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; + +#[rstest] +#[case(PathToBottom::from("1011"), 1, PathToBottom::from("011"))] +#[case(PathToBottom::from("1011"), 2, PathToBottom::from("11"))] +#[case(PathToBottom::from("1011"), 3, PathToBottom::from("1"))] +#[case(PathToBottom::from("1011"), 4, PathToBottom::new(U256::ZERO.into(), EdgePathLength::new(0).unwrap()).unwrap())] +#[should_panic] +#[case(PathToBottom::from("1011"), 5, PathToBottom::from("0"))] +fn test_remove_first_edges( + #[case] path_to_bottom: PathToBottom, + #[case] n_edges: u8, + #[case] expected: PathToBottom, +) { + assert_eq!( + path_to_bottom + .remove_first_edges(EdgePathLength::new(n_edges).unwrap()) + .unwrap(), + expected + ); +} diff --git a/crates/committer/src/patricia_merkle_tree/node_data/leaf.rs b/crates/committer/src/patricia_merkle_tree/node_data/leaf.rs new file mode 100644 index 00000000000..7cdde637e17 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/leaf.rs @@ -0,0 +1,113 @@ +use std::collections::HashMap; +use std::fmt::Debug; +use std::future::Future; +use std::sync::Arc; + +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::errors::{LeafError, LeafResult}; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::storage::db_object::{DBObject, Deserializable}; + +pub trait Leaf: Clone + Sync + Send + DBObject + Deserializable + Default + Debug + Eq { + /// Returns true if leaf is empty. + fn is_empty(&self) -> bool; + + /// Creates a leaf. + /// This function is async to allow computation of a leaf on the fly; in simple cases, it can + /// be enough to return the leaf data directly using [Self::from_modifications]. + // Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see + // https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#async-fn-in-public-traits + // for details. + fn create( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> impl Future> + Send; + + /// Extracts the leaf data from the leaf modifications. Returns an error if the leaf data is + /// missing. + fn from_modifications( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> LeafResult { + let leaf_data = leaf_modifications + .get(index) + .ok_or(LeafError::MissingLeafModificationData(*index))? + .clone(); + Ok(leaf_data) + } +} + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct ContractState { + pub nonce: Nonce, + pub storage_root_hash: HashOutput, + pub class_hash: ClassHash, +} + +impl Leaf for StarknetStorageValue { + fn is_empty(&self) -> bool { + self.0 == Felt::ZERO + } + + async fn create( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> LeafResult { + Self::from_modifications(index, leaf_modifications) + } +} + +impl Leaf for CompiledClassHash { + fn is_empty(&self) -> bool { + self.0 == Felt::ZERO + } + + async fn create( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> LeafResult { + Self::from_modifications(index, leaf_modifications) + } +} + +impl Leaf for ContractState { + fn is_empty(&self) -> bool { + self.nonce.0 == Felt::ZERO + && self.class_hash.0 == Felt::ZERO + && self.storage_root_hash.0 == Felt::ZERO + } + + async fn create( + index: &NodeIndex, + leaf_modifications: Arc>, + ) -> LeafResult { + Self::from_modifications(index, leaf_modifications) + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum SkeletonLeaf { + Zero, + NonZero, +} + +impl SkeletonLeaf { + pub(crate) fn is_zero(&self) -> bool { + self == &Self::Zero + } +} + +impl From for SkeletonLeaf { + fn from(value: Felt) -> Self { + if value == Felt::ZERO { + Self::Zero + } else { + Self::NonZero + } + } +} + +pub type LeafModifications = HashMap; diff --git a/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde.rs b/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde.rs new file mode 100644 index 00000000000..93ac61dc8eb --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde.rs @@ -0,0 +1,120 @@ +use std::collections::HashMap; + +use serde_json::Value; + +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::types::SubTreeHeight; +use crate::storage::db_object::{DBObject, Deserializable}; +use crate::storage::errors::DeserializationError; +use crate::storage::storage_trait::{StarknetPrefix, StorageValue}; + +#[cfg(test)] +#[path = "leaf_serde_test.rs"] +pub mod leaf_serde_test; + +impl DBObject for StarknetStorageValue { + /// Serializes the value into a 32-byte vector. + fn serialize(&self) -> StorageValue { + StorageValue(self.0.to_bytes_be().to_vec()) + } + + fn get_prefix(&self) -> Vec { + StarknetPrefix::StorageLeaf.to_storage_prefix() + } +} + +impl DBObject for CompiledClassHash { + /// Creates a json string describing the leaf and casts it into a byte vector. + fn serialize(&self) -> StorageValue { + let json_string = format!(r#"{{"compiled_class_hash": "{}"}}"#, self.0.to_hex()); + StorageValue(json_string.into_bytes()) + } + + fn get_prefix(&self) -> Vec { + StarknetPrefix::CompiledClassLeaf.to_storage_prefix() + } +} + +impl DBObject for ContractState { + /// Creates a json string describing the leaf and casts it into a byte vector. + fn serialize(&self) -> StorageValue { + let json_string = format!( + r#"{{"contract_hash": "{}", "storage_commitment_tree": {{"root": "{}", "height": {}}}, "nonce": "{}"}}"#, + self.class_hash.0.to_fixed_hex_string(), + self.storage_root_hash.0.to_fixed_hex_string(), + SubTreeHeight::ACTUAL_HEIGHT, + self.nonce.0.to_hex(), + ); + StorageValue(json_string.into_bytes()) + } + + fn get_prefix(&self) -> Vec { + StarknetPrefix::StateTreeLeaf.to_storage_prefix() + } +} + +impl Deserializable for StarknetStorageValue { + fn deserialize(value: &StorageValue) -> Result { + Ok(Self(Felt::from_bytes_be_slice(&value.0))) + } + + fn prefix() -> Vec { + StarknetPrefix::StorageLeaf.to_storage_prefix() + } +} + +impl Deserializable for CompiledClassHash { + fn deserialize(value: &StorageValue) -> Result { + let json_str = std::str::from_utf8(&value.0)?; + let map: HashMap = serde_json::from_str(json_str)?; + let hash_as_hex = + map.get("compiled_class_hash") + .ok_or(DeserializationError::NonExistingKey( + "compiled_class_hash".to_string(), + ))?; + Ok(Self::from_hex(hash_as_hex)?) + } + + fn prefix() -> Vec { + StarknetPrefix::CompiledClassLeaf.to_storage_prefix() + } +} + +impl Deserializable for ContractState { + fn deserialize(value: &StorageValue) -> Result { + let json_str = std::str::from_utf8(&value.0)?; + let deserialized_map: Value = serde_json::from_str(json_str)?; + let get_leaf_key = |map: &Value, key: &str| { + let s = get_key_from_map(map, key)? + .as_str() + .ok_or(DeserializationError::LeafTypeError)? + .to_string(); + Ok::(s) + }; + let class_hash_as_hex = get_leaf_key(&deserialized_map, "contract_hash")?; + let nonce_as_hex = get_leaf_key(&deserialized_map, "nonce")?; + let root_hash_as_hex = get_leaf_key( + get_key_from_map(&deserialized_map, "storage_commitment_tree")?, + "root", + )?; + + Ok(Self { + nonce: Nonce::from_hex(&nonce_as_hex)?, + storage_root_hash: HashOutput::from_hex(&root_hash_as_hex)?, + class_hash: ClassHash::from_hex(&class_hash_as_hex)?, + }) + } + + fn prefix() -> Vec { + StarknetPrefix::StateTreeLeaf.to_storage_prefix() + } +} + +fn get_key_from_map<'a>(map: &'a Value, key: &str) -> Result<&'a Value, DeserializationError> { + map.get(key) + .ok_or(DeserializationError::NonExistingKey(key.to_string())) +} diff --git a/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde_test.rs b/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde_test.rs new file mode 100644 index 00000000000..2c86c25b571 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/node_data/leaf_serde_test.rs @@ -0,0 +1,41 @@ +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; + +use rstest::rstest; +use std::fmt::Debug; + +#[rstest] +#[case::zero_storage_leaf(StarknetStorageValue(Felt::ZERO))] +#[case::non_zero_storage_leaf(StarknetStorageValue(Felt::from(999_u128)))] +#[case::zero_compiled_class_leaf(CompiledClassHash(Felt::ZERO))] +#[case::non_zero_compiled_class_leaf(CompiledClassHash(Felt::from(11_u128)))] +#[case::zero_contract_state_leaf(ContractState { + nonce: Nonce(Felt::ZERO), storage_root_hash: HashOutput(Felt::ZERO), class_hash: ClassHash(Felt::ZERO) + }) +] +#[case::partial_zero_contract_state_leaf(ContractState { + nonce: Nonce(Felt::ZERO), storage_root_hash: HashOutput(Felt::from(2359743529034_u128)), class_hash: ClassHash(Felt::from(1349866415897798_u128)) + }) +] +#[case::without_zero_contract_state_leaf(ContractState { + nonce: Nonce(Felt::from(23479515749555_u128)), storage_root_hash: HashOutput(Felt::from(2359743529034_u128)), class_hash: ClassHash(Felt::from(1349866415897798_u128)) + }) +] +fn test_leaf_serde(#[case] leaf: L) { + let serialized = leaf.serialize(); + let deserialized = L::deserialize(&serialized).unwrap(); + assert_eq!(deserialized, leaf); +} + +#[rstest] +#[case::storage_leaf(StarknetStorageValue::default())] +#[case::compiled_class_leaf(CompiledClassHash::default())] +#[case::contract_state_leaf(ContractState::default())] +fn test_default_is_empty(#[case] leaf: L) { + assert!(leaf.is_empty()) +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree.rs new file mode 100644 index 00000000000..7ca88b9db0d --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree.rs @@ -0,0 +1,7 @@ +pub mod config; +pub mod create_tree; +pub mod errors; +pub mod node; +pub mod skeleton_forest; +pub mod tree; +pub mod utils; diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/config.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/config.rs new file mode 100644 index 00000000000..e3d5bf3c1f7 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/config.rs @@ -0,0 +1,87 @@ +use crate::block_committer::input::StarknetStorageValue; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::node_data::leaf::{ContractState, Leaf, LeafModifications}; +use crate::patricia_merkle_tree::original_skeleton_tree::errors::OriginalSkeletonTreeError; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeResult; +use crate::patricia_merkle_tree::types::NodeIndex; + +/// Configures the creation of an original skeleton tree. +pub(crate) trait OriginalSkeletonTreeConfig { + /// Configures whether modified leaves should be compared to the previous leaves and log out a + /// warning when encountering a trivial modification. + fn compare_modified_leaves(&self) -> bool; + + /// Compares the previous leaf to the modified and returns true iff they are equal. + fn compare_leaf( + &self, + index: &NodeIndex, + previous_leaf: &L, + ) -> OriginalSkeletonTreeResult; +} + +#[macro_export] +macro_rules! generate_trie_config { + ($struct_name:ident, $leaf_type:ty) => { + pub(crate) struct $struct_name<'a> { + modifications: &'a LeafModifications<$leaf_type>, + compare_modified_leaves: bool, + } + + impl<'a> $struct_name<'a> { + #[allow(dead_code)] + pub(crate) fn new( + modifications: &'a LeafModifications<$leaf_type>, + compare_modified_leaves: bool, + ) -> Self { + Self { + modifications, + compare_modified_leaves, + } + } + } + + impl OriginalSkeletonTreeConfig<$leaf_type> for $struct_name<'_> { + fn compare_modified_leaves(&self) -> bool { + self.compare_modified_leaves + } + + fn compare_leaf( + &self, + index: &NodeIndex, + previous_leaf: &$leaf_type, + ) -> OriginalSkeletonTreeResult { + let new_leaf = self + .modifications + .get(index) + .ok_or(OriginalSkeletonTreeError::ReadModificationsError(*index))?; + Ok(new_leaf == previous_leaf) + } + } + }; +} + +generate_trie_config!(OriginalSkeletonStorageTrieConfig, StarknetStorageValue); + +generate_trie_config!(OriginalSkeletonClassesTrieConfig, CompiledClassHash); + +pub(crate) struct OriginalSkeletonContractsTrieConfig; + +impl OriginalSkeletonTreeConfig for OriginalSkeletonContractsTrieConfig { + fn compare_modified_leaves(&self) -> bool { + false + } + + fn compare_leaf( + &self, + _index: &NodeIndex, + _previous_leaf: &ContractState, + ) -> OriginalSkeletonTreeResult { + Ok(false) + } +} + +impl OriginalSkeletonContractsTrieConfig { + pub(crate) fn new() -> Self { + Self + } +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree.rs new file mode 100644 index 00000000000..01e6fd448bb --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree.rs @@ -0,0 +1,377 @@ +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::FilledNode; +use crate::patricia_merkle_tree::node_data::inner_node::BinaryData; +use crate::patricia_merkle_tree::node_data::inner_node::EdgeData; +use crate::patricia_merkle_tree::node_data::inner_node::NodeData; +use crate::patricia_merkle_tree::node_data::inner_node::PathToBottom; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonTreeConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeResult; +use crate::patricia_merkle_tree::original_skeleton_tree::utils::split_leaves; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use crate::patricia_merkle_tree::types::SubTreeHeight; +use crate::patricia_merkle_tree::{ + original_skeleton_tree::node::OriginalSkeletonNode, types::NodeIndex, +}; +use crate::storage::errors::StorageError; +use crate::storage::storage_trait::create_db_key; +use crate::storage::storage_trait::StarknetPrefix; +use crate::storage::storage_trait::Storage; +use crate::storage::storage_trait::StorageKey; +use log::warn; +use std::borrow::Borrow; +use std::collections::HashMap; +use std::fmt::Debug; + +#[cfg(test)] +#[path = "create_tree_test.rs"] +pub mod create_tree_test; + +/// Logs out a warning of a trivial modification. +macro_rules! log_trivial_modification { + ($index:expr, $value:expr) => { + warn!( + "Encountered a trivial modification at index {:?}, with value {:?}", + $index, $value + ); + }; +} + +#[derive(Debug, PartialEq)] +struct SubTree<'a> { + pub sorted_leaf_indices: SortedLeafIndices<'a>, + pub root_index: NodeIndex, + pub root_hash: HashOutput, +} + +impl<'a> SubTree<'a> { + pub(crate) fn get_height(&self) -> SubTreeHeight { + SubTreeHeight::new(SubTreeHeight::ACTUAL_HEIGHT.0 - (self.root_index.bit_length() - 1)) + } + + pub(crate) fn split_leaves(&self) -> [SortedLeafIndices<'a>; 2] { + split_leaves(&self.root_index, &self.sorted_leaf_indices) + } + + pub(crate) fn is_unmodified(&self) -> bool { + self.sorted_leaf_indices.is_empty() + } + + /// Returns the bottom subtree which is referred from `self` by the given path. When creating + /// the bottom subtree some indices that were modified under `self` are not modified under the + /// bottom subtree (leaves that were previously empty). These indices are returned as well. + fn get_bottom_subtree( + &self, + path_to_bottom: &PathToBottom, + bottom_hash: HashOutput, + ) -> (Self, Vec<&NodeIndex>) { + let bottom_index = path_to_bottom.bottom_index(self.root_index); + let bottom_height = self.get_height() - SubTreeHeight::new(path_to_bottom.length.into()); + let leftmost_in_subtree = bottom_index << bottom_height.into(); + let rightmost_in_subtree = + leftmost_in_subtree - NodeIndex::ROOT + (NodeIndex::ROOT << bottom_height.into()); + let leftmost_index = self.sorted_leaf_indices.bisect_left(&leftmost_in_subtree); + let rightmost_index = self.sorted_leaf_indices.bisect_right(&rightmost_in_subtree); + let bottom_leaves = self + .sorted_leaf_indices + .subslice(leftmost_index, rightmost_index); + let previously_empty_leaf_indices = self.sorted_leaf_indices.get_indices() + [..leftmost_index] + .iter() + .chain(self.sorted_leaf_indices.get_indices()[rightmost_index..].iter()) + .collect(); + + ( + Self { + sorted_leaf_indices: bottom_leaves, + root_index: bottom_index, + root_hash: bottom_hash, + }, + previously_empty_leaf_indices, + ) + } + + fn get_children_subtrees(&self, left_hash: HashOutput, right_hash: HashOutput) -> (Self, Self) { + let [left_leaves, right_leaves] = self.split_leaves(); + let left_root_index = self.root_index * 2.into(); + ( + SubTree { + sorted_leaf_indices: left_leaves, + root_index: left_root_index, + root_hash: left_hash, + }, + SubTree { + sorted_leaf_indices: right_leaves, + root_index: left_root_index + NodeIndex::ROOT, + root_hash: right_hash, + }, + ) + } + + fn is_leaf(&self) -> bool { + self.root_index.is_leaf() + } +} + +impl<'a> OriginalSkeletonTreeImpl<'a> { + /// Fetches the Patricia witnesses, required to build the original skeleton tree from storage. + /// Given a list of subtrees, traverses towards their leaves and fetches all non-empty, + /// unmodified nodes. If `compare_modified_leaves` is set, function logs out a warning when + /// encountering a trivial modification. Fills the previous leaf values if it is not none. + fn fetch_nodes( + &mut self, + subtrees: Vec>, + storage: &impl Storage, + config: &impl OriginalSkeletonTreeConfig, + mut previous_leaves: Option<&mut HashMap>, + ) -> OriginalSkeletonTreeResult<()> { + if subtrees.is_empty() { + return Ok(()); + } + let should_fetch_modified_leaves = + config.compare_modified_leaves() || previous_leaves.is_some(); + let mut next_subtrees = Vec::new(); + let filled_roots = Self::calculate_subtrees_roots::(&subtrees, storage)?; + for (filled_root, subtree) in filled_roots.into_iter().zip(subtrees.iter()) { + match filled_root.data { + // Binary node. + NodeData::Binary(BinaryData { + left_hash, + right_hash, + }) => { + if subtree.is_unmodified() { + self.nodes.insert( + subtree.root_index, + OriginalSkeletonNode::UnmodifiedSubTree(filled_root.hash), + ); + continue; + } + self.nodes + .insert(subtree.root_index, OriginalSkeletonNode::Binary); + let (left_subtree, right_subtree) = + subtree.get_children_subtrees(left_hash, right_hash); + + self.handle_subtree( + &mut next_subtrees, + left_subtree, + should_fetch_modified_leaves, + ); + self.handle_subtree( + &mut next_subtrees, + right_subtree, + should_fetch_modified_leaves, + ) + } + // Edge node. + NodeData::Edge(EdgeData { + bottom_hash, + path_to_bottom, + }) => { + self.nodes.insert( + subtree.root_index, + OriginalSkeletonNode::Edge(path_to_bottom), + ); + if subtree.is_unmodified() { + self.nodes.insert( + path_to_bottom.bottom_index(subtree.root_index), + OriginalSkeletonNode::UnmodifiedSubTree(bottom_hash), + ); + continue; + } + // Parse bottom. + let (bottom_subtree, previously_empty_leaves_indices) = + subtree.get_bottom_subtree(&path_to_bottom, bottom_hash); + if let Some(ref mut leaves) = previous_leaves { + leaves.extend( + previously_empty_leaves_indices + .iter() + .map(|idx| (**idx, L::default())) + .collect::>(), + ); + } + OriginalSkeletonTreeImpl::log_warning_for_empty_leaves( + &previously_empty_leaves_indices, + config, + )?; + + self.handle_subtree( + &mut next_subtrees, + bottom_subtree, + should_fetch_modified_leaves, + ); + } + // Leaf node. + NodeData::Leaf(previous_leaf) => { + if subtree.is_unmodified() { + warn!("Unexpectedly deserialized leaf sibling.") + } else { + // Modified leaf. + if config.compare_modified_leaves() + && config.compare_leaf(&subtree.root_index, &previous_leaf)? + { + log_trivial_modification!(subtree.root_index, previous_leaf); + } + // If previous values of modified leaves are requested, add this leaf. + if let Some(ref mut leaves) = previous_leaves { + leaves.insert(subtree.root_index, previous_leaf); + } + } + } + } + } + self.fetch_nodes::(next_subtrees, storage, config, previous_leaves) + } + + //TODO(Aviv, 17/07/2024): Split between storage prefix implementation and function logic. + fn calculate_subtrees_roots( + subtrees: &[SubTree<'a>], + storage: &impl Storage, + ) -> OriginalSkeletonTreeResult>> { + let mut subtrees_roots = vec![]; + let db_keys: Vec = subtrees + .iter() + .map(|subtree| { + create_db_key( + if subtree.is_leaf() { + L::prefix() + } else { + StarknetPrefix::InnerNode.to_storage_prefix() + }, + &subtree.root_hash.0.to_bytes_be(), + ) + }) + .collect(); + + let db_vals = storage.mget(&db_keys); + for ((subtree, optional_val), db_key) in + subtrees.iter().zip(db_vals.iter()).zip(db_keys.into_iter()) + { + let val = optional_val.ok_or(StorageError::MissingKey(db_key))?; + subtrees_roots.push(FilledNode::deserialize( + subtree.root_hash, + val, + subtree.is_leaf(), + )?) + } + Ok(subtrees_roots) + } + + pub(crate) fn create_impl( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult { + if sorted_leaf_indices.is_empty() { + return Ok(Self::create_unmodified(root_hash)); + } + if root_hash == HashOutput::ROOT_OF_EMPTY_TREE { + OriginalSkeletonTreeImpl::log_warning_for_empty_leaves( + sorted_leaf_indices.get_indices(), + config, + )?; + return Ok(Self::create_empty(sorted_leaf_indices)); + } + let main_subtree = SubTree { + sorted_leaf_indices, + root_index: NodeIndex::ROOT, + root_hash, + }; + let mut skeleton_tree = Self { + nodes: HashMap::new(), + sorted_leaf_indices, + }; + skeleton_tree.fetch_nodes::(vec![main_subtree], storage, config, None)?; + Ok(skeleton_tree) + } + + pub(crate) fn create_and_get_previous_leaves_impl( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult<(Self, HashMap)> { + if sorted_leaf_indices.is_empty() { + let unmodified = Self::create_unmodified(root_hash); + return Ok((unmodified, HashMap::new())); + } + if root_hash == HashOutput::ROOT_OF_EMPTY_TREE { + return Ok(( + Self::create_empty(sorted_leaf_indices), + sorted_leaf_indices + .get_indices() + .iter() + .map(|idx| (*idx, L::default())) + .collect(), + )); + } + let main_subtree = SubTree { + sorted_leaf_indices, + root_index: NodeIndex::ROOT, + root_hash, + }; + let mut skeleton_tree = Self { + nodes: HashMap::new(), + sorted_leaf_indices, + }; + let mut leaves = HashMap::new(); + skeleton_tree.fetch_nodes::(vec![main_subtree], storage, config, Some(&mut leaves))?; + Ok((skeleton_tree, leaves)) + } + + fn create_unmodified(root_hash: HashOutput) -> Self { + Self { + nodes: HashMap::from([( + NodeIndex::ROOT, + OriginalSkeletonNode::UnmodifiedSubTree(root_hash), + )]), + sorted_leaf_indices: SortedLeafIndices::default(), + } + } + + fn create_empty(sorted_leaf_indices: SortedLeafIndices<'a>) -> Self { + Self { + nodes: HashMap::new(), + sorted_leaf_indices, + } + } + + /// Handles a subtree referred by an edge or a binary node. Decides whether we deserialize the + /// referred subtree or not. + fn handle_subtree( + &mut self, + next_subtrees: &mut Vec>, + subtree: SubTree<'a>, + should_fetch_modified_leaves: bool, + ) { + if !subtree.is_leaf() || (should_fetch_modified_leaves && !subtree.is_unmodified()) { + next_subtrees.push(subtree); + } else if subtree.is_unmodified() { + // Leaf sibling. + self.nodes.insert( + subtree.root_index, + OriginalSkeletonNode::UnmodifiedSubTree(subtree.root_hash), + ); + } + } + + /// Given leaf indices that were previously empty leaves, logs out a warning for trivial + /// modification if a leaf is modified to an empty leaf. + /// If this check is suppressed by configuration, does nothing. + fn log_warning_for_empty_leaves + Debug>( + leaf_indices: &[T], + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult<()> { + if !config.compare_modified_leaves() { + return Ok(()); + } + let empty_leaf = L::default(); + for leaf_index in leaf_indices { + if config.compare_leaf(leaf_index.borrow(), &empty_leaf)? { + log_trivial_modification!(leaf_index, empty_leaf); + } + } + Ok(()) + } +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs new file mode 100644 index 00000000000..bb43b99c58f --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs @@ -0,0 +1,573 @@ +use super::OriginalSkeletonTreeImpl; +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use crate::patricia_merkle_tree::internal_test_utils::OriginalSkeletonMockTrieConfig; +use crate::patricia_merkle_tree::internal_test_utils::{small_tree_index_to_full, MockLeaf}; +use crate::patricia_merkle_tree::node_data::inner_node::EdgePath; +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; +use crate::patricia_merkle_tree::node_data::leaf::{ContractState, LeafModifications}; +use crate::patricia_merkle_tree::original_skeleton_tree::create_tree::SubTree; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTree; +use crate::patricia_merkle_tree::types::SubTreeHeight; +use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices}; +use crate::storage::db_object::DBObject; +use crate::storage::map_storage::MapStorage; +use crate::storage::storage_trait::{create_db_key, StarknetPrefix, StorageKey, StorageValue}; +use ethnum::U256; +use pretty_assertions::assert_eq; +use rstest::rstest; +use std::collections::HashMap; + +#[rstest] +// This test assumes for simplicity that hash is addition (i.e hash(a,b) = a + b). +/// +/// Old tree structure: +/// +/// 50 +/// / \ +/// 30 20 +/// / \ \ +/// 17 13 * +/// / \ \ \ +/// 8 9 11 15 +/// +/// Modified leaves indices: [8, 10, 13] +/// +/// Expected skeleton: +/// +/// B +/// / \ +/// B E +/// / \ \ +/// B E * +/// / \ \ \ +/// NZ 9 11 15 +/// +/// + +#[case::simple_tree_of_height_3( + HashMap::from([ + create_root_edge_entry(50, SubTreeHeight::new(3)), + create_binary_entry(8, 9), + create_edge_entry(11, 1, 1), + create_binary_entry(17, 13), + create_edge_entry(15, 3, 2), + create_binary_entry(30, 20), + create_mock_leaf_entry(8), + create_mock_leaf_entry(9), + create_mock_leaf_entry(11), + create_mock_leaf_entry(15) + ]).into(), + create_mock_leaf_modifications(vec![(8, 8), (10, 3), (13, 2)]), + HashOutput(Felt::from(50_u128 + 248_u128)), + create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_binary_skeleton_node(2), + create_edge_skeleton_node(3, 3, 2), + create_binary_skeleton_node(4), + create_edge_skeleton_node(5, 1, 1), + create_unmodified_subtree_skeleton_node(9, 9), + create_unmodified_subtree_skeleton_node(15, 15), + create_unmodified_subtree_skeleton_node(11, 11) + ], + 3 + ), + SubTreeHeight::new(3), +)] +/// Old tree structure: +/// +/// 29 +/// / \ +/// 13 16 +/// / / \ +/// 12 5 11 +/// / \ \ / \ +/// 10 2 3 4 7 +/// +/// Modified leaves indices: [8, 11, 13] +/// +/// Expected skeleton: +/// +/// B +/// / \ +/// E B +/// / / \ +/// B E E +/// / \ \ \ +/// NZ 2 NZ NZ +/// + +#[case::another_simple_tree_of_height_3( + HashMap::from([ + create_root_edge_entry(29, SubTreeHeight::new(3)), + create_binary_entry(10, 2), + create_edge_entry(3, 1, 1), + create_binary_entry(4, 7), + create_edge_entry(12, 0, 1), + create_binary_entry(5, 11), + create_binary_entry(13, 16), + create_mock_leaf_entry(10), + create_mock_leaf_entry(2), + create_mock_leaf_entry(3), + create_mock_leaf_entry(4), + create_mock_leaf_entry(7) + ]).into(), + create_mock_leaf_modifications(vec![(8, 5), (11, 1), (13, 3)]), + HashOutput(Felt::from(29_u128 + 248_u128)), + create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_edge_skeleton_node(2, 0, 1), + create_binary_skeleton_node(3), + create_binary_skeleton_node(4), + create_edge_skeleton_node(6, 1, 1), + create_unmodified_subtree_skeleton_node(7, 11), + create_unmodified_subtree_skeleton_node(9, 2), + ], + 3 + ), + SubTreeHeight::new(3), +)] +/// Old tree structure: +/// +/// 116 +/// / \ +/// 26 90 +/// / / \ +/// * 25 65 +/// / \ / \ +/// 24 * 6 59 +/// / \ \ / / \ +/// 11 13 20 5 19 40 +/// +/// Modified leaves indices: [18, 25, 29, 30] +/// +/// Expected skeleton: +/// +/// B +/// / \ +/// E B +/// / / \ +/// * E B +/// / \ / \ +/// 24 * E B +/// \ / \ +/// 20 5 40 +/// +#[case::tree_of_height_4_with_long_edge( + HashMap::from([ + create_root_edge_entry(116, SubTreeHeight::new(4)), + create_binary_entry(11, 13), + create_edge_entry(5, 0, 1), + create_binary_entry(19, 40), + create_edge_entry(20, 3, 2), + create_binary_entry(6, 59), + create_edge_entry(24, 0, 2), + create_binary_entry(25, 65), + create_binary_entry(26, 90), + create_mock_leaf_entry(11), + create_mock_leaf_entry(13), + create_mock_leaf_entry(20), + create_mock_leaf_entry(5), + create_mock_leaf_entry(19), + create_mock_leaf_entry(40), + ]).into(), + create_mock_leaf_modifications(vec![(18, 5), (25, 1), (29, 15), (30, 19)]), + HashOutput(Felt::from(116_u128 + 247_u128)), + create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_edge_skeleton_node(2, 0, 2), + create_binary_skeleton_node(3), + create_edge_skeleton_node(6, 3, 2), + create_binary_skeleton_node(7), + create_unmodified_subtree_skeleton_node(8, 24), + create_edge_skeleton_node(14, 0, 1), + create_binary_skeleton_node(15), + create_unmodified_subtree_skeleton_node(27, 20), + create_unmodified_subtree_skeleton_node(28, 5), + create_unmodified_subtree_skeleton_node(31, 40) + ], + 4 + ), + SubTreeHeight::new(4), +)] +fn test_create_tree( + #[case] storage: MapStorage, + #[case] leaf_modifications: LeafModifications, + #[case] root_hash: HashOutput, + #[case] expected_skeleton_nodes: HashMap, + #[case] subtree_height: SubTreeHeight, + #[values(true, false)] compare_modified_leaves: bool, +) { + let leaf_modifications: LeafModifications = leaf_modifications + .into_iter() + .map(|(idx, leaf)| (NodeIndex::from_subtree_index(idx, subtree_height), leaf)) + .collect(); + let config = OriginalSkeletonMockTrieConfig::new(&leaf_modifications, compare_modified_leaves); + let mut sorted_leaf_indices: Vec = leaf_modifications.keys().copied().collect(); + let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices); + let skeleton_tree = OriginalSkeletonTreeImpl::create::( + &storage, + root_hash, + sorted_leaf_indices, + &config, + ) + .unwrap(); + assert_eq!(&skeleton_tree.nodes, &expected_skeleton_nodes); +} + +/// case::single_right_child +/// 1 +/// \ +/// 3 +/// +/// Bottom subtree: +/// 3 +/// +/// case::single_left_child +/// 1 +/// / +/// 2 +/// +/// Bottom subtree: +/// 2 +/// +/// case::missing_nodes +/// +/// 1 +/// / +/// * +/// / +/// 4 +/// / \ +/// 8 9 +/// +/// Bottom subtree: +/// +/// 4 +/// / \ +/// 8 9 +/// +/// case::long_left_path +/// +/// 1 +/// / +/// * +/// / +/// ... +/// / +/// +/// NodeIndex::FIRST_LEAF +/// +/// Bottom subtree: +/// +/// NodeIndex::FIRST_LEAF +/// +/// case::long_right_path +/// +/// 1 +/// \ +/// * +/// \ +/// ... +/// +/// \ +/// NodeIndex::MAX +/// +/// Bottom subtree: +/// +/// NodeIndex::MAX +/// +/// case::should_delete_new_leaf +/// +/// 1 +/// / \ +/// 2 new +/// +/// Bottom subtree: +/// +/// 2 +/// +/// case::should_delete_new_leafs +/// +/// 1 +/// / \ +/// * * +/// / \ / +/// 4 5 6 +/// / \ / \ / +/// 8 9 10 11 12 +/// new new new +/// +/// Bottom subtree: +/// +/// 5 +/// / \ +/// 11 10 +/// +#[rstest] +#[case::single_right_child( + SubTreeHeight(1), + &[U256::from(3_u128)], + PathToBottom::new(EdgePath(U256::ONE), EdgePathLength::new(1).unwrap()).unwrap(), + &[U256::from(3_u128)], + U256::from(3_u128), + )] +#[case::single_left_child( + SubTreeHeight(1), + &[U256::from(2_u128)], + PathToBottom::new(EdgePath(U256::ZERO), EdgePathLength::new(1).unwrap()).unwrap(), + &[U256::from(2_u128)], + U256::from(2_u128), +)] +#[case::missing_nodes( + SubTreeHeight(3), + &[U256::from(8_u128),U256::from(9_u128)], + PathToBottom::new(EdgePath(U256::ZERO),EdgePathLength::new(2).unwrap()).unwrap(), + &[U256::from(8_u128),U256::from(9_u128)], + U256::from(4_u128), +)] +#[case::long_left_path( + SubTreeHeight::ACTUAL_HEIGHT, + &[NodeIndex::FIRST_LEAF.0], + PathToBottom::new(EdgePath(U256::ZERO), EdgePathLength::new(SubTreeHeight::ACTUAL_HEIGHT.0).unwrap()).unwrap(), + &[NodeIndex::FIRST_LEAF.0], + NodeIndex::FIRST_LEAF.0, +)] +#[case::long_right_path( + SubTreeHeight::ACTUAL_HEIGHT, + &[NodeIndex::MAX.0], + PathToBottom::new(EdgePath(NodeIndex::MAX.0 >> 1), EdgePathLength::new(SubTreeHeight::ACTUAL_HEIGHT.0).unwrap()).unwrap(), + &[NodeIndex::MAX.0], + NodeIndex::MAX.0, + )] +#[case::should_delete_new_leaf( + SubTreeHeight(1), + &[U256::from(2_u128), U256::from(3_u128)], + PathToBottom::new(EdgePath(U256::ZERO), EdgePathLength::new(1).unwrap()).unwrap(), + &[U256::from(2_u128)], + U256::from(2_u128), +)] +#[case::should_delete_new_leafs( + SubTreeHeight(3), + &[U256::from(8_u128), U256::from(9_u128), U256::from(10_u128), U256::from(11_u128), U256::from(12_u128)], + PathToBottom::new(EdgePath(U256::ONE), EdgePathLength::new(2).unwrap()).unwrap(), + &[U256::from(10_u128), U256::from(11_u128)], + U256::from(5_u128), +)] +fn test_get_bottom_subtree( + #[case] height: SubTreeHeight, + #[case] sorted_leaf_indices: &[U256], + #[case] path_to_bottom: PathToBottom, + #[case] expected_sorted_leaf_indices: &[U256], + #[case] expected_root_index: U256, +) { + // Cast the input to the correct type for subtree. + let root_index = small_tree_index_to_full(U256::ONE, height); + + let mut leaf_indices = sorted_leaf_indices + .iter() + .map(|&idx| small_tree_index_to_full(idx, height)) + .collect::>(); + let sorted_leaf_indices = SortedLeafIndices::new(&mut leaf_indices); + // Cast the expected output to the correct type for subtree. + let mut expected_leaf_indices = expected_sorted_leaf_indices + .iter() + .map(|&idx| small_tree_index_to_full(idx, height)) + .collect::>(); + let expected_sorted_leaf_indices = SortedLeafIndices::new(&mut expected_leaf_indices); + + let expected_previously_empty_leaf_indices = create_previously_empty_leaf_indices( + sorted_leaf_indices.get_indices(), + expected_sorted_leaf_indices.get_indices(), + ); + + // Create the input Subtree. + let tree = SubTree { + sorted_leaf_indices, + root_index, + root_hash: HashOutput(Felt::ONE), + }; + + // Get the bottom subtree. + let (subtree, previously_empty_leaf_indices) = + tree.get_bottom_subtree(&path_to_bottom, HashOutput(Felt::TWO)); + + let expected_root_index = small_tree_index_to_full(expected_root_index, height); + + // Create the expected subtree. + let expected_subtree = SubTree { + sorted_leaf_indices: expected_sorted_leaf_indices, + root_index: expected_root_index, + root_hash: HashOutput(Felt::TWO), + }; + assert_eq!( + previously_empty_leaf_indices, + expected_previously_empty_leaf_indices + ); + assert_eq!(subtree, expected_subtree); +} + +pub(crate) fn create_32_bytes_entry(simple_val: u128) -> [u8; 32] { + U256::from(simple_val).to_be_bytes() +} + +pub(crate) fn create_mock_leaf_entry(val: u128) -> (StorageKey, StorageValue) { + let leaf = MockLeaf(Felt::from(val)); + (leaf.get_db_key(&leaf.0.to_bytes_be()), leaf.serialize()) +} + +pub(crate) fn create_storage_leaf_entry(val: u128) -> (StorageKey, StorageValue) { + let leaf = StarknetStorageValue(Felt::from(val)); + (leaf.get_db_key(&leaf.0.to_bytes_be()), leaf.serialize()) +} + +pub(crate) fn create_compiled_class_leaf_entry(val: u128) -> (StorageKey, StorageValue) { + let leaf = CompiledClassHash(Felt::from(val)); + (leaf.get_db_key(&leaf.0.to_bytes_be()), leaf.serialize()) +} + +pub(crate) fn create_contract_state_leaf_entry(val: u128) -> (StorageKey, StorageValue) { + let felt = Felt::from(val); + let leaf = ContractState { + nonce: Nonce(felt), + storage_root_hash: HashOutput(felt), + class_hash: ClassHash(felt), + }; + (leaf.get_db_key(&felt.to_bytes_be()), leaf.serialize()) +} + +fn create_patricia_key(val: u128) -> StorageKey { + create_db_key( + StarknetPrefix::InnerNode.to_storage_prefix(), + &U256::from(val).to_be_bytes(), + ) +} + +fn create_binary_val(left: u128, right: u128) -> StorageValue { + StorageValue( + (create_32_bytes_entry(left) + .into_iter() + .chain(create_32_bytes_entry(right))) + .collect(), + ) +} + +fn create_edge_val(hash: u128, path: u128, length: u8) -> StorageValue { + StorageValue( + create_32_bytes_entry(hash) + .into_iter() + .chain(create_32_bytes_entry(path)) + .chain([length]) + .collect(), + ) +} + +fn create_mock_leaf_modifications( + leaf_modifications: Vec<(u128, u128)>, +) -> LeafModifications { + leaf_modifications + .into_iter() + .map(|(idx, val)| (NodeIndex::from(idx), MockLeaf(Felt::from(val)))) + .collect() +} + +pub(crate) fn create_binary_entry(left: u128, right: u128) -> (StorageKey, StorageValue) { + ( + create_patricia_key(left + right), + create_binary_val(left, right), + ) +} + +pub(crate) fn create_edge_entry(hash: u128, path: u128, length: u8) -> (StorageKey, StorageValue) { + ( + create_patricia_key(hash + path + u128::from(length)), + create_edge_val(hash, path, length), + ) +} + +pub(crate) fn create_expected_skeleton_nodes( + nodes: Vec<(NodeIndex, OriginalSkeletonNode)>, + height: u8, +) -> HashMap { + let subtree_height = SubTreeHeight::new(height); + nodes + .into_iter() + .map(|(node_index, node)| { + ( + NodeIndex::from_subtree_index(node_index, subtree_height), + node, + ) + }) + .chain([( + NodeIndex::ROOT, + OriginalSkeletonNode::Edge( + PathToBottom::new(0.into(), EdgePathLength::new(251 - height).unwrap()).unwrap(), + ), + )]) + .collect() +} + +pub(crate) fn create_binary_skeleton_node(idx: u128) -> (NodeIndex, OriginalSkeletonNode) { + (NodeIndex::from(idx), OriginalSkeletonNode::Binary) +} + +pub(crate) fn create_edge_skeleton_node( + idx: u128, + path: u128, + length: u8, +) -> (NodeIndex, OriginalSkeletonNode) { + ( + NodeIndex::from(idx), + OriginalSkeletonNode::Edge( + PathToBottom::new(path.into(), EdgePathLength::new(length).unwrap()).unwrap(), + ), + ) +} + +pub(crate) fn create_unmodified_subtree_skeleton_node( + idx: u128, + hash_output: u128, +) -> (NodeIndex, OriginalSkeletonNode) { + ( + NodeIndex::from(idx), + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::from(hash_output))), + ) +} + +pub(crate) fn create_root_edge_entry( + old_root: u128, + subtree_height: SubTreeHeight, +) -> (StorageKey, StorageValue) { + // Assumes path is 0. + let length = SubTreeHeight::ACTUAL_HEIGHT.0 - subtree_height.0; + let new_root = old_root + u128::from(length); + let key = create_db_key( + StarknetPrefix::InnerNode.to_storage_prefix(), + &Felt::from(new_root).to_bytes_be(), + ); + let value = StorageValue( + Felt::from(old_root) + .to_bytes_be() + .into_iter() + .chain(Felt::from(0_u128).to_bytes_be()) + .chain([length]) + .collect(), + ); + (key, value) +} + +fn create_previously_empty_leaf_indices<'a>( + tree_leaf_indices: &'a [NodeIndex], + subtree_leaf_indices: &'a [NodeIndex], +) -> Vec<&'a NodeIndex> { + tree_leaf_indices + .iter() + .filter(|idx| !subtree_leaf_indices.contains(idx)) + .collect() +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/errors.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/errors.rs new file mode 100644 index 00000000000..27f86272e32 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/errors.rs @@ -0,0 +1,23 @@ +use std::fmt::Debug; + +use thiserror::Error; + +use crate::{ + patricia_merkle_tree::types::NodeIndex, + storage::errors::{DeserializationError, StorageError}, +}; + +#[derive(Debug, Error)] +pub enum OriginalSkeletonTreeError { + #[error( + "Failed to deserialize the storage value: {0:?} while building the original skeleton tree." + )] + Deserialization(#[from] DeserializationError), + #[error( + "Unable to read from storage the storage key: {0:?} while building the \ + original skeleton tree." + )] + StorageRead(#[from] StorageError), + #[error("Failed to read the modified leaf at index {0:?}")] + ReadModificationsError(NodeIndex), +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/node.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/node.rs new file mode 100644 index 00000000000..0843201ffda --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/node.rs @@ -0,0 +1,11 @@ +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::node_data::inner_node::PathToBottom; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// A node in the structure of a Patricia-Merkle tree, before the update. +pub(crate) enum OriginalSkeletonNode { + Binary, + Edge(PathToBottom), + // Represents a root of a subtree where none of it's descendants has changed. + UnmodifiedSubTree(HashOutput), +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest.rs new file mode 100644 index 00000000000..f3704c329fc --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest.rs @@ -0,0 +1,152 @@ +use crate::block_committer::input::Config; +use crate::block_committer::input::ContractAddress; +use crate::block_committer::input::StarknetStorageValue; +use crate::forest_errors::ForestError; +use crate::forest_errors::ForestResult; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::node_data::leaf::LeafModifications; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonClassesTrieConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonContractsTrieConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonStorageTrieConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTree; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use crate::storage::storage_trait::Storage; +use std::collections::HashMap; + +#[cfg(test)] +#[path = "skeleton_forest_test.rs"] +pub mod skeleton_forest_test; + +#[derive(Debug, PartialEq)] +pub(crate) struct OriginalSkeletonForest<'a> { + pub(crate) classes_trie: OriginalSkeletonTreeImpl<'a>, + pub(crate) contracts_trie: OriginalSkeletonTreeImpl<'a>, + pub(crate) storage_tries: HashMap>, +} + +impl<'a> OriginalSkeletonForest<'a> { + /// Creates an original skeleton forest that includes the storage tries of the modified contracts, + /// the classes trie and the contracts trie. Additionally, returns the original contract states that + /// are needed to compute the contract state tree. + pub(crate) fn create( + storage: impl Storage, + contracts_trie_root_hash: HashOutput, + classes_trie_root_hash: HashOutput, + storage_updates: &HashMap>, + classes_updates: &LeafModifications, + forest_sorted_indices: &ForestSortedIndices<'a>, + config: &impl Config, + ) -> ForestResult<(Self, HashMap)> + where + Self: std::marker::Sized, + { + let (contracts_trie, original_contracts_trie_leaves) = Self::create_contracts_trie( + contracts_trie_root_hash, + &storage, + forest_sorted_indices.contracts_trie_sorted_indices, + )?; + let storage_tries = Self::create_storage_tries( + storage_updates, + &original_contracts_trie_leaves, + &storage, + config, + &forest_sorted_indices.storage_tries_sorted_indices, + )?; + let classes_trie = Self::create_classes_trie( + classes_updates, + classes_trie_root_hash, + &storage, + config, + forest_sorted_indices.classes_trie_sorted_indices, + )?; + + Ok(( + Self { + classes_trie, + contracts_trie, + storage_tries, + }, + original_contracts_trie_leaves, + )) + } + + /// Creates the contracts trie original skeleton. + /// Also returns the previous contracts state of the modified contracts. + fn create_contracts_trie( + contracts_trie_root_hash: HashOutput, + storage: &impl Storage, + contracts_trie_sorted_indices: SortedLeafIndices<'a>, + ) -> ForestResult<( + OriginalSkeletonTreeImpl<'a>, + HashMap, + )> { + Ok(OriginalSkeletonTreeImpl::create_and_get_previous_leaves( + storage, + contracts_trie_root_hash, + contracts_trie_sorted_indices, + &OriginalSkeletonContractsTrieConfig::new(), + )?) + } + + fn create_storage_tries( + actual_storage_updates: &HashMap>, + original_contracts_trie_leaves: &HashMap, + storage: &impl Storage, + config: &impl Config, + storage_tries_sorted_indices: &HashMap>, + ) -> ForestResult>> { + let mut storage_tries = HashMap::new(); + for (address, updates) in actual_storage_updates { + let sorted_leaf_indices = storage_tries_sorted_indices + .get(address) + .ok_or(ForestError::MissingSortedLeafIndices(*address))?; + let contract_state = original_contracts_trie_leaves + .get(&NodeIndex::from_contract_address(address)) + .ok_or(ForestError::MissingContractCurrentState(*address))?; + let config = OriginalSkeletonStorageTrieConfig::new( + updates, + config.warn_on_trivial_modifications(), + ); + + let original_skeleton = OriginalSkeletonTreeImpl::create( + storage, + contract_state.storage_root_hash, + *sorted_leaf_indices, + &config, + )?; + storage_tries.insert(*address, original_skeleton); + } + Ok(storage_tries) + } + + fn create_classes_trie( + actual_classes_updates: &LeafModifications, + classes_trie_root_hash: HashOutput, + storage: &impl Storage, + config: &impl Config, + contracts_trie_sorted_indices: SortedLeafIndices<'a>, + ) -> ForestResult> { + let config = OriginalSkeletonClassesTrieConfig::new( + actual_classes_updates, + config.warn_on_trivial_modifications(), + ); + + Ok(OriginalSkeletonTreeImpl::create( + storage, + classes_trie_root_hash, + contracts_trie_sorted_indices, + &config, + )?) + } +} + +/// Holds all the indices of the modified leaves in the Starknet forest grouped by tree and sorted. +pub(crate) struct ForestSortedIndices<'a> { + pub(crate) storage_tries_sorted_indices: HashMap>, + pub(crate) contracts_trie_sorted_indices: SortedLeafIndices<'a>, + pub(crate) classes_trie_sorted_indices: SortedLeafIndices<'a>, +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest_test.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest_test.rs new file mode 100644 index 00000000000..3e9f019f78c --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/skeleton_forest_test.rs @@ -0,0 +1,390 @@ +use pretty_assertions::assert_eq; +use rstest::rstest; +use std::collections::HashMap; + +use super::OriginalSkeletonForest; +use crate::block_committer::commit::get_all_modified_indices; +use crate::block_committer::input::{ + ConfigImpl, ContractAddress, Input, StarknetStorageKey, StarknetStorageValue, StateDiff, +}; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::original_skeleton_tree::create_tree::create_tree_test::{ + create_32_bytes_entry, create_binary_entry, create_binary_skeleton_node, create_edge_entry, + create_edge_skeleton_node, create_expected_skeleton_nodes, + create_unmodified_subtree_skeleton_node, +}; +use crate::patricia_merkle_tree::original_skeleton_tree::create_tree::create_tree_test::{ + create_compiled_class_leaf_entry, create_contract_state_leaf_entry, create_root_edge_entry, + create_storage_leaf_entry, +}; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::types::SubTreeHeight; +use crate::patricia_merkle_tree::{ + original_skeleton_tree::skeleton_forest::ForestSortedIndices, + original_skeleton_tree::tree::OriginalSkeletonTreeImpl, types::SortedLeafIndices, +}; +use crate::storage::map_storage::MapStorage; + +macro_rules! compare_skeleton_tree { + ($actual_skeleton:expr, $expected_skeleton:expr, $expected_indices:expr) => {{ + let mut indices = create_expected_sorted_indices($expected_indices); + let sorted_indices = SortedLeafIndices::new(&mut indices); + let copied_expected_skeleton = + create_original_skeleton_with_sorted_indices(sorted_indices, $expected_skeleton); + assert_eq!($actual_skeleton, &copied_expected_skeleton); + }}; +} + +// This test assumes for simplicity that hash is addition (i.e hash(a,b) = a + b). +// I.e., the value of a binary node is the sum of its children's values, and the value of an edge +// node is the sum of its path, bottom value and path length. +/// Old forest structure: +/// +/// Global tree: Classes tree: +/// +/// 248 + 861 + 0 248 + 155 + 0 +/// / / +/// ... ... +/// / / +/// / / +/// 861 155 +/// / \ / +/// 305 556 154 +/// / \ / \ +/// 304 554 80 74 +/// / \ / \ / \ \ +/// 303 1 277 277 33 47 72 +/// +/// Modified leaves (full) indices: [8, 14, 15] ## Modified leaves (full) indices: [8, 14, 15] +/// +/// +/// Contracts #6, #7: Contract #0: +/// +/// 248 + 29 + 0 248 + 55 + 0 +/// / / +/// ... ... +/// / / +/// / / +/// 29 55 +/// / \ / \ +/// 13 16 35 20 +/// / / \ / \ \ +/// 12 5 11 17 18 * +/// / \ \ / \ / \ \ \ +/// 10 2 3 4 7 8 9 16 15 +/// +/// Modified leaves (full) indices: [8, 11, 13] ## Modified leaves (full) indices: [8, 10, 13] +/// +/// Expected skeleton forest: +/// Global tree: Classes tree: +/// +/// B E +/// / \ / +/// E E B +/// / \ / \ +/// * B B E +/// / / \ \ +/// 303 NZ 47 UB +/// +/// Contracts #6, #7: Contract #0: +/// +/// +/// B B +/// / \ / \ +/// E B B E +/// / / \ / \ \ +/// B E E B E * +/// / \ \ \ / \ \ \ +/// NZ 2 NZ NZ NZ 9 16 15 +/// + +#[rstest] +#[case( + Input { + storage: HashMap::from([ + // Roots. + create_root_edge_entry(29, SubTreeHeight::new(3)), + create_root_edge_entry(55, SubTreeHeight::new(3)), + create_root_edge_entry(155, SubTreeHeight::new(3)), + create_root_edge_entry(861, SubTreeHeight::new(3)), + // Contracts trie inner nodes. + create_binary_entry(303, 1), + create_binary_entry(277, 277), + create_edge_entry(304, 0, 1), + create_edge_entry(554, 1, 1), + create_binary_entry(305, 556), + // Contracts trie leaves. + create_contract_state_leaf_entry(277), + create_contract_state_leaf_entry(303), + create_contract_state_leaf_entry(1), + // Classes trie inner nodes. + create_binary_entry(33, 47), + create_edge_entry(72, 1, 1), + create_binary_entry(80, 74), + create_edge_entry(154, 0, 1), + // Classes trie leaves. + create_compiled_class_leaf_entry(33), + create_compiled_class_leaf_entry(47), + create_compiled_class_leaf_entry(72), + // Storage tries #6, #7 inner nodes. + create_binary_entry(10, 2), + create_edge_entry(3, 1, 1), + create_binary_entry(4, 7), + create_edge_entry(12, 0, 1), + create_binary_entry(5, 11), + create_binary_entry(13, 16), + // Storage tries #6, #7 leaves. + create_storage_leaf_entry(2), + create_storage_leaf_entry(3), + create_storage_leaf_entry(4), + create_storage_leaf_entry(7), + create_storage_leaf_entry(10), + // Storage trie #0 inner nodes. + create_binary_entry(8, 9), + create_edge_entry(16, 1, 1), + create_edge_entry(15, 3, 2), + create_binary_entry(17, 18), + create_binary_entry(35, 20), + // Storage trie #0 leaves. + create_storage_leaf_entry(8), + create_storage_leaf_entry(9), + create_storage_leaf_entry(15), + create_storage_leaf_entry(16), + ]), + state_diff: StateDiff { + storage_updates: create_storage_updates(&[ + (7, &[0, 3, 5]), + (6, &[0, 3, 5]), + (0, &[0, 2, 5]), + ]), + class_hash_to_compiled_class_hash: create_class_hash_to_compiled_class_hash(&[(6, 1), (0, 7), (7, 9)]), + ..Default::default() + }, + contracts_trie_root_hash: HashOutput(Felt::from(861_u128 + 248_u128)), + classes_trie_root_hash: HashOutput(Felt::from(155_u128 + 248_u128)), + config: ConfigImpl::new(true, log::LevelFilter::Debug), + }, OriginalSkeletonForest{ + classes_trie: OriginalSkeletonTreeImpl { + nodes: create_expected_skeleton_nodes( + vec![ + create_edge_skeleton_node(1, 0, 1), + create_binary_skeleton_node(2), + create_binary_skeleton_node(4), + create_edge_skeleton_node(5, 1, 1), + create_unmodified_subtree_skeleton_node(11, 72), + create_unmodified_subtree_skeleton_node(9, 47) + ], + 3 + ), + sorted_leaf_indices: SortedLeafIndices::new(&mut []) + }, + contracts_trie: OriginalSkeletonTreeImpl { + nodes: create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_edge_skeleton_node(2, 0, 1), + create_binary_skeleton_node(4), + create_unmodified_subtree_skeleton_node(9, 1), + create_edge_skeleton_node(3, 1, 1), + create_binary_skeleton_node(7), + ], + 3 + ), + sorted_leaf_indices: SortedLeafIndices::new(&mut []) + }, + storage_tries: HashMap::from([ + ( + ContractAddress(Felt::from(0_u128)), + OriginalSkeletonTreeImpl { + nodes: create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_binary_skeleton_node(2), + create_edge_skeleton_node(3, 3, 2), + create_binary_skeleton_node(4), + create_edge_skeleton_node(5, 1, 1), + create_unmodified_subtree_skeleton_node(9, 9), + create_unmodified_subtree_skeleton_node(15, 15), + create_unmodified_subtree_skeleton_node(11, 16), + ], + 3 + ), + sorted_leaf_indices: SortedLeafIndices::new(&mut []) + } + ), + ( + ContractAddress(Felt::from(6_u128)), + OriginalSkeletonTreeImpl { + nodes: create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_edge_skeleton_node(2, 0, 1), + create_binary_skeleton_node(3), + create_binary_skeleton_node(4), + create_edge_skeleton_node(6, 1, 1), + create_unmodified_subtree_skeleton_node(7, 11), + create_unmodified_subtree_skeleton_node(9, 2), + ], + 3 + ), + sorted_leaf_indices: SortedLeafIndices::new(&mut []) + } + ), + ( + ContractAddress(Felt::from(7_u128)), + OriginalSkeletonTreeImpl { + nodes: create_expected_skeleton_nodes( + vec![ + create_binary_skeleton_node(1), + create_edge_skeleton_node(2, 0, 1), + create_binary_skeleton_node(3), + create_binary_skeleton_node(4), + create_edge_skeleton_node(6, 1, 1), + create_unmodified_subtree_skeleton_node(7, 11), + create_unmodified_subtree_skeleton_node(9, 2), + ], + 3 + ), + sorted_leaf_indices: SortedLeafIndices::new(&mut []) + } + ) + ]), + }, + create_contract_leaves(&[ + (7, 29 + 248), + (6, 29 + 248), + (0, 55 + 248), + ]), + HashMap::from([(0, vec![2, 5, 0]), (6, vec![3, 5, 0]), (7, vec![5, 3, 0])]), + vec![6, 7, 0], + vec![7, 6, 0], +)] +fn test_create_original_skeleton_forest( + #[case] input: Input, + #[case] expected_forest: OriginalSkeletonForest<'_>, + #[case] expected_original_contracts_trie_leaves: HashMap, + #[case] expected_storage_tries_sorted_indices: HashMap>, + #[case] expected_contracts_trie_sorted_indices: Vec, + #[case] expected_classes_trie_sorted_indices: Vec, +) { + let (mut storage_tries_indices, mut contracts_trie_indices, mut classes_trie_indices) = + get_all_modified_indices(&input.state_diff); + let forest_sorted_indices = ForestSortedIndices { + storage_tries_sorted_indices: storage_tries_indices + .iter_mut() + .map(|(address, indices)| (*address, SortedLeafIndices::new(indices))) + .collect(), + contracts_trie_sorted_indices: SortedLeafIndices::new(&mut contracts_trie_indices), + classes_trie_sorted_indices: SortedLeafIndices::new(&mut classes_trie_indices), + }; + let (actual_forest, original_contracts_trie_leaves) = OriginalSkeletonForest::create( + MapStorage::from(input.storage), + input.contracts_trie_root_hash, + input.classes_trie_root_hash, + &input.state_diff.actual_storage_updates(), + &input.state_diff.actual_classes_updates(), + &forest_sorted_indices, + &ConfigImpl::new(false, log::LevelFilter::Debug), + ) + .unwrap(); + let expected_original_contracts_trie_leaves = expected_original_contracts_trie_leaves + .into_iter() + .map(|(address, state)| (NodeIndex::from_contract_address(&address), state)) + .collect(); + assert_eq!( + original_contracts_trie_leaves, + expected_original_contracts_trie_leaves + ); + + compare_skeleton_tree!( + &actual_forest.classes_trie, + &expected_forest.classes_trie, + &expected_classes_trie_sorted_indices + ); + + compare_skeleton_tree!( + &actual_forest.contracts_trie, + &expected_forest.contracts_trie, + &expected_contracts_trie_sorted_indices + ); + + for (contract, indices) in expected_storage_tries_sorted_indices { + let contract_address = ContractAddress(Felt::from(contract)); + compare_skeleton_tree!( + &actual_forest.storage_tries[&contract_address], + &expected_forest.storage_tries[&contract_address], + &indices + ); + } +} + +fn create_contract_leaves(leaves: &[(u128, u128)]) -> HashMap { + leaves + .iter() + .map(|(idx, root)| { + ( + ContractAddress(Felt::from_bytes_be_slice(&create_32_bytes_entry(*idx))), + ContractState { + nonce: Nonce(Felt::from(*root)), + storage_root_hash: HashOutput(Felt::from(*root)), + class_hash: ClassHash(Felt::from(*root)), + }, + ) + }) + .collect() +} + +fn create_storage_updates( + updates: &[(u8, &[u8])], +) -> HashMap> { + updates + .iter() + .map(|(address, address_indices)| { + ( + ContractAddress(Felt::from(u128::from(*address))), + address_indices + .iter() + .map(|val| { + ( + StarknetStorageKey(Felt::from(u128::from(*val))), + StarknetStorageValue(Felt::from(u128::from(*val))), + ) + }) + .collect(), + ) + }) + .collect() +} + +fn create_class_hash_to_compiled_class_hash( + map: &[(u128, u128)], +) -> HashMap { + map.iter() + .map(|(class_hash, compiled_class_hash)| { + ( + ClassHash(Felt::from(*class_hash)), + CompiledClassHash(Felt::from(*compiled_class_hash)), + ) + }) + .collect() +} + +fn create_original_skeleton_with_sorted_indices<'a>( + indices: SortedLeafIndices<'a>, + skeleton: &OriginalSkeletonTreeImpl<'_>, +) -> OriginalSkeletonTreeImpl<'a> { + OriginalSkeletonTreeImpl { + nodes: skeleton.nodes.clone(), + sorted_leaf_indices: indices, + } +} + +fn create_expected_sorted_indices(indices: &[u128]) -> Vec { + indices + .iter() + .map(|idx| NodeIndex::FIRST_LEAF + NodeIndex::from(*idx)) + .collect() +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/tree.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/tree.rs new file mode 100644 index 00000000000..68a195eb9c5 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/tree.rs @@ -0,0 +1,78 @@ +use std::collections::HashMap; + +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::node_data::leaf::Leaf; +use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonTreeConfig; +use crate::patricia_merkle_tree::original_skeleton_tree::errors::OriginalSkeletonTreeError; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices}; +use crate::storage::storage_trait::Storage; + +pub(crate) type OriginalSkeletonNodeMap = HashMap; +pub(crate) type OriginalSkeletonTreeResult = Result; + +/// Consider a Patricia-Merkle Tree which should be updated with new leaves. +/// This trait represents the structure of the subtree which will be modified in the +/// update. It also contains the hashes (for edge siblings - also the edge data) of the unmodified +/// nodes on the Merkle paths from the updated leaves to the root. +pub(crate) trait OriginalSkeletonTree<'a>: Sized { + fn create( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult; + + fn get_nodes(&self) -> &OriginalSkeletonNodeMap; + + fn get_nodes_mut(&mut self) -> &mut OriginalSkeletonNodeMap; + + fn create_and_get_previous_leaves( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult<(Self, HashMap)>; + + #[allow(dead_code)] + fn get_sorted_leaf_indices(&self) -> SortedLeafIndices<'a>; +} + +// TODO(Dori, 1/7/2024): Make this a tuple struct. +#[derive(Debug, PartialEq)] +pub(crate) struct OriginalSkeletonTreeImpl<'a> { + pub(crate) nodes: HashMap, + pub(crate) sorted_leaf_indices: SortedLeafIndices<'a>, +} + +impl<'a> OriginalSkeletonTree<'a> for OriginalSkeletonTreeImpl<'a> { + fn create( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult { + Self::create_impl(storage, root_hash, sorted_leaf_indices, config) + } + + fn get_nodes(&self) -> &OriginalSkeletonNodeMap { + &self.nodes + } + + fn get_nodes_mut(&mut self) -> &mut OriginalSkeletonNodeMap { + &mut self.nodes + } + + fn create_and_get_previous_leaves( + storage: &impl Storage, + root_hash: HashOutput, + sorted_leaf_indices: SortedLeafIndices<'a>, + config: &impl OriginalSkeletonTreeConfig, + ) -> OriginalSkeletonTreeResult<(Self, HashMap)> { + Self::create_and_get_previous_leaves_impl(storage, root_hash, sorted_leaf_indices, config) + } + + fn get_sorted_leaf_indices(&self) -> SortedLeafIndices<'a> { + self.sorted_leaf_indices + } +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils.rs new file mode 100644 index 00000000000..09a2046773a --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils.rs @@ -0,0 +1,47 @@ +use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices, SubTreeHeight}; + +#[cfg(test)] +#[path = "utils_test.rs"] +pub mod utils_test; + +/// Returns the height of the node with the given index. +pub(crate) fn get_node_height(index: &NodeIndex) -> SubTreeHeight { + SubTreeHeight::new(SubTreeHeight::ACTUAL_HEIGHT.0 + 1 - index.bit_length()) +} + +/// Splits leaf_indices into two arrays according to the given root: the left child leaves and +/// the right child leaves. Assumes that all leaves are descendants of the root. +pub(crate) fn split_leaves<'a>( + root_index: &NodeIndex, + leaf_indices: &SortedLeafIndices<'a>, +) -> [SortedLeafIndices<'a>; 2] { + if leaf_indices.is_empty() { + return [SortedLeafIndices::default(), SortedLeafIndices::default()]; + } + + let root_height = get_node_height(root_index); + let assert_descendant = |leaf_index: &NodeIndex| { + if (*leaf_index >> u8::from(root_height)) != *root_index { + panic!( + "Leaf {leaf_index:?} is not a descendant of the root {root_index:?} \ + (root height={root_height:?})." + ); + } + }; + + let first_leaf = leaf_indices.first().expect("Unexpected empty array."); + assert_descendant(first_leaf); + + if leaf_indices.len() > 1 { + assert_descendant( + leaf_indices + .last() + .expect("leaf_indices unexpectedly empty."), + ); + } + + let right_child_index = (*root_index << 1) + 1; + let leftmost_index_in_right_subtree = right_child_index << (u8::from(root_height) - 1); + let leaves_split = leaf_indices.bisect_left(&leftmost_index_in_right_subtree); + leaf_indices.divide_at_index(leaves_split) +} diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils_test.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils_test.rs new file mode 100644 index 00000000000..52590b46757 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/utils_test.rs @@ -0,0 +1,104 @@ +use super::split_leaves; +use crate::patricia_merkle_tree::external_test_utils::get_random_u256; +use crate::patricia_merkle_tree::internal_test_utils::as_fully_indexed; +use crate::patricia_merkle_tree::internal_test_utils::random; +use crate::patricia_merkle_tree::internal_test_utils::small_tree_index_to_full; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use crate::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight}; +use ethnum::{uint, U256}; +use rand::rngs::ThreadRng; +use rand::Rng; +use rstest::rstest; + +/// Creates an array of increasing random U256 numbers, with jumps of up to 'jump' between two +/// consecutive numbers. +fn create_increasing_random_array( + rng: &mut R, + size: usize, + start: U256, + jump: U256, +) -> Vec { + let size_u256: U256 = size.try_into().unwrap(); + assert!(jump > 0 && start + jump * size_u256 < U256::MAX); + let mut ret: Vec = Vec::with_capacity(size); + let mut low = start; + for i in 0..size { + ret.push(get_random_u256(rng, low, low + jump)); + low = ret[i] + 1; + } + ret +} + +#[rstest] +#[case::small_tree_one_side( + 3_u8, U256::ONE, as_fully_indexed(subtree_height, [uint!("8"), uint!("10"), uint!("11")].into_iter()), + &[uint!("8"), uint!("10"), uint!("11")], &[] +)] +#[case::small_tree_two_sides( + 3_u8, U256::ONE, as_fully_indexed(subtree_height, [uint!("8"), uint!("10"), uint!("14")].into_iter()), + &[uint!("8"), uint!("10")], &[uint!("14")] +)] +#[should_panic] +#[case::small_tree_wrong_height( + 3_u8, U256::ONE, as_fully_indexed(subtree_height, [uint!("8"), uint!("10"), uint!("16")].into_iter()), &[], &[] +)] +#[should_panic] +#[case::small_tree_not_descendant( + 3_u8, uint!("2"), as_fully_indexed(subtree_height, [uint!("8"), uint!("10"), uint!("14")].into_iter()), &[], &[] +)] +fn test_split_leaves( + #[case] subtree_height: u8, + #[case] root_index: U256, + #[case] mut leaf_indices: Vec, + #[case] expected_left: &[U256], + #[case] expected_right: &[U256], +) { + let height = SubTreeHeight(subtree_height); + let root_index = small_tree_index_to_full(root_index, height); + let mut left_full_indices = as_fully_indexed(subtree_height, expected_left.iter().copied()); + let mut right_full_indices = as_fully_indexed(subtree_height, expected_right.iter().copied()); + + let expected = [ + SortedLeafIndices::new(&mut left_full_indices), + SortedLeafIndices::new(&mut right_full_indices), + ]; + assert_eq!( + split_leaves(&root_index, &SortedLeafIndices::new(&mut leaf_indices)), + expected + ); +} + +#[rstest] +fn test_split_leaves_big_tree(mut random: ThreadRng) { + let left_leaf_indices = create_increasing_random_array( + &mut random, + 100, + NodeIndex::FIRST_LEAF.into(), + U256::ONE << 200, + ); + let right_leaf_indices = create_increasing_random_array( + &mut random, + 100, + (U256::from(NodeIndex::FIRST_LEAF) + U256::from(NodeIndex::MAX)) / 2 + 1, + U256::ONE << 100, + ); + test_split_leaves( + SubTreeHeight::ACTUAL_HEIGHT.into(), + NodeIndex::ROOT.into(), + [ + left_leaf_indices + .clone() + .into_iter() + .map(NodeIndex::new) + .collect::>(), + right_leaf_indices + .clone() + .into_iter() + .map(NodeIndex::new) + .collect(), + ] + .concat(), + left_leaf_indices.as_slice(), + right_leaf_indices.as_slice(), + ) +} diff --git a/crates/committer/src/patricia_merkle_tree/types.rs b/crates/committer/src/patricia_merkle_tree/types.rs new file mode 100644 index 00000000000..c014d3ae846 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/types.rs @@ -0,0 +1,289 @@ +use crate::block_committer::input::{ContractAddress, StarknetStorageKey}; +use crate::felt::Felt; +use crate::patricia_merkle_tree::errors::TypesError; +use crate::patricia_merkle_tree::filled_tree::node::ClassHash; +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; + +use ethnum::U256; + +#[cfg(test)] +#[path = "types_test.rs"] +pub mod types_test; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, derive_more::Sub, derive_more::Display)] +pub struct SubTreeHeight(pub(crate) u8); + +impl SubTreeHeight { + pub const ACTUAL_HEIGHT: SubTreeHeight = SubTreeHeight(251); + + pub fn new(height: u8) -> Self { + if height > Self::ACTUAL_HEIGHT.0 { + panic!("Height {height} is too large."); + } + Self(height) + } +} + +impl From for u8 { + fn from(value: SubTreeHeight) -> Self { + value.0 + } +} + +#[derive( + Clone, Copy, Debug, PartialEq, Eq, Hash, derive_more::BitAnd, derive_more::Sub, PartialOrd, Ord, +)] +pub struct NodeIndex(pub U256); + +// Wraps a U256. Maximal possible value is the largest index in a tree of height 251 (2 ^ 252 - 1). +impl NodeIndex { + pub const BITS: u8 = SubTreeHeight::ACTUAL_HEIGHT.0 + 1; + + /// [NodeIndex] constant that represents the root index. + pub const ROOT: Self = Self(U256::ONE); + + /// [NodeIndex] constant that represents the first leaf index. + // TODO(Tzahi, 15/6/2024): Support height < 128 bits. + pub const FIRST_LEAF: Self = Self(U256::from_words(1_u128 << (Self::BITS - 1 - 128), 0)); + + #[allow(clippy::as_conversions)] + /// [NodeIndex] constant that represents the largest index in a tree. + // TODO(Tzahi, 15/6/2024): Support height < 128 bits. + pub const MAX: Self = Self(U256::from_words( + u128::MAX >> (U256::BITS - Self::BITS as u32), + u128::MAX, + )); + + pub fn new(index: U256) -> Self { + assert!(index <= Self::MAX.0, "Index {index} is too large."); + Self(index) + } + + pub(crate) fn is_leaf(&self) -> bool { + Self::FIRST_LEAF <= *self && *self <= Self::MAX + } + + // TODO(Amos, 1/5/2024): Move to EdgePath. + pub(crate) fn compute_bottom_index( + index: NodeIndex, + path_to_bottom: &PathToBottom, + ) -> NodeIndex { + let PathToBottom { path, length, .. } = path_to_bottom; + (index << u8::from(*length)) + Self::new(path.into()) + } + + pub(crate) fn get_children_indices(&self) -> [Self; 2] { + let left_child = *self << 1; + [left_child, left_child + 1] + } + + /// Returns the number of leading zeroes when represented with Self::BITS bits. + pub(crate) fn leading_zeros(&self) -> u8 { + (self.0.leading_zeros() - (U256::BITS - u32::from(Self::BITS))) + .try_into() + .expect("Leading zeroes are unexpectedly larger than a u8.") + } + + pub(crate) fn bit_length(&self) -> u8 { + Self::BITS - self.leading_zeros() + } + + /// Get the LCA (Lowest Common Ancestor) of the two nodes. + pub(crate) fn get_lca(&self, other: &NodeIndex) -> NodeIndex { + if self == other { + return *self; + } + + let bit_length = self.bit_length(); + let other_bit_length = other.bit_length(); + // Bring self and other to a common (low) height. + let (adapted_self, adapted_other) = if self < other { + (*self, *other >> (other_bit_length - bit_length)) + } else { + (*self >> (bit_length - other_bit_length), *other) + }; + + let xor = adapted_self.0 ^ adapted_other.0; + // The length of the remainder after removing the common prefix of the two nodes. + let post_common_prefix_len = NodeIndex::new(xor).bit_length(); + + let lca = adapted_self.0 >> post_common_prefix_len; + NodeIndex::new(lca) + } + + /// Returns the path from the node to its given descendant (0 length if node == descendant). + /// Panics if the supposed descendant is not really a descendant. + pub(crate) fn get_path_to_descendant(&self, descendant: Self) -> PathToBottom { + let descendant_bit_length = descendant.bit_length(); + let bit_length = self.bit_length(); + if bit_length > descendant_bit_length { + panic!("The descendant is not a really descendant of the node."); + }; + + let distance = descendant_bit_length - bit_length; + let delta = descendant - (*self << distance); + if descendant >> distance != *self { + panic!("The descendant is not a really descendant of the node."); + }; + + PathToBottom::new( + delta.0.into(), + EdgePathLength::new(distance).expect("Illegal length"), + ) + .expect("Illegal PathToBottom") + } + + pub(crate) fn from_starknet_storage_key(key: &StarknetStorageKey) -> Self { + Self::from_leaf_felt(&key.0) + } + + pub(crate) fn from_contract_address(address: &ContractAddress) -> Self { + Self::from_leaf_felt(&address.0) + } + + pub(crate) fn from_class_hash(class_hash: &ClassHash) -> Self { + Self::from_leaf_felt(&class_hash.0) + } + + fn from_leaf_felt(felt: &Felt) -> Self { + Self::FIRST_LEAF + Self::from_felt_value(felt) + } + + fn from_felt_value(felt: &Felt) -> Self { + Self(U256::from(felt)) + } +} + +impl std::ops::Add for NodeIndex { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self::new(self.0 + rhs.0) + } +} + +impl std::ops::Mul for NodeIndex { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + Self::new(self.0 * rhs.0) + } +} + +impl std::ops::Add for NodeIndex { + type Output = Self; + + fn add(self, rhs: u128) -> Self { + self + Self::from(rhs) + } +} + +impl std::ops::Shl for NodeIndex { + type Output = Self; + + /// Returns the index of the left descendant (child for rhs=1) of the node. + fn shl(self, rhs: u8) -> Self::Output { + Self::new(self.0 << rhs) + } +} + +impl std::ops::Shr for NodeIndex { + type Output = Self; + + /// Returns the index of the ancestor (parent for rhs=1) of the node. + fn shr(self, rhs: u8) -> Self::Output { + Self::new(self.0 >> rhs) + } +} + +impl From for NodeIndex { + fn from(value: u128) -> Self { + Self::new(U256::from(value)) + } +} + +impl From for U256 { + fn from(value: NodeIndex) -> Self { + value.0 + } +} + +impl TryFrom for Felt { + type Error = TypesError; + + fn try_from(value: NodeIndex) -> Result { + if value.0 > U256::from_be_bytes(Self::MAX.to_bytes_be()) { + return Err(TypesError::ConversionError { + from: value, + to: "Felt", + reason: "NodeIndex is too large", + }); + } + let bytes = value.0.to_be_bytes(); + Ok(Self::from_bytes_be_slice(&bytes)) + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub(crate) struct SortedLeafIndices<'a>(&'a [NodeIndex]); + +impl<'a> SortedLeafIndices<'a> { + /// Creates a new instance by sorting the given indices. + // TODO(Nimrod, 1/8/2024): Remove duplicates from the given indices. + pub(crate) fn new(indices: &'a mut [NodeIndex]) -> Self { + indices.sort(); + Self(indices) + } + + /// Returns a subslice of the indices stored at self, at the range [leftmost_idx, rightmost_idx). + pub(crate) fn subslice(&self, leftmost_idx: usize, rightmost_idx: usize) -> Self { + Self(&self.0[leftmost_idx..rightmost_idx]) + } + + /// Divides the slice held by self into two instances. One holds the range [0, idx), the + /// other holds the range [idx, len(self)). + pub(crate) fn divide_at_index(&self, idx: usize) -> [Self; 2] { + [Self(&self.0[..idx]), Self(&self.0[idx..])] + } + + pub(crate) fn get_indices(&self) -> &'a [NodeIndex] { + self.0 + } + + pub(crate) fn contains(&self, value: &NodeIndex) -> bool { + self.0.contains(value) + } + + pub(crate) fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub(crate) fn len(&self) -> usize { + self.0.len() + } + + pub(crate) fn last(&self) -> Option<&NodeIndex> { + self.0.last() + } + + pub(crate) fn first(&self) -> Option<&NodeIndex> { + self.0.first() + } + + /// Returns the leftmost position where `leftmost_value` can be inserted to the slice and + /// maintain sorted order. Assumes that the elements in the slice are unique. + pub(crate) fn bisect_left(&self, leftmost_value: &NodeIndex) -> usize { + match self.0.binary_search(leftmost_value) { + Ok(pos) | Err(pos) => pos, + } + } + + /// Returns the rightmost position where `rightmost_value` can be inserted to the slice and + /// maintain sorted order. Assumes that the elements in the slice are unique. + pub(crate) fn bisect_right(&self, rightmost_value: &NodeIndex) -> usize { + match self.0.binary_search(rightmost_value) { + Err(pos) => pos, + Ok(pos) => pos + 1, + } + } +} diff --git a/crates/committer/src/patricia_merkle_tree/types_test.rs b/crates/committer/src/patricia_merkle_tree/types_test.rs new file mode 100644 index 00000000000..1db478d6a9b --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/types_test.rs @@ -0,0 +1,149 @@ +use crate::block_committer::input::{ContractAddress, StarknetStorageKey}; +use crate::felt::Felt; +use crate::patricia_merkle_tree::external_test_utils::get_random_u256; +use crate::patricia_merkle_tree::internal_test_utils::random; +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; +use crate::patricia_merkle_tree::types::NodeIndex; + +use ethnum::{uint, U256}; +use rand::rngs::ThreadRng; +use rand::Rng; +use rstest::rstest; + +#[rstest] +#[case(1, 1, 1, 3)] +#[case(1, 0, 2, 4)] +#[case(0xDAD, 0xFEE, 12, 0xDADFEE)] +#[case(0xDEAFBEE, 0xBFF, 16, 0xDEAFBEE0BFF)] +fn test_compute_bottom_index( + #[case] node_index: u128, + #[case] path: u128, + #[case] length: u8, + #[case] expected: u128, +) { + let bottom_index = NodeIndex::compute_bottom_index( + NodeIndex::from(node_index), + &PathToBottom::new(path.into(), EdgePathLength::new(length).unwrap()).unwrap(), + ); + let expected = NodeIndex::from(expected); + assert_eq!(bottom_index, expected); +} + +#[rstest] +fn test_cast_to_node_index( + #[values(0, 15, 0xDEADBEEF)] leaf_index: u128, + #[values(true, false)] from_contract_address: bool, +) { + let expected_node_index = NodeIndex::FIRST_LEAF + leaf_index; + let actual = if from_contract_address { + NodeIndex::from_contract_address(&ContractAddress(Felt::from(leaf_index))) + } else { + NodeIndex::from_starknet_storage_key(&StarknetStorageKey(Felt::from(leaf_index))) + }; + assert_eq!(actual, expected_node_index); +} + +#[rstest] +#[case(uint!("1"), uint!("1"), uint!("1"))] +#[case(uint!("2"), uint!("5"), uint!("2"))] +#[case(uint!("5"), uint!("2"), uint!("2"))] +#[case(uint!("8"), uint!("10"), uint!("2"))] +#[case(uint!("9"), uint!("12"), uint!("1"))] +#[case(uint!("1"), uint!("2"), uint!("1"))] +#[case(uint!("2"), uint!("1"), uint!("1"))] +#[case( + U256::from_words(1<<121, 0), + U256::from_words(1<<123, 0), + U256::from_words(1<<121, 0) +)] +#[case( + U256::from_words(6<<121, 12109832645278165874326859176438297), + U256::from_words(7<<121, 34269583569287659876592876529763453), + uint!("3") +)] +#[case( + uint!("3"), + U256::from_str_hex("0xd2794ec01eb68c0f3334f2e9e6a3fee480249162fbb5b1cc491c1738368de89").unwrap(), + uint!("3") +)] +fn test_get_lca(#[case] node_index: U256, #[case] other: U256, #[case] expected: U256) { + let root_index = NodeIndex::new(node_index); + let other_index = NodeIndex::new(other); + let lca = root_index.get_lca(&other_index); + let expected = NodeIndex::new(expected); + assert_eq!(lca, expected); +} + +#[rstest] +fn test_get_lca_big(mut random: ThreadRng) { + let lca = NodeIndex::new(get_random_u256( + &mut random, + U256::ZERO, + (NodeIndex::MAX >> 1).into(), + )); + + let left_child = lca << 1; + let right_child = left_child + 1; + let mut random_extension = |index: NodeIndex| { + let extension_bits = index.leading_zeros(); + let extension: u128 = random.gen_range(0..(1 << extension_bits)); + (index << extension_bits) + NodeIndex::new(U256::from(extension)) + }; + + let left_descendant = random_extension(left_child); + let right_descendant = random_extension(right_child); + assert_eq!(left_descendant.get_lca(&right_descendant), lca); +} + +#[rstest] +#[case(3, 3, 0, 0)] +#[case(2, 10, 2, 2)] +#[should_panic] +#[case(2, 3, 0, 0)] +#[should_panic] +#[case(2, 6, 0, 0)] +#[should_panic] +#[case(6, 2, 0, 0)] +fn test_get_path_to_descendant( + #[case] root_index: u8, + #[case] descendant: u8, + #[case] expected_path: u8, + #[case] expected_length: u8, +) { + let root_index = NodeIndex::new(root_index.into()); + let descendant = NodeIndex::new(descendant.into()); + let path_to_bottom = root_index.get_path_to_descendant(descendant); + assert_eq!(path_to_bottom.path, U256::from(expected_path).into()); + assert_eq!( + path_to_bottom.length, + EdgePathLength::new(expected_length).unwrap() + ); +} + +#[rstest] +fn test_get_path_to_descendant_big() { + let root_index = NodeIndex::new(U256::from(rand::thread_rng().gen::())); + let max_bits = NodeIndex::BITS - 128; + let extension: u128 = rand::thread_rng().gen_range(0..1 << max_bits); + let extension_index = NodeIndex::new(U256::from(extension)); + + let descendant = (root_index << extension_index.bit_length()) + extension_index; + let path_to_bottom = root_index.get_path_to_descendant(descendant); + assert_eq!(path_to_bottom.path, extension.into()); + assert_eq!( + path_to_bottom.length, + EdgePathLength::new(extension_index.bit_length()).unwrap() + ); +} + +#[rstest] +fn test_nodeindex_to_felt_conversion() { + let index = NodeIndex::MAX; + assert!(Felt::try_from(index).is_err()); +} + +#[rstest] +fn test_felt_printing() { + let felt = Felt::from(17_u8); + assert_eq!(format!("{:?}", felt), "17"); +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree.rs new file mode 100644 index 00000000000..2869b48e3e6 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree.rs @@ -0,0 +1,6 @@ +pub mod create_tree_helper; +pub mod errors; +pub mod hash_function; +pub mod node; +pub mod skeleton_forest; +pub mod tree; diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper.rs new file mode 100644 index 00000000000..b32b44147d0 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper.rs @@ -0,0 +1,431 @@ +use std::collections::HashMap; + +use crate::patricia_merkle_tree::node_data::inner_node::EdgePathLength; +use crate::patricia_merkle_tree::node_data::inner_node::PathToBottom; +use crate::patricia_merkle_tree::node_data::leaf::LeafModifications; +use crate::patricia_merkle_tree::node_data::leaf::SkeletonLeaf; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonNodeMap; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTree; +use crate::patricia_merkle_tree::original_skeleton_tree::utils::split_leaves; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use crate::patricia_merkle_tree::updated_skeleton_tree::errors::UpdatedSkeletonTreeError; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonNodeMap; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeResult; + +#[cfg(test)] +#[path = "create_tree_helper_test.rs"] +pub mod create_tree_helper_test; + +#[derive(Debug, PartialEq, Eq)] +/// A temporary skeleton node used during the computation of the updated skeleton tree. +pub(crate) enum TempSkeletonNode { + // A deleted node. + Empty, + // A new/modified leaf. + Leaf, + Original(OriginalSkeletonNode), +} + +impl TempSkeletonNode { + fn is_empty(&self) -> bool { + *self == Self::Empty + } +} + +/// Returns the path from the given root_index to the LCA of the given subtree node indices. +/// Assumes the nodes are: +/// * Descendants of the given index. +/// * A non-empty array. +/// Note that the if the LCA is the root, the path will be empty (0 length). +fn get_path_to_lca( + root_index: &NodeIndex, + subtree_indices: &SortedLeafIndices<'_>, +) -> PathToBottom { + if subtree_indices.is_empty() { + panic!("Unexpected empty array."); + } + let first_index = *subtree_indices.first().expect("Unexpected empty array."); + let lca = if subtree_indices.len() == 1 { + first_index + } else { + first_index.get_lca(subtree_indices.last().expect("Unexpected empty array")) + }; + root_index.get_path_to_descendant(lca) +} + +/// Returns whether a root of a subtree has leaves on both sides. Assumes that all leaves are +/// descendants of the root. +fn has_leaves_on_both_sides(root_index: &NodeIndex, leaf_indices: &SortedLeafIndices<'_>) -> bool { + if leaf_indices.is_empty() { + return false; + } + split_leaves(root_index, leaf_indices) + .iter() + .all(|leaves_in_side| !leaves_in_side.is_empty()) +} + +impl UpdatedSkeletonTreeImpl { + /// Finalize the skeleton bottom layer := the updated skeleton nodes created directly from the + /// original skeleton and leaf modifications, without being dependant in any descendants + /// (i.e., modified leaves, and unmodified nodes). + pub(crate) fn finalize_bottom_layer<'a>( + original_skeleton: &impl OriginalSkeletonTree<'a>, + leaf_modifications: &LeafModifications, + ) -> UpdatedSkeletonNodeMap { + leaf_modifications + .iter() + .filter(|(_, leaf)| !leaf.is_zero()) + .map(|(index, _)| (*index, UpdatedSkeletonNode::Leaf)) + .chain( + original_skeleton + .get_nodes() + .iter() + .filter_map(|(index, node)| match node { + OriginalSkeletonNode::UnmodifiedSubTree(hash) => { + Some((*index, UpdatedSkeletonNode::UnmodifiedSubTree(*hash))) + } + OriginalSkeletonNode::Binary | OriginalSkeletonNode::Edge(_) => None, + }), + ) + .collect() + } + + /// Finalize the tree middle layers (i.e., not the bottom layer defined above). + pub(crate) fn finalize_middle_layers<'a>( + &mut self, + original_skeleton: &mut impl OriginalSkeletonTree<'a>, + ) -> TempSkeletonNode { + let sorted_leaf_indices = original_skeleton.get_sorted_leaf_indices(); + if original_skeleton.get_nodes().is_empty() { + self.update_node_in_empty_tree(&NodeIndex::ROOT, &sorted_leaf_indices) + } else { + self.update_node_in_nonempty_tree( + &NodeIndex::ROOT, + original_skeleton.get_nodes_mut(), + &sorted_leaf_indices, + ) + } + } + + /// Updates the originally empty Patricia-Merkle tree rooted at the given index, with leaf + /// modifications (already updated in the skeleton mapping) in the given leaf_indices. + /// Returns the root temporary skeleton node as inferred from the subtree. + pub(crate) fn update_node_in_empty_tree( + &mut self, + root_index: &NodeIndex, + leaf_indices: &SortedLeafIndices<'_>, + ) -> TempSkeletonNode { + if root_index.is_leaf() { + // Leaf. As this is an empty tree, the leaf *should* be new. + assert!( + leaf_indices.len() == 1 + && leaf_indices.first().expect("Unexpected empty array.") == root_index, + "Unexpected leaf index (root_index={root_index:?}, leaf_indices={leaf_indices:?})." + ); + if !self.skeleton_tree.contains_key(root_index) { + // "Deletion" of an original empty leaf (as non-zero leaf modifications are finalized in `finalize_bottom_layer`). + // Supported but not expected. + return TempSkeletonNode::Empty; + } + return TempSkeletonNode::Leaf; + } + + if has_leaves_on_both_sides(root_index, leaf_indices) { + // Binary node. + let [left_indices, right_indices] = split_leaves(root_index, leaf_indices); + let [left_child_index, right_child_index] = root_index.get_children_indices(); + let left_child = self.update_node_in_empty_tree(&left_child_index, &left_indices); + let right_child = self.update_node_in_empty_tree(&right_child_index, &right_indices); + return self.node_from_binary_data(root_index, &left_child, &right_child); + } + + // Edge node. + let path_to_lca = get_path_to_lca(root_index, leaf_indices); + let bottom_index = path_to_lca.bottom_index(*root_index); + let bottom = self.update_node_in_empty_tree(&bottom_index, leaf_indices); + self.node_from_edge_data(&path_to_lca, &bottom_index, &bottom) + } + + /// Updates the Patricia tree rooted at the given index, with the given leaves; returns the root. + pub(crate) fn update_node_in_nonempty_tree( + &mut self, + root_index: &NodeIndex, + original_skeleton: &mut OriginalSkeletonNodeMap, + leaf_indices: &SortedLeafIndices<'_>, + ) -> TempSkeletonNode { + if root_index.is_leaf() && leaf_indices.contains(root_index) { + // A new/modified/deleted leaf. + if self.skeleton_tree.contains_key(root_index) { + // A new/modified leaf. + return TempSkeletonNode::Leaf; + } else { + // A deleted leaf. + return TempSkeletonNode::Empty; + }; + }; + + // Not a leaf or an unmodified node. + let original_node = *original_skeleton + .get(root_index) + .unwrap_or_else(|| panic!("Node {root_index:?} not found.")); + + if leaf_indices.is_empty() { + match original_node { + OriginalSkeletonNode::Binary => unreachable!( + "Index {root_index:?} is an original Binary node without leaf modifications - + it should be an unmodified subtree instead." + ), + OriginalSkeletonNode::Edge(_) | OriginalSkeletonNode::UnmodifiedSubTree(_) => { + return TempSkeletonNode::Original(original_node); + } + } + }; + + match original_node { + OriginalSkeletonNode::UnmodifiedSubTree(_) => { + unreachable!( + "An unmodified subtree can't have any leaf_modifications in its subtree." + ) + } + OriginalSkeletonNode::Binary => { + let [left_indices, right_indices] = split_leaves(root_index, leaf_indices); + let [left_child_index, right_child_index] = root_index.get_children_indices(); + let left = self.update_node_in_nonempty_tree( + &left_child_index, + original_skeleton, + &left_indices, + ); + let right = self.update_node_in_nonempty_tree( + &right_child_index, + original_skeleton, + &right_indices, + ); + self.node_from_binary_data(root_index, &left, &right) + } + OriginalSkeletonNode::Edge(path_to_bottom) => { + self.update_edge_node(root_index, &path_to_bottom, original_skeleton, leaf_indices) + } + } + } + + /// Builds a (probably binary) node from its two updated children. Returns the TempSkeletonNode + /// matching the given root for the subtree it is the root of. If one or more children are + /// empty, the resulting node will not be binary. + fn node_from_binary_data( + &mut self, + root_index: &NodeIndex, + left: &TempSkeletonNode, + right: &TempSkeletonNode, + ) -> TempSkeletonNode { + let [left_index, right_index] = root_index.get_children_indices(); + + if !left.is_empty() && !right.is_empty() { + // Both children are non-empty - a binary node. + // Finalize children, as a binary node cannot change form. + for (index, node) in [(left_index, left), (right_index, right)] { + let TempSkeletonNode::Original(original_node) = node else { + match node { + TempSkeletonNode::Leaf => { + // Leaf is finalized in the initial phase of updated skeleton creation. + assert!( + self.skeleton_tree.contains_key(&index), + "Leaf index {index:?} doesn't appear in the skeleton." + ); + continue; + } + TempSkeletonNode::Empty => unreachable!("Unexpected empty node."), + TempSkeletonNode::Original(_) => { + unreachable!("node is not an Original variant.") + } + } + }; + let updated = match original_node { + OriginalSkeletonNode::Binary => UpdatedSkeletonNode::Binary, + OriginalSkeletonNode::Edge(path_to_bottom) => { + UpdatedSkeletonNode::Edge(*path_to_bottom) + } + OriginalSkeletonNode::UnmodifiedSubTree(_) => { + // Unmodified nodes are finalized in the initial phase of updated skeleton + // creation. + continue; + } + }; + self.skeleton_tree.insert(index, updated); + } + + return TempSkeletonNode::Original(OriginalSkeletonNode::Binary); + } + + // At least one of the children is empty. + let (child_node, child_index, child_direction) = if *right == TempSkeletonNode::Empty { + (left, left_index, PathToBottom::LEFT_CHILD) + } else { + (right, right_index, PathToBottom::RIGHT_CHILD) + }; + self.node_from_edge_data(&child_direction, &child_index, child_node) + } + + /// Builds a (probably edge) node from its given updated descendant. Returns the + /// TempSkeletonNode matching the given root (the source for the path to bottom) for the subtree + /// it is the root of. If bottom is empty, returns an empty node. + fn node_from_edge_data( + &mut self, + path: &PathToBottom, + bottom_index: &NodeIndex, + bottom: &TempSkeletonNode, + ) -> TempSkeletonNode { + let TempSkeletonNode::Original(original_node) = bottom else { + match bottom { + TempSkeletonNode::Empty => { + return TempSkeletonNode::Empty; + } + TempSkeletonNode::Leaf => { + // Leaf is finalized in the initial phase of updated skeleton creation. + assert!( + self.skeleton_tree.contains_key(bottom_index), + "bottom {bottom_index:?} is a non-empty leaf but doesn't appear in the \ + skeleton." + ); + return TempSkeletonNode::Original(OriginalSkeletonNode::Edge(*path)); + } + TempSkeletonNode::Original(_) => unreachable!("bottom is not an Original variant."), + }; + }; + TempSkeletonNode::Original(match original_node { + OriginalSkeletonNode::Edge(path_to_bottom) => { + OriginalSkeletonNode::Edge(path.concat_paths(*path_to_bottom)) + } + OriginalSkeletonNode::Binary => { + // Finalize bottom - a binary descendant cannot change form. + self.skeleton_tree + .insert(*bottom_index, UpdatedSkeletonNode::Binary); + OriginalSkeletonNode::Edge(*path) + } + OriginalSkeletonNode::UnmodifiedSubTree(_) => OriginalSkeletonNode::Edge(*path), + }) + } + + /// Update an original subtree rooted with an edge node. + fn update_edge_node( + &mut self, + root_index: &NodeIndex, + path_to_bottom: &PathToBottom, + original_skeleton: &mut OriginalSkeletonNodeMap, + leaf_indices: &SortedLeafIndices<'_>, + ) -> TempSkeletonNode { + let [left_child_index, right_child_index] = root_index.get_children_indices(); + let [left_indices, right_indices] = split_leaves(root_index, leaf_indices); + let was_left_nonempty = path_to_bottom.is_left_descendant(); + if (!right_indices.is_empty() && was_left_nonempty) + || (!left_indices.is_empty() && !was_left_nonempty) + { + // The root has a new leaf on its originally empty subtree. + let ( + nonempty_subtree_child_index, + nonempty_subtree_leaf_indices, + empty_subtree_child_index, + empty_subtree_leaf_indices, + ) = if was_left_nonempty { + ( + left_child_index, + left_indices, + right_child_index, + right_indices, + ) + } else { + ( + right_child_index, + right_indices, + left_child_index, + left_indices, + ) + }; + + // 1. Handle the originally non-empty subtree, replacing the root with the child in the + // direction of the edge. + if u8::from(path_to_bottom.length) > 1 { + // Bottom is not a child of the root, removing the first edge returns a valid new + // edge node. Inject the new node to the original skeleton as if it was in it + // originally (fake original). + let fake_original_child_node = OriginalSkeletonNode::Edge( + path_to_bottom + .remove_first_edges(EdgePathLength::ONE) + .expect("Original Edge node is unexpectedly trivial"), + ); + original_skeleton.insert(nonempty_subtree_child_index, fake_original_child_node); + }; + + let orig_nonempty_subtree_child = self.update_node_in_nonempty_tree( + &nonempty_subtree_child_index, + original_skeleton, + &nonempty_subtree_leaf_indices, + ); + + // 2. Handle the originally empty subtree. + let orig_empty_subtree_child = self + .update_node_in_empty_tree(&empty_subtree_child_index, &empty_subtree_leaf_indices); + let (left, right) = if was_left_nonempty { + (orig_nonempty_subtree_child, orig_empty_subtree_child) + } else { + (orig_empty_subtree_child, orig_nonempty_subtree_child) + }; + + return self.node_from_binary_data(root_index, &left, &right); + } + + // All leaves are on the edge's subtree - they have a non-trivial common path with the edge. + // Create a new edge to the LCA of the leaves and the bottom. + let path_to_leaves_lca = get_path_to_lca(root_index, leaf_indices); + let leaves_lca_index = path_to_leaves_lca.bottom_index(*root_index); + + let bottom_index = path_to_bottom.bottom_index(*root_index); + let path_to_new_bottom = get_path_to_lca( + root_index, + &SortedLeafIndices::new(&mut [leaves_lca_index, bottom_index]), + ); + + let new_bottom_index = path_to_new_bottom.bottom_index(*root_index); + if new_bottom_index == bottom_index { + // All leaf_indices are in the bottom_node subtree. + assert_eq!(&path_to_new_bottom, path_to_bottom); + } else { + // Inject the new node to the original skeleton as if it was in it + // originally (fake original). + let fake_original_new_bottom_node = OriginalSkeletonNode::Edge( + path_to_bottom + .remove_first_edges(path_to_new_bottom.length) + .expect("Unexpectedly failed to remove first edges."), + ); + + original_skeleton.insert(new_bottom_index, fake_original_new_bottom_node); + } + + let bottom = + self.update_node_in_nonempty_tree(&new_bottom_index, original_skeleton, leaf_indices); + + self.node_from_edge_data(&path_to_new_bottom, &new_bottom_index, &bottom) + } + + pub(crate) fn create_unmodified<'a>( + original_skeleton: &impl OriginalSkeletonTree<'a>, + ) -> UpdatedSkeletonTreeResult { + let original_root_node = original_skeleton + .get_nodes() + .get(&NodeIndex::ROOT) + .ok_or(UpdatedSkeletonTreeError::MissingNode(NodeIndex::ROOT))?; + let OriginalSkeletonNode::UnmodifiedSubTree(root_hash) = original_root_node else { + panic!("A root of tree without modifications is expected to be an unmodified node.") + }; + + Ok(Self { + skeleton_tree: HashMap::from([( + NodeIndex::ROOT, + UpdatedSkeletonNode::UnmodifiedSubTree(*root_hash), + )]), + }) + } +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper_test.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper_test.rs new file mode 100644 index 00000000000..a039882fe77 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/create_tree_helper_test.rs @@ -0,0 +1,519 @@ +use crate::patricia_merkle_tree::filled_tree::tree::FilledTree; +use crate::patricia_merkle_tree::internal_test_utils::MockLeaf; +use crate::patricia_merkle_tree::internal_test_utils::MockTrie; +use crate::patricia_merkle_tree::types::SortedLeafIndices; +use ethnum::{uint, U256}; +use pretty_assertions::assert_eq; +use rstest::{fixture, rstest}; +use std::collections::HashMap; +use std::sync::Arc; + +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::internal_test_utils::OriginalSkeletonMockTrieConfig; +use crate::patricia_merkle_tree::internal_test_utils::{ + as_fully_indexed, get_initial_updated_skeleton, small_tree_index_to_full, +}; +use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonNodeMap; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl; +use crate::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight}; +use crate::patricia_merkle_tree::updated_skeleton_tree::create_tree_helper::{ + get_path_to_lca, has_leaves_on_both_sides, TempSkeletonNode, +}; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; +use crate::patricia_merkle_tree::updated_skeleton_tree::{ + hash_function::TreeHashFunctionImpl, tree::UpdatedSkeletonTree, +}; +use crate::storage::map_storage::MapStorage; + +#[fixture] +fn initial_updated_skeleton( + #[default(&[])] original_skeleton: &[(NodeIndex, OriginalSkeletonNode)], + #[default(&[])] leaf_modifications: &[(NodeIndex, u8)], +) -> UpdatedSkeletonTreeImpl { + get_initial_updated_skeleton(original_skeleton, leaf_modifications) +} + +#[rstest] +#[case::small_tree_positive( + 3, 2, as_fully_indexed(subtree_height, + vec![uint!("8"),uint!("10"),uint!("11")].into_iter() + ), + true) + ] +#[case::small_tree_negative(3, 2, as_fully_indexed( + subtree_height, vec![uint!("10"),uint!("11")].into_iter()), false) + ] +#[case::large_tree_farthest_leaves( + 251, + 1, + vec![NodeIndex::FIRST_LEAF, NodeIndex::MAX], + true)] +#[case::large_tree_positive_consecutive_indices_of_different_sides( + 251, + 1, + as_fully_indexed(subtree_height, vec![ + (U256::from(3u8) << 250) - U256::ONE, U256::from(3u8) << 250 + ].into_iter() + ), + true)] +#[case::large_tree_negative_one_shift_of_positive_case( + 251, + 1, + as_fully_indexed(subtree_height, vec![ + U256::from(3u8) << 250, (U256::from(3u8) << 250) + U256::ONE + ].into_iter()), + false)] +fn test_has_leaves_on_both_sides( + #[case] subtree_height: u8, + #[case] root_index: u8, + #[case] mut leaf_indices: Vec, + #[case] expected: bool, +) { + let height = SubTreeHeight(subtree_height); + let root_index = small_tree_index_to_full(root_index.into(), height); + assert_eq!( + has_leaves_on_both_sides(&root_index, &SortedLeafIndices::new(&mut leaf_indices)), + expected + ); +} + +#[rstest] +#[case::first_leaf_not_descendant(3, 3, vec![NodeIndex::from(8), NodeIndex::from(12)])] +#[case::last_leaf_not_descendant( + 3, + 2, + as_fully_indexed(3, vec![uint!("8"), uint!("12")].into_iter()) +)] +#[should_panic(expected = "is not a descendant of the root")] +fn test_has_leaves_on_both_sides_assertions( + #[case] subtree_height: u8, + #[case] root_index: u8, + #[case] mut leaf_indices: Vec, +) { + let height = SubTreeHeight(subtree_height); + let root_index = small_tree_index_to_full(root_index.into(), height); + has_leaves_on_both_sides(&root_index, &SortedLeafIndices::new(&mut leaf_indices)); +} + +#[rstest] +#[case::small_tree_single_leaf( + 1, + vec![U256::from(8_u8)], + PathToBottom::new( U256::ZERO.into(), EdgePathLength::new(3).unwrap()).unwrap() +)] +#[case::small_tree_few_leaves( + 1, + vec![ + U256::from(12_u8), U256::from(13_u8), U256::from(14_u8) + ], + PathToBottom::new(U256::ONE.into(), EdgePathLength::ONE).unwrap() +)] +#[case::small_tree_few_leaves2( + 1, + vec![U256::from(12_u8),U256::from(13_u8)], + PathToBottom::new(2_u128.into(), EdgePathLength::new(2).unwrap()).unwrap() +)] +#[case::large_tree_positive_consecutive_indices_of_different_sides( + 1, + vec![(U256::from(3u8) << 250) - U256::ONE, U256::from(3u8) << 250], + PathToBottom::new(U256::ZERO.into(), EdgePathLength::new(0).unwrap()).unwrap())] +#[case::large_tree_positive_consecutive_indices( + 3<<126, + vec![U256::from(3u8) << 250, (U256::from(3u8) << 250)+ U256::ONE], + PathToBottom::new(U256::ZERO.into(), EdgePathLength::new(123).unwrap()).unwrap())] +fn test_get_path_to_lca( + #[case] root_index: u128, + #[case] leaf_indices: Vec, + #[case] expected: PathToBottom, +) { + let root_index = NodeIndex::new(root_index.into()); + assert_eq!( + get_path_to_lca( + &root_index, + &SortedLeafIndices::new( + &mut leaf_indices + .iter() + .map(|index: ðnum::U256| NodeIndex::new(*index)) + .collect::>()[..] + ) + ), + expected + ); +} + +#[rstest] +#[case::two_deleted_leaves( + &NodeIndex::from(1), + &TempSkeletonNode::Empty, + &TempSkeletonNode::Empty, + &[(NodeIndex::from(2),0), (NodeIndex::from(3),0)], + TempSkeletonNode::Empty, + &[] +)] +#[case::one_deleted_leaf( + &NodeIndex::from(1), + &TempSkeletonNode::Leaf, + &TempSkeletonNode::Empty, + &[(NodeIndex::from(2), 1), (NodeIndex::from(3), 0)], + TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD) + ), + &[] +)] +#[case::two_leaves( + &NodeIndex::from(5), + &TempSkeletonNode::Leaf, + &TempSkeletonNode::Leaf, + &[(NodeIndex::from(10),1), (NodeIndex::from(11),1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[] +)] +#[case::two_nodes( + &NodeIndex::from(5), + &TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[ + (NodeIndex::from(10),UpdatedSkeletonNode::Binary), + (NodeIndex::from(11), UpdatedSkeletonNode::Binary + )] +)] +#[case::deleted_left_child( + &NodeIndex::from(5), + &TempSkeletonNode::Empty, + &TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[(NodeIndex::from(20), 0)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD)), + &[(NodeIndex::from(11),UpdatedSkeletonNode::Binary)] +)] +#[case::deleted_two_children( + &NodeIndex::from(5), + &TempSkeletonNode::Empty, + &TempSkeletonNode::Empty, + &[(NodeIndex::from(20), 0), (NodeIndex::from(22), 0)], + TempSkeletonNode::Empty, + &[] +)] +#[case::left_edge_right_deleted( + &NodeIndex::from(5), + &TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD)), + &TempSkeletonNode::Empty, + &[(NodeIndex::from(22), 0)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::from("01"))), + &[] +)] +fn test_node_from_binary_data( + #[case] root_index: &NodeIndex, + #[case] left: &TempSkeletonNode, + #[case] right: &TempSkeletonNode, + #[case] _leaf_modifications: &[(NodeIndex, u8)], + #[case] expected_node: TempSkeletonNode, + #[case] expected_skeleton_additions: &[(NodeIndex, UpdatedSkeletonNode)], + #[with(&[], _leaf_modifications)] mut initial_updated_skeleton: UpdatedSkeletonTreeImpl, +) { + let mut expected_skeleton_tree = initial_updated_skeleton.skeleton_tree.clone(); + expected_skeleton_tree.extend(expected_skeleton_additions.iter().cloned()); + let temp_node = initial_updated_skeleton.node_from_binary_data(root_index, left, right); + assert_eq!(temp_node, expected_node); + assert_eq!( + initial_updated_skeleton.skeleton_tree, + expected_skeleton_tree + ); +} + +#[rstest] +#[case::to_empty( + &PathToBottom::LEFT_CHILD, + &NodeIndex::ROOT, + &TempSkeletonNode::Empty, + &[], + TempSkeletonNode::Empty, + &[], +)] +#[case::to_edge( + &PathToBottom::from("00"), + &NodeIndex::from(4), + &TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::from("11")) + ), + &[], + TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::from("0011")) + ), + &[], +)] +#[case::to_unmodified_bottom( + &PathToBottom::from("101"), + &NodeIndex::from(5), + &TempSkeletonNode::Original(OriginalSkeletonNode::UnmodifiedSubTree( + HashOutput::ZERO + )), + &[], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::from("101"))), + &[], +)] +#[case::to_binary( + &PathToBottom::RIGHT_CHILD, + &NodeIndex::from(7), + &TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[], + TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD) + ), + &[(NodeIndex::from(7), UpdatedSkeletonNode::Binary)] +)] +#[case::to_non_empty_leaf( + &PathToBottom::RIGHT_CHILD, + &NodeIndex::from(7), + &TempSkeletonNode::Leaf, + &[(NodeIndex::from(7), 1)], + TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD) + ), + &[] +)] +fn test_node_from_edge_data( + #[case] path: &PathToBottom, + #[case] bottom_index: &NodeIndex, + #[case] bottom: &TempSkeletonNode, + #[case] _leaf_modifications: &[(NodeIndex, u8)], + #[case] expected_node: TempSkeletonNode, + #[case] expected_skeleton_additions: &[(NodeIndex, UpdatedSkeletonNode)], + #[with(&[], _leaf_modifications)] mut initial_updated_skeleton: UpdatedSkeletonTreeImpl, +) { + let mut expected_skeleton_tree = initial_updated_skeleton.skeleton_tree.clone(); + expected_skeleton_tree.extend(expected_skeleton_additions.iter().cloned()); + let temp_node = initial_updated_skeleton.node_from_edge_data(path, bottom_index, bottom); + assert_eq!(temp_node, expected_node); + assert_eq!( + initial_updated_skeleton.skeleton_tree, + expected_skeleton_tree + ); +} + +#[rstest] +#[case::one_leaf( + &NodeIndex::ROOT, + &[(NodeIndex::FIRST_LEAF, 1)], + TempSkeletonNode::Original( + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(251).as_str())) + ), + &[], +)] +// Note: the root is only finalized in the outer (create) function, so it doesn't appear in the +// skeleton created in the test. +#[case::leaves_on_both_sides( + &NodeIndex::ROOT, + &[(NodeIndex::FIRST_LEAF, 1), (NodeIndex::MAX, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[ + (NodeIndex::from(2), + UpdatedSkeletonNode::Edge(PathToBottom::from("0".repeat(250).as_str()))), + (NodeIndex::from(3), + UpdatedSkeletonNode::Edge(PathToBottom::from("1".repeat(250).as_str())))], +)] +#[case::root_is_a_leaf( + &NodeIndex::FIRST_LEAF, + &[(NodeIndex::FIRST_LEAF, 1)], + TempSkeletonNode::Leaf, + &[] +)] +fn test_update_node_in_empty_tree( + #[case] root_index: &NodeIndex, + #[case] leaf_modifications: &[(NodeIndex, u8)], + #[case] expected_node: TempSkeletonNode, + #[case] expected_skeleton_additions: &[(NodeIndex, UpdatedSkeletonNode)], + #[with(&[], leaf_modifications)] mut initial_updated_skeleton: UpdatedSkeletonTreeImpl, +) { + let mut leaf_indices: Vec = + leaf_modifications.iter().map(|(index, _)| *index).collect(); + let mut expected_skeleton_tree = initial_updated_skeleton.skeleton_tree.clone(); + expected_skeleton_tree.extend(expected_skeleton_additions.iter().cloned()); + let temp_node = initial_updated_skeleton + .update_node_in_empty_tree(root_index, &SortedLeafIndices::new(&mut leaf_indices)); + assert_eq!(temp_node, expected_node); + assert_eq!( + initial_updated_skeleton.skeleton_tree, + expected_skeleton_tree + ); +} + +#[rstest] +#[case::modified_leaf( + &NodeIndex::FIRST_LEAF, + vec![ + (NodeIndex::FIRST_LEAF + 1, + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::ONE))) + ], + &[(NodeIndex::FIRST_LEAF, 1)], + TempSkeletonNode::Leaf, + &[], +)] +#[case::deleted_leaf( + &NodeIndex::FIRST_LEAF, + vec![ + (NodeIndex::FIRST_LEAF + 1, + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::ONE))) + ], + &[(NodeIndex::FIRST_LEAF, 0)], + TempSkeletonNode::Empty, + &[], +)] +#[case::orig_binary_with_modified_leaf( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF + 1, + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::ONE))), + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Binary) + ], + &[(NodeIndex::FIRST_LEAF, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[], +)] +#[case::orig_binary_with_deleted_leaf( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF + 1, + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::ONE))), + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Binary) + ], + &[(NodeIndex::FIRST_LEAF, 0)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD)), + &[], +)] +#[case::orig_binary_with_deleted_leaves( + &(NodeIndex::FIRST_LEAF >> 1), + vec![(NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Binary)], + &[(NodeIndex::FIRST_LEAF, 0), (NodeIndex::FIRST_LEAF + 1, 0)], + TempSkeletonNode::Empty, + &[], +)] +#[case::orig_binary_with_binary_modified_children( + &(NodeIndex::FIRST_LEAF >> 2), + vec![ + (NodeIndex::FIRST_LEAF >> 2, OriginalSkeletonNode::Binary), + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Binary), + ((NodeIndex::FIRST_LEAF >> 1) + 1,OriginalSkeletonNode::Binary) + ], + &[ + (NodeIndex::FIRST_LEAF, 1), + (NodeIndex::FIRST_LEAF + 1, 1), + (NodeIndex::FIRST_LEAF + 2, 1), + (NodeIndex::FIRST_LEAF + 3, 1) + ], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[ + (NodeIndex::FIRST_LEAF >> 1, UpdatedSkeletonNode::Binary), + ((NodeIndex::FIRST_LEAF >> 1) + 1, UpdatedSkeletonNode::Binary) + ], +)] +// The following cases test the `update_edge_node` function as well. +#[case::orig_edge_with_deleted_bottom( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + ], + &[(NodeIndex::FIRST_LEAF, 0)], + TempSkeletonNode::Empty, + &[], +)] +#[case::orig_edge_with_modified_bottom( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + ], + &[(NodeIndex::FIRST_LEAF, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + &[], +)] +#[case::orig_edge_with_two_modified_leaves( + &(NodeIndex::FIRST_LEAF >> 1), + vec![(NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD))], + &[(NodeIndex::FIRST_LEAF, 1), (NodeIndex::FIRST_LEAF + 1, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[ + (NodeIndex::FIRST_LEAF, UpdatedSkeletonNode::Leaf), + (NodeIndex::FIRST_LEAF + 1, UpdatedSkeletonNode::Leaf) + ], +)] +#[case::orig_edge_with_unmodified_bottom_and_added_leaf( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + (NodeIndex::FIRST_LEAF, OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::ONE))) + ], + &[(NodeIndex::FIRST_LEAF + 1, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Binary), + &[], +)] +#[case::orig_edge_with_deleted_bottom_and_added_leaf( + &(NodeIndex::FIRST_LEAF >> 1), + vec![ + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + ], + &[(NodeIndex::FIRST_LEAF, 0), (NodeIndex::FIRST_LEAF + 1, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::RIGHT_CHILD)), + &[], +)] +#[case::orig_edge_with_modified_leaves_beneath_bottom( + &(NodeIndex::FIRST_LEAF >> 2), + vec![ + (NodeIndex::FIRST_LEAF >> 2, OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + (NodeIndex::FIRST_LEAF >> 1, OriginalSkeletonNode::Binary), + ], + &[(NodeIndex::FIRST_LEAF, 1), (NodeIndex::FIRST_LEAF + 1, 1)], + TempSkeletonNode::Original(OriginalSkeletonNode::Edge(PathToBottom::LEFT_CHILD)), + &[(NodeIndex::FIRST_LEAF >> 1, UpdatedSkeletonNode::Binary)], +)] +fn test_update_node_in_nonempty_tree( + #[case] root_index: &NodeIndex, + #[case] original_skeleton: Vec<(NodeIndex, OriginalSkeletonNode)>, + #[case] leaf_modifications: &[(NodeIndex, u8)], + #[case] expected_node: TempSkeletonNode, + #[case] expected_skeleton_additions: &[(NodeIndex, UpdatedSkeletonNode)], + #[with(&original_skeleton, leaf_modifications)] + mut initial_updated_skeleton: UpdatedSkeletonTreeImpl, +) { + let mut original_skeleton: OriginalSkeletonNodeMap = original_skeleton.into_iter().collect(); + let mut leaf_indices: Vec = + leaf_modifications.iter().map(|(index, _)| *index).collect(); + let mut expected_skeleton_tree = initial_updated_skeleton.skeleton_tree.clone(); + expected_skeleton_tree.extend(expected_skeleton_additions.iter().cloned()); + let temp_node = initial_updated_skeleton.update_node_in_nonempty_tree( + root_index, + &mut original_skeleton, + &SortedLeafIndices::new(&mut leaf_indices), + ); + assert_eq!(temp_node, expected_node); + assert_eq!( + initial_updated_skeleton.skeleton_tree, + expected_skeleton_tree + ); +} + +#[rstest] +#[case::empty_tree(HashOutput::ROOT_OF_EMPTY_TREE)] +#[case::non_empty_tree(HashOutput(Felt::from(77_u128)))] +#[tokio::test] +async fn test_update_non_modified_storage_tree(#[case] root_hash: HashOutput) { + let empty_map = HashMap::new(); + let config = OriginalSkeletonMockTrieConfig::new(&empty_map, false); + let mut original_skeleton_tree = OriginalSkeletonTreeImpl::create_impl::( + &MapStorage::default(), + root_hash, + SortedLeafIndices::new(&mut []), + &config, + ) + .unwrap(); + let updated = + UpdatedSkeletonTreeImpl::create(&mut original_skeleton_tree, &HashMap::new()).unwrap(); + let filled = MockTrie::create::(Arc::new(updated), Arc::new(empty_map)) + .await + .unwrap(); + assert_eq!(root_hash, filled.get_root_hash()); +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/errors.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/errors.rs new file mode 100644 index 00000000000..ff00804db27 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/errors.rs @@ -0,0 +1,7 @@ +use crate::patricia_merkle_tree::types::NodeIndex; + +#[derive(Debug, thiserror::Error)] +pub enum UpdatedSkeletonTreeError { + #[error("Missing node at index {0:?}.")] + MissingNode(NodeIndex), +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function.rs new file mode 100644 index 00000000000..ad00cd46d89 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function.rs @@ -0,0 +1,145 @@ +use starknet_types_core::hash::{Pedersen, Poseidon, StarkHash}; + +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use crate::patricia_merkle_tree::node_data::inner_node::{ + BinaryData, EdgeData, NodeData, PathToBottom, +}; +use crate::patricia_merkle_tree::node_data::leaf::{ContractState, Leaf}; + +#[cfg(test)] +#[path = "hash_function_test.rs"] +pub mod hash_function_test; + +/// Trait for hash functions. +pub(crate) trait HashFunction { + /// Computes the hash of the given input. + fn hash(left: &Felt, right: &Felt) -> HashOutput; +} + +/// Implementation of HashFunction for Pedersen hash function. +pub struct PedersenHashFunction; +impl HashFunction for PedersenHashFunction { + fn hash(left: &Felt, right: &Felt) -> HashOutput { + HashOutput(Felt(Pedersen::hash(&left.0, &right.0))) + } +} + +/// Implementation of HashFunction for Poseidon hash function. +pub struct PoseidonHashFunction; +impl HashFunction for PoseidonHashFunction { + fn hash(left: &Felt, right: &Felt) -> HashOutput { + HashOutput(Felt(Poseidon::hash(&left.0, &right.0))) + } +} + +pub(crate) trait TreeHashFunction { + /// Computes the hash of the given leaf. + fn compute_leaf_hash(leaf_data: &L) -> HashOutput; + + /// Computes the hash for the given node data. + fn compute_node_hash(node_data: &NodeData) -> HashOutput; + + /// The default implementation for internal nodes is based on the following reference: + /// https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/starknet-state/#trie_construction + fn compute_node_hash_with_inner_hash_function( + node_data: &NodeData, + ) -> HashOutput { + match node_data { + NodeData::Binary(BinaryData { + left_hash, + right_hash, + }) => H::hash(&left_hash.0, &right_hash.0), + NodeData::Edge(EdgeData { + bottom_hash: hash_output, + path_to_bottom: PathToBottom { path, length, .. }, + }) => HashOutput(H::hash(&hash_output.0, &Felt::from(path)).0 + Felt::from(*length)), + NodeData::Leaf(leaf_data) => Self::compute_leaf_hash(leaf_data), + } + } +} + +pub struct TreeHashFunctionImpl; + +impl TreeHashFunctionImpl { + // TODO(Aner, 11/4/24): Verify the correctness of the implementation. + pub const CONTRACT_STATE_HASH_VERSION: Felt = Felt::ZERO; + + // The hex string corresponding to b'CONTRACT_CLASS_LEAF_V0' in big-endian. + pub const CONTRACT_CLASS_LEAF_V0: &'static str = + "0x434f4e54524143545f434c4153535f4c4541465f5630"; +} + +/// Implementation of TreeHashFunction for contracts trie. +/// The implementation is based on the following reference: +/// https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/starknet-state/#trie_construction +impl TreeHashFunction for TreeHashFunctionImpl { + fn compute_leaf_hash(contract_state: &ContractState) -> HashOutput { + HashOutput( + Pedersen::hash( + &Pedersen::hash( + &Pedersen::hash( + &contract_state.class_hash.0.into(), + &contract_state.storage_root_hash.0.into(), + ), + &contract_state.nonce.0.into(), + ), + &Self::CONTRACT_STATE_HASH_VERSION.into(), + ) + .into(), + ) + } + fn compute_node_hash(node_data: &NodeData) -> HashOutput { + Self::compute_node_hash_with_inner_hash_function::(node_data) + } +} + +/// Implementation of TreeHashFunction for the classes trie. +/// The implementation is based on the following reference: +/// https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/starknet-state/#trie_construction +impl TreeHashFunction for TreeHashFunctionImpl { + fn compute_leaf_hash(compiled_class_hash: &CompiledClassHash) -> HashOutput { + let contract_class_leaf_version: Felt = Felt::from_hex(Self::CONTRACT_CLASS_LEAF_V0) + .expect( + "could not parse hex string corresponding to b'CONTRACT_CLASS_LEAF_V0' to Felt", + ); + HashOutput( + Poseidon::hash( + &contract_class_leaf_version.into(), + &compiled_class_hash.0.into(), + ) + .into(), + ) + } + fn compute_node_hash(node_data: &NodeData) -> HashOutput { + Self::compute_node_hash_with_inner_hash_function::(node_data) + } +} + +/// Implementation of TreeHashFunction for the storage trie. +/// The implementation is based on the following reference: +/// https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/starknet-state/#trie_construction +impl TreeHashFunction for TreeHashFunctionImpl { + fn compute_leaf_hash(storage_value: &StarknetStorageValue) -> HashOutput { + HashOutput(storage_value.0) + } + fn compute_node_hash(node_data: &NodeData) -> HashOutput { + Self::compute_node_hash_with_inner_hash_function::(node_data) + } +} + +/// Combined trait for all specific implementations. +pub(crate) trait ForestHashFunction: + TreeHashFunction + + TreeHashFunction + + TreeHashFunction +{ +} +impl ForestHashFunction for T where + T: TreeHashFunction + + TreeHashFunction + + TreeHashFunction +{ +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function_test.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function_test.rs new file mode 100644 index 00000000000..8b80da1a318 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/hash_function_test.rs @@ -0,0 +1,136 @@ +use crate::block_committer::input::StarknetStorageValue; +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::filled_tree::node::Nonce; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash}; +use crate::patricia_merkle_tree::node_data::inner_node::{ + BinaryData, EdgeData, EdgePathLength, NodeData, PathToBottom, +}; +use crate::patricia_merkle_tree::node_data::leaf::ContractState; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::{ + TreeHashFunction, TreeHashFunctionImpl, +}; +use rstest::rstest; +use starknet_types_core::hash::{Pedersen, StarkHash}; + +#[rstest] +#[case(Felt::ONE, Felt::TWO, Felt::from_hex("0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026").unwrap())] +#[case(Felt::from(0xBE_u128), Felt::from(0xA0BEE_u128), Felt::from_hex("0x4e8f149d7d5adb77a8c85b631a3acb6fb9aa5ecb06ea4ec105753629243e380").unwrap())] +#[case(Felt::from(0x1234_u128), Felt::from(0xABCD_u128), Felt::from_hex("0x615bb8d47888d2987ad0c63fc06e9e771930986a4dd8adc55617febfcf3639e").unwrap())] +fn test_tree_hash_function_impl_binary_node( + #[case] left_hash: Felt, + #[case] right_hash: Felt, + #[case] expected_hash: Felt, +) { + let hash_output = TreeHashFunctionImpl::compute_node_hash( + &NodeData::::Binary(BinaryData { + left_hash: HashOutput(left_hash), + right_hash: HashOutput(right_hash), + }), + ); + assert_eq!( + hash_output, + HashOutput(Pedersen::hash(&left_hash.into(), &right_hash.into()).into()) + ); + assert_eq!(hash_output, HashOutput(expected_hash)); +} + +#[rstest] +#[case(Felt::ONE, 2_u128, 3, Felt::from_hex("0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58029").unwrap())] +#[case(Felt::from(0xBE_u128), 0xA0BEE_u128, 0xBB, Felt::from_hex("0x4e8f149d7d5adb77a8c85b631a3acb6fb9aa5ecb06ea4ec105753629243e43b").unwrap())] +#[case(Felt::from(0x1234ABCD_u128),42_u128,6, Felt::from_hex("0x1d937094c09b5f8e26a662d21911871e3cbc6858d55cc49af9848ea6fed4e9").unwrap())] +fn test_tree_hash_function_impl_edge_node( + #[case] bottom_hash: Felt, + #[case] edge_path: u128, + #[case] length: u8, + #[case] expected_hash: Felt, +) { + let hash_output = TreeHashFunctionImpl::compute_node_hash( + &NodeData::::Edge(EdgeData { + bottom_hash: HashOutput(bottom_hash), + path_to_bottom: PathToBottom::new( + edge_path.into(), + EdgePathLength::new(length).unwrap(), + ) + .unwrap(), + }), + ); + let direct_hash_computation = HashOutput( + Felt::from(Pedersen::hash(&bottom_hash.into(), &edge_path.into())) + length.into(), + ); + assert_eq!(hash_output, HashOutput(expected_hash)); + assert_eq!(hash_output, direct_hash_computation); +} + +#[rstest] +fn test_constant_contract_class_leaf_v0() { + assert_eq!( + hex::decode(TreeHashFunctionImpl::CONTRACT_CLASS_LEAF_V0.trim_start_matches("0x")).unwrap(), + b"CONTRACT_CLASS_LEAF_V0".as_slice() + ); +} + +#[rstest] +// Random StateTreeTuples and the expected hash results were generated and computed elsewhere. +#[case( + NodeData::Leaf( + ContractState { + class_hash: ClassHash(Felt::from_hex("0x150917f3bba17e3c0be685981d6cf8874098a857f354d374688e76eb69f44ab").unwrap()), + storage_root_hash: HashOutput(Felt::from_hex("0x5d6b3a46ac855f3cea9af60e13cc6c81bf237b901f49f73981a521d4cb6c50c").unwrap()), + nonce: Nonce(Felt::from_hex("0x38").unwrap()) + + } + ), + Felt::from_hex("0x3f27688d56740e5e238acde5b408154563c4f6e05514b8029e86ad51c388f8b").unwrap() +)] +#[case( + NodeData::Leaf( + ContractState{ + class_hash: ClassHash(Felt::from_hex("0x2c9982b9bd36f16e409c98616e43dbc9e4b47db8a8e8edc3b915bc4dab3c61c").unwrap()), + storage_root_hash: HashOutput(Felt::from_hex("0x63d7c2a04df01e361238cf4bf07b7cee2e3c5ee58b4ec37cf279aed9ac8d013").unwrap()), + nonce: Nonce(Felt::from_hex("0x1b").unwrap()) + } + ), + Felt::from_hex("0x26e95377fcfa70a9882dc08653b7dc77165befe23971aa2fa5b926ff81af6cc").unwrap() +)] +#[case( + NodeData::Leaf( + ContractState{ + class_hash: ClassHash(Felt::from_hex("0x314bd50b446c4e8c3a82b0eb9326e532432fbd925ab7afea236f7f8618848a2").unwrap()), + storage_root_hash: HashOutput(Felt::from_hex("0x1118159298289b372808e6b008b6bc9d68f5ebc060962ea1331fdc70cf3d047").unwrap()), + nonce: Nonce(Felt::from_hex("0x47").unwrap()) + } + ), + Felt::from_hex("0x1b20bbb35009bf03f86fb092b56a9c44deedbcca6addf8f7640f54a48ba5bbc").unwrap() +)] +fn test_tree_hash_function_contract_state_leaf( + #[case] node_data: NodeData, + #[case] expected_hash: Felt, +) { + let hash_output = TreeHashFunctionImpl::compute_node_hash(&node_data); + assert_eq!(hash_output, HashOutput(expected_hash)); +} + +#[rstest] +#[case( + NodeData::Leaf(CompiledClassHash(Felt::from_hex("0xACDC").unwrap())), + Felt::from_hex("0x49ed9a06987e7e55770d6c4d7d16b819ad984bf4aed552042847380cc31210d").unwrap() +)] +fn test_tree_hash_function_compiled_class_hash_leaf( + #[case] node_data: NodeData, + #[case] expected_hash: Felt, +) { + let hash_output = TreeHashFunctionImpl::compute_node_hash(&node_data); + assert_eq!(hash_output, HashOutput(expected_hash)); +} + +#[rstest] +// Expected hash value was computed independently. +#[case(NodeData::Leaf(StarknetStorageValue(Felt::from_hex("0xDEAFBEEF").unwrap())), Felt::from_hex("0xDEAFBEEF").unwrap())] +fn test_tree_hash_function_storage_leaf( + #[case] node_data: NodeData, + #[case] expected_hash: Felt, +) { + let hash_output = TreeHashFunctionImpl::compute_node_hash(&node_data); + assert_eq!(hash_output, HashOutput(expected_hash)); +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/node.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/node.rs new file mode 100644 index 00000000000..0789412f04d --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/node.rs @@ -0,0 +1,12 @@ +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::node_data::inner_node::PathToBottom; + +/// A node in the structure of a Patricia-Merkle tree, after the update. +#[derive(Debug, Clone, PartialEq)] +pub(crate) enum UpdatedSkeletonNode { + Binary, + Edge(PathToBottom), + // Represents a root of a subtree where none of it's descendants has changed. + UnmodifiedSubTree(HashOutput), + Leaf, +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/skeleton_forest.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/skeleton_forest.rs new file mode 100644 index 00000000000..3875f99177f --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/skeleton_forest.rs @@ -0,0 +1,100 @@ +use std::collections::HashMap; + +use crate::block_committer::input::ContractAddress; +use crate::felt::Felt; +use crate::forest_errors::{ForestError, ForestResult}; +use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, Nonce}; +use crate::patricia_merkle_tree::node_data::leaf::{ + ContractState, LeafModifications, SkeletonLeaf, +}; +use crate::patricia_merkle_tree::original_skeleton_tree::skeleton_forest::OriginalSkeletonForest; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTree; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; + +pub(crate) struct UpdatedSkeletonForest { + pub(crate) classes_trie: UpdatedSkeletonTreeImpl, + pub(crate) contracts_trie: UpdatedSkeletonTreeImpl, + pub(crate) storage_tries: HashMap, +} + +impl UpdatedSkeletonForest { + pub(crate) fn create( + original_skeleton_forest: &mut OriginalSkeletonForest<'_>, + class_hash_leaf_modifications: &LeafModifications, + storage_updates: &HashMap>, + original_contracts_trie_leaves: &HashMap, + address_to_class_hash: &HashMap, + address_to_nonce: &HashMap, + ) -> ForestResult + where + Self: std::marker::Sized, + { + // Classes trie. + let classes_trie = UpdatedSkeletonTreeImpl::create( + &mut original_skeleton_forest.classes_trie, + class_hash_leaf_modifications, + )?; + + // Storage tries. + let mut contracts_trie_leaves = HashMap::new(); + let mut storage_tries = HashMap::new(); + + for (address, updates) in storage_updates { + let original_storage_trie = original_skeleton_forest + .storage_tries + .get_mut(address) + .ok_or(ForestError::MissingOriginalSkeleton(*address))?; + + let updated_storage_trie = + UpdatedSkeletonTreeImpl::create(original_storage_trie, updates)?; + let storage_trie_becomes_empty = updated_storage_trie.is_empty(); + + storage_tries.insert(*address, updated_storage_trie); + + let current_leaf = original_contracts_trie_leaves + .get(&NodeIndex::from_contract_address(address)) + .ok_or(ForestError::MissingContractCurrentState(*address))?; + + let skeleton_leaf = Self::updated_contract_skeleton_leaf( + address_to_nonce.get(address), + address_to_class_hash.get(address), + current_leaf, + storage_trie_becomes_empty, + ); + contracts_trie_leaves.insert(NodeIndex::from_contract_address(address), skeleton_leaf); + } + + // Contracts trie. + let contracts_trie = UpdatedSkeletonTreeImpl::create( + &mut original_skeleton_forest.contracts_trie, + &contracts_trie_leaves, + )?; + + Ok(Self { + classes_trie, + contracts_trie, + storage_tries, + }) + } + + /// Given the previous contract state, whether the contract's storage has become empty or not, + /// optional new nonce & new class hash, the function creates a skeleton leaf. + fn updated_contract_skeleton_leaf( + new_nonce: Option<&Nonce>, + new_class_hash: Option<&ClassHash>, + previous_state: &ContractState, + storage_becomes_empty: bool, + ) -> SkeletonLeaf { + let actual_new_nonce = new_nonce.unwrap_or(&previous_state.nonce); + let actual_new_class_hash = new_class_hash.unwrap_or(&previous_state.class_hash); + if storage_becomes_empty + && actual_new_nonce.0 == Felt::ZERO + && actual_new_class_hash.0 == Felt::ZERO + { + SkeletonLeaf::Zero + } else { + SkeletonLeaf::NonZero + } + } +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree.rs new file mode 100644 index 00000000000..5e41f085da9 --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree.rs @@ -0,0 +1,116 @@ +use std::collections::HashMap; + +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::node_data::leaf::{LeafModifications, SkeletonLeaf}; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTree; +use crate::patricia_merkle_tree::types::NodeIndex; +use crate::patricia_merkle_tree::updated_skeleton_tree::create_tree_helper::TempSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::errors::UpdatedSkeletonTreeError; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; + +#[cfg(test)] +#[path = "tree_test.rs"] +pub mod tree_test; + +pub(crate) type UpdatedSkeletonNodeMap = HashMap; +pub(crate) type UpdatedSkeletonTreeResult = Result; + +/// Consider a Patricia-Merkle Tree which has been updated with new leaves. +/// This trait represents the structure of the subtree which was modified in the update. +/// It also contains the hashes of the unmodified nodes on the Merkle paths from the updated leaves +/// to the root. +pub(crate) trait UpdatedSkeletonTree<'a>: Sized + Send + Sync { + /// Creates an updated tree from an original tree and modifications. + fn create( + original_skeleton: &mut impl OriginalSkeletonTree<'a>, + leaf_modifications: &LeafModifications, + ) -> UpdatedSkeletonTreeResult; + + /// Does the skeleton represents an empty-tree (i.e. all leaves are empty). + fn is_empty(&self) -> bool; + + /// Returns an iterator over all (node index, node) pairs in the tree. + fn get_nodes(&self) -> impl Iterator; + + /// Returns the node with the given index. + fn get_node(&self, index: NodeIndex) -> UpdatedSkeletonTreeResult<&UpdatedSkeletonNode>; +} +// TODO(Dori, 1/7/2024): Make this a tuple struct. +pub(crate) struct UpdatedSkeletonTreeImpl { + pub(crate) skeleton_tree: UpdatedSkeletonNodeMap, +} + +impl<'a> UpdatedSkeletonTree<'a> for UpdatedSkeletonTreeImpl { + fn create( + original_skeleton: &mut impl OriginalSkeletonTree<'a>, + leaf_modifications: &LeafModifications, + ) -> UpdatedSkeletonTreeResult { + if leaf_modifications.is_empty() { + return Self::create_unmodified(original_skeleton); + } + let skeleton_tree = Self::finalize_bottom_layer(original_skeleton, leaf_modifications); + + let mut updated_skeleton_tree = UpdatedSkeletonTreeImpl { skeleton_tree }; + + let temp_root_node = updated_skeleton_tree.finalize_middle_layers(original_skeleton); + // Finalize root. + match temp_root_node { + TempSkeletonNode::Empty => assert!(updated_skeleton_tree.skeleton_tree.is_empty()), + TempSkeletonNode::Leaf => { + unreachable!("Root node cannot be a leaf") + } + TempSkeletonNode::Original(original_skeleton_node) => { + let new_node = match original_skeleton_node { + OriginalSkeletonNode::Binary => UpdatedSkeletonNode::Binary, + OriginalSkeletonNode::Edge(path_to_bottom) => { + UpdatedSkeletonNode::Edge(path_to_bottom) + } + OriginalSkeletonNode::UnmodifiedSubTree(_) => { + unreachable!( + "Root node cannot be unmodified when there are some modifications." + ) + } + }; + + updated_skeleton_tree + .skeleton_tree + .insert(NodeIndex::ROOT, new_node) + .map_or((), |_| { + panic!("Root node already exists in the updated skeleton tree") + }) + } + }; + Ok(updated_skeleton_tree) + } + + fn is_empty(&self) -> bool { + // An updated skeleton tree is empty in two cases: + // (i) The inner map is empty. + // (ii)The root is considered as unmodified with a hash of an empty tree. + let is_map_empty = self.skeleton_tree.is_empty(); + match self.skeleton_tree.get(&NodeIndex::ROOT) { + Some(UpdatedSkeletonNode::UnmodifiedSubTree(root_hash)) => { + *root_hash == HashOutput::ROOT_OF_EMPTY_TREE + } + Some(_modified_root) => false, + None => { + assert!(is_map_empty, "Non-empty tree must have a root node."); + true + } + } + } + + fn get_node(&self, index: NodeIndex) -> UpdatedSkeletonTreeResult<&UpdatedSkeletonNode> { + match self.skeleton_tree.get(&index) { + Some(node) => Ok(node), + None => Err(UpdatedSkeletonTreeError::MissingNode(index)), + } + } + + fn get_nodes(&self) -> impl Iterator { + self.skeleton_tree + .iter() + .map(|(index, node)| (*index, node.clone())) + } +} diff --git a/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree_test.rs b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree_test.rs new file mode 100644 index 00000000000..fc2f1654dbe --- /dev/null +++ b/crates/committer/src/patricia_merkle_tree/updated_skeleton_tree/tree_test.rs @@ -0,0 +1,166 @@ +use std::collections::HashMap; + +use rstest::{fixture, rstest}; + +use crate::felt::Felt; +use crate::hash::hash_trait::HashOutput; +use crate::patricia_merkle_tree::internal_test_utils::OriginalSkeletonMockTrieConfig; +use crate::patricia_merkle_tree::internal_test_utils::{get_initial_updated_skeleton, MockLeaf}; +use crate::patricia_merkle_tree::node_data::inner_node::PathToBottom; +use crate::patricia_merkle_tree::node_data::leaf::{LeafModifications, SkeletonLeaf}; +use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; +use crate::patricia_merkle_tree::original_skeleton_tree::tree::{ + OriginalSkeletonTree, OriginalSkeletonTreeImpl, +}; +use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices, SubTreeHeight}; +use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; +use crate::patricia_merkle_tree::updated_skeleton_tree::tree::{ + UpdatedSkeletonTree, UpdatedSkeletonTreeImpl, +}; +use crate::storage::map_storage::MapStorage; + +#[allow(clippy::as_conversions)] +const TREE_HEIGHT: usize = SubTreeHeight::ACTUAL_HEIGHT.0 as usize; + +#[fixture] +fn initial_updated_skeleton( + #[default(&[])] original_skeleton: &[(NodeIndex, OriginalSkeletonNode)], + #[default(&[])] leaf_modifications: &[(NodeIndex, u8)], +) -> UpdatedSkeletonTreeImpl { + get_initial_updated_skeleton(original_skeleton, leaf_modifications) +} + +#[rstest] +#[case::empty_to_empty_illegal_modifications(&[], &[(NodeIndex::FIRST_LEAF, 0)], &[])] +#[case::empty_to_edge( + &[], + &[(NodeIndex::FIRST_LEAF, 1)], + &[ + (NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str()))) + ], +)] +#[case::empty_to_binary( + &[], + &[(NodeIndex::FIRST_LEAF, 1), (NodeIndex::FIRST_LEAF + 1, 1)], + &([ + (NodeIndex::FIRST_LEAF >> 1, UpdatedSkeletonNode::Binary), + (NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT - 1).as_str()))), + ]), +)] +#[case::nonempty_to_empty_tree( + &[ + (NodeIndex::ROOT, + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str()))) + ], + &[(NodeIndex::FIRST_LEAF, 0)], + &[] +)] +#[case::non_empty_to_binary( + &[ + (NodeIndex::ROOT, + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str())), + )], + &[ + (NodeIndex::FIRST_LEAF, 1), + (NodeIndex::FIRST_LEAF + 1, 1) + ], + &[ + ( + NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT - 1).as_str())) + ), + (NodeIndex::FIRST_LEAF >> 1, UpdatedSkeletonNode::Binary) + ] +)] +#[case::non_empty_replace_edge_bottom( + &[ + (NodeIndex::ROOT, + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str())), + )], + &[ + (NodeIndex::FIRST_LEAF, 0), + (NodeIndex::FIRST_LEAF + 1, 1) + ], + &[ + (NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from(("0".repeat(TREE_HEIGHT - 1) + "1").as_str()))) + ] +)] +#[case::fake_modification( + &[ + (NodeIndex::ROOT, + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str())), + )], + &[ + (NodeIndex::FIRST_LEAF, 1), + ], + &[ + (NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from(("0".repeat(TREE_HEIGHT)).as_str()))) + ] +)] +#[case::fake_deletion( + &[ + (NodeIndex::ROOT, + OriginalSkeletonNode::Edge(PathToBottom::from("0".repeat(TREE_HEIGHT).as_str()))), + (NodeIndex::FIRST_LEAF, + OriginalSkeletonNode::UnmodifiedSubTree(HashOutput(Felt::from(1_u8)))) + ], + &[ + (NodeIndex::FIRST_LEAF + 1, 0), + ], + &[ + (NodeIndex::ROOT, + UpdatedSkeletonNode::Edge(PathToBottom::from(("0".repeat(TREE_HEIGHT)).as_str()))) + ] +)] +fn test_updated_skeleton_tree_impl_create( + #[case] original_skeleton: &[(NodeIndex, OriginalSkeletonNode)], + #[case] leaf_modifications: &[(NodeIndex, u8)], + #[case] expected_skeleton_additions: &[(NodeIndex, UpdatedSkeletonNode)], + #[with(original_skeleton, leaf_modifications)] + initial_updated_skeleton: UpdatedSkeletonTreeImpl, +) { + let leaf_modifications: LeafModifications = leaf_modifications + .iter() + .map(|(index, val)| (*index, (*val).into())) + .collect(); + let mut leaf_indices: Vec = leaf_modifications.keys().copied().collect(); + let sorted_leaf_indices = SortedLeafIndices::new(&mut leaf_indices); + let mut original_skeleton = OriginalSkeletonTreeImpl { + nodes: original_skeleton.iter().cloned().collect(), + sorted_leaf_indices, + }; + let updated_skeleton_tree = + UpdatedSkeletonTreeImpl::create(&mut original_skeleton, &leaf_modifications).unwrap(); + + let mut expected_skeleton_tree = initial_updated_skeleton.skeleton_tree.clone(); + expected_skeleton_tree.extend(expected_skeleton_additions.iter().cloned()); + + assert_eq!(updated_skeleton_tree.skeleton_tree, expected_skeleton_tree); +} + +#[rstest] +#[case::empty_modifications(HashMap::new())] +#[case::non_empty_modifications(HashMap::from([(NodeIndex::FIRST_LEAF + NodeIndex::from(7), MockLeaf::default())]))] +fn test_updated_empty_tree(#[case] modifications: LeafModifications) { + let storage: MapStorage = HashMap::new().into(); + let mut indices: Vec = modifications.keys().copied().collect(); + let mut original_skeleton = OriginalSkeletonTreeImpl::create( + &storage, + HashOutput::ROOT_OF_EMPTY_TREE, + SortedLeafIndices::new(&mut indices), + &OriginalSkeletonMockTrieConfig::new(&modifications, false), + ) + .unwrap(); + + let skeleton_modifications = modifications + .into_iter() + .map(|(idx, leaf)| (idx, leaf.0.into())) + .collect(); + let updated_skeleton_tree = + UpdatedSkeletonTreeImpl::create(&mut original_skeleton, &skeleton_modifications).unwrap(); + assert!(updated_skeleton_tree.is_empty()); +} diff --git a/crates/committer/src/storage.rs b/crates/committer/src/storage.rs new file mode 100644 index 00000000000..2a7f1a9eaf9 --- /dev/null +++ b/crates/committer/src/storage.rs @@ -0,0 +1,4 @@ +pub mod db_object; +pub mod errors; +pub mod map_storage; +pub mod storage_trait; diff --git a/crates/committer/src/storage/db_object.rs b/crates/committer/src/storage/db_object.rs new file mode 100644 index 00000000000..882266b6c60 --- /dev/null +++ b/crates/committer/src/storage/db_object.rs @@ -0,0 +1,25 @@ +use crate::storage::errors::DeserializationError; +use crate::storage::storage_trait::{StorageKey, StorageValue}; + +pub trait DBObject { + /// Serializes the given value. + fn serialize(&self) -> StorageValue; + + //TODO(Aviv, 17/07/2024): Define a trait `T` for storage prefix and return `impl T` here. + /// Returns the storage key prefix of the DB object. + fn get_prefix(&self) -> Vec; + + /// Returns a `StorageKey` from a prefix and a suffix. + fn get_db_key(&self, suffix: &[u8]) -> StorageKey { + StorageKey([self.get_prefix(), b":".to_vec(), suffix.to_vec()].concat()) + } +} + +pub trait Deserializable: Sized { + /// Deserializes the given value. + fn deserialize(value: &StorageValue) -> Result; + + //TODO(Aviv, 17/07/2024): Define a trait `T` for storage prefix and return `impl T` here. + /// The prefix used to store in DB. + fn prefix() -> Vec; +} diff --git a/crates/committer/src/storage/errors.rs b/crates/committer/src/storage/errors.rs new file mode 100644 index 00000000000..7ab56ebcbe2 --- /dev/null +++ b/crates/committer/src/storage/errors.rs @@ -0,0 +1,41 @@ +use crate::patricia_merkle_tree::node_data::errors::{EdgePathError, PathToBottomError}; +use crate::storage::storage_trait::StorageKey; + +use serde_json; +use starknet_types_core::felt::FromStrError; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum StorageError { + #[error("The key {0:?} does not exist in storage.")] + MissingKey(StorageKey), +} + +#[derive(thiserror::Error, Debug)] +pub enum SerializationError { + #[error("Serialize error: {0}")] + SerializeError(#[from] serde_json::Error), +} + +#[derive(thiserror::Error, Debug)] +pub enum DeserializationError { + #[error("There is a key duplicate at {0} mapping.")] + KeyDuplicate(String), + #[error("The key {0} unexpectedly doesn't exist.")] + NonExistingKey(String), + #[error(transparent)] + ParsingError(#[from] serde_json::Error), + #[error(transparent)] + EdgePathError(#[from] EdgePathError), + #[error(transparent)] + PathToBottomError(#[from] PathToBottomError), + #[error("Unexpected prefix ({0:?}) variant when deserializing a leaf.")] + // TODO(Aviv, 17/07/2024): Define a trait `T` for storage prefix and return `impl T` here. + LeafPrefixError(Vec), + #[error(transparent)] + StringConversionError(#[from] std::str::Utf8Error), + #[error(transparent)] + FeltParsingError(#[from] FromStrError), + #[error("Encountered an invalid type when deserializing a leaf.")] + LeafTypeError, +} diff --git a/crates/committer/src/storage/map_storage.rs b/crates/committer/src/storage/map_storage.rs new file mode 100644 index 00000000000..4c35d547b60 --- /dev/null +++ b/crates/committer/src/storage/map_storage.rs @@ -0,0 +1,38 @@ +use std::collections::HashMap; + +use crate::storage::storage_trait::{Storage, StorageKey, StorageValue}; +use serde::Serialize; + +#[derive(Serialize, Debug, Default)] +#[cfg_attr(any(test, feature = "testing"), derive(Clone))] +pub struct MapStorage { + pub storage: HashMap, +} + +impl Storage for MapStorage { + fn get(&self, key: &StorageKey) -> Option<&StorageValue> { + self.storage.get(key) + } + + fn set(&mut self, key: StorageKey, value: StorageValue) -> Option { + self.storage.insert(key, value) + } + + fn mget(&self, keys: &[StorageKey]) -> Vec> { + keys.iter().map(|key| self.get(key)).collect::>() + } + + fn mset(&mut self, key_to_value: HashMap) { + self.storage.extend(key_to_value); + } + + fn delete(&mut self, key: &StorageKey) -> Option { + self.storage.remove(key) + } +} + +impl From> for MapStorage { + fn from(storage: HashMap) -> Self { + Self { storage } + } +} diff --git a/crates/committer/src/storage/storage_trait.rs b/crates/committer/src/storage/storage_trait.rs new file mode 100644 index 00000000000..29d87a35758 --- /dev/null +++ b/crates/committer/src/storage/storage_trait.rs @@ -0,0 +1,82 @@ +use serde::{Serialize, Serializer}; + +use crate::felt::Felt; +use std::collections::HashMap; + +#[derive(Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "testing"), derive(Clone))] +pub struct StorageKey(pub Vec); + +#[derive(Debug, Eq, PartialEq, Serialize)] +#[cfg_attr(any(test, feature = "testing"), derive(Clone))] +pub struct StorageValue(pub Vec); + +pub trait Storage: From> { + /// Returns value from storage, if it exists. + fn get(&self, key: &StorageKey) -> Option<&StorageValue>; + + /// Sets value in storage. If key already exists, its value is overwritten and the old value is + /// returned. + fn set(&mut self, key: StorageKey, value: StorageValue) -> Option; + + /// Returns values from storage in same order of given keys. Value is None for keys that do not + /// exist. + fn mget(&self, keys: &[StorageKey]) -> Vec>; + + /// Sets values in storage. + fn mset(&mut self, key_to_value: HashMap); + + /// Deletes value from storage and returns its value if it exists. Returns None if not. + fn delete(&mut self, key: &StorageKey) -> Option; +} + +// TODO(Aviv, 17/07/2024); Split between Storage prefix representation (trait) and node +// specific implementation (enum). +#[derive(Clone, Debug)] +pub enum StarknetPrefix { + InnerNode, + StorageLeaf, + StateTreeLeaf, + CompiledClassLeaf, +} + +/// Describes a storage prefix as used in Aerospike DB. +impl StarknetPrefix { + pub(crate) fn to_bytes(&self) -> &'static [u8] { + match self { + Self::InnerNode => b"patricia_node", + Self::StorageLeaf => b"starknet_storage_leaf", + Self::StateTreeLeaf => b"contract_state", + Self::CompiledClassLeaf => b"contract_class_leaf", + } + } + + pub(crate) fn to_storage_prefix(&self) -> Vec { + self.to_bytes().to_vec() + } +} + +impl From for StorageKey { + fn from(value: Felt) -> Self { + StorageKey(value.to_bytes_be().to_vec()) + } +} + +/// To send storage to Python storage, it is necessary to serialize it. +impl Serialize for StorageKey { + /// Serializes `StorageKey` to hexadecimal string representation. + /// Needed since serde's Serialize derive attribute only works on + /// HashMaps with String keys. + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Convert Vec to hexadecimal string representation and serialize it. + serializer.serialize_str(&hex::encode(&self.0)) + } +} + +/// Returns a `StorageKey` from a prefix and a suffix. +pub(crate) fn create_db_key(prefix: Vec, suffix: &[u8]) -> StorageKey { + StorageKey([prefix, b":".to_vec(), suffix.to_vec()].concat()) +} diff --git a/crates/committer_cli/BUILD b/crates/committer_cli/BUILD new file mode 100644 index 00000000000..3b5d6c45ba5 --- /dev/null +++ b/crates/committer_cli/BUILD @@ -0,0 +1,12 @@ +# To be used together with a bazel WORKSPACE file that contains the following definitions. +load("@committer_crate//:defs.bzl", "all_crate_deps") +load("@rules_rust//rust:defs.bzl", "rust_binary") + +rust_binary( + name="committer_exe", + srcs=glob(["src/**/*.rs"]), + visibility=["//visibility:public"], + deps=all_crate_deps(), + proc_macro_deps=all_crate_deps(proc_macro=True), + edition="2021", +) diff --git a/crates/committer_cli/Cargo.toml b/crates/committer_cli/Cargo.toml new file mode 100644 index 00000000000..47da4b0ed82 --- /dev/null +++ b/crates/committer_cli/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "committer_cli" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Cli for the committer package." + +[lints] +workspace = true + +[dev-dependencies] +criterion = { workspace = true, features = ["html_reports"] } +pretty_assertions.workspace = true + +[dependencies] +clap.workspace = true +committer = { path = "../committer", features = ["testing"] } +derive_more.workspace = true +ethnum.workspace = true +hex.workspace = true +indexmap.workspace = true +log.workspace = true +rand.workspace = true +rand_distr.workspace = true +serde.workspace = true +serde_json.workspace = true +serde_repr.workspace = true +simplelog.workspace = true +starknet-types-core.workspace = true +starknet_api.workspace = true +strum.workspace = true +strum_macros.workspace = true +thiserror.workspace = true +tokio.workspace = true + +[[bench]] +harness = false +name = "committer_bench" +path = "benches/committer_bench.rs" + +# Optional dependencies required for tests and the testing feature. +# See [here](https://github.com/bnjbvr/cargo-machete/issues/128). +[package.metadata.cargo-machete] +ignored = ["hex", "strum_macros"] diff --git a/crates/committer_cli/benches/bench_split_and_prepare_post.sh b/crates/committer_cli/benches/bench_split_and_prepare_post.sh new file mode 100644 index 00000000000..5ff1faedfc3 --- /dev/null +++ b/crates/committer_cli/benches/bench_split_and_prepare_post.sh @@ -0,0 +1,26 @@ +#!/bin/env bash + +set -e + +benchmarks_list=${1} +benchmark_results=${2} +# Benchmark the new code, splitting the benchmarks +# TODO: split the output file instead. +cat ${benchmarks_list} | + while read line; do + cargo bench $line > ${line}.txt; + sed -i '/'"${line}"'/,$!d' ${line}.txt; + done + +# Prepare the results for posting comment. +echo "Benchmark movements:" > ${benchmark_results} +cat ${benchmarks_list} | + while read line; do + if grep -q "regressed" ${line}.txt; then + echo "**${line} performance regressed!**" >> ${benchmark_results}; + cat ${line}.txt >> ${benchmark_results}; + elif grep -q "improved" ${line}.txt; then + echo "_${line} performance improved_ :smiley_cat:" >> ${benchmark_results}; + cat ${line}.txt >> ${benchmark_results}; + fi; + done diff --git a/crates/committer_cli/benches/committer_bench.rs b/crates/committer_cli/benches/committer_bench.rs new file mode 100644 index 00000000000..a83442c4c52 --- /dev/null +++ b/crates/committer_cli/benches/committer_bench.rs @@ -0,0 +1,87 @@ +#![allow(clippy::unwrap_used)] + +// This file is for benchmarking the committer flow. +// The input files for the different benchmarks are downloaded from GCS, using the prefix stored in +// committer_cli/src/tests/flow_test_files_prefix. In order to update them, generate a new random +// prefix (the hash of the initial new commit can be used) and update it in the mentioned file. +// Then upload the new files to GCS with this new prefix (run e.g., +// gcloud storage cp LOCAL_FILE gs://committer-testing-artifacts/NEW_PREFIX/tree_flow_inputs.json). + +use std::{collections::HashMap, sync::Arc}; + +use committer::{ + block_committer::input::StarknetStorageValue, + patricia_merkle_tree::{ + external_test_utils::tree_computation_flow, node_data::leaf::LeafModifications, + types::NodeIndex, + }, +}; +use committer_cli::{commands::parse_and_commit, tests::utils::parse_from_python::TreeFlowInput}; +use criterion::{criterion_group, criterion_main, Criterion}; + +const CONCURRENCY_MODE: bool = true; +const SINGLE_TREE_FLOW_INPUT: &str = include_str!("tree_flow_inputs.json"); +const FLOW_TEST_INPUT: &str = include_str!("committer_flow_inputs.json"); +const OUTPUT_PATH: &str = "benchmark_output.txt"; + +pub fn single_tree_flow_benchmark(criterion: &mut Criterion) { + let TreeFlowInput { + leaf_modifications, + storage, + root_hash, + } = serde_json::from_str(SINGLE_TREE_FLOW_INPUT).unwrap(); + + let runtime = match CONCURRENCY_MODE { + true => tokio::runtime::Builder::new_multi_thread().build().unwrap(), + false => tokio::runtime::Builder::new_current_thread() + .build() + .unwrap(), + }; + + let leaf_modifications = leaf_modifications + .into_iter() + .map(|(k, v)| (NodeIndex::FIRST_LEAF + k, v)) + .collect::>(); + let arc_leaf_modifications = Arc::new(leaf_modifications); + + criterion.bench_function("tree_computation_flow", |benchmark| { + benchmark.iter(|| { + runtime.block_on(tree_computation_flow( + Arc::clone(&arc_leaf_modifications), + &storage, + root_hash, + )); + }) + }); +} + +pub fn full_committer_flow_benchmark(criterion: &mut Criterion) { + let runtime = match CONCURRENCY_MODE { + true => tokio::runtime::Builder::new_multi_thread().build().unwrap(), + false => tokio::runtime::Builder::new_current_thread() + .build() + .unwrap(), + }; + + // TODO(Aner, 8/7/2024): use structs for deserialization. + let input: HashMap = serde_json::from_str(FLOW_TEST_INPUT).unwrap(); + let committer_input_string = input.get("committer_input").unwrap(); + + // TODO(Aner, 27/06/2024): output path should be a pipe (file on memory) + // to avoid disk IO in the benchmark. + criterion.bench_function("full_committer_flow", |benchmark| { + benchmark.iter(|| { + runtime.block_on(parse_and_commit( + committer_input_string, + OUTPUT_PATH.to_owned(), + )); + }) + }); +} + +criterion_group!( + benches, + single_tree_flow_benchmark, + full_committer_flow_benchmark +); +criterion_main!(benches); diff --git a/crates/committer_cli/benches/committer_flow_inputs.json b/crates/committer_cli/benches/committer_flow_inputs.json new file mode 100644 index 00000000000..c42fd23ef52 --- /dev/null +++ b/crates/committer_cli/benches/committer_flow_inputs.json @@ -0,0 +1 @@ +This file is a placeholder for inputs to single_tree_flow regression test and benchmark. diff --git a/crates/committer_cli/benches/tree_flow_inputs.json b/crates/committer_cli/benches/tree_flow_inputs.json new file mode 100644 index 00000000000..c42fd23ef52 --- /dev/null +++ b/crates/committer_cli/benches/tree_flow_inputs.json @@ -0,0 +1 @@ +This file is a placeholder for inputs to single_tree_flow regression test and benchmark. diff --git a/crates/committer_cli/src/block_hash.rs b/crates/committer_cli/src/block_hash.rs new file mode 100644 index 00000000000..ae4c4eea2f4 --- /dev/null +++ b/crates/committer_cli/src/block_hash.rs @@ -0,0 +1,20 @@ +use serde::Deserialize; +use starknet_api::{ + block::BlockHeaderWithoutHash, + block_hash::block_hash_calculator::{BlockHeaderCommitments, TransactionHashingData}, + data_availability::L1DataAvailabilityMode, + state::ThinStateDiff, +}; + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +pub struct BlockCommitmentsInput { + pub transactions_data: Vec, + pub state_diff: ThinStateDiff, + pub l1_da_mode: L1DataAvailabilityMode, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +pub struct BlockHashInput { + pub header: BlockHeaderWithoutHash, + pub block_commitments: BlockHeaderCommitments, +} diff --git a/crates/committer_cli/src/commands.rs b/crates/committer_cli/src/commands.rs new file mode 100644 index 00000000000..93d9b643a71 --- /dev/null +++ b/crates/committer_cli/src/commands.rs @@ -0,0 +1,26 @@ +use committer::block_committer::{ + commit::commit_block, + input::{Config, ConfigImpl, Input}, +}; + +use crate::{ + filled_tree_output::filled_forest::SerializedForest, + parse_input::read::{parse_input, write_to_file}, +}; + +pub async fn parse_and_commit(input_string: &str, output_path: String) { + let input = parse_input(input_string).expect("Failed to parse the given input."); + // Set the given log level. + log::set_max_level(input.config.logger_level()); + commit(input, output_path).await; +} + +pub async fn commit(input: Input, output_path: String) { + let serialized_filled_forest = SerializedForest( + commit_block(input) + .await + .expect("Failed to commit the given block."), + ); + let output = serialized_filled_forest.forest_to_output(); + write_to_file(&output_path, &output); +} diff --git a/crates/committer_cli/src/filled_tree_output.rs b/crates/committer_cli/src/filled_tree_output.rs new file mode 100644 index 00000000000..147e322f4f2 --- /dev/null +++ b/crates/committer_cli/src/filled_tree_output.rs @@ -0,0 +1,2 @@ +pub mod errors; +pub mod filled_forest; diff --git a/crates/committer_cli/src/filled_tree_output/errors.rs b/crates/committer_cli/src/filled_tree_output/errors.rs new file mode 100644 index 00000000000..c8191bfb9d2 --- /dev/null +++ b/crates/committer_cli/src/filled_tree_output/errors.rs @@ -0,0 +1,16 @@ +use committer::patricia_merkle_tree::filled_tree::errors::{ + ClassesTrieError, ContractsTrieError, StorageTrieError, +}; +use std::fmt::Debug; + +#[derive(thiserror::Error, Debug)] +pub enum FilledForestError { + #[error(transparent)] + SerializationError(#[from] serde_json::Error), + #[error(transparent)] + StorageTrie(#[from] StorageTrieError), + #[error(transparent)] + ClassesTrie(#[from] ClassesTrieError), + #[error(transparent)] + ContractsTrie(#[from] ContractsTrieError), +} diff --git a/crates/committer_cli/src/filled_tree_output/filled_forest.rs b/crates/committer_cli/src/filled_tree_output/filled_forest.rs new file mode 100644 index 00000000000..19ccac7332c --- /dev/null +++ b/crates/committer_cli/src/filled_tree_output/filled_forest.rs @@ -0,0 +1,30 @@ +use committer::patricia_merkle_tree::filled_tree::forest::FilledForest; +use committer::storage::map_storage::MapStorage; +use serde::Serialize; + +pub struct SerializedForest(pub FilledForest); + +#[derive(Debug, Serialize)] +#[allow(dead_code)] +pub struct Output { + // New fact storage. + storage: MapStorage, + // New contract storage root. + contract_storage_root_hash: String, + // New compiled class root. + compiled_class_root_hash: String, +} + +impl SerializedForest { + pub fn forest_to_output(&self) -> Output { + let mut storage = MapStorage::default(); + self.0.write_to_storage(&mut storage); + let contract_storage_root_hash = self.0.get_contract_root_hash().0; + let compiled_class_root_hash = self.0.get_compiled_class_root_hash().0; + Output { + storage, + contract_storage_root_hash: contract_storage_root_hash.to_hex(), + compiled_class_root_hash: compiled_class_root_hash.to_hex(), + } + } +} diff --git a/crates/committer_cli/src/lib.rs b/crates/committer_cli/src/lib.rs new file mode 100644 index 00000000000..f7a4598a155 --- /dev/null +++ b/crates/committer_cli/src/lib.rs @@ -0,0 +1,5 @@ +pub mod block_hash; +pub mod commands; +pub mod filled_tree_output; +pub mod parse_input; +pub mod tests; diff --git a/crates/committer_cli/src/main.rs b/crates/committer_cli/src/main.rs new file mode 100644 index 00000000000..76cf222f17e --- /dev/null +++ b/crates/committer_cli/src/main.rs @@ -0,0 +1,114 @@ +use clap::{Args, Parser, Subcommand}; +use committer_cli::block_hash::{BlockCommitmentsInput, BlockHashInput}; +use committer_cli::commands::parse_and_commit; +use committer_cli::parse_input::read::{load_from_stdin, read_from_stdin, write_to_file}; +use committer_cli::tests::python_tests::PythonTest; +use simplelog::{ColorChoice, Config, LevelFilter, TermLogger, TerminalMode}; +use starknet_api::block_hash::block_hash_calculator::{ + calculate_block_commitments, calculate_block_hash, +}; + +/// Committer CLI. +#[derive(Debug, Parser)] +#[clap(name = "committer-cli", version)] +pub struct CommitterCliArgs { + #[clap(flatten)] + global_options: GlobalOptions, + + #[clap(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + /// Calculates the block hash. + BlockHash { + /// File path to output. + #[clap(long, short = 'o', default_value = "stdout")] + output_path: String, + }, + /// Given previous state tree skeleton and a state diff, computes the new commitment. + /// Calculates commitments needed for the block hash. + BlockHashCommitments { + /// File path to output. + #[clap(long, short = 'o', default_value = "stdout")] + output_path: String, + }, + /// Given previous state tree skeleton and a state diff, computes the new commitment. + Commit { + /// File path to output. + #[clap(long, short = 'o', default_value = "stdout")] + output_path: String, + }, + PythonTest { + /// File path to output. + #[clap(long, short = 'o', default_value = "stdout")] + output_path: String, + + /// Test name. + #[clap(long)] + test_name: String, + }, +} + +#[derive(Debug, Args)] +struct GlobalOptions {} + +#[tokio::main] +/// Main entry point of the committer CLI. +async fn main() { + // Initialize the logger + if let Err(error) = TermLogger::init( + LevelFilter::Info, // Set the logging level + Config::default(), // Use the default log format + TerminalMode::Mixed, // Use mixed mode to log to both stdout and stderr + ColorChoice::Auto, // Automatically choose whether to use colored output + ) { + eprintln!("Failed to initialize the logger: {:?}", error); + } + + let args = CommitterCliArgs::parse(); + + match args.command { + Command::Commit { output_path } => { + // TODO(Aner, 15/7/24): try moving read_from_stdin into function. + parse_and_commit(&read_from_stdin(), output_path).await; + } + + Command::PythonTest { + output_path, + test_name, + } => { + // Create PythonTest from test_name. + let test = PythonTest::try_from(test_name) + .unwrap_or_else(|error| panic!("Failed to create PythonTest: {}", error)); + let stdin_input = read_from_stdin(); + + // Run relevant test. + let output = test + .run(Some(&stdin_input)) + .await + .unwrap_or_else(|error| panic!("Failed to run test: {}", error)); + + // Write test's output. + write_to_file(&output_path, &output); + } + + Command::BlockHash { output_path } => { + let block_hash_input: BlockHashInput = load_from_stdin(); + let block_hash = + calculate_block_hash(block_hash_input.header, block_hash_input.block_commitments); + write_to_file(&output_path, &block_hash); + } + + Command::BlockHashCommitments { output_path } => { + let commitments_input: BlockCommitmentsInput = load_from_stdin(); + let commitments = calculate_block_commitments( + &commitments_input.transactions_data, + &commitments_input.state_diff, + commitments_input.l1_da_mode, + ); + write_to_file(&output_path, &commitments); + } + } +} diff --git a/crates/committer_cli/src/parse_input.rs b/crates/committer_cli/src/parse_input.rs new file mode 100644 index 00000000000..7dd235236a8 --- /dev/null +++ b/crates/committer_cli/src/parse_input.rs @@ -0,0 +1,3 @@ +pub mod cast; +pub mod raw_input; +pub mod read; diff --git a/crates/committer_cli/src/parse_input/cast.rs b/crates/committer_cli/src/parse_input/cast.rs new file mode 100644 index 00000000000..0afd0f60d44 --- /dev/null +++ b/crates/committer_cli/src/parse_input/cast.rs @@ -0,0 +1,113 @@ +use crate::parse_input::raw_input::RawInput; +use committer::block_committer::input::{ + ConfigImpl, ContractAddress, Input, StarknetStorageKey, StarknetStorageValue, StateDiff, +}; +use committer::felt::Felt; +use committer::hash::hash_trait::HashOutput; +use committer::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; +use committer::storage::errors::DeserializationError; +use committer::storage::storage_trait::{StorageKey, StorageValue}; + +use std::collections::HashMap; + +pub type InputImpl = Input; + +impl TryFrom for InputImpl { + type Error = DeserializationError; + fn try_from(raw_input: RawInput) -> Result { + let mut storage = HashMap::new(); + for entry in raw_input.storage { + add_unique( + &mut storage, + "storage", + StorageKey(entry.key), + StorageValue(entry.value), + )?; + } + + let mut address_to_class_hash = HashMap::new(); + for entry in raw_input.state_diff.address_to_class_hash { + add_unique( + &mut address_to_class_hash, + "address to class hash", + ContractAddress(Felt::from_bytes_be_slice(&entry.key)), + ClassHash(Felt::from_bytes_be_slice(&entry.value)), + )?; + } + + let mut address_to_nonce = HashMap::new(); + for entry in raw_input.state_diff.address_to_nonce { + add_unique( + &mut address_to_nonce, + "address to nonce", + ContractAddress(Felt::from_bytes_be_slice(&entry.key)), + Nonce(Felt::from_bytes_be_slice(&entry.value)), + )?; + } + + let mut class_hash_to_compiled_class_hash = HashMap::new(); + for entry in raw_input.state_diff.class_hash_to_compiled_class_hash { + add_unique( + &mut class_hash_to_compiled_class_hash, + "class hash to compiled class hash", + ClassHash(Felt::from_bytes_be_slice(&entry.key)), + CompiledClassHash(Felt::from_bytes_be_slice(&entry.value)), + )?; + } + + let mut storage_updates = HashMap::new(); + for outer_entry in raw_input.state_diff.storage_updates { + let inner_map = outer_entry + .storage_updates + .iter() + .map(|inner_entry| { + ( + StarknetStorageKey(Felt::from_bytes_be_slice(&inner_entry.key)), + StarknetStorageValue(Felt::from_bytes_be_slice(&inner_entry.value)), + ) + }) + .collect(); + add_unique( + &mut storage_updates, + "starknet storage updates", + ContractAddress(Felt::from_bytes_be_slice(&outer_entry.address)), + inner_map, + )?; + } + + Ok(Input { + storage, + state_diff: StateDiff { + address_to_class_hash, + address_to_nonce, + class_hash_to_compiled_class_hash, + storage_updates, + }, + contracts_trie_root_hash: HashOutput(Felt::from_bytes_be_slice( + &raw_input.contracts_trie_root_hash, + )), + classes_trie_root_hash: HashOutput(Felt::from_bytes_be_slice( + &raw_input.classes_trie_root_hash, + )), + config: raw_input.config.into(), + }) + } +} + +pub(crate) fn add_unique( + map: &mut HashMap, + map_name: &str, + key: K, + value: V, +) -> Result<(), DeserializationError> +where + K: std::cmp::Eq + std::hash::Hash + std::fmt::Debug, +{ + if map.contains_key(&key) { + return Err(DeserializationError::KeyDuplicate(format!( + "{map_name}: {key:?}" + ))); + } + map.insert(key, value); + Ok(()) +} diff --git a/crates/committer_cli/src/parse_input/raw_input.rs b/crates/committer_cli/src/parse_input/raw_input.rs new file mode 100644 index 00000000000..d58dc863de1 --- /dev/null +++ b/crates/committer_cli/src/parse_input/raw_input.rs @@ -0,0 +1,83 @@ +use committer::block_committer::input::ConfigImpl; +use log::LevelFilter; +use serde::{Deserialize, Serialize}; +use serde_repr::Deserialize_repr; +type RawFelt = [u8; 32]; + +#[derive(Deserialize, Debug)] +/// Input to the committer. +pub(crate) struct RawInput { + /// Storage. Will be casted to HashMap, Vec> to simulate DB access. + pub storage: Vec, + pub state_diff: RawStateDiff, + pub contracts_trie_root_hash: RawFelt, + pub classes_trie_root_hash: RawFelt, + pub config: RawConfigImpl, +} + +#[derive(Deserialize, Debug)] +/// Fact storage entry. +pub(crate) struct RawStorageEntry { + pub key: Vec, + pub value: Vec, +} + +#[derive(Deserialize, Debug)] +pub(crate) struct RawConfigImpl { + warn_on_trivial_modifications: bool, + log_level: PythonLogLevel, +} + +#[derive(Deserialize_repr, Debug, Default, Serialize)] +#[repr(usize)] +/// Describes a log level https://docs.python.org/3/library/logging.html#logging-levels +pub(crate) enum PythonLogLevel { + NotSet = 0, + Info = 20, + Warning = 30, + Error = 40, + Critical = 50, + // If an unknown variant is given, the default log level is Debug. + #[serde(other)] + #[default] + Debug = 10, +} + +impl From for ConfigImpl { + fn from(raw_config: RawConfigImpl) -> Self { + let log_level = match raw_config.log_level { + PythonLogLevel::NotSet => LevelFilter::Trace, + PythonLogLevel::Debug => LevelFilter::Debug, + PythonLogLevel::Info => LevelFilter::Info, + PythonLogLevel::Warning => LevelFilter::Warn, + PythonLogLevel::Error | PythonLogLevel::Critical => LevelFilter::Error, + }; + ConfigImpl::new(raw_config.warn_on_trivial_modifications, log_level) + } +} + +#[derive(Deserialize, Debug)] +pub(crate) struct RawFeltMapEntry { + pub key: RawFelt, + pub value: RawFelt, +} + +#[derive(Deserialize, Debug)] +/// Represents storage updates. Later will be casted to HashMap> entry. +pub(crate) struct RawStorageUpdates { + pub address: RawFelt, + pub storage_updates: Vec, +} + +#[derive(Deserialize, Debug)] +/// Represents state diff. +pub(crate) struct RawStateDiff { + /// Will be casted to HashMap. + pub address_to_class_hash: Vec, + /// Will be casted to HashMap. + pub address_to_nonce: Vec, + /// Will be casted to HashMap. + pub class_hash_to_compiled_class_hash: Vec, + /// Will be casted to HashMap>. + pub storage_updates: Vec, +} diff --git a/crates/committer_cli/src/parse_input/read.rs b/crates/committer_cli/src/parse_input/read.rs new file mode 100644 index 00000000000..f8f8e4df0c8 --- /dev/null +++ b/crates/committer_cli/src/parse_input/read.rs @@ -0,0 +1,34 @@ +use std::{ + fs::File, + io::{self, BufWriter}, +}; + +use committer::storage::errors::DeserializationError; +use serde::{Deserialize, Serialize}; + +use crate::parse_input::cast::InputImpl; +use crate::parse_input::raw_input::RawInput; + +#[cfg(test)] +#[path = "read_test.rs"] +pub mod read_test; + +type DeserializationResult = Result; + +pub fn parse_input(input: &str) -> DeserializationResult { + serde_json::from_str::(input)?.try_into() +} + +pub fn read_from_stdin() -> String { + io::read_to_string(io::stdin()).expect("Failed to read from stdin.") +} + +pub fn load_from_stdin Deserialize<'a>>() -> T { + let stdin = read_from_stdin(); + serde_json::from_str(&stdin).expect("Failed to load from stdin") +} + +pub fn write_to_file(file_path: &str, object: &T) { + let file_buffer = BufWriter::new(File::create(file_path).expect("Failed to create file")); + serde_json::to_writer(file_buffer, object).expect("Failed to serialize"); +} diff --git a/crates/committer_cli/src/parse_input/read_test.rs b/crates/committer_cli/src/parse_input/read_test.rs new file mode 100644 index 00000000000..8cce55c4fcd --- /dev/null +++ b/crates/committer_cli/src/parse_input/read_test.rs @@ -0,0 +1,287 @@ +use committer::{ + block_committer::input::{ + ConfigImpl, ContractAddress, Input, StarknetStorageKey, StarknetStorageValue, StateDiff, + }, + felt::Felt, + hash::hash_trait::HashOutput, + patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}, + storage::{ + errors::DeserializationError, + storage_trait::{StorageKey, StorageValue}, + }, +}; +use pretty_assertions::assert_eq; +use std::collections::HashMap; + +use super::parse_input; + +#[test] +fn test_simple_input_parsing() { + let input = r#" +[ + [ + [ + [14,6,78,90], + [245,90,0,0,1] + ], + [ + [14,6,43,90], + [9,0,0,0,1] + ] + ], + [ + [ + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ], + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + ], + [ + + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ], + [ + [0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + + ], + [ + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ], + [ + [0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + ], + [ + [ + [0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [ + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ], + [ + [0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + ] + ] + ] + ], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19], + [0, 0, 0, 0, 0, 0, 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, 0], + {"warn_on_trivial_modifications": true, "log_level": 5} +] + +"#; + let expected_storage = HashMap::from([ + ( + StorageKey([14, 6, 78, 90].to_vec()), + StorageValue([245, 90, 0, 0, 1].to_vec()), + ), + ( + StorageKey([14, 6, 43, 90].to_vec()), + StorageValue([9, 0, 0, 0, 1].to_vec()), + ), + ]); + + let expected_address_to_class_hash = HashMap::from([ + ( + ContractAddress(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + ClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ( + ContractAddress(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + ClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ]); + + let expected_address_to_nonce = HashMap::from([ + ( + ContractAddress(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + Nonce(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ( + ContractAddress(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + Nonce(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ]); + + let expected_class_hash_to_compiled_class_hash = HashMap::from([ + ( + ClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + CompiledClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ( + ClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, + 0, 0, 0, 0, 0, 0, + ])), + CompiledClassHash(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ])), + ), + ]); + + let expected_storage_updates = HashMap::from([( + ContractAddress(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, + 0, 0, 0, 0, 0, + ])), + HashMap::from([ + ( + StarknetStorageKey(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, + 0, 0, 0, 0, 0, 0, + ])), + StarknetStorageValue(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ])), + ), + ( + StarknetStorageKey(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 98, 0, 0, 0, 156, 0, 0, 0, 0, 0, 11, 5, 0, 0, 0, 0, 0, 1, 0, 89, + 0, 0, 0, 0, 0, 0, 0, + ])), + StarknetStorageValue(Felt::from_bytes_be_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + ])), + ), + ]), + )]); + + let expected_contracts_trie_root_hash = HashOutput(Felt::from(19_u128)); + let expected_classes_trie_root_hash = HashOutput(Felt::from(256_u128)); + let expected_input = Input { + storage: expected_storage, + state_diff: StateDiff { + address_to_class_hash: expected_address_to_class_hash, + address_to_nonce: expected_address_to_nonce, + class_hash_to_compiled_class_hash: expected_class_hash_to_compiled_class_hash, + storage_updates: expected_storage_updates, + }, + contracts_trie_root_hash: expected_contracts_trie_root_hash, + classes_trie_root_hash: expected_classes_trie_root_hash, + config: ConfigImpl::new(true, log::LevelFilter::Debug), + }; + assert_eq!(parse_input(input).unwrap(), expected_input); +} + +#[test] +fn test_input_parsing_with_storage_key_duplicate() { + let input = r#" +[ + [ + [ + [14,6,78,90], + [245,90,0,0,1] + ], + [ + [14,6,78,90], + [9,0,0,0,1] + ] + ], + [ + [], + [], + [], + [] + ], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 3], + {"warn_on_trivial_modifications": true, "log_level": 20} +] + +"#; + let expected_error = "storage: StorageKey([14, 6, 78, 90])"; + assert!(matches!( + parse_input(input).unwrap_err(), + DeserializationError::KeyDuplicate(key) if key == expected_error + )); +} + +#[test] +fn test_input_parsing_with_mapping_key_duplicate() { + let input = r#" +[ + [ + [ + [14,6,78,90], + [245,90,0,0,1] + ], + [ + [0,6,0,90], + [9,0,0,0,1] + ] + ], + [ + [ + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ], + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 89, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 77, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + ], + [], + [], + [] + ], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 5], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 3], + {"warn_on_trivial_modifications": false, "log_level": 30} +] + +"#; + let expected_error = + "address to class hash: ContractAddress(6646139978924584093298644040422522880)"; + assert!(matches!( + parse_input(input).unwrap_err(), + DeserializationError::KeyDuplicate(key) if key == expected_error + )); +} diff --git a/crates/committer_cli/src/tests.rs b/crates/committer_cli/src/tests.rs new file mode 100644 index 00000000000..9709423dafb --- /dev/null +++ b/crates/committer_cli/src/tests.rs @@ -0,0 +1,4 @@ +pub mod python_tests; +#[cfg(test)] +pub mod regression_tests; +pub mod utils; diff --git a/crates/committer_cli/src/tests/flow_test_files_prefix b/crates/committer_cli/src/tests/flow_test_files_prefix new file mode 100644 index 00000000000..af417ba7e0c --- /dev/null +++ b/crates/committer_cli/src/tests/flow_test_files_prefix @@ -0,0 +1 @@ +23ffcf5 diff --git a/crates/committer_cli/src/tests/python_tests.rs b/crates/committer_cli/src/tests/python_tests.rs new file mode 100644 index 00000000000..8ba1341972f --- /dev/null +++ b/crates/committer_cli/src/tests/python_tests.rs @@ -0,0 +1,718 @@ +use crate::filled_tree_output::errors::FilledForestError; +use crate::filled_tree_output::filled_forest::SerializedForest; +use crate::parse_input::cast::InputImpl; +use crate::parse_input::read::parse_input; +use crate::tests::utils::parse_from_python::parse_input_single_storage_tree_flow_test; +use crate::tests::utils::random_structs::DummyRandomValue; +use committer::block_committer::input::{ + ContractAddress, StarknetStorageKey, StarknetStorageValue, StateDiff, +}; +use committer::felt::Felt; +use committer::hash::hash_trait::HashOutput; +use committer::patricia_merkle_tree::filled_tree::forest::FilledForest; +use committer::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use committer::patricia_merkle_tree::filled_tree::node::{ClassHash, FilledNode, Nonce}; +use committer::patricia_merkle_tree::node_data::inner_node::{ + BinaryData, EdgeData, EdgePathLength, NodeData, PathToBottom, +}; +use committer::patricia_merkle_tree::node_data::leaf::ContractState; +use committer::patricia_merkle_tree::types::SubTreeHeight; +use log::error; + +use committer::patricia_merkle_tree::external_test_utils::single_tree_flow_test; +use committer::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunctionImpl; +use committer::storage::db_object::DBObject; +use committer::storage::errors::{DeserializationError, SerializationError}; +use committer::storage::map_storage::MapStorage; +use committer::storage::storage_trait::{Storage, StorageKey, StorageValue}; +use ethnum::U256; +use serde_json::json; +use starknet_api::block_hash::block_hash_calculator::{ + TransactionHashingData, TransactionOutputForHash, +}; +use starknet_api::state::ThinStateDiff; +use starknet_api::transaction::TransactionExecutionStatus; +use starknet_types_core::hash::{Pedersen, StarkHash}; +use std::fmt::Debug; +use std::{collections::HashMap, io}; +use thiserror; + +use super::utils::objects::{get_thin_state_diff, get_transaction_output_for_hash, get_tx_data}; +use super::utils::parse_from_python::TreeFlowInput; + +// Enum representing different Python tests. +pub enum PythonTest { + ExampleTest, + FeltSerialize, + HashFunction, + BinarySerialize, + InputParsing, + NodeKey, + StorageSerialize, + ComparePythonHashConstants, + StorageNode, + FilledForestOutput, + TreeHeightComparison, + ParseTxOutput, + ParseStateDiff, + ParseTxData, + SerializeForRustCommitterFlowTest, + ComputeHashSingleTree, + MaybePanic, + LogError, +} + +/// Error type for PythonTest enum. +#[derive(Debug, thiserror::Error)] +pub enum PythonTestError { + #[error("Unknown test name: {0}")] + UnknownTestName(String), + #[error(transparent)] + ParseInputError(#[from] serde_json::Error), + #[error(transparent)] + ParseIntError(#[from] std::num::ParseIntError), + #[error("{0}")] + KeyNotFound(String), + #[error(transparent)] + InvalidCastError(#[from] std::num::TryFromIntError), + #[error(transparent)] + DeserializationTestFailure(#[from] DeserializationError), + #[error(transparent)] + StdinReadError(#[from] io::Error), + #[error("None value found in input.")] + NoneInputError, + #[error(transparent)] + SerializationError(#[from] SerializationError), + #[error(transparent)] + FilledForest(#[from] FilledForestError), +} + +/// Implements conversion from a string to a `PythonTest`. +impl TryFrom for PythonTest { + type Error = PythonTestError; + + fn try_from(value: String) -> Result { + match value.as_str() { + "example_test" => Ok(Self::ExampleTest), + "felt_serialize_test" => Ok(Self::FeltSerialize), + "hash_function_test" => Ok(Self::HashFunction), + "binary_serialize_test" => Ok(Self::BinarySerialize), + "input_parsing" => Ok(Self::InputParsing), + "node_db_key_test" => Ok(Self::NodeKey), + "storage_serialize_test" => Ok(Self::StorageSerialize), + "compare_python_hash_constants" => Ok(Self::ComparePythonHashConstants), + "storage_node_test" => Ok(Self::StorageNode), + "filled_forest_output" => Ok(Self::FilledForestOutput), + "compare_tree_height" => Ok(Self::TreeHeightComparison), + "parse_tx_output_test" => Ok(Self::ParseTxOutput), + "parse_state_diff_test" => Ok(Self::ParseStateDiff), + "parse_tx_data_test" => Ok(Self::ParseTxData), + "serialize_to_rust_committer_flow_test" => Ok(Self::SerializeForRustCommitterFlowTest), + "tree_test" => Ok(Self::ComputeHashSingleTree), + "maybe_panic" => Ok(Self::MaybePanic), + "log_error" => Ok(Self::LogError), + _ => Err(PythonTestError::UnknownTestName(value)), + } + } +} + +impl PythonTest { + /// Returns the input string if it's `Some`, or an error if it's `None`. + pub fn non_optional_input(input: Option<&str>) -> Result<&str, PythonTestError> { + input.ok_or_else(|| PythonTestError::NoneInputError) + } + + /// Runs the test with the given arguments. + pub async fn run(&self, input: Option<&str>) -> Result { + match self { + Self::ExampleTest => { + let example_input: HashMap = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(example_test(example_input)) + } + Self::FeltSerialize => { + let felt = Self::non_optional_input(input)?.parse::()?; + Ok(felt_serialize_test(felt)) + } + Self::HashFunction => { + let hash_input: HashMap = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(test_hash_function(hash_input)) + } + Self::BinarySerialize => { + let binary_input: HashMap = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(test_binary_serialize_test(binary_input)) + } + Self::InputParsing => { + let committer_input = serde_json::from_str(Self::non_optional_input(input)?)?; + parse_input_test(committer_input) + } + Self::StorageSerialize => storage_serialize_test(), + Self::NodeKey => Ok(test_node_db_key()), + Self::ComparePythonHashConstants => Ok(python_hash_constants_compare()), + Self::StorageNode => { + let storage_node_input: HashMap = + serde_json::from_str(Self::non_optional_input(input)?)?; + test_storage_node(storage_node_input) + } + Self::FilledForestOutput => filled_forest_output_test(), + Self::TreeHeightComparison => Ok(get_actual_tree_height()), + Self::ParseTxOutput => { + let tx_output: TransactionOutputForHash = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(parse_tx_output_test(tx_output)) + } + Self::ParseStateDiff => { + let tx_output: ThinStateDiff = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(parse_state_diff_test(tx_output)) + } + Self::ParseTxData => { + let tx_data: TransactionHashingData = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(parse_tx_data_test(tx_data)) + } + Self::SerializeForRustCommitterFlowTest => { + // TODO(Aner, 8/7/2024): refactor using structs for deserialization. + let input: HashMap = + serde_json::from_str(Self::non_optional_input(input)?)?; + Ok(serialize_for_rust_committer_flow_test(input)) + } + Self::ComputeHashSingleTree => { + // 1. Get and deserialize input. + let TreeFlowInput { + leaf_modifications, + storage, + root_hash, + } = serde_json::from_str(Self::non_optional_input(input)?)?; + // 2. Run the test. + let output = single_tree_flow_test(leaf_modifications, storage, root_hash).await; + // 3. Serialize and return output. + Ok(output) + } + Self::MaybePanic => { + let is_panic: bool = serde_json::from_str(Self::non_optional_input(input)?)?; + if is_panic { + panic!("panic test") + } + Ok("Done!".to_owned()) + } + Self::LogError => { + log::error!("This is an error log message."); + log::warn!("This is a warn log message."); + log::info!("This is an info log message."); + log::debug!("This is a debug log message."); + panic!("This is a panic message."); + } + } + } +} + +// Test that the fetching of the input to flow test is working. +// TODO(Aner, 8/7/2024): refactor using structs for deserialization and rename the function. +fn serialize_for_rust_committer_flow_test(input: HashMap) -> String { + let TreeFlowInput { + leaf_modifications, + storage, + root_hash, + } = parse_input_single_storage_tree_flow_test(&input); + // Serialize the leaf modifications to an object that can be JSON-serialized. + let leaf_modifications_to_print: HashMap> = leaf_modifications + .into_iter() + .map(|(k, v)| (k.0.to_string(), v.serialize().0)) + .collect(); + + // Create a json string to compare with the expected string in python. + serde_json::to_string(&json!( + {"leaf_modifications": leaf_modifications_to_print, "storage": storage.storage, "root_hash": root_hash.0} + )).expect("serialization failed") +} + +fn get_or_key_not_found<'a, T: Debug>( + map: &'a HashMap, + key: &'a str, +) -> Result<&'a T, PythonTestError> { + map.get(key).ok_or_else(|| { + PythonTestError::KeyNotFound(format!( + "Failed to get value for key '{}' from {:?}.", + key, map + )) + }) +} + +fn get_actual_tree_height() -> String { + SubTreeHeight::ACTUAL_HEIGHT.to_string() +} + +pub(crate) fn example_test(test_args: HashMap) -> String { + let x = test_args.get("x").expect("Failed to get value for key 'x'"); + let y = test_args.get("y").expect("Failed to get value for key 'y'"); + format!("Calling example test with args: x: {}, y: {}", x, y) +} + +pub(crate) fn parse_tx_output_test(tx_execution_info: TransactionOutputForHash) -> String { + let expected_object = get_transaction_output_for_hash(&tx_execution_info.execution_status); + is_success_string(expected_object == tx_execution_info) +} + +pub(crate) fn parse_state_diff_test(state_diff: ThinStateDiff) -> String { + let expected_object = get_thin_state_diff(); + is_success_string(expected_object == state_diff) +} + +pub(crate) fn parse_tx_data_test(tx_data: TransactionHashingData) -> String { + let expected_object = get_tx_data(&TransactionExecutionStatus::Succeeded); + is_success_string(expected_object == tx_data) +} + +fn is_success_string(is_success: bool) -> String { + match is_success { + true => "Success", + false => "Failure", + } + .to_owned() +} + +/// Serializes a Felt into a string. +pub(crate) fn felt_serialize_test(felt: u128) -> String { + let bytes = Felt::from(felt).to_bytes_be().to_vec(); + serde_json::to_string(&bytes) + .unwrap_or_else(|error| panic!("Failed to serialize felt: {}", error)) +} + +pub(crate) fn test_hash_function(hash_input: HashMap) -> String { + // Fetch x and y from the input. + let x = hash_input + .get("x") + .expect("Failed to get value for key 'x'"); + let y = hash_input + .get("y") + .expect("Failed to get value for key 'y'"); + + // Convert x and y to Felt. + let x_felt = Felt::from(*x); + let y_felt = Felt::from(*y); + + // Compute the hash. + let hash_result = Pedersen::hash(&x_felt.into(), &y_felt.into()); + + // Serialize the hash result. + serde_json::to_string(&hash_result) + .unwrap_or_else(|error| panic!("Failed to serialize hash result: {}", error)) +} + +/// Serializes binary data into a JSON string. +/// # Arguments +/// +/// * `left` - The left 128-bit integer used to create binary data. +/// * `right` - The right 128-bit integer used to create binary data. +/// +/// # Returns +/// +/// A JSON string representing the value of serialized binary data. +pub(crate) fn test_binary_serialize_test(binary_input: HashMap) -> String { + // Extract left and right values from the input. + let left = binary_input + .get("left") + .expect("Failed to get value for key 'left'"); + let right = binary_input + .get("right") + .expect("Failed to get value for key 'right'"); + + // Create a map to store the serialized binary data. + let mut map: HashMap> = HashMap::new(); + + // Create binary data from the left and right values. + let binary_data = BinaryData { + left_hash: HashOutput(Felt::from(*left)), + right_hash: HashOutput(Felt::from(*right)), + }; + + // Create a filled node (irrelevant leaf type) with binary data and zero hash. + let filled_node: FilledNode = FilledNode { + data: NodeData::Binary(binary_data), + hash: HashOutput(Felt::ZERO), + }; + + // Serialize the binary node and insert it into the map under the key "value". + let value = filled_node.serialize(); + map.insert("value".to_string(), value.0); + + // Serialize the map to a JSON string and handle serialization errors. + serde_json::to_string(&map) + .unwrap_or_else(|error| panic!("Failed to serialize binary fact: {}", error)) +} + +pub(crate) fn parse_input_test(committer_input: String) -> Result { + Ok(create_output_to_python(parse_input(&committer_input)?)) +} + +fn create_output_to_python(actual_input: InputImpl) -> String { + let (storage_keys_hash, storage_values_hash) = hash_storage(&actual_input.storage); + let (state_diff_keys_hash, state_diff_values_hash) = hash_state_diff(&actual_input.state_diff); + format!( + r#" + {{ + "storage_size": {}, + "address_to_class_hash_size": {}, + "address_to_nonce_size": {}, + "class_hash_to_compiled_class_hash": {}, + "outer_storage_updates_size": {}, + "global_tree_root_hash": {:?}, + "classes_tree_root_hash": {:?}, + "storage_keys_hash": {:?}, + "storage_values_hash": {:?}, + "state_diff_keys_hash": {:?}, + "state_diff_values_hash": {:?} + }}"#, + actual_input.storage.len(), + actual_input.state_diff.address_to_class_hash.len(), + actual_input.state_diff.address_to_nonce.len(), + actual_input + .state_diff + .class_hash_to_compiled_class_hash + .len(), + actual_input.state_diff.storage_updates.len(), + actual_input.contracts_trie_root_hash.0.to_bytes_be(), + actual_input.classes_trie_root_hash.0.to_bytes_be(), + storage_keys_hash, + storage_values_hash, + state_diff_keys_hash, + state_diff_values_hash + ) +} + +/// Calculates the 'hash' of the parsed state diff in order to verify the state diff sent +/// from python was parsed correctly. +fn hash_state_diff(state_diff: &StateDiff) -> (Vec, Vec) { + let (address_to_class_hash_keys_hash, address_to_class_hash_values_hash) = + hash_address_to_class_hash(&state_diff.address_to_class_hash); + let (address_to_nonce_keys_hash, address_to_nonce_values_hash) = + hash_address_to_nonce(&state_diff.address_to_nonce); + let ( + class_hash_to_compiled_class_hash_keys_hash, + class_hash_to_compiled_class_hash_values_hash, + ) = hash_class_hash_to_compiled_class_hash(&state_diff.class_hash_to_compiled_class_hash); + let (storage_updates_keys_hash, storage_updates_values_hash) = + hash_storage_updates(&state_diff.storage_updates); + let mut state_diff_keys_hash = xor_hash( + &address_to_class_hash_keys_hash, + &address_to_nonce_keys_hash, + ); + state_diff_keys_hash = xor_hash( + &state_diff_keys_hash, + &class_hash_to_compiled_class_hash_keys_hash, + ); + state_diff_keys_hash = xor_hash(&state_diff_keys_hash, &storage_updates_keys_hash); + let mut state_diff_values_hash = xor_hash( + &address_to_class_hash_values_hash, + &address_to_nonce_values_hash, + ); + state_diff_values_hash = xor_hash( + &state_diff_values_hash, + &class_hash_to_compiled_class_hash_values_hash, + ); + state_diff_values_hash = xor_hash(&state_diff_values_hash, &storage_updates_values_hash); + (state_diff_keys_hash, state_diff_values_hash) +} + +fn hash_storage_updates( + storage_updates: &HashMap>, +) -> (Vec, Vec) { + let mut keys_hash = vec![0; 32]; + let mut values_hash = vec![0; 32]; + for (key, inner_map) in storage_updates { + keys_hash = xor_hash(&keys_hash, &key.0.to_bytes_be()); + let (inner_map_keys_hash, inner_map_values_hash) = hash_storage_updates_map(inner_map); + values_hash = xor_hash(&values_hash, &inner_map_keys_hash); + values_hash = xor_hash(&values_hash, &inner_map_values_hash); + } + (keys_hash, values_hash) +} + +macro_rules! generate_storage_map_xor_hasher { + ($fn_name:ident, $key_type:ty, $val_type:ty) => { + fn $fn_name(inner_map: &HashMap<$key_type, $val_type>) -> (Vec, Vec) { + let mut keys_hash = vec![0; 32]; + let mut values_hash = vec![0; 32]; + for (key, value) in inner_map { + keys_hash = xor_hash(&keys_hash, &key.0.to_bytes_be()); + values_hash = xor_hash(&values_hash, &value.0.to_bytes_be()); + } + (keys_hash, values_hash) + } + }; +} + +generate_storage_map_xor_hasher!( + hash_storage_updates_map, + StarknetStorageKey, + StarknetStorageValue +); +generate_storage_map_xor_hasher!( + hash_class_hash_to_compiled_class_hash, + ClassHash, + CompiledClassHash +); +generate_storage_map_xor_hasher!(hash_address_to_class_hash, ContractAddress, ClassHash); +generate_storage_map_xor_hasher!(hash_address_to_nonce, ContractAddress, Nonce); + +fn hash_storage(storage: &HashMap) -> (Vec, Vec) { + let mut keys_hash = vec![0; 32]; + let mut values_hash = vec![0; 32]; + for (key, value) in storage { + keys_hash = xor_hash(&keys_hash, &key.0); + values_hash = xor_hash(&values_hash, &value.0); + } + (keys_hash, values_hash) +} + +fn xor_hash(x: &[u8], y: &[u8]) -> Vec { + x.iter().zip(y.iter()).map(|(a, b)| a ^ b).collect() +} + +/// Creates and serializes storage keys for different node types. +/// +/// This function generates and serializes storage keys for various node types, including binary nodes, +/// edge nodes, storage leaf nodes, state tree leaf nodes, and compiled class leaf nodes. The resulting +/// keys are stored in a `HashMap` and serialized into a JSON string. +/// +/// # Returns +/// +/// A JSON string representing the serialized storage keys for different node types. +/// +pub(crate) fn test_node_db_key() -> String { + let zero = Felt::ZERO; + + // Generate keys for different node types. + let hash = HashOutput(zero); + + let binary_node: FilledNode = FilledNode { + data: NodeData::Binary(BinaryData { + left_hash: hash, + right_hash: hash, + }), + hash, + }; + let binary_node_key = binary_node.db_key().0; + + let edge_node: FilledNode = FilledNode { + data: NodeData::Edge(EdgeData { + bottom_hash: hash, + path_to_bottom: Default::default(), + }), + hash, + }; + + let edge_node_key = edge_node.db_key().0; + + let storage_leaf = FilledNode { + data: NodeData::Leaf(StarknetStorageValue(zero)), + hash, + }; + let storage_leaf_key = storage_leaf.db_key().0; + + let state_tree_leaf = FilledNode { + data: NodeData::Leaf(ContractState { + class_hash: ClassHash(zero), + storage_root_hash: HashOutput(zero), + nonce: Nonce(zero), + }), + hash, + }; + let state_tree_leaf_key = state_tree_leaf.db_key().0; + + let compiled_class_leaf = FilledNode { + data: NodeData::Leaf(CompiledClassHash(zero)), + hash, + }; + let compiled_class_leaf_key = compiled_class_leaf.db_key().0; + + // Store keys in a HashMap. + let mut map: HashMap> = HashMap::new(); + + map.insert("binary_node_key".to_string(), binary_node_key); + map.insert("edge_node_key".to_string(), edge_node_key); + map.insert("storage_leaf_key".to_string(), storage_leaf_key); + map.insert("state_tree_leaf_key".to_string(), state_tree_leaf_key); + map.insert( + "compiled_class_leaf_key".to_string(), + compiled_class_leaf_key, + ); + + // Serialize the map to a JSON string and handle serialization errors. + serde_json::to_string(&map) + .unwrap_or_else(|error| panic!("Failed to serialize storage prefix: {}", error)) +} + +/// This function storage_serialize_test generates a MapStorage containing StorageKey and StorageValue +/// pairs for u128 values in the range 0..=1000, +/// serializes it to a JSON string using Serde, +/// and returns the serialized JSON string or panics with an error message if serialization fails. +pub(crate) fn storage_serialize_test() -> Result { + let mut storage = MapStorage { + storage: HashMap::new(), + }; + for i in 0..=99_u128 { + let key = StorageKey(Felt::from(i).to_bytes_be().to_vec()); + let value = StorageValue(Felt::from(i).to_bytes_be().to_vec()); + storage.set(key, value); + } + + Ok(serde_json::to_string(&storage)?) +} + +fn python_hash_constants_compare() -> String { + format!( + "[{:?}, {:?}]", + TreeHashFunctionImpl::CONTRACT_STATE_HASH_VERSION.to_bytes_be(), + Felt::from_hex(TreeHashFunctionImpl::CONTRACT_CLASS_LEAF_V0).expect( + "could not parse hex string corresponding to b'CONTRACT_CLASS_LEAF_V0' to Felt", + ).to_bytes_be() + ) +} + +/// Processes a map containing JSON strings for different node data. +/// Creates `NodeData` objects for each node type, stores them in a storage, and serializes the map to a JSON string. +/// +/// # Arguments +/// * `data` - A map containing JSON strings for different node data: +/// - `"binary"`: Binary node data. +/// - `"edge"`: Edge node data. +/// - `"storage"`: Storage leaf data. +/// - `"contract_state_leaf"`: Contract state leaf data. +/// - `"contract_class_leaf"`: Compiled class leaf data. +/// +/// # Returns +/// A `Result` containing a serialized map of all nodes on success, or an error if keys are missing or parsing fails. +fn test_storage_node(data: HashMap) -> Result { + // Create a storage to store the nodes. + let mut rust_fact_storage = MapStorage { + storage: HashMap::new(), + }; + + // Parse the binary node data from the input. + let binary_json = get_or_key_not_found(&data, "binary")?; + let binary_data: HashMap = serde_json::from_str(binary_json)?; + + // Create a binary node from the parsed data. + let binary_rust: FilledNode = FilledNode { + data: NodeData::Binary(BinaryData { + left_hash: HashOutput(Felt::from(*get_or_key_not_found(&binary_data, "left")?)), + right_hash: HashOutput(Felt::from(*get_or_key_not_found(&binary_data, "right")?)), + }), + hash: HashOutput(Felt::from(*get_or_key_not_found(&binary_data, "hash")?)), + }; + + // Store the binary node in the storage. + rust_fact_storage.set(binary_rust.db_key(), binary_rust.serialize()); + + // Parse the edge node data from the input. + let edge_json = get_or_key_not_found(&data, "edge")?; + let edge_data: HashMap = serde_json::from_str(edge_json)?; + + // Create an edge node from the parsed data. + let edge_rust: FilledNode = FilledNode { + data: NodeData::Edge(EdgeData { + bottom_hash: HashOutput(Felt::from(*get_or_key_not_found(&edge_data, "bottom")?)), + path_to_bottom: PathToBottom::new( + U256::from(*get_or_key_not_found(&edge_data, "path")?).into(), + EdgePathLength::new((*get_or_key_not_found(&edge_data, "length")?).try_into()?) + .expect("Invalid length"), + ) + .expect("Illegal PathToBottom"), + }), + hash: HashOutput(Felt::from(*get_or_key_not_found(&edge_data, "hash")?)), + }; + + // Store the edge node in the storage. + rust_fact_storage.set(edge_rust.db_key(), edge_rust.serialize()); + + // Parse the storage leaf data from the input. + let storage_leaf_json = get_or_key_not_found(&data, "storage")?; + let storage_leaf_data: HashMap = serde_json::from_str(storage_leaf_json)?; + + // Create a storage leaf node from the parsed data. + let storage_leaf_rust = FilledNode { + data: NodeData::Leaf(StarknetStorageValue(Felt::from(*get_or_key_not_found( + &storage_leaf_data, + "value", + )?))), + hash: HashOutput(Felt::from(*get_or_key_not_found( + &storage_leaf_data, + "hash", + )?)), + }; + + // Store the storage leaf node in the storage. + rust_fact_storage.set(storage_leaf_rust.db_key(), storage_leaf_rust.serialize()); + + // Parse the contract state leaf data from the input. + let contract_state_leaf = get_or_key_not_found(&data, "contract_state_leaf")?; + let contract_state_leaf_data: HashMap = + serde_json::from_str(contract_state_leaf)?; + + // Create a contract state leaf node from the parsed data. + let contract_state_leaf_rust = FilledNode { + data: NodeData::Leaf(ContractState { + class_hash: ClassHash(Felt::from(*get_or_key_not_found( + &contract_state_leaf_data, + "contract_hash", + )?)), + storage_root_hash: HashOutput(Felt::from(*get_or_key_not_found( + &contract_state_leaf_data, + "root", + )?)), + nonce: Nonce(Felt::from(*get_or_key_not_found( + &contract_state_leaf_data, + "nonce", + )?)), + }), + + hash: HashOutput(Felt::from(*get_or_key_not_found( + &contract_state_leaf_data, + "hash", + )?)), + }; + + // Store the contract state leaf node in the storage. + rust_fact_storage.set( + contract_state_leaf_rust.db_key(), + contract_state_leaf_rust.serialize(), + ); + + // Parse the compiled class leaf data from the input. + let compiled_class_leaf = get_or_key_not_found(&data, "contract_class_leaf")?; + let compiled_class_leaf_data: HashMap = + serde_json::from_str(compiled_class_leaf)?; + + // Create a compiled class leaf node from the parsed data. + let compiled_class_leaf_rust = FilledNode { + data: NodeData::Leaf(CompiledClassHash(Felt::from(*get_or_key_not_found( + &compiled_class_leaf_data, + "compiled_class_hash", + )?))), + hash: HashOutput(Felt::from(*get_or_key_not_found( + &compiled_class_leaf_data, + "hash", + )?)), + }; + + // Store the compiled class leaf node in the storage. + rust_fact_storage.set( + compiled_class_leaf_rust.db_key(), + compiled_class_leaf_rust.serialize(), + ); + + // Serialize the storage to a JSON string and handle serialization errors. + Ok(serde_json::to_string(&rust_fact_storage)?) +} + +/// Generates a dummy random filled forest and serializes it to a JSON string. +pub(crate) fn filled_forest_output_test() -> Result { + let dummy_forest = SerializedForest(FilledForest::dummy_random(&mut rand::thread_rng(), None)); + let output = dummy_forest.forest_to_output(); + let output_string = serde_json::to_string(&output).expect("Failed to serialize"); + Ok(output_string) +} diff --git a/crates/committer_cli/src/tests/regression_tests.rs b/crates/committer_cli/src/tests/regression_tests.rs new file mode 100644 index 00000000000..f6f1d1b5187 --- /dev/null +++ b/crates/committer_cli/src/tests/regression_tests.rs @@ -0,0 +1,193 @@ +use std::{collections::HashMap, fs}; + +use committer::{ + block_committer::input::{ConfigImpl, Input}, + patricia_merkle_tree::external_test_utils::single_tree_flow_test, +}; +use serde::{Deserialize, Deserializer}; +use serde_json::{Map, Value}; + +use crate::{ + commands::commit, parse_input::read::parse_input, + tests::utils::parse_from_python::TreeFlowInput, +}; + +use super::utils::parse_from_python::parse_input_single_storage_tree_flow_test; + +//TODO(Aner, 20/06/2024): these tests needs to be fixed to be run correctly in the CI: +//1. Fix the test to measure cpu_time and not wall_time. +//2. Fix the max time threshold to be the expected time for the benchmark test. +const MAX_TIME_FOR_SINGLE_TREE_BECHMARK_TEST: f64 = 5.0; +const MAX_TIME_FOR_COMMITTER_FLOW_BECHMARK_TEST: f64 = 5.0; +const SINGLE_TREE_FLOW_INPUT: &str = include_str!("../../benches/tree_flow_inputs.json"); +const FLOW_TEST_INPUT: &str = include_str!("../../benches/committer_flow_inputs.json"); +const OUTPUT_PATH: &str = "benchmark_output.txt"; +const EXPECTED_NUMBER_OF_FILES: usize = 100; + +#[derive(derive_more::Deref)] +struct FactMap(Map); + +impl<'de> Deserialize<'de> for FactMap { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self( + serde_json::from_str(&String::deserialize(deserializer)?).unwrap(), + )) + } +} + +struct CommitterInput(Input); + +impl<'de> Deserialize<'de> for CommitterInput { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self( + parse_input(&String::deserialize(deserializer)?).unwrap(), + )) + } +} + +#[derive(Deserialize)] +struct CommitterRegressionInput { + committer_input: CommitterInput, + contract_states_root: String, + contract_classes_root: String, + expected_facts: FactMap, +} + +#[derive(Deserialize)] +struct TreeRegressionOutput { + root_hash: Value, + storage_changes: Value, +} + +#[derive(Deserialize)] +struct StorageObject { + storage: Value, +} + +#[derive(Deserialize)] +struct CommitterRegressionOutput { + contract_storage_root_hash: Value, + compiled_class_root_hash: Value, + storage: StorageObject, +} + +struct TreeRegressionInput { + tree_flow_input: TreeFlowInput, + expected_hash: String, + expected_storage_changes: Map, +} + +// TODO(Aner, 9/8/24): remove this impl and use the Deserialize derive, by changing the input format. +impl<'de> Deserialize<'de> for TreeRegressionInput { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let map = HashMap::deserialize(deserializer)?; + Ok(Self { + tree_flow_input: parse_input_single_storage_tree_flow_test(&map), + expected_hash: map.get("expected_hash").unwrap().to_string(), + expected_storage_changes: serde_json::from_str( + map.get("expected_storage_changes").unwrap(), + ) + .unwrap(), + }) + } +} + +#[ignore = "To avoid running the regression test in Coverage or without the --release flag."] +#[tokio::test(flavor = "multi_thread")] +pub async fn test_regression_single_tree() { + let TreeRegressionInput { + tree_flow_input: + TreeFlowInput { + leaf_modifications, + storage, + root_hash, + }, + expected_hash, + expected_storage_changes, + } = serde_json::from_str(SINGLE_TREE_FLOW_INPUT).unwrap(); + + let start = std::time::Instant::now(); + // Benchmark the single tree flow test. + let output = single_tree_flow_test(leaf_modifications, storage, root_hash).await; + let execution_time = std::time::Instant::now() - start; + + // Assert correctness of the output of the single tree flow test. + let TreeRegressionOutput { + root_hash, + storage_changes: Value::Object(actual_storage_changes), + } = serde_json::from_str(&output).unwrap() + else { + panic!("Expected storage changes object to be an object."); + }; + assert_eq!(root_hash, expected_hash); + + assert_eq!(actual_storage_changes, expected_storage_changes); + + // 4. Assert the execution time does not exceed the threshold. + assert!(execution_time.as_secs_f64() < MAX_TIME_FOR_SINGLE_TREE_BECHMARK_TEST); +} + +pub async fn test_single_committer_flow(input: &str, output_path: &str) { + let CommitterRegressionInput { + committer_input, + contract_states_root: expected_contract_states_root, + contract_classes_root: expected_contract_classes_root, + expected_facts, + } = serde_json::from_str(input).unwrap(); + + let start = std::time::Instant::now(); + // Benchmark the committer flow test. + commit(committer_input.0, output_path.to_owned()).await; + let execution_time = std::time::Instant::now() - start; + + // Assert correctness of the output of the committer flow test. + let CommitterRegressionOutput { + contract_storage_root_hash, + compiled_class_root_hash, + storage: StorageObject { + storage: Value::Object(storage_changes), + }, + } = serde_json::from_str(&std::fs::read_to_string(output_path).unwrap()).unwrap() + else { + panic!("Expected the storage to be an object."); + }; + + assert_eq!(contract_storage_root_hash, expected_contract_states_root); + assert_eq!(compiled_class_root_hash, expected_contract_classes_root); + assert_eq!(storage_changes, *expected_facts); + + // Assert the execution time does not exceed the threshold. + assert!(execution_time.as_secs_f64() < MAX_TIME_FOR_COMMITTER_FLOW_BECHMARK_TEST); +} +#[ignore = "To avoid running the regression test in Coverage or without the --release flag."] +#[tokio::test(flavor = "multi_thread")] +pub async fn test_regression_committer_flow() { + test_single_committer_flow(FLOW_TEST_INPUT, OUTPUT_PATH).await; +} + +#[ignore = "To avoid running the regression test in Coverage or without the --release flag."] +#[tokio::test(flavor = "multi_thread")] +pub async fn test_regression_committer_all_files() { + assert_eq!( + fs::read_dir("./benches/regression_files").unwrap().count(), + EXPECTED_NUMBER_OF_FILES + ); + let dir_path = fs::read_dir("./benches/regression_files").unwrap(); + for file_path in dir_path { + // TODO(Aner, 23/07/24): multi-thread the test. + test_single_committer_flow( + &fs::read_to_string(file_path.unwrap().path()).unwrap(), + OUTPUT_PATH, + ) + .await; + } +} diff --git a/crates/committer_cli/src/tests/utils.rs b/crates/committer_cli/src/tests/utils.rs new file mode 100644 index 00000000000..2b502e0ae2b --- /dev/null +++ b/crates/committer_cli/src/tests/utils.rs @@ -0,0 +1,3 @@ +pub mod objects; +pub mod parse_from_python; +pub mod random_structs; diff --git a/crates/committer_cli/src/tests/utils/objects.rs b/crates/committer_cli/src/tests/utils/objects.rs new file mode 100644 index 00000000000..7a8273c1100 --- /dev/null +++ b/crates/committer_cli/src/tests/utils/objects.rs @@ -0,0 +1,82 @@ +use indexmap::indexmap; +use starknet_api::{ + block_hash::block_hash_calculator::{TransactionHashingData, TransactionOutputForHash}, + core::{ClassHash, CompiledClassHash, ContractAddress, EthAddress, Nonce, PatriciaKey}, + state::{StorageKey, ThinStateDiff}, + transaction::{ + Event, EventContent, EventData, EventKey, Fee, GasVector, L2ToL1Payload, MessageToL1, + RevertedTransactionExecutionStatus, TransactionExecutionStatus, TransactionHash, + TransactionSignature, + }, +}; +use starknet_types_core::felt::Felt; + +pub(crate) fn get_transaction_output_for_hash( + execution_status: &TransactionExecutionStatus, +) -> TransactionOutputForHash { + let expected_execution_status = match execution_status { + TransactionExecutionStatus::Succeeded => TransactionExecutionStatus::Succeeded, + TransactionExecutionStatus::Reverted(_) => { + TransactionExecutionStatus::Reverted(RevertedTransactionExecutionStatus { + revert_reason: "reason".to_owned(), + }) + } + }; + TransactionOutputForHash { + actual_fee: Fee(0), + events: vec![Event { + from_address: ContractAddress(PatriciaKey::from(2_u128)), + content: EventContent { + keys: vec![EventKey(Felt::from_bytes_be_slice(&[1_u8]))], + data: EventData(vec![Felt::from_bytes_be_slice(&[0_u8])]), + }, + }], + execution_status: expected_execution_status, + gas_consumed: GasVector { + l1_gas: 0, + l1_data_gas: 64, + }, + messages_sent: vec![MessageToL1 { + from_address: ContractAddress(PatriciaKey::from(2_u128)), + to_address: EthAddress::try_from(Felt::from_bytes_be_slice(&[1_u8])) + .expect("to_address"), + payload: L2ToL1Payload(vec![Felt::from_bytes_be_slice(&[0_u8])]), + }], + } +} + +pub(crate) fn get_thin_state_diff() -> ThinStateDiff { + ThinStateDiff { + deployed_contracts: indexmap! { + ContractAddress::from(1_u128) => ClassHash(Felt::from_bytes_be_slice(&[2_u8])) + }, + storage_diffs: indexmap! { + ContractAddress::from(7_u128) => indexmap! { + StorageKey::from(8_u128) => Felt::from_bytes_be_slice(&[9_u8]), + }, + }, + declared_classes: indexmap! { + ClassHash(Felt::from_bytes_be_slice(&[13_u8])) => + CompiledClassHash(Felt::from_bytes_be_slice(&[14_u8])) + }, + deprecated_declared_classes: vec![ + ClassHash(Felt::from_bytes_be_slice(&[16_u8])), + ClassHash(Felt::from_bytes_be_slice(&[15_u8])), + ], + nonces: indexmap! { + ContractAddress::from(3_u128) => Nonce(Felt::from_bytes_be_slice(&[4_u8])), + }, + replaced_classes: indexmap! {}, + } +} + +pub(crate) fn get_tx_data(execution_status: &TransactionExecutionStatus) -> TransactionHashingData { + TransactionHashingData { + transaction_signature: Some(TransactionSignature(vec![ + Felt::from_bytes_be_slice(&[1_u8]), + Felt::from_bytes_be_slice(&[2_u8]), + ])), + transaction_output: get_transaction_output_for_hash(execution_status), + transaction_hash: TransactionHash(Felt::from_bytes_be_slice(&[3_u8])), + } +} diff --git a/crates/committer_cli/src/tests/utils/parse_from_python.rs b/crates/committer_cli/src/tests/utils/parse_from_python.rs new file mode 100644 index 00000000000..3c574b6eb64 --- /dev/null +++ b/crates/committer_cli/src/tests/utils/parse_from_python.rs @@ -0,0 +1,75 @@ +use crate::parse_input::cast::add_unique; +use crate::parse_input::raw_input::RawStorageEntry; +use committer::block_committer::input::StarknetStorageValue; +use committer::felt::Felt; +use committer::hash::hash_trait::HashOutput; +use committer::patricia_merkle_tree::node_data::leaf::LeafModifications; +use committer::patricia_merkle_tree::types::NodeIndex; +use committer::storage::map_storage::MapStorage; +use committer::storage::storage_trait::StorageKey; +use committer::storage::storage_trait::StorageValue; +use ethnum::U256; +use serde::Deserialize; +use serde::Deserializer; +use std::collections::HashMap; + +pub struct TreeFlowInput { + pub leaf_modifications: LeafModifications, + pub storage: MapStorage, + pub root_hash: HashOutput, +} + +impl<'de> Deserialize<'de> for TreeFlowInput { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let map = HashMap::deserialize(deserializer)?; + Ok(parse_input_single_storage_tree_flow_test(&map)) + } +} + +#[allow(clippy::unwrap_used)] +/// Parse input for single storage tree flow test. +/// Returns the leaf modifications, fetched nodes (in storage) and the root hash. +pub fn parse_input_single_storage_tree_flow_test(input: &HashMap) -> TreeFlowInput { + // Fetch leaf_modifications. + let leaf_modifications_json = input.get("leaf_modifications").unwrap(); + let leaf_modifications_map = + serde_json::from_str::>(leaf_modifications_json).unwrap(); + let leaf_modifications = leaf_modifications_map + .iter() + .map(|(k, v)| { + ( + NodeIndex::new(U256::from_str_hex(k).unwrap()), + StarknetStorageValue(Felt::from_hex(v).unwrap()), + ) + }) + .collect(); + + // Fetch storage. + let raw_storage = + serde_json::from_str::>(input.get("storage").unwrap()).unwrap(); + + let mut storage = HashMap::new(); + for entry in raw_storage { + add_unique( + &mut storage, + "storage", + StorageKey(entry.key), + StorageValue(entry.value), + ) + .unwrap(); + } + + let map_storage = MapStorage { storage }; + + // Fetch root_hash. + let root_hash = HashOutput(Felt::from_hex(input.get("root_hash").unwrap()).unwrap()); + + TreeFlowInput { + leaf_modifications, + storage: map_storage, + root_hash, + } +} diff --git a/crates/committer_cli/src/tests/utils/random_structs.rs b/crates/committer_cli/src/tests/utils/random_structs.rs new file mode 100644 index 00000000000..e9f777b1024 --- /dev/null +++ b/crates/committer_cli/src/tests/utils/random_structs.rs @@ -0,0 +1,253 @@ +use committer::block_committer::input::ContractAddress; +use committer::block_committer::input::StarknetStorageValue; +use committer::felt::Felt; +use committer::hash::hash_trait::HashOutput; +use committer::patricia_merkle_tree::external_test_utils::get_random_u256; +use committer::patricia_merkle_tree::filled_tree::forest::FilledForest; +use committer::patricia_merkle_tree::filled_tree::node::ClassHash; +use committer::patricia_merkle_tree::filled_tree::node::CompiledClassHash; +use committer::patricia_merkle_tree::filled_tree::node::FilledNode; +use committer::patricia_merkle_tree::filled_tree::node::Nonce; +use committer::patricia_merkle_tree::filled_tree::tree::ClassesTrie; +use committer::patricia_merkle_tree::filled_tree::tree::ContractsTrie; +use committer::patricia_merkle_tree::filled_tree::tree::StorageTrie; +use committer::patricia_merkle_tree::filled_tree::tree::StorageTrieMap; +use committer::patricia_merkle_tree::node_data::inner_node::BinaryData; +use committer::patricia_merkle_tree::node_data::inner_node::EdgeData; +use committer::patricia_merkle_tree::node_data::inner_node::NodeDataDiscriminants as NodeDataVariants; +use committer::patricia_merkle_tree::node_data::inner_node::{ + EdgePath, EdgePathLength, NodeData, PathToBottom, +}; +use committer::patricia_merkle_tree::node_data::leaf::ContractState; +use committer::patricia_merkle_tree::types::NodeIndex; +use ethnum::U256; +use rand::prelude::IteratorRandom; +use rand::Rng; +use rand_distr::num_traits::ToPrimitive; +use rand_distr::{Distribution, Geometric}; +use std::cmp::min; +use std::collections::HashMap; +use strum::IntoEnumIterator; + +pub trait RandomValue { + fn random(rng: &mut R, max: Option) -> Self; +} + +pub trait DummyRandomValue { + fn dummy_random(rng: &mut R, max: Option) -> Self; +} + +impl RandomValue for Felt { + fn random(rng: &mut R, _max: Option) -> Self { + Felt::try_from(&get_random_u256(rng, U256::ONE, U256::from(&Felt::MAX) + 1)) + .expect("Failed to create a random Felt") + } +} + +impl RandomValue for HashOutput { + fn random(rng: &mut R, max: Option) -> Self { + HashOutput(Felt::random(rng, max)) + } +} + +impl RandomValue for StarknetStorageValue { + fn random(rng: &mut R, max: Option) -> Self { + StarknetStorageValue(Felt::random(rng, max)) + } +} + +impl RandomValue for CompiledClassHash { + fn random(rng: &mut R, max: Option) -> Self { + CompiledClassHash(Felt::random(rng, max)) + } +} + +impl RandomValue for ContractState { + fn random(rng: &mut R, max: Option) -> Self { + ContractState { + nonce: Nonce(Felt::random(rng, max)), + storage_root_hash: HashOutput::random(rng, max), + class_hash: ClassHash(Felt::random(rng, max)), + } + } +} + +impl RandomValue for BinaryData { + fn random(rng: &mut R, max: Option) -> Self { + Self { + left_hash: HashOutput::random(rng, max), + right_hash: HashOutput::random(rng, max), + } + } +} + +impl RandomValue for PathToBottom { + fn random(rng: &mut R, max: Option) -> Self { + // Crate a random path and than calculate the length of the path. + let path = EdgePath::random(rng, max); + // TODO(Aviv, 27/6/2024): use a built in function once we migrate to a better big-integer library + // Randomly choose the number of real leading zeros in the path (up to the maximum possible). + // Real leading zero is a zero that refer to a left node, and not a padding zero. + let max_real_leading_zeros = path.0.leading_zeros() - EdgePath::MAX.0.leading_zeros(); + let real_leading_zeros = std::cmp::min( + Geometric::new(0.5) + .expect("Failed to create random variable.") + .sample(rng) + .to_u32() + .expect("failed to cast random variable to u32"), + max_real_leading_zeros, + ); + let length: u8 = (256_u32 - path.0.leading_zeros() + real_leading_zeros) + .try_into() + .expect("Leading zeros conversion to u8 failed"); + + Self::new(path, EdgePathLength::new(length).expect("Invalid length")) + .expect("Illegal PathToBottom") + } +} + +impl RandomValue for EdgePath { + fn random(rng: &mut R, max: Option) -> Self { + // The maximum value is the maximum between max and EdgePath::MAX. + let max_value = match max { + Some(m) => min(m, EdgePath::MAX.0), + None => EdgePath::MAX.0, + }; + + Self(get_random_u256(rng, U256::ONE, max_value + 1)) + } +} + +impl RandomValue for EdgeData { + fn random(rng: &mut R, max: Option) -> Self { + Self { + bottom_hash: HashOutput::random(rng, max), + path_to_bottom: PathToBottom::random(rng, max), + } + } +} + +macro_rules! random_node_data { + ($leaf:ty) => { + impl RandomValue for NodeData<$leaf> { + fn random(rng: &mut R, max: Option) -> Self { + match NodeDataVariants::iter() + .choose(rng) + .expect("Failed to choose a random variant for NodeData") + { + NodeDataVariants::Binary => NodeData::Binary(BinaryData::random(rng, max)), + NodeDataVariants::Edge => NodeData::Edge(EdgeData::random(rng, max)), + NodeDataVariants::Leaf => NodeData::Leaf(<$leaf>::random(rng, max)), + } + } + } + }; +} + +random_node_data!(StarknetStorageValue); +random_node_data!(CompiledClassHash); +random_node_data!(ContractState); + +impl RandomValue for NodeIndex { + fn random(rng: &mut R, max: Option) -> Self { + // The maximum value is the maximum between max and NodeIndex::MAX. + let max_value = match max { + Some(m) => min(m, U256::from(NodeIndex::MAX)), + None => U256::from(NodeIndex::MAX), + }; + + Self::new(get_random_u256(rng, U256::ONE, max_value + 1)) + } +} + +macro_rules! random_filled_node { + ($leaf:ty) => { + impl RandomValue for FilledNode<$leaf> { + fn random(rng: &mut R, max: Option) -> Self { + Self { + data: NodeData::random(rng, max), + hash: HashOutput::random(rng, max), + } + } + } + }; +} + +random_filled_node!(StarknetStorageValue); +random_filled_node!(CompiledClassHash); +random_filled_node!(ContractState); + +impl RandomValue for ContractAddress { + fn random(rng: &mut R, max: Option) -> Self { + ContractAddress(Felt::random(rng, max)) + } +} + +macro_rules! random_filled_tree { + ($tree:ty, $leaf:ty) => { + impl DummyRandomValue for $tree { + fn dummy_random(rng: &mut R, max_size: Option) -> Self { + // The maximum node number is the maximum between max and 101. + let max_node_number = match max_size { + Some(m) => m, + None => U256::from(101_u8), + } + .as_usize(); + + let mut nodes: Vec<(NodeIndex, FilledNode<$leaf>)> = (0..max_node_number) + .map(|_| { + ( + NodeIndex::random(rng, max_size), + FilledNode::random(rng, max_size), + ) + }) + .collect(); + + nodes.push((NodeIndex::ROOT, FilledNode::random(rng, max_size))); + + Self { + tree_map: nodes.into_iter().collect(), + root_hash: HashOutput(Felt::random(rng, max_size)), + } + } + } + }; +} + +random_filled_tree!(StorageTrie, StarknetStorageValue); +random_filled_tree!(ClassesTrie, CompiledClassHash); +random_filled_tree!(ContractsTrie, ContractState); + +impl DummyRandomValue for FilledForest { + /// Generates a dummy random filled forest. + /// The forest contains max(m,98) dummy random storage tries, + /// a dummy random contract tree and a dummy random compiled class tree. + /// Does not necessary represent a valid forest. + fn dummy_random(rng: &mut R, max_size: Option) -> Self { + // The maximum storage tries number is the maximum between max and 98. + // We also use this number to be the maximum tree size, + let max_trees_number = match max_size { + Some(m) => m, + None => U256::from(98_u8), + } + .as_usize(); + + let storage_tries: StorageTrieMap = (0..max_trees_number) + .map(|_| { + ( + ContractAddress::random(rng, max_size), + StorageTrie::dummy_random(rng, max_size), + ) + }) + .collect::>(); + + let contracts_trie = ContractsTrie::dummy_random(rng, max_size); + let classes_trie = ClassesTrie::dummy_random(rng, max_size); + + Self { + storage_tries, + contracts_trie, + classes_trie, + } + } +} diff --git a/crates/gateway/Cargo.toml b/crates/gateway/Cargo.toml new file mode 100644 index 00000000000..0d93cbfdb09 --- /dev/null +++ b/crates/gateway/Cargo.toml @@ -0,0 +1,45 @@ +[package] +edition.workspace = true +license.workspace = true +name = "starknet_gateway" +repository.workspace = true +version.workspace = true + +[lints] +workspace = true + +[features] +testing = [] + +[dependencies] +async-trait.workspace = true +axum.workspace = true +blockifier= { workspace = true, features = ["testing"] } +cairo-lang-starknet-classes.workspace = true +cairo-vm.workspace = true +hyper.workspace = true +num-traits.workspace = true +papyrus_config.workspace = true +papyrus_rpc.workspace = true +reqwest.workspace = true +serde.workspace = true +serde_json.workspace = true +starknet_api.workspace = true +starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } +starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +starknet_sierra_compile = { path = "../starknet_sierra_compile", version = "0.0" } +starknet-types-core.workspace = true +mempool_test_utils = { path = "../mempool_test_utils", version = "0.0"} +thiserror.workspace = true +tokio.workspace = true +tracing.workspace = true +validator.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +mockall.workspace = true +mockito.workspace = true +num-bigint.workspace = true +pretty_assertions.workspace = true +rstest.workspace = true +starknet_mempool = { path = "../mempool", version = "0.0" } diff --git a/crates/gateway/src/communication.rs b/crates/gateway/src/communication.rs new file mode 100644 index 00000000000..c3e7b192d82 --- /dev/null +++ b/crates/gateway/src/communication.rs @@ -0,0 +1,11 @@ +use starknet_mempool_infra::component_server::empty_component_server::{ + create_empty_server, EmptyServer, +}; + +use crate::gateway::Gateway; + +pub type GatewayServer = EmptyServer; + +pub fn create_gateway_server(gateway: Gateway) -> GatewayServer { + create_empty_server(gateway) +} diff --git a/crates/gateway/src/compilation.rs b/crates/gateway/src/compilation.rs new file mode 100644 index 00000000000..e1c4ea2131d --- /dev/null +++ b/crates/gateway/src/compilation.rs @@ -0,0 +1,113 @@ +use std::panic; +use std::sync::OnceLock; + +use blockifier::execution::contract_class::{ClassInfo, ContractClass, ContractClassV1}; +use cairo_lang_starknet_classes::casm_contract_class::{ + CasmContractClass, CasmContractEntryPoints, +}; +use cairo_lang_starknet_classes::contract_class::ContractClass as CairoLangContractClass; +use starknet_api::core::CompiledClassHash; +use starknet_api::rpc_transaction::RPCDeclareTransaction; +use starknet_sierra_compile::compile::compile_sierra_to_casm; +use starknet_sierra_compile::errors::CompilationUtilError; +use starknet_sierra_compile::utils::into_contract_class_for_compilation; + +use crate::config::GatewayCompilerConfig; +use crate::errors::{GatewayError, GatewayResult}; +use crate::utils::is_subsequence; + +#[cfg(test)] +#[path = "compilation_test.rs"] +mod compilation_test; + +// TODO(Arni): Pass the compiler with dependancy injection. +#[derive(Clone)] +pub struct GatewayCompiler { + #[allow(dead_code)] + pub config: GatewayCompilerConfig, +} + +impl GatewayCompiler { + /// Formats the contract class for compilation, compiles it, and returns the compiled contract + /// class wrapped in a [`ClassInfo`]. + /// Assumes the contract class is of a Sierra program which is compiled to Casm. + pub fn process_declare_tx( + &self, + declare_tx: &RPCDeclareTransaction, + ) -> GatewayResult { + let RPCDeclareTransaction::V3(tx) = declare_tx; + let rpc_contract_class = &tx.contract_class; + let cairo_lang_contract_class = into_contract_class_for_compilation(rpc_contract_class); + + let casm_contract_class = self.compile(cairo_lang_contract_class)?; + + validate_compiled_class_hash(&casm_contract_class, &tx.compiled_class_hash)?; + validate_casm_class(&casm_contract_class)?; + + Ok(ClassInfo::new( + &ContractClass::V1(ContractClassV1::try_from(casm_contract_class)?), + rpc_contract_class.sierra_program.len(), + rpc_contract_class.abi.len(), + )?) + } + + // TODO(Arni): Pass the compilation args from the config. + fn compile( + &self, + cairo_lang_contract_class: CairoLangContractClass, + ) -> Result { + let catch_unwind_result = + panic::catch_unwind(|| compile_sierra_to_casm(cairo_lang_contract_class)); + let casm_contract_class = + catch_unwind_result.map_err(|_| CompilationUtilError::CompilationPanic)??; + + Ok(casm_contract_class) + } +} + +// TODO(Arni): Add test. +fn validate_casm_class(contract_class: &CasmContractClass) -> Result<(), GatewayError> { + let CasmContractEntryPoints { external, l1_handler, constructor } = + &contract_class.entry_points_by_type; + let entry_points_iterator = external.iter().chain(l1_handler.iter()).chain(constructor.iter()); + + for entry_point in entry_points_iterator { + let builtins = &entry_point.builtins; + if !is_subsequence(builtins, supported_builtins()) { + return Err(GatewayError::UnsupportedBuiltins { + builtins: builtins.clone(), + supported_builtins: supported_builtins().to_vec(), + }); + } + } + Ok(()) +} + +// TODO(Arni): Add to a config. +// TODO(Arni): Use the Builtin enum from Starknet-api, and explicitly tag each builtin as supported +// or unsupported so that the compiler would alert us on new builtins. +fn supported_builtins() -> &'static Vec { + static SUPPORTED_BUILTINS: OnceLock> = OnceLock::new(); + SUPPORTED_BUILTINS.get_or_init(|| { + // The OS expects this order for the builtins. + const SUPPORTED_BUILTIN_NAMES: [&str; 7] = + ["pedersen", "range_check", "ecdsa", "bitwise", "ec_op", "poseidon", "segment_arena"]; + SUPPORTED_BUILTIN_NAMES.iter().map(|builtin| builtin.to_string()).collect::>() + }) +} + +/// Validates that the compiled class hash of the compiled contract class matches the supplied +/// compiled class hash. +fn validate_compiled_class_hash( + casm_contract_class: &CasmContractClass, + supplied_compiled_class_hash: &CompiledClassHash, +) -> Result<(), GatewayError> { + let compiled_class_hash = CompiledClassHash(casm_contract_class.compiled_class_hash()); + if compiled_class_hash != *supplied_compiled_class_hash { + return Err(GatewayError::CompiledClassHashMismatch { + supplied: *supplied_compiled_class_hash, + hash_result: compiled_class_hash, + }); + } + Ok(()) +} diff --git a/crates/gateway/src/compilation_test.rs b/crates/gateway/src/compilation_test.rs new file mode 100644 index 00000000000..913f71857c5 --- /dev/null +++ b/crates/gateway/src/compilation_test.rs @@ -0,0 +1,70 @@ +use assert_matches::assert_matches; +use blockifier::execution::contract_class::ContractClass; +use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; +use mempool_test_utils::starknet_api_test_utils::declare_tx; +use rstest::{fixture, rstest}; +use starknet_api::core::CompiledClassHash; +use starknet_api::rpc_transaction::{RPCDeclareTransaction, RPCTransaction}; +use starknet_sierra_compile::errors::CompilationUtilError; + +use crate::compilation::GatewayCompiler; +use crate::errors::GatewayError; + +#[fixture] +fn gateway_compiler() -> GatewayCompiler { + GatewayCompiler { config: Default::default() } +} + +// TODO(Arni): Redesign this test once the compiler is passed with dependancy injection. +#[rstest] +fn test_compile_contract_class_compiled_class_hash_mismatch(gateway_compiler: GatewayCompiler) { + let mut tx = assert_matches!( + declare_tx(), + RPCTransaction::Declare(RPCDeclareTransaction::V3(tx)) => tx + ); + let expected_hash = tx.compiled_class_hash; + let wrong_supplied_hash = CompiledClassHash::default(); + tx.compiled_class_hash = wrong_supplied_hash; + let declare_tx = RPCDeclareTransaction::V3(tx); + + let result = gateway_compiler.process_declare_tx(&declare_tx); + assert_matches!( + result.unwrap_err(), + GatewayError::CompiledClassHashMismatch { supplied, hash_result } + if supplied == wrong_supplied_hash && hash_result == expected_hash + ); +} + +#[rstest] +fn test_compile_contract_class_bad_sierra(gateway_compiler: GatewayCompiler) { + let mut tx = assert_matches!( + declare_tx(), + RPCTransaction::Declare(RPCDeclareTransaction::V3(tx)) => tx + ); + // Truncate the sierra program to trigger an error. + tx.contract_class.sierra_program = tx.contract_class.sierra_program[..100].to_vec(); + let declare_tx = RPCDeclareTransaction::V3(tx); + + let result = gateway_compiler.process_declare_tx(&declare_tx); + assert_matches!( + result.unwrap_err(), + GatewayError::CompilationError(CompilationUtilError::AllowedLibfuncsError( + AllowedLibfuncsError::SierraProgramError + )) + ) +} + +#[rstest] +fn test_process_declare_tx_success(gateway_compiler: GatewayCompiler) { + let declare_tx = assert_matches!( + declare_tx(), + RPCTransaction::Declare(declare_tx) => declare_tx + ); + let RPCDeclareTransaction::V3(declare_tx_v3) = &declare_tx; + let contract_class = &declare_tx_v3.contract_class; + + let class_info = gateway_compiler.process_declare_tx(&declare_tx).unwrap(); + assert_matches!(class_info.contract_class(), ContractClass::V1(_)); + assert_eq!(class_info.sierra_program_length(), contract_class.sierra_program.len()); + assert_eq!(class_info.abi_length(), contract_class.abi.len()); +} diff --git a/crates/gateway/src/compiler_version.rs b/crates/gateway/src/compiler_version.rs new file mode 100644 index 00000000000..0aaf177f22d --- /dev/null +++ b/crates/gateway/src/compiler_version.rs @@ -0,0 +1,111 @@ +use std::collections::BTreeMap; + +use cairo_lang_starknet_classes::compiler_version::VersionId as CairoLangVersionId; +use num_traits::ToPrimitive; +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; +use thiserror::Error; +use validator::Validate; + +#[derive(Debug, Error)] +#[cfg_attr(test, derive(PartialEq))] +pub enum VersionIdError { + #[error("{message}")] + InvalidVersion { message: String }, +} + +// TODO(Arni): Share this struct with the Cairo lang crate. +#[derive(Clone, Copy, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct VersionId { + pub major: usize, + pub minor: usize, + pub patch: usize, +} + +impl VersionId { + pub const MIN: Self = Self { major: 0, minor: 0, patch: 0 }; + pub const MAX: Self = Self { major: usize::MAX, minor: usize::MAX, patch: usize::MAX }; +} + +impl From<&VersionId> for CairoLangVersionId { + fn from(version: &VersionId) -> Self { + CairoLangVersionId { major: version.major, minor: version.minor, patch: version.patch } + } +} + +impl std::fmt::Display for VersionId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + CairoLangVersionId::from(self).fmt(f) + } +} + +impl VersionId { + pub fn from_sierra_program(sierra_program: &[Felt]) -> Result { + let sierra_program_length = sierra_program.len(); + + if sierra_program_length < 3 { + return Err(VersionIdError::InvalidVersion { + message: format!( + "Sierra program is too short. got program of length {} which is not long \ + enough to hold the version field.", + sierra_program_length + ), + }); + } + + fn get_version_component( + sierra_program: &[Felt], + index: usize, + ) -> Result { + let felt = &sierra_program[index]; + felt.to_usize().ok_or(VersionIdError::InvalidVersion { + message: format!("version contains a value that is out of range: {:?}", felt), + }) + } + + Ok(VersionId { + major: get_version_component(sierra_program, 0)?, + minor: get_version_component(sierra_program, 1)?, + patch: get_version_component(sierra_program, 2)?, + }) + } +} + +impl PartialOrd for VersionId { + fn partial_cmp(&self, other: &Self) -> Option { + if self.major != other.major { + return Some(self.major.cmp(&other.major)); + } + if self.minor != other.minor { + return Some(self.minor.cmp(&other.minor)); + } + self.patch.partial_cmp(&other.patch) + } +} + +impl SerializeConfig for VersionId { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "major", + &self.major, + "The major version of the configuration.", + ParamPrivacyInput::Public, + ), + ser_param( + "minor", + &self.minor, + "The minor version of the configuration.", + ParamPrivacyInput::Public, + ), + ser_param( + "patch", + &self.patch, + "The patch version of the configuration.", + ParamPrivacyInput::Public, + ), + ]) + } +} diff --git a/crates/gateway/src/config.rs b/crates/gateway/src/config.rs new file mode 100644 index 00000000000..49970fa7a0c --- /dev/null +++ b/crates/gateway/src/config.rs @@ -0,0 +1,306 @@ +use std::collections::BTreeMap; +use std::net::IpAddr; + +use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; +use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ChainId, ContractAddress, Nonce}; +use starknet_types_core::felt::Felt; +use validator::Validate; + +use crate::compiler_version::VersionId; + +#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] +pub struct GatewayConfig { + pub network_config: GatewayNetworkConfig, + pub stateless_tx_validator_config: StatelessTransactionValidatorConfig, + pub stateful_tx_validator_config: StatefulTransactionValidatorConfig, + pub compiler_config: GatewayCompilerConfig, +} + +impl SerializeConfig for GatewayConfig { + fn dump(&self) -> BTreeMap { + vec![ + append_sub_config_name(self.network_config.dump(), "network_config"), + append_sub_config_name( + self.stateless_tx_validator_config.dump(), + "stateless_tx_validator_config", + ), + append_sub_config_name( + self.stateful_tx_validator_config.dump(), + "stateful_tx_validator_config", + ), + append_sub_config_name(self.compiler_config.dump(), "compiler_config"), + ] + .into_iter() + .flatten() + .collect() + } +} + +/// The gateway network connection related configuration. +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct GatewayNetworkConfig { + pub ip: IpAddr, + pub port: u16, +} + +impl SerializeConfig for GatewayNetworkConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "ip", + &self.ip.to_string(), + "The gateway server ip.", + ParamPrivacyInput::Public, + ), + ser_param("port", &self.port, "The gateway server port.", ParamPrivacyInput::Public), + ]) + } +} + +impl Default for GatewayNetworkConfig { + fn default() -> Self { + Self { ip: "0.0.0.0".parse().unwrap(), port: 8080 } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct StatelessTransactionValidatorConfig { + // If true, validates that the resource bounds are not zero. + pub validate_non_zero_l1_gas_fee: bool, + pub validate_non_zero_l2_gas_fee: bool, + pub max_calldata_length: usize, + pub max_signature_length: usize, + + // Declare txs specific config. + pub max_bytecode_size: usize, + pub max_raw_class_size: usize, + pub min_sierra_version: VersionId, + pub max_sierra_version: VersionId, +} + +impl Default for StatelessTransactionValidatorConfig { + fn default() -> Self { + StatelessTransactionValidatorConfig { + validate_non_zero_l1_gas_fee: true, + validate_non_zero_l2_gas_fee: false, + max_calldata_length: 4000, + max_signature_length: 4000, + max_bytecode_size: 81920, + max_raw_class_size: 4089446, + min_sierra_version: VersionId { major: 1, minor: 1, patch: 0 }, + max_sierra_version: VersionId { major: 1, minor: 5, patch: usize::MAX }, + } + } +} + +impl SerializeConfig for StatelessTransactionValidatorConfig { + fn dump(&self) -> BTreeMap { + let members = BTreeMap::from_iter([ + ser_param( + "validate_non_zero_l1_gas_fee", + &self.validate_non_zero_l1_gas_fee, + "If true, validates that a transaction has non-zero L1 resource bounds.", + ParamPrivacyInput::Public, + ), + ser_param( + "validate_non_zero_l2_gas_fee", + &self.validate_non_zero_l2_gas_fee, + "If true, validates that a transaction has non-zero L2 resource bounds.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_signature_length", + &self.max_signature_length, + "Limitation of signature length.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_calldata_length", + &self.max_calldata_length, + "Limitation of calldata length.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_bytecode_size", + &self.max_bytecode_size, + "Limitation of contract bytecode size.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_raw_class_size", + &self.max_raw_class_size, + "Limitation of contract class object size.", + ParamPrivacyInput::Public, + ), + ]); + vec![ + members, + append_sub_config_name(self.min_sierra_version.dump(), "min_sierra_version"), + append_sub_config_name(self.max_sierra_version.dump(), "max_sierra_version"), + ] + .into_iter() + .flatten() + .collect() + } +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] +pub struct RpcStateReaderConfig { + pub url: String, + pub json_rpc_version: String, +} + +#[cfg(any(feature = "testing", test))] +impl RpcStateReaderConfig { + pub fn create_for_testing() -> Self { + Self { url: "http://localhost:8080".to_string(), json_rpc_version: "2.0".to_string() } + } +} + +impl SerializeConfig for RpcStateReaderConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param("url", &self.url, "The url of the rpc server.", ParamPrivacyInput::Public), + ser_param( + "json_rpc_version", + &self.json_rpc_version, + "The json rpc version.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +// TODO(Arni): Remove this struct once Chain info supports Papyrus serialization. +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct ChainInfoConfig { + pub chain_id: ChainId, + pub strk_fee_token_address: ContractAddress, + pub eth_fee_token_address: ContractAddress, +} + +impl From for ChainInfo { + fn from(chain_info: ChainInfoConfig) -> Self { + Self { + chain_id: chain_info.chain_id, + fee_token_addresses: FeeTokenAddresses { + strk_fee_token_address: chain_info.strk_fee_token_address, + eth_fee_token_address: chain_info.eth_fee_token_address, + }, + } + } +} + +impl From for ChainInfoConfig { + fn from(chain_info: ChainInfo) -> Self { + let FeeTokenAddresses { strk_fee_token_address, eth_fee_token_address } = + chain_info.fee_token_addresses; + Self { chain_id: chain_info.chain_id, strk_fee_token_address, eth_fee_token_address } + } +} + +impl Default for ChainInfoConfig { + fn default() -> Self { + ChainInfo::default().into() + } +} + +impl ChainInfoConfig { + pub fn create_for_testing() -> Self { + BlockContext::create_for_testing().chain_info().clone().into() + } +} + +impl SerializeConfig for ChainInfoConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "chain_id", + &self.chain_id, + "The chain ID of the StarkNet chain.", + ParamPrivacyInput::Public, + ), + ser_param( + "strk_fee_token_address", + &self.strk_fee_token_address, + "Address of the STRK fee token.", + ParamPrivacyInput::Public, + ), + ser_param( + "eth_fee_token_address", + &self.eth_fee_token_address, + "Address of the ETH fee token.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct StatefulTransactionValidatorConfig { + pub max_nonce_for_validation_skip: Nonce, + pub validate_max_n_steps: u32, + pub max_recursion_depth: usize, + pub chain_info: ChainInfoConfig, +} + +impl Default for StatefulTransactionValidatorConfig { + fn default() -> Self { + StatefulTransactionValidatorConfig { + max_nonce_for_validation_skip: Nonce(Felt::ONE), + validate_max_n_steps: 1_000_000, + max_recursion_depth: 50, + chain_info: ChainInfoConfig::default(), + } + } +} + +impl SerializeConfig for StatefulTransactionValidatorConfig { + fn dump(&self) -> BTreeMap { + let members = BTreeMap::from_iter([ + ser_param( + "max_nonce_for_validation_skip", + &self.max_nonce_for_validation_skip, + "Maximum nonce for which the validation is skipped.", + ParamPrivacyInput::Public, + ), + ser_param( + "validate_max_n_steps", + &self.validate_max_n_steps, + "Maximum number of steps the validation function is allowed to take.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_recursion_depth", + &self.max_recursion_depth, + "Maximum recursion depth for nested calls during blockifier validation.", + ParamPrivacyInput::Public, + ), + ]); + let sub_configs = append_sub_config_name(self.chain_info.dump(), "chain_info"); + vec![members, sub_configs].into_iter().flatten().collect() + } +} + +impl StatefulTransactionValidatorConfig { + pub fn create_for_testing() -> Self { + StatefulTransactionValidatorConfig { + max_nonce_for_validation_skip: Default::default(), + validate_max_n_steps: 1000000, + max_recursion_depth: 50, + chain_info: ChainInfoConfig::create_for_testing(), + } + } +} + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] +pub struct GatewayCompilerConfig {} + +impl SerializeConfig for GatewayCompilerConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::new() + } +} diff --git a/crates/gateway/src/errors.rs b/crates/gateway/src/errors.rs new file mode 100644 index 00000000000..0ea24fba0cc --- /dev/null +++ b/crates/gateway/src/errors.rs @@ -0,0 +1,155 @@ +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use blockifier::blockifier::stateful_validator::StatefulValidatorError; +use blockifier::execution::errors::ContractClassError; +use blockifier::state::errors::StateError; +use blockifier::transaction::errors::TransactionExecutionError; +use cairo_vm::types::errors::program_errors::ProgramError; +use serde_json::{Error as SerdeError, Value}; +use starknet_api::block::GasPrice; +use starknet_api::core::CompiledClassHash; +use starknet_api::transaction::{Resource, ResourceBounds}; +use starknet_api::StarknetApiError; +use starknet_sierra_compile::errors::CompilationUtilError; +use thiserror::Error; +use tokio::task::JoinError; + +use crate::compiler_version::{VersionId, VersionIdError}; + +/// Errors directed towards the end-user, as a result of gateway requests. +#[derive(Debug, Error)] +pub enum GatewayError { + #[error(transparent)] + CompilationError(#[from] CompilationUtilError), + #[error( + "The supplied compiled class hash {supplied:?} does not match the hash of the Casm class \ + compiled from the supplied Sierra {hash_result:?}" + )] + CompiledClassHashMismatch { supplied: CompiledClassHash, hash_result: CompiledClassHash }, + #[error(transparent)] + DeclaredContractClassError(#[from] ContractClassError), + #[error(transparent)] + DeclaredContractProgramError(#[from] ProgramError), + #[error("Internal server error: {0}")] + InternalServerError(#[from] JoinError), + #[error("Error sending message: {0}")] + MessageSendError(String), + #[error(transparent)] + StatefulTransactionValidatorError(#[from] StatefulTransactionValidatorError), + #[error(transparent)] + StatelessTransactionValidatorError(#[from] StatelessTransactionValidatorError), + #[error("{builtins:?} is not a subsquence of {supported_builtins:?}")] + UnsupportedBuiltins { builtins: Vec, supported_builtins: Vec }, +} + +pub type GatewayResult = Result; + +impl IntoResponse for GatewayError { + // TODO(Arni, 1/5/2024): Be more fine tuned about the error response. Not all Gateway errors + // are internal server errors. + fn into_response(self) -> Response { + let body = self.to_string(); + (StatusCode::INTERNAL_SERVER_ERROR, body).into_response() + } +} + +#[derive(Debug, Error)] +#[cfg_attr(test, derive(PartialEq))] +pub enum StatelessTransactionValidatorError { + #[error("Expected a positive amount of {resource:?}. Got {resource_bounds:?}.")] + ZeroResourceBounds { resource: Resource, resource_bounds: ResourceBounds }, + #[error( + "Calldata length exceeded maximum: length {calldata_length} + (allowed length: {max_calldata_length})." + )] + CalldataTooLong { calldata_length: usize, max_calldata_length: usize }, + #[error( + "Signature length exceeded maximum: length {signature_length} + (allowed length: {max_signature_length})." + )] + SignatureTooLong { signature_length: usize, max_signature_length: usize }, + #[error(transparent)] + InvalidSierraVersion(#[from] VersionIdError), + #[error( + "Sierra versions older than {min_version} or newer than {max_version} are not supported. \ + The Sierra version of the declared contract is {version}." + )] + UnsupportedSierraVersion { version: VersionId, min_version: VersionId, max_version: VersionId }, + #[error( + "Cannot declare contract class with bytecode size of {bytecode_size}; max allowed size: \ + {max_bytecode_size}." + )] + BytecodeSizeTooLarge { bytecode_size: usize, max_bytecode_size: usize }, + #[error( + "Cannot declare contract class with size of {contract_class_object_size}; max allowed \ + size: {max_contract_class_object_size}." + )] + ContractClassObjectSizeTooLarge { + contract_class_object_size: usize, + max_contract_class_object_size: usize, + }, + #[error("Entry points must be unique and sorted.")] + EntryPointsNotUniquelySorted, +} + +pub type StatelessTransactionValidatorResult = Result; + +#[derive(Debug, Error)] +pub enum StatefulTransactionValidatorError { + #[error(transparent)] + StarknetApiError(#[from] StarknetApiError), + #[error(transparent)] + StateError(#[from] StateError), + #[error(transparent)] + StatefulValidatorError(#[from] StatefulValidatorError), + #[error(transparent)] + TransactionExecutionError(#[from] TransactionExecutionError), +} + +pub type StatefulTransactionValidatorResult = Result; + +/// Errors originating from `[`Gateway::run`]` command, to be handled by infrastructure code. +#[derive(Debug, Error)] +pub enum GatewayRunError { + #[error(transparent)] + ServerStartupError(#[from] hyper::Error), +} + +#[derive(Debug, Error)] +pub enum RPCStateReaderError { + #[error("Block not found for request {0}")] + BlockNotFound(Value), + #[error("Class hash not found for request {0}")] + ClassHashNotFound(Value), + #[error("Failed to parse gas price {:?}", 0)] + GasPriceParsingFailure(GasPrice), + #[error("Contract address not found for request {0}")] + ContractAddressNotFound(Value), + #[error(transparent)] + ReqwestError(#[from] reqwest::Error), + #[error("RPC error: {0}")] + RPCError(StatusCode), + #[error("Unexpected error code: {0}")] + UnexpectedErrorCode(u16), +} + +pub type RPCStateReaderResult = Result; + +impl From for StateError { + fn from(err: RPCStateReaderError) -> Self { + match err { + RPCStateReaderError::ClassHashNotFound(request) => { + match serde_json::from_value(request["params"]["class_hash"].clone()) { + Ok(class_hash) => StateError::UndeclaredClassHash(class_hash), + Err(e) => serde_err_to_state_err(e), + } + } + _ => StateError::StateReadError(err.to_string()), + } + } +} + +// Converts a serde error to the error type of the state reader. +pub fn serde_err_to_state_err(err: SerdeError) -> StateError { + StateError::StateReadError(format!("Failed to parse rpc result {:?}", err.to_string())) +} diff --git a/crates/gateway/src/gateway.rs b/crates/gateway/src/gateway.rs new file mode 100644 index 00000000000..61c1b4764e8 --- /dev/null +++ b/crates/gateway/src/gateway.rs @@ -0,0 +1,162 @@ +use std::clone::Clone; +use std::net::SocketAddr; +use std::sync::Arc; + +use async_trait::async_trait; +use axum::extract::State; +use axum::routing::{get, post}; +use axum::{Json, Router}; +use starknet_api::rpc_transaction::RPCTransaction; +use starknet_api::transaction::TransactionHash; +use starknet_mempool_infra::component_runner::{ComponentStartError, ComponentStarter}; +use starknet_mempool_types::communication::SharedMempoolClient; +use starknet_mempool_types::mempool_types::{Account, MempoolInput}; +use tracing::{info, instrument}; + +use crate::compilation::GatewayCompiler; +use crate::config::{GatewayConfig, GatewayNetworkConfig, RpcStateReaderConfig}; +use crate::errors::{GatewayError, GatewayResult, GatewayRunError}; +use crate::rpc_state_reader::RpcStateReaderFactory; +use crate::state_reader::StateReaderFactory; +use crate::stateful_transaction_validator::StatefulTransactionValidator; +use crate::stateless_transaction_validator::StatelessTransactionValidator; +use crate::utils::{external_tx_to_thin_tx, get_sender_address}; + +#[cfg(test)] +#[path = "gateway_test.rs"] +pub mod gateway_test; + +pub struct Gateway { + pub config: GatewayConfig, + app_state: AppState, +} + +#[derive(Clone)] +pub struct AppState { + pub stateless_tx_validator: StatelessTransactionValidator, + pub stateful_tx_validator: Arc, + pub state_reader_factory: Arc, + pub gateway_compiler: GatewayCompiler, + pub mempool_client: SharedMempoolClient, +} + +impl Gateway { + pub fn new( + config: GatewayConfig, + state_reader_factory: Arc, + gateway_compiler: GatewayCompiler, + mempool_client: SharedMempoolClient, + ) -> Self { + let app_state = AppState { + stateless_tx_validator: StatelessTransactionValidator { + config: config.stateless_tx_validator_config.clone(), + }, + stateful_tx_validator: Arc::new(StatefulTransactionValidator { + config: config.stateful_tx_validator_config.clone(), + }), + state_reader_factory, + gateway_compiler, + mempool_client, + }; + Gateway { config, app_state } + } + + pub async fn run(&mut self) -> Result<(), GatewayRunError> { + // Parses the bind address from GatewayConfig, returning an error for invalid addresses. + let GatewayNetworkConfig { ip, port } = self.config.network_config; + let addr = SocketAddr::new(ip, port); + let app = self.app(); + + // Create a server that runs forever. + Ok(axum::Server::bind(&addr).serve(app.into_make_service()).await?) + } + + pub fn app(&self) -> Router { + Router::new() + .route("/is_alive", get(is_alive)) + .route("/add_tx", post(add_tx)) + .with_state(self.app_state.clone()) + } +} + +// Gateway handlers. + +#[instrument] +async fn is_alive() -> GatewayResult { + unimplemented!("Future handling should be implemented here."); +} + +#[instrument(skip(app_state))] +async fn add_tx( + State(app_state): State, + Json(tx): Json, +) -> GatewayResult> { + let mempool_input = tokio::task::spawn_blocking(move || { + process_tx( + app_state.stateless_tx_validator, + app_state.stateful_tx_validator.as_ref(), + app_state.state_reader_factory.as_ref(), + app_state.gateway_compiler, + tx, + ) + }) + .await??; + + let tx_hash = mempool_input.tx.tx_hash; + + app_state + .mempool_client + .add_tx(mempool_input) + .await + .map_err(|e| GatewayError::MessageSendError(e.to_string()))?; + // TODO: Also return `ContractAddress` for deploy and `ClassHash` for Declare. + Ok(Json(tx_hash)) +} + +fn process_tx( + stateless_tx_validator: StatelessTransactionValidator, + stateful_tx_validator: &StatefulTransactionValidator, + state_reader_factory: &dyn StateReaderFactory, + gateway_compiler: GatewayCompiler, + tx: RPCTransaction, +) -> GatewayResult { + // TODO(Arni, 1/5/2024): Perform congestion control. + + // Perform stateless validations. + stateless_tx_validator.validate(&tx)?; + + // Compile Sierra to Casm. + let optional_class_info = match &tx { + RPCTransaction::Declare(declare_tx) => { + Some(gateway_compiler.process_declare_tx(declare_tx)?) + } + _ => None, + }; + + let validator = stateful_tx_validator.instantiate_validator(state_reader_factory)?; + let tx_hash = stateful_tx_validator.run_validate(&tx, optional_class_info, validator)?; + + // TODO(Arni): Add the Sierra and the Casm to the mempool input. + Ok(MempoolInput { + tx: external_tx_to_thin_tx(&tx, tx_hash), + account: Account { sender_address: get_sender_address(&tx), ..Default::default() }, + }) +} + +pub fn create_gateway( + config: GatewayConfig, + rpc_state_reader_config: RpcStateReaderConfig, + mempool_client: SharedMempoolClient, +) -> Gateway { + let state_reader_factory = Arc::new(RpcStateReaderFactory { config: rpc_state_reader_config }); + let gateway_compiler = GatewayCompiler { config: config.compiler_config }; + Gateway::new(config, state_reader_factory, gateway_compiler, mempool_client) +} + +#[async_trait] +impl ComponentStarter for Gateway { + async fn start(&mut self) -> Result<(), ComponentStartError> { + info!("Gateway::start()"); + self.run().await.map_err(|_| ComponentStartError::InternalComponentError) + } +} diff --git a/crates/gateway/src/gateway_test.rs b/crates/gateway/src/gateway_test.rs new file mode 100644 index 00000000000..d88d55cbb48 --- /dev/null +++ b/crates/gateway/src/gateway_test.rs @@ -0,0 +1,109 @@ +use std::sync::Arc; + +use axum::body::{Bytes, HttpBody}; +use axum::extract::State; +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use blockifier::context::ChainInfo; +use blockifier::test_utils::CairoVersion; +use mempool_test_utils::starknet_api_test_utils::invoke_tx; +use mockall::predicate::eq; +use starknet_api::core::ContractAddress; +use starknet_api::rpc_transaction::RPCTransaction; +use starknet_api::transaction::TransactionHash; +use starknet_mempool_types::communication::MockMempoolClient; +use starknet_mempool_types::mempool_types::{Account, AccountState, MempoolInput, ThinTransaction}; + +use crate::compilation::GatewayCompiler; +use crate::config::{ + GatewayCompilerConfig, StatefulTransactionValidatorConfig, StatelessTransactionValidatorConfig, +}; +use crate::gateway::{add_tx, AppState, SharedMempoolClient}; +use crate::state_reader_test_utils::{local_test_state_reader_factory, TestStateReaderFactory}; +use crate::stateful_transaction_validator::StatefulTransactionValidator; +use crate::stateless_transaction_validator::StatelessTransactionValidator; +use crate::utils::{external_tx_to_account_tx, get_tx_hash}; + +pub fn app_state( + mempool_client: SharedMempoolClient, + state_reader_factory: TestStateReaderFactory, +) -> AppState { + AppState { + stateless_tx_validator: StatelessTransactionValidator { + config: StatelessTransactionValidatorConfig { + validate_non_zero_l1_gas_fee: true, + max_calldata_length: 10, + max_signature_length: 2, + max_bytecode_size: 10000, + max_raw_class_size: 1000000, + ..Default::default() + }, + }, + stateful_tx_validator: Arc::new(StatefulTransactionValidator { + config: StatefulTransactionValidatorConfig::create_for_testing(), + }), + gateway_compiler: GatewayCompiler { config: GatewayCompilerConfig {} }, + state_reader_factory: Arc::new(state_reader_factory), + mempool_client, + } +} + +type SenderAddress = ContractAddress; + +fn create_tx() -> (RPCTransaction, SenderAddress) { + let tx = invoke_tx(CairoVersion::Cairo1); + let sender_address = match &tx { + RPCTransaction::Invoke(starknet_api::rpc_transaction::RPCInvokeTransaction::V3( + invoke_tx, + )) => invoke_tx.sender_address, + _ => panic!("Unexpected transaction type"), + }; + (tx, sender_address) +} + +#[tokio::test] +async fn test_add_tx() { + let (tx, sender_address) = create_tx(); + let tx_hash = calculate_hash(&tx); + + let mut mock_mempool_client = MockMempoolClient::new(); + mock_mempool_client + .expect_add_tx() + .once() + .with(eq(MempoolInput { + tx: ThinTransaction { sender_address, tx_hash, tip: *tx.tip(), nonce: *tx.nonce() }, + account: Account { sender_address, state: AccountState { nonce: *tx.nonce() } }, + })) + .return_once(|_| Ok(())); + let state_reader_factory = local_test_state_reader_factory(CairoVersion::Cairo1, false); + let app_state = app_state(Arc::new(mock_mempool_client), state_reader_factory); + + let response = add_tx(State(app_state), tx.into()).await.into_response(); + + let status_code = response.status(); + let response_bytes = &to_bytes(response).await; + + assert_eq!(status_code, StatusCode::OK, "{response_bytes:?}"); + assert_eq!(tx_hash, serde_json::from_slice(response_bytes).unwrap()); +} + +async fn to_bytes(res: Response) -> Bytes { + res.into_body().collect().await.unwrap().to_bytes() +} + +fn calculate_hash(external_tx: &RPCTransaction) -> TransactionHash { + let optional_class_info = match &external_tx { + RPCTransaction::Declare(_declare_tx) => { + panic!("Declare transactions are not supported in this test") + } + _ => None, + }; + + let account_tx = external_tx_to_account_tx( + external_tx, + optional_class_info, + &ChainInfo::create_for_testing().chain_id, + ) + .unwrap(); + get_tx_hash(&account_tx) +} diff --git a/crates/gateway/src/lib.rs b/crates/gateway/src/lib.rs new file mode 100644 index 00000000000..bb9ff7c55fa --- /dev/null +++ b/crates/gateway/src/lib.rs @@ -0,0 +1,18 @@ +pub mod communication; +mod compilation; +mod compiler_version; +pub mod config; +pub mod errors; +pub mod gateway; +mod rpc_objects; +mod rpc_state_reader; +#[cfg(test)] +mod rpc_state_reader_test; +mod state_reader; +#[cfg(test)] +mod state_reader_test_utils; +mod stateful_transaction_validator; +mod stateless_transaction_validator; +#[cfg(test)] +mod test_utils; +mod utils; diff --git a/crates/gateway/src/rpc_objects.rs b/crates/gateway/src/rpc_objects.rs new file mode 100644 index 00000000000..15adf23c15f --- /dev/null +++ b/crates/gateway/src/rpc_objects.rs @@ -0,0 +1,127 @@ +use std::num::NonZeroU128; + +use blockifier::blockifier::block::{BlockInfo, GasPrices}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp, GasPrice}; +use starknet_api::core::{ClassHash, ContractAddress, GlobalRoot}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::state::StorageKey; + +use crate::errors::RPCStateReaderError; + +// Starknet Spec error codes: +// TODO(yael 30/4/2024): consider turning these into an enum. +pub const RPC_ERROR_CONTRACT_ADDRESS_NOT_FOUND: u16 = 20; +pub const RPC_ERROR_BLOCK_NOT_FOUND: u16 = 24; +pub const RPC_CLASS_HASH_NOT_FOUND: u16 = 28; + +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] +pub enum BlockId { + #[serde(rename = "latest")] + Latest, + #[serde(rename = "pending")] + Pending, + #[serde(rename = "block_hash")] + Hash(BlockHash), + #[serde(rename = "block_number")] + Number(BlockNumber), +} + +#[derive(Serialize, Deserialize)] +pub struct GetNonceParams { + pub block_id: BlockId, + pub contract_address: ContractAddress, +} + +#[derive(Serialize, Deserialize)] +pub struct GetStorageAtParams { + pub contract_address: ContractAddress, + pub key: StorageKey, + pub block_id: BlockId, +} + +#[derive(Serialize, Deserialize)] +pub struct GetClassHashAtParams { + pub contract_address: ContractAddress, + pub block_id: BlockId, +} + +#[derive(Serialize, Deserialize)] +pub struct GetCompiledContractClassParams { + pub class_hash: ClassHash, + pub block_id: BlockId, +} + +#[derive(Deserialize, Serialize)] +pub struct GetBlockWithTxHashesParams { + pub block_id: BlockId, +} + +#[derive(Debug, Default, Deserialize, Serialize)] +pub struct ResourcePrice { + pub price_in_wei: GasPrice, + pub price_in_fri: GasPrice, +} + +#[derive(Debug, Default, Deserialize, Serialize)] +pub struct BlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub sequencer_address: ContractAddress, + pub new_root: GlobalRoot, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub l1_data_gas_price: ResourcePrice, + pub l1_da_mode: L1DataAvailabilityMode, + pub starknet_version: String, +} + +impl TryInto for BlockHeader { + type Error = RPCStateReaderError; + fn try_into(self) -> Result { + Ok(BlockInfo { + block_number: self.block_number, + sequencer_address: self.sequencer_address, + block_timestamp: self.timestamp, + gas_prices: GasPrices { + eth_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_wei)?, + strk_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_fri)?, + eth_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_wei)?, + strk_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_fri)?, + }, + use_kzg_da: matches!(self.l1_da_mode, L1DataAvailabilityMode::Blob), + }) + } +} + +fn parse_gas_price(gas_price: GasPrice) -> Result { + NonZeroU128::new(gas_price.0).ok_or(RPCStateReaderError::GasPriceParsingFailure(gas_price)) +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(untagged)] +pub enum RpcResponse { + Success(RpcSuccessResponse), + Error(RpcErrorResponse), +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct RpcSuccessResponse { + pub jsonrpc: Option, + pub result: Value, + pub id: u32, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct RpcErrorResponse { + pub jsonrpc: Option, + pub error: RpcSpecError, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct RpcSpecError { + pub code: u16, + pub message: String, +} diff --git a/crates/gateway/src/rpc_state_reader.rs b/crates/gateway/src/rpc_state_reader.rs new file mode 100644 index 00000000000..a5af4fe6dfc --- /dev/null +++ b/crates/gateway/src/rpc_state_reader.rs @@ -0,0 +1,171 @@ +use blockifier::blockifier::block::BlockInfo; +use blockifier::execution::contract_class::{ContractClass, ContractClassV0, ContractClassV1}; +use blockifier::state::errors::StateError; +use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult}; +use papyrus_rpc::CompiledContractClass; +use reqwest::blocking::Client as BlockingClient; +use serde::Serialize; +use serde_json::{json, Value}; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::StorageKey; +use starknet_types_core::felt::Felt; + +use crate::config::RpcStateReaderConfig; +use crate::errors::{serde_err_to_state_err, RPCStateReaderError, RPCStateReaderResult}; +use crate::rpc_objects::{ + BlockHeader, BlockId, GetBlockWithTxHashesParams, GetClassHashAtParams, + GetCompiledContractClassParams, GetNonceParams, GetStorageAtParams, RpcResponse, + RPC_CLASS_HASH_NOT_FOUND, RPC_ERROR_BLOCK_NOT_FOUND, RPC_ERROR_CONTRACT_ADDRESS_NOT_FOUND, +}; +use crate::state_reader::{MempoolStateReader, StateReaderFactory}; + +pub struct RpcStateReader { + pub config: RpcStateReaderConfig, + pub block_id: BlockId, +} + +impl RpcStateReader { + pub fn from_number(config: &RpcStateReaderConfig, block_number: BlockNumber) -> Self { + Self { config: config.clone(), block_id: BlockId::Number(block_number) } + } + pub fn from_latest(config: &RpcStateReaderConfig) -> Self { + Self { config: config.clone(), block_id: BlockId::Latest } + } + // Note: This function is blocking though it is sending a request to the rpc server and waiting + // for the response. + pub fn send_rpc_request( + &self, + method: &str, + params: impl Serialize, + ) -> RPCStateReaderResult { + let request_body = json!({ + "jsonrpc": self.config.json_rpc_version, + "id": 0, + "method": method, + "params": json!(params), + }); + + let client = BlockingClient::new(); + let response = client + .post(self.config.url.clone()) + .header("Content-Type", "application/json") + .json(&request_body) + .send()?; + + if !response.status().is_success() { + return Err(RPCStateReaderError::RPCError(response.status())); + } + + let rpc_response: RpcResponse = response.json::()?; + + match rpc_response { + RpcResponse::Success(rpc_success_response) => Ok(rpc_success_response.result), + RpcResponse::Error(rpc_error_response) => match rpc_error_response.error.code { + RPC_ERROR_BLOCK_NOT_FOUND => Err(RPCStateReaderError::BlockNotFound(request_body)), + RPC_ERROR_CONTRACT_ADDRESS_NOT_FOUND => { + Err(RPCStateReaderError::ContractAddressNotFound(request_body)) + } + RPC_CLASS_HASH_NOT_FOUND => { + Err(RPCStateReaderError::ClassHashNotFound(request_body)) + } + _ => Err(RPCStateReaderError::UnexpectedErrorCode(rpc_error_response.error.code)), + }, + } + } +} + +impl MempoolStateReader for RpcStateReader { + fn get_block_info(&self) -> StateResult { + let get_block_params = GetBlockWithTxHashesParams { block_id: self.block_id }; + + // The response from the rpc is a full block but we only deserialize the header. + let block_header: BlockHeader = serde_json::from_value( + self.send_rpc_request("starknet_getBlockWithTxHashes", get_block_params)?, + ) + .map_err(serde_err_to_state_err)?; + let block_info = block_header.try_into()?; + Ok(block_info) + } +} + +impl BlockifierStateReader for RpcStateReader { + fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + ) -> StateResult { + let get_storage_at_params = + GetStorageAtParams { block_id: self.block_id, contract_address, key }; + + let result = self.send_rpc_request("starknet_getStorageAt", get_storage_at_params)?; + let value: Felt = serde_json::from_value(result).map_err(serde_err_to_state_err)?; + Ok(value) + } + + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { + let get_nonce_params = GetNonceParams { block_id: self.block_id, contract_address }; + + let result = self.send_rpc_request("starknet_getNonce", get_nonce_params); + match result { + Ok(value) => { + let nonce: Nonce = serde_json::from_value(value).map_err(serde_err_to_state_err)?; + Ok(nonce) + } + Err(RPCStateReaderError::ContractAddressNotFound(_)) => Ok(Nonce::default()), + Err(e) => Err(e)?, + } + } + + fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { + let get_compiled_class_params = + GetCompiledContractClassParams { class_hash, block_id: self.block_id }; + + let result = + self.send_rpc_request("starknet_getCompiledContractClass", get_compiled_class_params)?; + let contract_class: CompiledContractClass = + serde_json::from_value(result).map_err(serde_err_to_state_err)?; + match contract_class { + CompiledContractClass::V1(contract_class_v1) => Ok(ContractClass::V1( + ContractClassV1::try_from(contract_class_v1).map_err(StateError::ProgramError)?, + )), + CompiledContractClass::V0(contract_class_v0) => Ok(ContractClass::V0( + ContractClassV0::try_from(contract_class_v0).map_err(StateError::ProgramError)?, + )), + } + } + + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { + let get_class_hash_at_params = + GetClassHashAtParams { contract_address, block_id: self.block_id }; + + let result = self.send_rpc_request("starknet_getClassHashAt", get_class_hash_at_params); + match result { + Ok(value) => { + let class_hash: ClassHash = + serde_json::from_value(value).map_err(serde_err_to_state_err)?; + Ok(class_hash) + } + Err(RPCStateReaderError::ContractAddressNotFound(_)) => Ok(ClassHash::default()), + Err(e) => Err(e)?, + } + } + + fn get_compiled_class_hash(&self, _class_hash: ClassHash) -> StateResult { + todo!() + } +} + +pub struct RpcStateReaderFactory { + pub config: RpcStateReaderConfig, +} + +impl StateReaderFactory for RpcStateReaderFactory { + fn get_state_reader_from_latest_block(&self) -> Box { + Box::new(RpcStateReader::from_latest(&self.config)) + } + + fn get_state_reader(&self, block_number: BlockNumber) -> Box { + Box::new(RpcStateReader::from_number(&self.config, block_number)) + } +} diff --git a/crates/gateway/src/rpc_state_reader_test.rs b/crates/gateway/src/rpc_state_reader_test.rs new file mode 100644 index 00000000000..3596d484d12 --- /dev/null +++ b/crates/gateway/src/rpc_state_reader_test.rs @@ -0,0 +1,205 @@ +use blockifier::execution::contract_class::ContractClass; +use blockifier::state::state_api::StateReader; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use papyrus_rpc::CompiledContractClass; +use serde::Serialize; +use serde_json::json; +use starknet_api::block::{BlockNumber, GasPrice}; +use starknet_api::core::{ClassHash, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::{class_hash, contract_address, felt, patricia_key}; + +use crate::config::RpcStateReaderConfig; +use crate::rpc_objects::{ + BlockHeader, BlockId, GetBlockWithTxHashesParams, GetClassHashAtParams, + GetCompiledContractClassParams, GetNonceParams, GetStorageAtParams, ResourcePrice, RpcResponse, + RpcSuccessResponse, +}; +use crate::rpc_state_reader::RpcStateReader; +use crate::state_reader::MempoolStateReader; + +async fn run_rpc_server() -> mockito::ServerGuard { + mockito::Server::new_async().await +} + +fn mock_rpc_interaction( + server: &mut mockito::ServerGuard, + json_rpc_version: &str, + method: &str, + params: impl Serialize, + expected_response: &RpcResponse, +) -> mockito::Mock { + let request_body = json!({ + "jsonrpc": json_rpc_version, + "id": 0, + "method": method, + "params": json!(params), + }); + server + .mock("POST", "/") + .match_header("Content-Type", "application/json") + .match_body(mockito::Matcher::Json(request_body)) + .with_status(201) + .with_body(serde_json::to_string(expected_response).unwrap()) + .create() +} + +#[tokio::test] +async fn test_get_block_info() { + let mut server = run_rpc_server().await; + let config = RpcStateReaderConfig { url: server.url(), ..Default::default() }; + + let expected_result = BlockNumber(100); + + let mock = mock_rpc_interaction( + &mut server, + &config.json_rpc_version, + "starknet_getBlockWithTxHashes", + GetBlockWithTxHashesParams { block_id: BlockId::Latest }, + &RpcResponse::Success(RpcSuccessResponse { + result: serde_json::to_value(BlockHeader { + block_number: expected_result, + // GasPrice must be non-zero. + l1_gas_price: ResourcePrice { + price_in_wei: GasPrice(1), + price_in_fri: GasPrice(1), + }, + l1_data_gas_price: ResourcePrice { + price_in_wei: GasPrice(1), + price_in_fri: GasPrice(1), + }, + ..Default::default() + }) + .unwrap(), + ..Default::default() + }), + ); + + let client = RpcStateReader::from_latest(&config); + let result = + tokio::task::spawn_blocking(move || client.get_block_info()).await.unwrap().unwrap(); + // TODO(yair): Add partial_eq for BlockInfo and assert_eq the whole BlockInfo. + assert_eq!(result.block_number, expected_result); + mock.assert_async().await; +} + +#[tokio::test] +async fn test_get_storage_at() { + let mut server = run_rpc_server().await; + let config = RpcStateReaderConfig { url: server.url(), ..Default::default() }; + + let expected_result = felt!("0x999"); + + let mock = mock_rpc_interaction( + &mut server, + &config.json_rpc_version, + "starknet_getStorageAt", + GetStorageAtParams { + block_id: BlockId::Latest, + contract_address: contract_address!("0x1"), + key: starknet_api::state::StorageKey::from(0u32), + }, + &RpcResponse::Success(RpcSuccessResponse { + result: serde_json::to_value(expected_result).unwrap(), + ..Default::default() + }), + ); + + let client = RpcStateReader::from_latest(&config); + let result = tokio::task::spawn_blocking(move || { + client.get_storage_at(contract_address!("0x1"), starknet_api::state::StorageKey::from(0u32)) + }) + .await + .unwrap() + .unwrap(); + assert_eq!(result, expected_result); + mock.assert_async().await; +} + +#[tokio::test] +async fn test_get_nonce_at() { + let mut server = run_rpc_server().await; + let config = RpcStateReaderConfig { url: server.url(), ..Default::default() }; + + let expected_result = Nonce(felt!("0x999")); + + let mock = mock_rpc_interaction( + &mut server, + &config.json_rpc_version, + "starknet_getNonce", + GetNonceParams { block_id: BlockId::Latest, contract_address: contract_address!("0x1") }, + &RpcResponse::Success(RpcSuccessResponse { + result: serde_json::to_value(expected_result).unwrap(), + ..Default::default() + }), + ); + + let client = RpcStateReader::from_latest(&config); + let result = tokio::task::spawn_blocking(move || client.get_nonce_at(contract_address!("0x1"))) + .await + .unwrap() + .unwrap(); + assert_eq!(result, expected_result); + mock.assert_async().await; +} + +#[tokio::test] +async fn test_get_compiled_contract_class() { + let mut server = run_rpc_server().await; + let config = RpcStateReaderConfig { url: server.url(), ..Default::default() }; + + let expected_result = CasmContractClass::default(); + + let mock = mock_rpc_interaction( + &mut server, + &config.json_rpc_version, + "starknet_getCompiledContractClass", + GetCompiledContractClassParams { + block_id: BlockId::Latest, + class_hash: class_hash!("0x1"), + }, + &RpcResponse::Success(RpcSuccessResponse { + result: serde_json::to_value(CompiledContractClass::V1(expected_result)).unwrap(), + ..Default::default() + }), + ); + + let client = RpcStateReader::from_latest(&config); + let result = + tokio::task::spawn_blocking(move || client.get_compiled_contract_class(class_hash!("0x1"))) + .await + .unwrap() + .unwrap(); + assert_eq!(result, ContractClass::V1(CasmContractClass::default().try_into().unwrap())); + mock.assert_async().await; +} + +#[tokio::test] +async fn test_get_class_hash_at() { + let mut server = run_rpc_server().await; + let config = RpcStateReaderConfig { url: server.url(), ..Default::default() }; + + let expected_result = class_hash!("0x999"); + + let mock = mock_rpc_interaction( + &mut server, + &config.json_rpc_version, + "starknet_getClassHashAt", + GetClassHashAtParams { + block_id: BlockId::Latest, + contract_address: contract_address!("0x1"), + }, + &RpcResponse::Success(RpcSuccessResponse { + result: serde_json::to_value(expected_result).unwrap(), + ..Default::default() + }), + ); + + let client = RpcStateReader::from_latest(&config); + let result = + tokio::task::spawn_blocking(move || client.get_class_hash_at(contract_address!("0x1"))) + .await + .unwrap() + .unwrap(); + assert_eq!(result, expected_result); + mock.assert_async().await; +} diff --git a/crates/gateway/src/state_reader.rs b/crates/gateway/src/state_reader.rs new file mode 100644 index 00000000000..0aa555b0509 --- /dev/null +++ b/crates/gateway/src/state_reader.rs @@ -0,0 +1,55 @@ +use blockifier::blockifier::block::BlockInfo; +use blockifier::execution::contract_class::ContractClass; +use blockifier::state::errors::StateError; +use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult}; +#[cfg(test)] +use mockall::automock; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::StorageKey; +use starknet_types_core::felt::Felt; + +pub trait MempoolStateReader: BlockifierStateReader + Send + Sync { + fn get_block_info(&self) -> Result; +} + +#[cfg_attr(test, automock)] +pub trait StateReaderFactory: Send + Sync { + fn get_state_reader_from_latest_block(&self) -> Box; + fn get_state_reader(&self, block_number: BlockNumber) -> Box; +} + +// By default, a Box does not implement the trait of the object it contains. +// Therefore, for using the Box, that the StateReaderFactory creates, +// we need to implement the MempoolStateReader trait for Box. +impl MempoolStateReader for Box { + fn get_block_info(&self) -> Result { + self.as_ref().get_block_info() + } +} + +impl BlockifierStateReader for Box { + fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + ) -> StateResult { + self.as_ref().get_storage_at(contract_address, key) + } + + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { + self.as_ref().get_nonce_at(contract_address) + } + + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { + self.as_ref().get_class_hash_at(contract_address) + } + + fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { + self.as_ref().get_compiled_contract_class(class_hash) + } + + fn get_compiled_class_hash(&self, class_hash: ClassHash) -> StateResult { + self.as_ref().get_compiled_class_hash(class_hash) + } +} diff --git a/crates/gateway/src/state_reader_test_utils.rs b/crates/gateway/src/state_reader_test_utils.rs new file mode 100644 index 00000000000..a806bed9b64 --- /dev/null +++ b/crates/gateway/src/state_reader_test_utils.rs @@ -0,0 +1,90 @@ +use blockifier::blockifier::block::BlockInfo; +use blockifier::context::BlockContext; +use blockifier::execution::contract_class::ContractClass; +use blockifier::state::errors::StateError; +use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult}; +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::dict_state_reader::DictStateReader; +use blockifier::test_utils::initial_test_state::test_state; +use blockifier::test_utils::{CairoVersion, BALANCE}; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::StorageKey; +use starknet_types_core::felt::Felt; + +use crate::state_reader::{MempoolStateReader, StateReaderFactory}; + +#[derive(Clone)] +pub struct TestStateReader { + pub block_info: BlockInfo, + pub blockifier_state_reader: DictStateReader, +} + +impl MempoolStateReader for TestStateReader { + fn get_block_info(&self) -> Result { + Ok(self.block_info.clone()) + } +} + +impl BlockifierStateReader for TestStateReader { + fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + ) -> StateResult { + self.blockifier_state_reader.get_storage_at(contract_address, key) + } + + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { + self.blockifier_state_reader.get_nonce_at(contract_address) + } + + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { + self.blockifier_state_reader.get_class_hash_at(contract_address) + } + + fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { + self.blockifier_state_reader.get_compiled_contract_class(class_hash) + } + + fn get_compiled_class_hash(&self, class_hash: ClassHash) -> StateResult { + self.blockifier_state_reader.get_compiled_class_hash(class_hash) + } +} + +pub struct TestStateReaderFactory { + pub state_reader: TestStateReader, +} + +impl StateReaderFactory for TestStateReaderFactory { + fn get_state_reader_from_latest_block(&self) -> Box { + Box::new(self.state_reader.clone()) + } + + fn get_state_reader(&self, _block_number: BlockNumber) -> Box { + Box::new(self.state_reader.clone()) + } +} + +pub fn local_test_state_reader_factory( + cairo_version: CairoVersion, + zero_balance: bool, +) -> TestStateReaderFactory { + let block_context = BlockContext::create_for_testing(); + let account_balance = if zero_balance { 0 } else { BALANCE }; + let account_contract = FeatureContract::AccountWithoutValidations(cairo_version); + let test_contract = FeatureContract::TestContract(cairo_version); + + let state_reader = test_state( + block_context.chain_info(), + account_balance, + &[(account_contract, 1), (test_contract, 1)], + ); + + TestStateReaderFactory { + state_reader: TestStateReader { + block_info: block_context.block_info().clone(), + blockifier_state_reader: state_reader.state, + }, + } +} diff --git a/crates/gateway/src/stateful_transaction_validator.rs b/crates/gateway/src/stateful_transaction_validator.rs new file mode 100644 index 00000000000..0d8c06929c1 --- /dev/null +++ b/crates/gateway/src/stateful_transaction_validator.rs @@ -0,0 +1,124 @@ +use blockifier::blockifier::block::BlockInfo; +use blockifier::blockifier::stateful_validator::{StatefulValidator, StatefulValidatorResult}; +use blockifier::bouncer::BouncerConfig; +use blockifier::context::BlockContext; +use blockifier::execution::contract_class::ClassInfo; +use blockifier::state::cached_state::CachedState; +use blockifier::transaction::account_transaction::AccountTransaction; +use blockifier::versioned_constants::VersionedConstants; +#[cfg(test)] +use mockall::automock; +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::rpc_transaction::{RPCInvokeTransaction, RPCTransaction}; +use starknet_api::transaction::TransactionHash; +use starknet_types_core::felt::Felt; + +use crate::config::StatefulTransactionValidatorConfig; +use crate::errors::StatefulTransactionValidatorResult; +use crate::state_reader::{MempoolStateReader, StateReaderFactory}; +use crate::utils::{external_tx_to_account_tx, get_sender_address, get_tx_hash}; + +#[cfg(test)] +#[path = "stateful_transaction_validator_test.rs"] +mod stateful_transaction_validator_test; + +pub struct StatefulTransactionValidator { + pub config: StatefulTransactionValidatorConfig, +} + +type BlockifierStatefulValidator = StatefulValidator>; + +// TODO(yair): move the trait to Blockifier. +#[cfg_attr(test, automock)] +pub trait StatefulTransactionValidatorTrait { + fn validate( + &mut self, + account_tx: AccountTransaction, + skip_validate: bool, + ) -> StatefulTransactionValidatorResult<()>; + + fn get_nonce(&mut self, account_address: ContractAddress) -> StatefulValidatorResult; +} + +impl StatefulTransactionValidatorTrait for BlockifierStatefulValidator { + fn validate( + &mut self, + account_tx: AccountTransaction, + skip_validate: bool, + ) -> StatefulTransactionValidatorResult<()> { + Ok(self.perform_validations(account_tx, skip_validate)?) + } + + fn get_nonce(&mut self, account_address: ContractAddress) -> StatefulValidatorResult { + self.get_nonce(account_address) + } +} + +impl StatefulTransactionValidator { + pub fn run_validate( + &self, + external_tx: &RPCTransaction, + optional_class_info: Option, + mut validator: V, + ) -> StatefulTransactionValidatorResult { + let account_tx = external_tx_to_account_tx( + external_tx, + optional_class_info, + &self.config.chain_info.chain_id, + )?; + let tx_hash = get_tx_hash(&account_tx); + let account_nonce = validator.get_nonce(get_sender_address(external_tx))?; + let skip_validate = skip_stateful_validations(external_tx, account_nonce); + validator.validate(account_tx, skip_validate)?; + Ok(tx_hash) + } + + pub fn instantiate_validator( + &self, + state_reader_factory: &dyn StateReaderFactory, + ) -> StatefulTransactionValidatorResult { + // TODO(yael 6/5/2024): consider storing the block_info as part of the + // StatefulTransactionValidator and update it only once a new block is created. + let latest_block_info = get_latest_block_info(state_reader_factory)?; + let state_reader = state_reader_factory.get_state_reader(latest_block_info.block_number); + let state = CachedState::new(state_reader); + let versioned_constants = VersionedConstants::latest_constants_with_overrides( + self.config.validate_max_n_steps, + self.config.max_recursion_depth, + ); + let mut block_info = latest_block_info; + block_info.block_number = block_info.block_number.unchecked_next(); + // TODO(yael 21/4/24): create the block context using pre_process_block once we will be + // able to read the block_hash of 10 blocks ago from papyrus. + let block_context = BlockContext::new( + block_info, + self.config.chain_info.clone().into(), + versioned_constants, + BouncerConfig::max(), + ); + + Ok(BlockifierStatefulValidator::create(state, block_context)) + } +} + +// Check if validation of an invoke transaction should be skipped due to deploy_account not being +// proccessed yet. This feature is used to improve UX for users sending deploy_account + invoke at +// once. +fn skip_stateful_validations(tx: &RPCTransaction, account_nonce: Nonce) -> bool { + match tx { + RPCTransaction::Invoke(RPCInvokeTransaction::V3(tx)) => { + // check if the transaction nonce is 1, meaning it is post deploy_account, and the + // account nonce is zero, meaning the account was not deployed yet. The mempool also + // verifies that the deploy_account transaction exists. + tx.nonce == Nonce(Felt::ONE) && account_nonce == Nonce(Felt::ZERO) + } + RPCTransaction::DeployAccount(_) | RPCTransaction::Declare(_) => false, + } +} + +pub fn get_latest_block_info( + state_reader_factory: &dyn StateReaderFactory, +) -> StatefulTransactionValidatorResult { + let state_reader = state_reader_factory.get_state_reader_from_latest_block(); + Ok(state_reader.get_block_info()?) +} diff --git a/crates/gateway/src/stateful_transaction_validator_test.rs b/crates/gateway/src/stateful_transaction_validator_test.rs new file mode 100644 index 00000000000..4dc509fbf6c --- /dev/null +++ b/crates/gateway/src/stateful_transaction_validator_test.rs @@ -0,0 +1,188 @@ +use assert_matches::assert_matches; +use blockifier::blockifier::stateful_validator::StatefulValidatorError; +use blockifier::context::BlockContext; +use blockifier::test_utils::dict_state_reader::DictStateReader; +use blockifier::test_utils::CairoVersion; +use blockifier::transaction::errors::{TransactionFeeError, TransactionPreValidationError}; +use mempool_test_utils::invoke_tx_args; +use mempool_test_utils::starknet_api_test_utils::{ + deploy_account_tx, external_invoke_tx, invoke_tx, TEST_SENDER_ADDRESS, VALID_L1_GAS_MAX_AMOUNT, + VALID_L1_GAS_MAX_PRICE_PER_UNIT, +}; +use mockall::predicate::eq; +use num_bigint::BigUint; +use pretty_assertions::assert_eq; +use rstest::{fixture, rstest}; +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::felt; +use starknet_api::rpc_transaction::RPCTransaction; +use starknet_api::transaction::TransactionHash; +use starknet_types_core::felt::Felt; + +use crate::compilation::GatewayCompiler; +use crate::config::{GatewayCompilerConfig, StatefulTransactionValidatorConfig}; +use crate::errors::{StatefulTransactionValidatorError, StatefulTransactionValidatorResult}; +use crate::state_reader::{MockStateReaderFactory, StateReaderFactory}; +use crate::state_reader_test_utils::{ + local_test_state_reader_factory, TestStateReader, TestStateReaderFactory, +}; +use crate::stateful_transaction_validator::{ + MockStatefulTransactionValidatorTrait, StatefulTransactionValidator, +}; + +#[fixture] +fn block_context() -> BlockContext { + BlockContext::create_for_testing() +} + +#[fixture] +fn stateful_validator(block_context: BlockContext) -> StatefulTransactionValidator { + StatefulTransactionValidator { + config: StatefulTransactionValidatorConfig { + max_nonce_for_validation_skip: Default::default(), + validate_max_n_steps: block_context.versioned_constants().validate_max_n_steps, + max_recursion_depth: block_context.versioned_constants().max_recursion_depth, + chain_info: block_context.chain_info().clone().into(), + }, + } +} + +#[rstest] +#[case::valid_tx( + invoke_tx(CairoVersion::Cairo1), + Ok(TransactionHash(felt!( + "0x152b8dd0c30e95fa3a4ee7a9398fcfc46fb00c048b4fdcfa9958c64d65899b8" + ))) +)] +#[case::invalid_tx( + invoke_tx(CairoVersion::Cairo1), + Err(StatefulTransactionValidatorError::StatefulValidatorError( + StatefulValidatorError::TransactionPreValidationError( + TransactionPreValidationError::TransactionFeeError( + TransactionFeeError::L1GasBoundsExceedBalance { + max_amount: VALID_L1_GAS_MAX_AMOUNT, + max_price: VALID_L1_GAS_MAX_PRICE_PER_UNIT, + balance: BigUint::ZERO, + } + ) + ) + )) +)] +fn test_stateful_tx_validator( + #[case] external_tx: RPCTransaction, + #[case] expected_result: StatefulTransactionValidatorResult, + stateful_validator: StatefulTransactionValidator, +) { + let optional_class_info = match &external_tx { + RPCTransaction::Declare(declare_tx) => Some( + GatewayCompiler { config: GatewayCompilerConfig {} } + .process_declare_tx(declare_tx) + .unwrap(), + ), + _ => None, + }; + + let expected_result_msg = format!("{:?}", expected_result); + + let mut mock_validator = MockStatefulTransactionValidatorTrait::new(); + mock_validator.expect_validate().return_once(|_, _| expected_result.map(|_| ())); + mock_validator.expect_get_nonce().returning(|_| Ok(Nonce(Felt::ZERO))); + + let result = stateful_validator.run_validate(&external_tx, optional_class_info, mock_validator); + assert_eq!(format!("{:?}", result), expected_result_msg); +} + +#[test] +fn test_instantiate_validator() { + let state_reader_factory = local_test_state_reader_factory(CairoVersion::Cairo1, false); + + let mut mock_state_reader_factory = MockStateReaderFactory::new(); + + // Make sure stateful_validator uses the latest block in the initiall call. + let latest_state_reader = state_reader_factory.get_state_reader_from_latest_block(); + mock_state_reader_factory + .expect_get_state_reader_from_latest_block() + .return_once(|| latest_state_reader); + + // Make sure stateful_validator uses the latest block in the following calls to the + // state_reader. + let latest_block = state_reader_factory.state_reader.block_info.block_number; + let state_reader = state_reader_factory.get_state_reader(latest_block); + mock_state_reader_factory + .expect_get_state_reader() + .with(eq(latest_block)) + .return_once(move |_| state_reader); + + let block_context = &BlockContext::create_for_testing(); + let stateful_validator = StatefulTransactionValidator { + config: StatefulTransactionValidatorConfig { + max_nonce_for_validation_skip: Default::default(), + validate_max_n_steps: block_context.versioned_constants().validate_max_n_steps, + max_recursion_depth: block_context.versioned_constants().max_recursion_depth, + chain_info: block_context.chain_info().clone().into(), + }, + }; + let blockifier_validator = stateful_validator.instantiate_validator(&mock_state_reader_factory); + assert!(blockifier_validator.is_ok()); +} + +#[rstest] +#[case::should_skip_validation( + external_invoke_tx(invoke_tx_args!{nonce: Nonce(Felt::ONE)}), + empty_state_reader_factory(), + true +)] +#[case::should_not_skip_validation_nonce_over_max_nonce_for_skip( + external_invoke_tx(invoke_tx_args!{nonce: Nonce(Felt::TWO)}), + empty_state_reader_factory(), + false +)] +#[case::should_not_skip_validation_non_invoke( + deploy_account_tx(), + empty_state_reader_factory(), + false +)] +#[case::should_not_skip_validation_account_nonce_1( + external_invoke_tx(invoke_tx_args!{sender_address: ContractAddress::from(TEST_SENDER_ADDRESS), nonce: Nonce(Felt::ONE)}), + state_reader_factory_account_nonce_1(ContractAddress::from(TEST_SENDER_ADDRESS)), + false +)] +// TODO(yael 10/7/2024): use mock validator in this test once ready. +fn test_skip_stateful_validation( + #[case] external_tx: RPCTransaction, + #[case] state_reader_factory: TestStateReaderFactory, + #[case] should_pass_validation: bool, + stateful_validator: StatefulTransactionValidator, +) { + let validator = stateful_validator.instantiate_validator(&state_reader_factory).unwrap(); + let result = stateful_validator.run_validate(&external_tx, None, validator); + if should_pass_validation { + assert_matches!(result, Ok(_)); + } else { + // To be sure that the validations were actually skipped, we check that the error came from + // the blockifier stateful validations, and not from the pre validations since those are + // executed also when skip_validate is true. + assert_matches!(result, Err(StatefulTransactionValidatorError::StatefulValidatorError(err)) + if !matches!(err, StatefulValidatorError::TransactionPreValidationError(_))); + } +} + +fn empty_state_reader_factory() -> TestStateReaderFactory { + let block_context = BlockContext::create_for_testing(); + TestStateReaderFactory { + state_reader: TestStateReader { + blockifier_state_reader: DictStateReader::default(), + block_info: block_context.block_info().clone(), + }, + } +} + +fn state_reader_factory_account_nonce_1(sender_address: ContractAddress) -> TestStateReaderFactory { + let mut state_reader_factory = empty_state_reader_factory(); + state_reader_factory + .state_reader + .blockifier_state_reader + .address_to_nonce + .insert(sender_address, Nonce(Felt::ONE)); + state_reader_factory +} diff --git a/crates/gateway/src/stateless_transaction_validator.rs b/crates/gateway/src/stateless_transaction_validator.rs new file mode 100644 index 00000000000..70805ab5ebc --- /dev/null +++ b/crates/gateway/src/stateless_transaction_validator.rs @@ -0,0 +1,196 @@ +use starknet_api::rpc_transaction::{ + RPCDeclareTransaction, RPCDeployAccountTransaction, RPCInvokeTransaction, RPCTransaction, + ResourceBoundsMapping, +}; +use starknet_api::state::EntryPoint; +use starknet_api::transaction::Resource; +use starknet_types_core::felt::Felt; + +use crate::compiler_version::VersionId; +use crate::config::StatelessTransactionValidatorConfig; +use crate::errors::{StatelessTransactionValidatorError, StatelessTransactionValidatorResult}; + +#[cfg(test)] +#[path = "stateless_transaction_validator_test.rs"] +mod stateless_transaction_validator_test; + +#[derive(Clone)] +pub struct StatelessTransactionValidator { + pub config: StatelessTransactionValidatorConfig, +} + +impl StatelessTransactionValidator { + pub fn validate(&self, tx: &RPCTransaction) -> StatelessTransactionValidatorResult<()> { + // TODO(Arni, 1/5/2024): Add a mechanism that validate the sender address is not blocked. + // TODO(Arni, 1/5/2024): Validate transaction version. + + self.validate_resource_bounds(tx)?; + self.validate_tx_size(tx)?; + + if let RPCTransaction::Declare(declare_tx) = tx { + self.validate_declare_tx(declare_tx)?; + } + Ok(()) + } + + fn validate_resource_bounds( + &self, + tx: &RPCTransaction, + ) -> StatelessTransactionValidatorResult<()> { + let resource_bounds_mapping = tx.resource_bounds(); + + if self.config.validate_non_zero_l1_gas_fee { + validate_resource_is_non_zero(resource_bounds_mapping, Resource::L1Gas)?; + } + if self.config.validate_non_zero_l2_gas_fee { + validate_resource_is_non_zero(resource_bounds_mapping, Resource::L2Gas)?; + } + + Ok(()) + } + + fn validate_tx_size(&self, tx: &RPCTransaction) -> StatelessTransactionValidatorResult<()> { + self.validate_tx_calldata_size(tx)?; + self.validate_tx_signature_size(tx)?; + + Ok(()) + } + + fn validate_tx_calldata_size( + &self, + tx: &RPCTransaction, + ) -> StatelessTransactionValidatorResult<()> { + let calldata = match tx { + RPCTransaction::Declare(_) => { + // Declare transaction has no calldata. + return Ok(()); + } + RPCTransaction::DeployAccount(RPCDeployAccountTransaction::V3(tx)) => { + &tx.constructor_calldata + } + RPCTransaction::Invoke(RPCInvokeTransaction::V3(tx)) => &tx.calldata, + }; + + let calldata_length = calldata.0.len(); + if calldata_length > self.config.max_calldata_length { + return Err(StatelessTransactionValidatorError::CalldataTooLong { + calldata_length, + max_calldata_length: self.config.max_calldata_length, + }); + } + + Ok(()) + } + + fn validate_tx_signature_size( + &self, + tx: &RPCTransaction, + ) -> StatelessTransactionValidatorResult<()> { + let signature = tx.signature(); + + let signature_length = signature.0.len(); + if signature_length > self.config.max_signature_length { + return Err(StatelessTransactionValidatorError::SignatureTooLong { + signature_length, + max_signature_length: self.config.max_signature_length, + }); + } + + Ok(()) + } + + fn validate_declare_tx( + &self, + declare_tx: &RPCDeclareTransaction, + ) -> StatelessTransactionValidatorResult<()> { + let contract_class = match declare_tx { + RPCDeclareTransaction::V3(tx) => &tx.contract_class, + }; + self.validate_sierra_version(&contract_class.sierra_program)?; + self.validate_class_length(contract_class)?; + self.validate_entry_points_sorted_and_unique(contract_class)?; + Ok(()) + } + + fn validate_sierra_version( + &self, + sierra_program: &[Felt], + ) -> StatelessTransactionValidatorResult<()> { + // Any patch version is valid. (i.e. when check version for upper bound, we ignore the Z + // part in a version X.Y.Z). + let max_sierra_version = VersionId { patch: usize::MAX, ..self.config.max_sierra_version }; + + let sierra_version = VersionId::from_sierra_program(sierra_program)?; + if self.config.min_sierra_version <= sierra_version && sierra_version <= max_sierra_version + { + return Ok(()); + } + + Err(StatelessTransactionValidatorError::UnsupportedSierraVersion { + version: sierra_version, + min_version: self.config.min_sierra_version, + max_version: self.config.max_sierra_version, + }) + } + + fn validate_class_length( + &self, + contract_class: &starknet_api::rpc_transaction::ContractClass, + ) -> StatelessTransactionValidatorResult<()> { + let bytecode_size = contract_class.sierra_program.len(); + if bytecode_size > self.config.max_bytecode_size { + return Err(StatelessTransactionValidatorError::BytecodeSizeTooLarge { + bytecode_size, + max_bytecode_size: self.config.max_bytecode_size, + }); + } + + let contract_class_object_size = serde_json::to_string(&contract_class) + .expect("Unexpected error serializing contract class.") + .len(); + if contract_class_object_size > self.config.max_raw_class_size { + return Err(StatelessTransactionValidatorError::ContractClassObjectSizeTooLarge { + contract_class_object_size, + max_contract_class_object_size: self.config.max_raw_class_size, + }); + } + + Ok(()) + } + + fn validate_entry_points_sorted_and_unique( + &self, + contract_class: &starknet_api::rpc_transaction::ContractClass, + ) -> StatelessTransactionValidatorResult<()> { + let is_sorted_unique = |entry_points: &[EntryPoint]| { + entry_points.windows(2).all(|pair| pair[0].selector < pair[1].selector) + }; + + if is_sorted_unique(&contract_class.entry_points_by_type.constructor) + && is_sorted_unique(&contract_class.entry_points_by_type.external) + && is_sorted_unique(&contract_class.entry_points_by_type.l1handler) + { + return Ok(()); + } + + Err(StatelessTransactionValidatorError::EntryPointsNotUniquelySorted) + } +} + +fn validate_resource_is_non_zero( + resource_bounds_mapping: &ResourceBoundsMapping, + resource: Resource, +) -> StatelessTransactionValidatorResult<()> { + let resource_bounds = match resource { + Resource::L1Gas => resource_bounds_mapping.l1_gas, + Resource::L2Gas => resource_bounds_mapping.l2_gas, + }; + if resource_bounds.max_amount == 0 || resource_bounds.max_price_per_unit == 0 { + return Err(StatelessTransactionValidatorError::ZeroResourceBounds { + resource, + resource_bounds, + }); + } + + Ok(()) +} diff --git a/crates/gateway/src/stateless_transaction_validator_test.rs b/crates/gateway/src/stateless_transaction_validator_test.rs new file mode 100644 index 00000000000..0d14f632136 --- /dev/null +++ b/crates/gateway/src/stateless_transaction_validator_test.rs @@ -0,0 +1,420 @@ +use std::vec; + +use assert_matches::assert_matches; +use mempool_test_utils::declare_tx_args; +use mempool_test_utils::starknet_api_test_utils::{ + create_resource_bounds_mapping, external_declare_tx, external_tx_for_testing, + zero_resource_bounds_mapping, TransactionType, NON_EMPTY_RESOURCE_BOUNDS, +}; +use rstest::rstest; +use starknet_api::core::EntryPointSelector; +use starknet_api::rpc_transaction::{ContractClass, EntryPointByType, ResourceBoundsMapping}; +use starknet_api::state::EntryPoint; +use starknet_api::transaction::{Calldata, Resource, ResourceBounds, TransactionSignature}; +use starknet_api::{calldata, felt}; +use starknet_types_core::felt::Felt; + +use crate::compiler_version::{VersionId, VersionIdError}; +use crate::config::StatelessTransactionValidatorConfig; +use crate::errors::StatelessTransactionValidatorResult; +use crate::stateless_transaction_validator::{ + StatelessTransactionValidator, StatelessTransactionValidatorError, +}; +use crate::test_utils::create_sierra_program; + +const MIN_SIERRA_VERSION: VersionId = VersionId { major: 1, minor: 1, patch: 0 }; +const MAX_SIERRA_VERSION: VersionId = VersionId { major: 1, minor: 5, patch: usize::MAX }; + +const DEFAULT_VALIDATOR_CONFIG_FOR_TESTING: StatelessTransactionValidatorConfig = + StatelessTransactionValidatorConfig { + validate_non_zero_l1_gas_fee: false, + validate_non_zero_l2_gas_fee: false, + max_calldata_length: 1, + max_signature_length: 1, + max_bytecode_size: 10000, + max_raw_class_size: 100000, + min_sierra_version: MIN_SIERRA_VERSION, + max_sierra_version: MAX_SIERRA_VERSION, + }; + +#[rstest] +#[case::ignore_resource_bounds( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: false, + validate_non_zero_l2_gas_fee: false, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + zero_resource_bounds_mapping(), + calldata![], + TransactionSignature::default() +)] +#[case::valid_l1_gas( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: true, + validate_non_zero_l2_gas_fee: false, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + create_resource_bounds_mapping(NON_EMPTY_RESOURCE_BOUNDS, ResourceBounds::default()), + calldata![], + TransactionSignature::default() +)] +#[case::valid_l2_gas( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: false, + validate_non_zero_l2_gas_fee: true, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + create_resource_bounds_mapping(ResourceBounds::default(), NON_EMPTY_RESOURCE_BOUNDS), + calldata![], + TransactionSignature::default() +)] +#[case::valid_l1_and_l2_gas( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: true, + validate_non_zero_l2_gas_fee: true, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + create_resource_bounds_mapping(NON_EMPTY_RESOURCE_BOUNDS, NON_EMPTY_RESOURCE_BOUNDS), + calldata![], + TransactionSignature::default() +)] +#[case::non_empty_valid_calldata( + DEFAULT_VALIDATOR_CONFIG_FOR_TESTING, + zero_resource_bounds_mapping(), + calldata![Felt::ONE], + TransactionSignature::default() +)] +#[case::non_empty_valid_signature( + DEFAULT_VALIDATOR_CONFIG_FOR_TESTING, + zero_resource_bounds_mapping(), + calldata![], + TransactionSignature(vec![Felt::ONE]) +)] +#[case::valid_tx( + DEFAULT_VALIDATOR_CONFIG_FOR_TESTING, + zero_resource_bounds_mapping(), + calldata![], + TransactionSignature::default() +)] +fn test_positive_flow( + #[case] config: StatelessTransactionValidatorConfig, + #[case] resource_bounds: ResourceBoundsMapping, + #[case] tx_calldata: Calldata, + #[case] signature: TransactionSignature, + #[values(TransactionType::Declare, TransactionType::DeployAccount, TransactionType::Invoke)] + tx_type: TransactionType, +) { + let tx_validator = StatelessTransactionValidator { config }; + let tx = external_tx_for_testing(tx_type, resource_bounds, tx_calldata, signature); + + assert_matches!(tx_validator.validate(&tx), Ok(())); +} + +#[rstest] +#[case::zero_l1_gas_resource_bounds( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: true, + validate_non_zero_l2_gas_fee: false, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + zero_resource_bounds_mapping(), + StatelessTransactionValidatorError::ZeroResourceBounds{ + resource: Resource::L1Gas, resource_bounds: ResourceBounds::default() + } +)] +#[case::zero_l2_gas_resource_bounds( + StatelessTransactionValidatorConfig{ + validate_non_zero_l1_gas_fee: false, + validate_non_zero_l2_gas_fee: true, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + create_resource_bounds_mapping(NON_EMPTY_RESOURCE_BOUNDS, ResourceBounds::default()), + StatelessTransactionValidatorError::ZeroResourceBounds{ + resource: Resource::L2Gas, resource_bounds: ResourceBounds::default() + } +)] +fn test_invalid_resource_bounds( + #[case] config: StatelessTransactionValidatorConfig, + #[case] resource_bounds: ResourceBoundsMapping, + #[case] expected_error: StatelessTransactionValidatorError, + #[values(TransactionType::Declare, TransactionType::DeployAccount, TransactionType::Invoke)] + tx_type: TransactionType, +) { + let tx_validator = StatelessTransactionValidator { config }; + let tx = external_tx_for_testing( + tx_type, + resource_bounds, + calldata![], + TransactionSignature::default(), + ); + + assert_eq!(tx_validator.validate(&tx).unwrap_err(), expected_error); +} + +#[rstest] +fn test_calldata_too_long( + #[values(TransactionType::DeployAccount, TransactionType::Invoke)] tx_type: TransactionType, +) { + let tx_validator = + StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING }; + let tx = external_tx_for_testing( + tx_type, + zero_resource_bounds_mapping(), + calldata![Felt::ONE, Felt::TWO], + TransactionSignature::default(), + ); + + assert_eq!( + tx_validator.validate(&tx).unwrap_err(), + StatelessTransactionValidatorError::CalldataTooLong { + calldata_length: 2, + max_calldata_length: 1 + } + ); +} + +#[rstest] +fn test_signature_too_long( + #[values(TransactionType::Declare, TransactionType::DeployAccount, TransactionType::Invoke)] + tx_type: TransactionType, +) { + let tx_validator = + StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING }; + let tx = external_tx_for_testing( + tx_type, + zero_resource_bounds_mapping(), + calldata![], + TransactionSignature(vec![Felt::ONE, Felt::TWO]), + ); + + assert_eq!( + tx_validator.validate(&tx).unwrap_err(), + StatelessTransactionValidatorError::SignatureTooLong { + signature_length: 2, + max_signature_length: 1 + } + ); +} + +#[rstest] +#[case::sierra_program_length_zero( + vec![], + StatelessTransactionValidatorError::InvalidSierraVersion ( + VersionIdError::InvalidVersion { + message: "Sierra program is too short. got program of length 0 which is not long enough \ + to hold the version field.".into() + } + ) +)] +#[case::sierra_program_length_one( + vec![felt!(1_u128)], + StatelessTransactionValidatorError::InvalidSierraVersion ( + VersionIdError::InvalidVersion { + message: "Sierra program is too short. got program of length 1 which is not long enough \ + to hold the version field.".into() + } + ) +)] +#[case::sierra_program_length_two( + vec![felt!(1_u128), felt!(3_u128)], + StatelessTransactionValidatorError::InvalidSierraVersion ( + VersionIdError::InvalidVersion { + message: "Sierra program is too short. got program of length 2 which is not long enough \ + to hold the version field.".into() + } + ) +)] +#[case::invalid_character_in_sierra_version( + vec![ + felt!(1_u128), + felt!(3_u128), + felt!(0x10000000000000000_u128), // Does not fit into a usize. + ], + StatelessTransactionValidatorError::InvalidSierraVersion ( + VersionIdError::InvalidVersion { + message: "version contains a value that is out of range: \ + 0x10000000000000000".into() + } + ) + ) +] +#[case::sierra_version_too_low( + create_sierra_program(&VersionId { major: 0, minor: 3, patch: 0 }), + StatelessTransactionValidatorError::UnsupportedSierraVersion { + version: VersionId{major: 0, minor: 3, patch: 0}, + min_version: MIN_SIERRA_VERSION, + max_version: MAX_SIERRA_VERSION, + }) +] +#[case::sierra_version_too_high( + create_sierra_program(&VersionId { major: 1, minor: 6, patch: 0 }), + StatelessTransactionValidatorError::UnsupportedSierraVersion { + version: VersionId { major: 1, minor: 6, patch: 0 }, + min_version: MIN_SIERRA_VERSION, + max_version: MAX_SIERRA_VERSION, + }) +] +fn test_declare_sierra_version_failure( + #[case] sierra_program: Vec, + #[case] expected_error: StatelessTransactionValidatorError, +) { + let tx_validator = + StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING }; + + let contract_class = ContractClass { sierra_program, ..Default::default() }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_eq!(tx_validator.validate(&tx).unwrap_err(), expected_error); +} + +#[rstest] +#[case::min_sierra_version(create_sierra_program(&MIN_SIERRA_VERSION))] +#[case::valid_sierra_version(create_sierra_program(&VersionId { major: 1, minor: 3, patch: 0 }))] +#[case::max_sierra_version_patch_zero(create_sierra_program(&VersionId { patch: 0, ..MAX_SIERRA_VERSION }))] +#[case::max_sierra_version_patch_non_trivial(create_sierra_program(&VersionId { patch: 1, ..MAX_SIERRA_VERSION }))] +#[case::max_sierra_version(create_sierra_program(&MAX_SIERRA_VERSION))] +fn test_declare_sierra_version_sucsses(#[case] sierra_program: Vec) { + let tx_validator = + StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING }; + + let contract_class = ContractClass { sierra_program, ..Default::default() }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_matches!(tx_validator.validate(&tx), Ok(())); +} + +#[test] +fn test_declare_bytecode_size_too_long() { + let config_max_bytecode_size = 10; + let tx_validator = StatelessTransactionValidator { + config: StatelessTransactionValidatorConfig { + max_bytecode_size: config_max_bytecode_size, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + }; + let sierra_program_length = config_max_bytecode_size + 1; + let sierra_program = vec![felt!(1_u128); sierra_program_length]; + let contract_class = ContractClass { sierra_program, ..Default::default() }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_matches!( + tx_validator.validate(&tx).unwrap_err(), + StatelessTransactionValidatorError::BytecodeSizeTooLarge { + bytecode_size, + max_bytecode_size + } if ( + bytecode_size, max_bytecode_size + ) == (sierra_program_length, config_max_bytecode_size) + ) +} + +#[test] +fn test_declare_contract_class_size_too_long() { + let config_max_raw_class_size = 100; // Some arbitrary value, which will fail the test. + let tx_validator = StatelessTransactionValidator { + config: StatelessTransactionValidatorConfig { + max_raw_class_size: config_max_raw_class_size, + ..DEFAULT_VALIDATOR_CONFIG_FOR_TESTING + }, + }; + let contract_class = + ContractClass { sierra_program: vec![felt!(1_u128); 3], ..Default::default() }; + let contract_class_length = serde_json::to_string(&contract_class).unwrap().len(); + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_matches!( + tx_validator.validate(&tx).unwrap_err(), + StatelessTransactionValidatorError::ContractClassObjectSizeTooLarge { + contract_class_object_size, max_contract_class_object_size + } if ( + contract_class_object_size, max_contract_class_object_size + ) == (contract_class_length, config_max_raw_class_size) + ) +} + +#[rstest] +#[case::valid( + vec![ + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + EntryPoint { selector: EntryPointSelector(felt!(2_u128)), ..Default::default() } + ], + Ok(()) +)] +#[case::no_entry_points( + vec![], + Ok(()) +)] +#[case::single_entry_point( + vec![ + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() } + ], + Ok(()) +)] +#[case::not_sorted( + vec![ + EntryPoint { selector: EntryPointSelector(felt!(2_u128)), ..Default::default() }, + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + ], + Err(StatelessTransactionValidatorError::EntryPointsNotUniquelySorted) +)] +#[case::not_unique( + vec![ + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + ], + Err(StatelessTransactionValidatorError::EntryPointsNotUniquelySorted) +)] +#[case::many_entry_points( + vec![ + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + EntryPoint { selector: EntryPointSelector(felt!(2_u128)), ..Default::default() }, + EntryPoint { selector: EntryPointSelector(felt!(1_u128)), ..Default::default() }, + ], + Err(StatelessTransactionValidatorError::EntryPointsNotUniquelySorted) +)] +fn test_declare_entry_points_not_sorted_by_selector( + #[case] entry_points: Vec, + #[case] expected: StatelessTransactionValidatorResult<()>, +) { + let tx_validator = + StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING }; + + let contract_class = ContractClass { + sierra_program: vec![felt!(1_u128); 3], + entry_points_by_type: EntryPointByType { + constructor: entry_points.clone(), + external: vec![], + l1handler: vec![], + }, + ..Default::default() + }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_eq!(tx_validator.validate(&tx), expected); + + let contract_class = ContractClass { + sierra_program: vec![felt!(1_u128); 3], + entry_points_by_type: EntryPointByType { + constructor: vec![], + external: entry_points.clone(), + l1handler: vec![], + }, + ..Default::default() + }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_eq!(tx_validator.validate(&tx), expected); + + let contract_class = ContractClass { + sierra_program: vec![felt!(1_u128); 3], + entry_points_by_type: EntryPointByType { + constructor: vec![], + external: vec![], + l1handler: entry_points, + }, + ..Default::default() + }; + let tx = external_declare_tx(declare_tx_args!(contract_class)); + + assert_eq!(tx_validator.validate(&tx), expected); +} diff --git a/crates/gateway/src/test_utils.rs b/crates/gateway/src/test_utils.rs new file mode 100644 index 00000000000..b9db31657ae --- /dev/null +++ b/crates/gateway/src/test_utils.rs @@ -0,0 +1,11 @@ +use starknet_types_core::felt::Felt; + +use crate::compiler_version::VersionId; + +pub fn create_sierra_program(version_id: &VersionId) -> Vec { + vec![ + Felt::from(u64::try_from(version_id.major).unwrap()), + Felt::from(u64::try_from(version_id.minor).unwrap()), + Felt::from(u64::try_from(version_id.patch).unwrap()), + ] +} diff --git a/crates/gateway/src/utils.rs b/crates/gateway/src/utils.rs new file mode 100644 index 00000000000..10af9340662 --- /dev/null +++ b/crates/gateway/src/utils.rs @@ -0,0 +1,179 @@ +use blockifier::execution::contract_class::ClassInfo; +use blockifier::transaction::account_transaction::AccountTransaction; +use blockifier::transaction::transactions::{ + DeclareTransaction as BlockifierDeclareTransaction, + DeployAccountTransaction as BlockifierDeployAccountTransaction, + InvokeTransaction as BlockifierInvokeTransaction, +}; +use starknet_api::core::{calculate_contract_address, ChainId, ClassHash, ContractAddress, Nonce}; +use starknet_api::rpc_transaction::{ + RPCDeclareTransaction, RPCDeployAccountTransaction, RPCInvokeTransaction, RPCTransaction, +}; +use starknet_api::transaction::{ + DeclareTransaction, DeclareTransactionV3, DeployAccountTransaction, DeployAccountTransactionV3, + InvokeTransaction, InvokeTransactionV3, Tip, TransactionHash, TransactionHasher, +}; +use starknet_mempool_types::mempool_types::ThinTransaction; + +use crate::errors::StatefulTransactionValidatorResult; + +#[cfg(test)] +#[path = "utils_test.rs"] +mod utils_test; + +macro_rules! implement_ref_getters { + ($(($member_name:ident, $member_type:ty));* $(;)?) => { + $(fn $member_name(&self) -> &$member_type { + match self { + starknet_api::rpc_transaction::RPCTransaction::Declare( + starknet_api::rpc_transaction::RPCDeclareTransaction::V3(tx) + ) => &tx.$member_name, + starknet_api::rpc_transaction::RPCTransaction::DeployAccount( + starknet_api::rpc_transaction::RPCDeployAccountTransaction::V3(tx) + ) => &tx.$member_name, + starknet_api::rpc_transaction::RPCTransaction::Invoke( + starknet_api::rpc_transaction::RPCInvokeTransaction::V3(tx) + ) => &tx.$member_name, + } + })* + }; +} + +impl RPCTransactionExt for RPCTransaction { + implement_ref_getters!( + (nonce, Nonce); + (tip, Tip) + ); +} + +pub fn external_tx_to_thin_tx( + external_tx: &RPCTransaction, + tx_hash: TransactionHash, +) -> ThinTransaction { + ThinTransaction { + tip: *external_tx.tip(), + nonce: *external_tx.nonce(), + sender_address: get_sender_address(external_tx), + tx_hash, + } +} + +pub fn get_sender_address(tx: &RPCTransaction) -> ContractAddress { + match tx { + RPCTransaction::Declare(RPCDeclareTransaction::V3(tx)) => tx.sender_address, + // TODO(Mohammad): Add support for deploy account. + RPCTransaction::DeployAccount(RPCDeployAccountTransaction::V3(_)) => { + ContractAddress::default() + } + RPCTransaction::Invoke(RPCInvokeTransaction::V3(tx)) => tx.sender_address, + } +} + +// TODO(Mohammad): Remove this trait once it is implemented in StarkNet API. +#[allow(dead_code)] +pub trait RPCTransactionExt { + fn nonce(&self) -> &Nonce; + fn tip(&self) -> &Tip; +} + +pub fn external_tx_to_account_tx( + external_tx: &RPCTransaction, + // FIXME(yael 15/4/24): calculate class_info inside the function once compilation code is ready + optional_class_info: Option, + chain_id: &ChainId, +) -> StatefulTransactionValidatorResult { + match external_tx { + RPCTransaction::Declare(RPCDeclareTransaction::V3(tx)) => { + let declare_tx = DeclareTransaction::V3(DeclareTransactionV3 { + class_hash: ClassHash::default(), /* FIXME(yael 15/4/24): call the starknet-api + * function once ready */ + resource_bounds: tx.resource_bounds.clone().into(), + tip: tx.tip, + signature: tx.signature.clone(), + nonce: tx.nonce, + compiled_class_hash: tx.compiled_class_hash, + sender_address: tx.sender_address, + nonce_data_availability_mode: tx.nonce_data_availability_mode, + fee_data_availability_mode: tx.fee_data_availability_mode, + paymaster_data: tx.paymaster_data.clone(), + account_deployment_data: tx.account_deployment_data.clone(), + }); + let tx_hash = declare_tx.calculate_transaction_hash(chain_id, &declare_tx.version())?; + let class_info = + optional_class_info.expect("declare transaction should contain class info"); + let declare_tx = BlockifierDeclareTransaction::new(declare_tx, tx_hash, class_info)?; + Ok(AccountTransaction::Declare(declare_tx)) + } + RPCTransaction::DeployAccount(RPCDeployAccountTransaction::V3(tx)) => { + let deploy_account_tx = DeployAccountTransaction::V3(DeployAccountTransactionV3 { + resource_bounds: tx.resource_bounds.clone().into(), + tip: tx.tip, + signature: tx.signature.clone(), + nonce: tx.nonce, + class_hash: tx.class_hash, + contract_address_salt: tx.contract_address_salt, + constructor_calldata: tx.constructor_calldata.clone(), + nonce_data_availability_mode: tx.nonce_data_availability_mode, + fee_data_availability_mode: tx.fee_data_availability_mode, + paymaster_data: tx.paymaster_data.clone(), + }); + let contract_address = calculate_contract_address( + deploy_account_tx.contract_address_salt(), + deploy_account_tx.class_hash(), + &deploy_account_tx.constructor_calldata(), + ContractAddress::default(), + )?; + let tx_hash = deploy_account_tx + .calculate_transaction_hash(chain_id, &deploy_account_tx.version())?; + let deploy_account_tx = BlockifierDeployAccountTransaction::new( + deploy_account_tx, + tx_hash, + contract_address, + ); + Ok(AccountTransaction::DeployAccount(deploy_account_tx)) + } + RPCTransaction::Invoke(RPCInvokeTransaction::V3(tx)) => { + let invoke_tx = InvokeTransaction::V3(InvokeTransactionV3 { + resource_bounds: tx.resource_bounds.clone().into(), + tip: tx.tip, + signature: tx.signature.clone(), + nonce: tx.nonce, + sender_address: tx.sender_address, + calldata: tx.calldata.clone(), + nonce_data_availability_mode: tx.nonce_data_availability_mode, + fee_data_availability_mode: tx.fee_data_availability_mode, + paymaster_data: tx.paymaster_data.clone(), + account_deployment_data: tx.account_deployment_data.clone(), + }); + let tx_hash = invoke_tx.calculate_transaction_hash(chain_id, &invoke_tx.version())?; + let invoke_tx = BlockifierInvokeTransaction::new(invoke_tx, tx_hash); + Ok(AccountTransaction::Invoke(invoke_tx)) + } + } +} + +// TODO(yael 9/5/54): Remove once we we transition to InternalTransaction +pub fn get_tx_hash(tx: &AccountTransaction) -> TransactionHash { + match tx { + AccountTransaction::Declare(tx) => tx.tx_hash, + AccountTransaction::DeployAccount(tx) => tx.tx_hash, + AccountTransaction::Invoke(tx) => tx.tx_hash, + } +} + +/// Checks whether 'subsequence' is a subsequence of 'sequence'. +pub fn is_subsequence(subsequence: &[T], sequence: &[T]) -> bool { + let mut offset = 0; + + for item in sequence { + if offset == subsequence.len() { + return true; + } + + if item == &subsequence[offset] { + offset += 1; + } + } + + offset == subsequence.len() +} diff --git a/crates/gateway/src/utils_test.rs b/crates/gateway/src/utils_test.rs new file mode 100644 index 00000000000..7b9d2fdb935 --- /dev/null +++ b/crates/gateway/src/utils_test.rs @@ -0,0 +1,78 @@ +use pretty_assertions::assert_eq; +use rstest::rstest; + +use crate::utils::is_subsequence; + +#[rstest] +#[case::empty( + &[], + &[], + true +)] +#[case::empty_subsequence( + &[], + &["a", "b"], + true +)] +#[case::empty_sequence( + &["a"], + &[], + false +)] +#[case::subsequence_1( + &["a"], + &["a", "b", "c"], + true +)] +#[case::subsequence_2( + &["b"], + &["a", "b", "c"], + true +)] +#[case::subsequence_3( + &["c"], + &["a", "b", "c"], + true +)] +#[case::subsequence_4( + &["a", "b"], + &["a", "b", "c"], + true +)] +#[case::subsequence_5( + &["a", "c"], + &["a", "b", "c"], + true +)] +#[case::subsequence_6( + &["b", "c"], + &["a", "b", "c"], + true +)] +#[case::subsequence_7( + &["a", "b", "c"], + &["a", "b", "c"], + true +)] +#[case::out_of_order_1( + &["b", "a"], + &["a", "b", "c"], + false +)] +#[case::out_of_order_2( + &["b", "a", "c"], + &["a", "b", "c"], + false +)] +#[case::unrelated( + &["a", "b", "d"], + &["a", "b", "c"], + false +)] +fn test_is_subsequence( + #[case] subsequence: &[&str], + #[case] sequence: &[&str], + #[case] expected_result: bool, +) { + assert_eq!(is_subsequence(subsequence, sequence), expected_result); +} diff --git a/crates/mempool/Cargo.toml b/crates/mempool/Cargo.toml new file mode 100644 index 00000000000..3c79703cffe --- /dev/null +++ b/crates/mempool/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "starknet_mempool" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +async-trait.workspace = true +derive_more.workspace = true +starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } +starknet_api.workspace = true +starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +tokio.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +itertools.workspace = true +pretty_assertions.workspace = true +rstest.workspace = true +starknet-types-core.workspace = true +starknet_api = { workspace = true, features = ["testing"] } +tokio.workspace = true diff --git a/crates/mempool/src/communication.rs b/crates/mempool/src/communication.rs new file mode 100644 index 00000000000..225498700d0 --- /dev/null +++ b/crates/mempool/src/communication.rs @@ -0,0 +1,58 @@ +use async_trait::async_trait; +use starknet_mempool_infra::component_definitions::ComponentRequestHandler; +use starknet_mempool_infra::component_runner::ComponentStarter; +use starknet_mempool_infra::component_server::local_component_server::LocalComponentServer; +use starknet_mempool_types::communication::{ + MempoolRequest, MempoolRequestAndResponseSender, MempoolResponse, +}; +use starknet_mempool_types::mempool_types::{MempoolInput, MempoolResult, ThinTransaction}; +use tokio::sync::mpsc::Receiver; + +use crate::mempool::Mempool; + +pub type MempoolServer = + LocalComponentServer; + +pub fn create_mempool_server( + mempool: Mempool, + rx_mempool: Receiver, +) -> MempoolServer { + let communication_wrapper = MempoolCommunicationWrapper::new(mempool); + LocalComponentServer::new(communication_wrapper, rx_mempool) +} + +/// Wraps the mempool to enable inbound async communication from other components. +pub struct MempoolCommunicationWrapper { + mempool: Mempool, +} + +impl MempoolCommunicationWrapper { + pub fn new(mempool: Mempool) -> Self { + MempoolCommunicationWrapper { mempool } + } + + fn add_tx(&mut self, mempool_input: MempoolInput) -> MempoolResult<()> { + self.mempool.add_tx(mempool_input) + } + + fn get_txs(&mut self, n_txs: usize) -> MempoolResult> { + self.mempool.get_txs(n_txs) + } +} + +#[async_trait] +impl ComponentRequestHandler for MempoolCommunicationWrapper { + async fn handle_request(&mut self, request: MempoolRequest) -> MempoolResponse { + match request { + MempoolRequest::AddTransaction(mempool_input) => { + MempoolResponse::AddTransaction(self.add_tx(mempool_input)) + } + MempoolRequest::GetTransactions(n_txs) => { + MempoolResponse::GetTransactions(self.get_txs(n_txs)) + } + } + } +} + +#[async_trait] +impl ComponentStarter for MempoolCommunicationWrapper {} diff --git a/crates/mempool/src/lib.rs b/crates/mempool/src/lib.rs new file mode 100644 index 00000000000..b19ab1492f7 --- /dev/null +++ b/crates/mempool/src/lib.rs @@ -0,0 +1,5 @@ +pub mod communication; +pub mod mempool; +pub(crate) mod transaction_queue; +// TODO(Mohammad): change to `pub(crate)`. +pub mod transaction_pool; diff --git a/crates/mempool/src/mempool.rs b/crates/mempool/src/mempool.rs new file mode 100644 index 00000000000..d6ee638272f --- /dev/null +++ b/crates/mempool/src/mempool.rs @@ -0,0 +1,145 @@ +use std::collections::HashMap; + +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::transaction::{Tip, TransactionHash}; +use starknet_mempool_types::errors::MempoolError; +use starknet_mempool_types::mempool_types::{ + Account, AccountState, MempoolInput, MempoolResult, ThinTransaction, +}; + +use crate::transaction_pool::TransactionPool; +use crate::transaction_queue::TransactionQueue; + +#[cfg(test)] +#[path = "mempool_test.rs"] +pub mod mempool_test; + +#[derive(Debug, Default)] +pub struct Mempool { + // TODO: add docstring explaining visibility and coupling of the fields. + // All transactions currently held in the mempool. + tx_pool: TransactionPool, + // Transactions eligible for sequencing. + tx_queue: TransactionQueue, +} + +impl Mempool { + pub fn new(inputs: impl IntoIterator) -> MempoolResult { + let mut mempool = Mempool::empty(); + + for input in inputs { + mempool.insert_tx(input)?; + } + Ok(mempool) + } + + pub fn empty() -> Self { + Mempool::default() + } + + /// Returns an iterator of the current eligible transactions for sequencing, ordered by their + /// priority. + pub fn iter(&self) -> impl Iterator { + self.tx_queue.iter() + } + + /// Retrieves up to `n_txs` transactions with the highest priority from the mempool. + /// Transactions are guaranteed to be unique across calls until `commit_block` is invoked. + // TODO: the last part about commit_block is incorrect if we delete txs in get_txs and then push + // back. TODO: Consider renaming to `pop_txs` to be more consistent with the standard + // library. + pub fn get_txs(&mut self, n_txs: usize) -> MempoolResult> { + let mut eligible_txs: Vec = Vec::with_capacity(n_txs); + for tx_hash in self.tx_queue.pop_chunk(n_txs) { + let tx = self.tx_pool.remove(tx_hash)?; + eligible_txs.push(tx); + } + + Ok(eligible_txs) + } + + /// Adds a new transaction to the mempool. + /// TODO: support fee escalation and transactions with future nonces. + /// TODO: check Account nonce and balance. + pub fn add_tx(&mut self, input: MempoolInput) -> MempoolResult<()> { + self.insert_tx(input) + } + + /// Update the mempool's internal state according to the committed block (resolves nonce gaps, + /// updates account balances). + // TODO: the part about resolving nonce gaps is incorrect if we delete txs in get_txs and then + // push back. + // state_changes: a map that associates each account address with the state of the committed + // block. + pub fn commit_block( + &mut self, + state_changes: HashMap, + ) -> MempoolResult<()> { + for (address, AccountState { nonce }) in state_changes { + let next_nonce = nonce.try_increment().map_err(|_| MempoolError::FeltOutOfRange)?; + + // Align the queue with the committed nonces. + if self + .tx_queue + .get_nonce(address) + .is_some_and(|queued_nonce| queued_nonce != next_nonce) + { + self.tx_queue.remove(address); + } + + if self.tx_queue.get_nonce(address).is_none() { + if let Some(tx) = self.tx_pool.get_by_address_and_nonce(address, nonce) { + self.tx_queue.insert(*tx); + } + } + + self.tx_pool.remove_up_to_nonce(address, next_nonce); + } + Ok(()) + } + + fn insert_tx(&mut self, input: MempoolInput) -> MempoolResult<()> { + let MempoolInput { tx, account } = input; + let tx_reference = TransactionReference::new(&tx); + + self.tx_pool.insert(tx)?; + + if is_eligible_for_sequencing(tx_reference, account) { + self.tx_queue.insert(tx_reference); + } + + Ok(()) + } + + #[cfg(test)] + pub(crate) fn _tx_pool(&self) -> &TransactionPool { + &self.tx_pool + } +} + +/// Provides a lightweight representation of a transaction for mempool usage (e.g., excluding +/// execution fields). +/// TODO(Mohammad): rename this struct to `ThinTransaction` once that name +/// becomes available, to better reflect its purpose and usage. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct TransactionReference { + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub tx_hash: TransactionHash, + pub tip: Tip, +} + +impl TransactionReference { + pub fn new(tx: &ThinTransaction) -> Self { + TransactionReference { + sender_address: tx.sender_address, + nonce: tx.nonce, + tx_hash: tx.tx_hash, + tip: tx.tip, + } + } +} + +fn is_eligible_for_sequencing(tx_reference: TransactionReference, account: Account) -> bool { + tx_reference.nonce == account.state.nonce +} diff --git a/crates/mempool/src/mempool_test.rs b/crates/mempool/src/mempool_test.rs new file mode 100644 index 00000000000..8f015548aa9 --- /dev/null +++ b/crates/mempool/src/mempool_test.rs @@ -0,0 +1,445 @@ +use std::cmp::Reverse; +use std::collections::HashMap; + +use assert_matches::assert_matches; +use itertools::{enumerate, zip_eq}; +use pretty_assertions::assert_eq; +use rstest::{fixture, rstest}; +use starknet_api::core::{ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::{Tip, TransactionHash}; +use starknet_api::{contract_address, felt, patricia_key}; +use starknet_mempool_types::errors::MempoolError; +use starknet_mempool_types::mempool_types::{Account, AccountState, ThinTransaction}; +use starknet_types_core::felt::Felt; + +use crate::mempool::{Mempool, MempoolInput, TransactionReference}; +use crate::transaction_pool::TransactionPool; +use crate::transaction_queue::TransactionQueue; + +/// Represents the internal state of the mempool. +/// Enables customized (and potentially inconsistent) creation for unit testing. +struct MempoolState { + tx_pool: TransactionPool, + tx_queue: TransactionQueue, +} + +impl MempoolState { + fn new(pool_txs: PoolTxs, queue_txs: QueueTxs) -> Self + where + PoolTxs: IntoIterator, + QueueTxs: IntoIterator, + { + let tx_pool: TransactionPool = pool_txs.into_iter().collect(); + let tx_queue: TransactionQueue = queue_txs.into_iter().collect(); + MempoolState { tx_pool, tx_queue } + } + + fn assert_eq_mempool_state(&self, mempool: &Mempool) { + assert_eq!(self.tx_pool, mempool.tx_pool); + assert_eq!(self.tx_queue, mempool.tx_queue); + } +} + +impl From for Mempool { + fn from(mempool_state: MempoolState) -> Mempool { + let MempoolState { tx_pool, tx_queue } = mempool_state; + Mempool { tx_pool, tx_queue } + } +} + +impl FromIterator for TransactionPool { + fn from_iter>(txs: T) -> Self { + let mut pool = Self::default(); + for tx in txs { + pool.insert(tx).unwrap(); + } + pool + } +} + +impl FromIterator for TransactionQueue { + fn from_iter>(txs: T) -> Self { + let mut queue = Self::default(); + for tx in txs { + queue.insert(tx); + } + queue + } +} + +#[track_caller] +fn add_tx(mempool: &mut Mempool, input: &MempoolInput) { + assert_eq!(mempool.add_tx(input.clone()), Ok(())); +} + +/// Creates a valid input for mempool's `add_tx` with optional default values. +/// Usage: +/// 1. add_tx_input!(tip: 1, tx_hash: 2, sender_address: 3_u8, tx_nonce: 4, account_nonce: 3) +/// 2. add_tx_input!(tx_hash: 2, sender_address: 3_u8, tx_nonce: 4, account_nonce: 3) +/// 3. add_tx_input!(tip: 1, tx_hash: 2, sender_address: 3_u8) +/// 4. add_tx_input!(tx_hash: 1, tx_nonce: 1, account_nonce: 0) +/// 5. add_tx_input!(tip: 1, tx_hash: 2) +macro_rules! add_tx_input { + (tip: $tip:expr, tx_hash: $tx_hash:expr, sender_address: $sender_address:expr, + tx_nonce: $tx_nonce:expr, account_nonce: $account_nonce:expr) => {{ + let sender_address = contract_address!($sender_address); + let account_nonce = Nonce(felt!($account_nonce)); + let account = Account { sender_address, state: AccountState {nonce: account_nonce}}; + let tx = ThinTransaction { + tip: Tip($tip), + tx_hash: TransactionHash(StarkHash::from($tx_hash)), + sender_address, + nonce: Nonce(felt!($tx_nonce)), + }; + MempoolInput { tx, account } + }}; + (tx_hash: $tx_hash:expr, sender_address: $sender_address:expr, tx_nonce: $tx_nonce:expr, account_nonce: $account_nonce:expr) => { + add_tx_input!(tip: 0, tx_hash: $tx_hash, sender_address: $sender_address, tx_nonce: $tx_nonce, account_nonce: $account_nonce) + }; + (tip: $tip:expr, tx_hash: $tx_hash:expr, sender_address: $sender_address:expr) => { + add_tx_input!(tip: $tip, tx_hash: $tx_hash, sender_address: $sender_address, tx_nonce: 0_u8, account_nonce: 0_u8) + }; + (tx_hash: $tx_hash:expr, tx_nonce: $tx_nonce:expr, account_nonce: $account_nonce:expr) => { + add_tx_input!(tip: 1, tx_hash: $tx_hash, sender_address: "0x0", tx_nonce: $tx_nonce, account_nonce: $account_nonce) + }; + (tip: $tip:expr, tx_hash: $tx_hash:expr) => { + add_tx_input!(tip: $tip, tx_hash: $tx_hash, sender_address: "0x0", tx_nonce: 0_u8, account_nonce: 0_u8) + }; +} + +#[fixture] +fn mempool() -> Mempool { + Mempool::empty() +} + +// TODO(Ayelet): replace with MempoolState checker. +#[track_caller] +fn assert_eq_mempool_state( + mempool: &Mempool, + expected_pool: &[ThinTransaction], + expected_queue: &[ThinTransaction], +) { + assert_eq_mempool_queue(mempool, expected_queue); + + let expected_pool: HashMap<_, _> = + expected_pool.iter().cloned().map(|tx| (tx.tx_hash, tx)).collect(); + assert_eq!(mempool._tx_pool()._tx_pool(), &expected_pool); +} + +// Asserts that the transactions in the mempool are in ascending order as per the expected +// transactions. +#[track_caller] +fn assert_eq_mempool_queue(mempool: &Mempool, expected_queue: &[ThinTransaction]) { + let mempool_txs = mempool.iter(); + let expected_queue = expected_queue.iter().map(TransactionReference::new); + + for (i, (expected_tx, mempool_tx)) in enumerate(zip_eq(expected_queue, mempool_txs)) { + assert_eq!(expected_tx, *mempool_tx, "Transaction {i} in the queue is not as expected"); + } +} + +#[rstest] +#[case::test_get_zero_txs(0)] +#[case::test_get_exactly_all_eligible_txs(3)] +#[case::test_get_more_than_all_eligible_txs(5)] +#[case::test_get_less_than_all_eligible_txs(2)] +fn test_get_txs(#[case] requested_txs: usize) { + // Setup. + let tx_tip_20_account_0 = add_tx_input!(tip: 20, tx_hash: 1, sender_address: "0x0").tx; + let tx_tip_30_account_1 = add_tx_input!(tip: 30, tx_hash: 2, sender_address: "0x1").tx; + let tx_tip_10_account_2 = add_tx_input!(tip: 10, tx_hash: 3, sender_address: "0x2").tx; + + let mut txs = vec![tx_tip_20_account_0, tx_tip_30_account_1, tx_tip_10_account_2]; + let tx_references_iterator = txs.iter().map(TransactionReference::new); + let txs_iterator = txs.iter().cloned(); + + let mut mempool: Mempool = MempoolState::new(txs_iterator, tx_references_iterator).into(); + + // Test. + let fetched_txs = mempool.get_txs(requested_txs).unwrap(); + + txs.sort_by_key(|tx| Reverse(tx.tip)); + + // Ensure we do not exceed the number of transactions available in the mempool. + let max_requested_txs = requested_txs.min(txs.len()); + + // Check that the returned transactions are the ones with the highest priority. + let (expected_queue, remaining_txs) = txs.split_at(max_requested_txs); + assert_eq!(fetched_txs, expected_queue); + + // Assert: non-returned transactions are still in the mempool. + let remaining_tx_references = remaining_txs.iter().map(TransactionReference::new); + let mempool_state = MempoolState::new(remaining_txs.to_vec(), remaining_tx_references); + mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +// TODO(Ayelet): remove ignore once replenishing is merged. +#[ignore] +fn test_get_txs_multi_nonce() { + // Setup. + let tx_address_0_nonce_0 = + add_tx_input!(tx_hash: 1, sender_address: "0x0", tx_nonce: 0_u8, account_nonce: 0_u8).tx; + let tx_address_0_nonce_1 = + add_tx_input!(tx_hash: 2, sender_address: "0x0", tx_nonce: 1_u8, account_nonce: 0_u8).tx; + + let queue_txs = [TransactionReference::new(&tx_address_0_nonce_0)]; + let pool_txs = [tx_address_0_nonce_0.clone(), tx_address_0_nonce_1.clone()]; + let mut mempool: Mempool = MempoolState::new(pool_txs, queue_txs).into(); + + // Test. + let txs = mempool.get_txs(2).unwrap(); + + // Assert that the account's next tx was added the queue. + assert_eq!(txs, &[tx_address_0_nonce_0, tx_address_0_nonce_1]); + let expected_mempool_state = MempoolState::new([], []); + expected_mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_add_tx(mut mempool: Mempool) { + // Setup. + let mut add_tx_inputs = [ + add_tx_input!(tip: 50, tx_hash: 1, sender_address: "0x0"), + add_tx_input!(tip: 100, tx_hash: 2, sender_address: "0x1"), + add_tx_input!(tip: 80, tx_hash: 3, sender_address: "0x2"), + ]; + + // Test. + for input in &add_tx_inputs { + add_tx(&mut mempool, input); + } + + // TODO(Ayelet): Consider share this code. + // Sort in an ascending priority order. + add_tx_inputs.sort_by_key(|input| std::cmp::Reverse(input.tx.tip)); + + // Assert: transactions are ordered by priority. + let expected_queue_txs: Vec = + add_tx_inputs.iter().map(|input| TransactionReference::new(&input.tx)).collect(); + let expected_pool_txs = add_tx_inputs.into_iter().map(|input| input.tx); + let expected_mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + expected_mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_add_tx_multi_nonce_success(mut mempool: Mempool) { + let input_address_0_nonce_0 = + add_tx_input!(tx_hash: 1, sender_address: "0x0", tx_nonce: 0_u8, account_nonce: 0_u8); + let input_address_1 = + add_tx_input!(tx_hash: 2, sender_address: "0x1", tx_nonce: 0_u8,account_nonce: 0_u8); + let input_address_0_nonce_1 = + add_tx_input!(tx_hash: 3, sender_address: "0x0", tx_nonce: 1_u8, account_nonce: 0_u8); + + add_tx(&mut mempool, &input_address_0_nonce_0); + add_tx(&mut mempool, &input_address_1); + add_tx(&mut mempool, &input_address_0_nonce_1); + + let expected_pool_all_txs = &[ + input_address_0_nonce_0.tx.clone(), + input_address_1.tx.clone(), + input_address_0_nonce_1.tx, + ]; + let expected_queue_only_zero_nonce_txs = &[input_address_1.tx, input_address_0_nonce_0.tx]; + + assert_eq_mempool_state(&mempool, expected_pool_all_txs, expected_queue_only_zero_nonce_txs); +} + +#[test] +fn test_new_with_duplicate_tx() { + let input = add_tx_input!(tip: 0, tx_hash: 1); + let same_input = input.clone(); + + assert!(matches!( + Mempool::new([input, same_input]), + Err(MempoolError::DuplicateTransaction { .. }) + )); +} + +#[rstest] +fn test_add_tx_with_duplicate_tx(mut mempool: Mempool) { + let input = add_tx_input!(tip: 50, tx_hash: Felt::ONE); + let same_input = input.clone(); + + add_tx(&mut mempool, &input); + + assert_matches!( + mempool.add_tx(same_input.clone()), + Err(MempoolError::DuplicateTransaction { .. }) + ); + // Assert that the original tx remains in the pool after the failed attempt. + assert_eq_mempool_queue(&mempool, &[same_input.tx]) +} + +#[rstest] +fn test_add_tx_with_identical_tip_succeeds(mut mempool: Mempool) { + // Setup. + let input1 = add_tx_input!(tip: 1, tx_hash: 2); + + // Create a transaction with identical tip, it should be allowed through since the priority + // queue tie-breaks identical tips by other tx-unique identifiers (for example tx hash). + let input2 = add_tx_input!(tip: 1, tx_hash: 1, sender_address: "0x1"); + + // Test. + add_tx(&mut mempool, &input1); + add_tx(&mut mempool, &input2); + + // Assert: both transactions are in the mempool. + let expected_queue_txs = + [TransactionReference::new(&input1.tx), TransactionReference::new(&input2.tx)]; + let expected_pool_txs = [input1.tx, input2.tx]; + let expected_mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + + // TODO: currently hash comparison tie-breaks the two. Once more robust tie-breaks are added + // replace this assertion with a dedicated test. + expected_mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_tip_priority_over_tx_hash(mut mempool: Mempool) { + let input_big_tip_small_hash = add_tx_input!(tip: 2, tx_hash: Felt::ONE); + + // Create a transaction with identical tip, it should be allowed through since the priority + // queue tie-breaks identical tips by other tx-unique identifiers (for example tx hash). + let input_small_tip_big_hash = add_tx_input!(tip: 1, tx_hash: Felt::TWO, sender_address: "0x1"); + + add_tx(&mut mempool, &input_big_tip_small_hash); + add_tx(&mut mempool, &input_small_tip_big_hash); + assert_eq_mempool_queue(&mempool, &[input_big_tip_small_hash.tx, input_small_tip_big_hash.tx]) +} + +#[rstest] +fn test_get_txs_with_holes_multiple_accounts() { + // Setup. + let tx_address_0_nonce_1 = + add_tx_input!(tx_hash: 2, sender_address: "0x0", tx_nonce: 1_u8, account_nonce: 0_u8).tx; + let tx_address_1_nonce_0 = + add_tx_input!(tx_hash: 3, sender_address: "0x1", tx_nonce: 0_u8, account_nonce: 0_u8).tx; + + let queue_txs = [TransactionReference::new(&tx_address_1_nonce_0)]; + let pool_txs = [tx_address_0_nonce_1.clone(), tx_address_1_nonce_0.clone()]; + let mut mempool: Mempool = MempoolState::new(pool_txs, queue_txs).into(); + + // Test. + let txs = mempool.get_txs(2).unwrap(); + + // Assert. + assert_eq!(txs, &[tx_address_1_nonce_0]); + + let expected_pool_txs = [tx_address_0_nonce_1]; + let expected_queue_txs = []; + let mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_add_tx_sequential_nonces(mut mempool: Mempool) { + // Setup. + let input_nonce_0 = add_tx_input!(tx_hash: 0, tx_nonce: 0_u8, account_nonce: 0_u8); + let input_nonce_1 = add_tx_input!(tx_hash: 1, tx_nonce: 1_u8, account_nonce: 0_u8); + + // Test. + add_tx(&mut mempool, &input_nonce_0); + add_tx(&mut mempool, &input_nonce_1); + + // Assert: only eligible transaction appears in the queue. + let expected_queue_txs = [TransactionReference::new(&input_nonce_0.tx)]; + let expected_pool_txs = [input_nonce_0.tx, input_nonce_1.tx]; + let expected_mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + + expected_mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_get_txs_with_holes_single_account() { + // Setup. + let input_nonce_1 = add_tx_input!(tx_hash: 0, tx_nonce: 1_u8, account_nonce: 0_u8); + + let pool_txs = [input_nonce_1.tx]; + let queue_txs = []; + let mut mempool: Mempool = MempoolState::new(pool_txs.clone(), queue_txs).into(); + + // Test. + let txs = mempool.get_txs(1).unwrap(); + + // Assert. + assert_eq!(txs, &[]); + + let mempool_state = MempoolState::new(pool_txs, queue_txs); + mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_add_tx_filling_hole(mut mempool: Mempool) { + // Setup. + let input_nonce_0 = add_tx_input!(tx_hash: 1, tx_nonce: 0_u8, account_nonce: 0_u8); + let input_nonce_1 = add_tx_input!(tx_hash: 2, tx_nonce: 1_u8, account_nonce: 0_u8); + + // Test: add the second transaction first, which creates a hole in the sequence. + add_tx(&mut mempool, &input_nonce_1); + + // Assert: the second transaction is in the pool and not in the queue. + let expected_queue_txs = []; + let expected_pool_txs = [input_nonce_1.tx.clone()]; + let expected_mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + expected_mempool_state.assert_eq_mempool_state(&mempool); + + // Test: add the first transaction, which fills the hole. + add_tx(&mut mempool, &input_nonce_0); + + // Assert: only the eligible transaction appears in the queue. + let expected_queue_txs = [TransactionReference::new(&input_nonce_0.tx)]; + let expected_pool_txs = [input_nonce_1.tx, input_nonce_0.tx]; + let expected_mempool_state = MempoolState::new(expected_pool_txs, expected_queue_txs); + expected_mempool_state.assert_eq_mempool_state(&mempool); +} + +#[rstest] +fn test_flow_filling_holes(mut mempool: Mempool) { + // Setup. + let input_address_0_nonce_0 = + add_tx_input!(tx_hash: 1, sender_address: "0x0", tx_nonce: 0_u8, account_nonce: 0_u8); + let input_address_0_nonce_1 = + add_tx_input!(tx_hash: 2, sender_address: "0x0", tx_nonce: 1_u8, account_nonce: 0_u8); + let input_address_1_nonce_0 = + add_tx_input!(tx_hash: 3, sender_address: "0x1", tx_nonce: 0_u8, account_nonce: 0_u8); + + // Test. + add_tx(&mut mempool, &input_address_0_nonce_1); + add_tx(&mut mempool, &input_address_1_nonce_0); + let txs = mempool.get_txs(2).unwrap(); + + // Assert: only the eligible transaction is returned. + assert_eq!(txs, &[input_address_1_nonce_0.tx]); + + // Test. + add_tx(&mut mempool, &input_address_0_nonce_0); + let txs = mempool.get_txs(2).unwrap(); + + // TODO(Ayelet): all transactions should be returned after replenishing. + // Assert: all remaining transactions are returned. + assert_eq!(txs, &[input_address_0_nonce_0.tx]); +} + +#[rstest] +#[ignore] + +fn test_commit_block_rewinds_nonce() { + // Setup. + let tx_address0_nonce5 = add_tx_input!(tip: 1, tx_hash: 2, sender_address: "0x0", tx_nonce: 5_u8, account_nonce: 4_u8).tx; + + let queued_txs = [TransactionReference::new(&tx_address0_nonce5)]; + let pool_txs = [tx_address0_nonce5]; + let mut mempool: Mempool = MempoolState::new(pool_txs, queued_txs).into(); + + // Test. + let state_changes = HashMap::from([ + (contract_address!("0x0"), AccountState { nonce: Nonce(felt!(3_u16)) }), + (contract_address!("0x1"), AccountState { nonce: Nonce(felt!(3_u16)) }), + ]); + assert!(mempool.commit_block(state_changes).is_ok()); + + // Assert. + assert_eq_mempool_queue(&mempool, &[]) +} diff --git a/crates/mempool/src/transaction_pool.rs b/crates/mempool/src/transaction_pool.rs new file mode 100644 index 00000000000..3c59f07c735 --- /dev/null +++ b/crates/mempool/src/transaction_pool.rs @@ -0,0 +1,141 @@ +use std::collections::{hash_map, BTreeMap, HashMap}; + +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::transaction::TransactionHash; +use starknet_mempool_types::errors::MempoolError; +use starknet_mempool_types::mempool_types::{MempoolResult, ThinTransaction}; + +use crate::mempool::TransactionReference; + +type HashToTransaction = HashMap; + +/// Contains all transactions currently held in the mempool. +/// Invariant: both data structures are consistent regarding the existence of transactions: +/// A transaction appears in one if and only if it appears in the other. +/// No duplicate transactions appear in the pool. +#[derive(Debug, Default, Eq, PartialEq)] +pub struct TransactionPool { + // Holds the complete transaction objects; it should be the sole entity that does so. + tx_pool: HashToTransaction, + // Transactions organized by account address, sorted by ascending nonce values. + txs_by_account: AccountTransactionIndex, +} + +impl TransactionPool { + pub fn insert(&mut self, tx: ThinTransaction) -> MempoolResult<()> { + let tx_reference = TransactionReference::new(&tx); + let tx_hash = tx_reference.tx_hash; + + // Insert to pool. + if let hash_map::Entry::Vacant(entry) = self.tx_pool.entry(tx_hash) { + entry.insert(tx); + } else { + return Err(MempoolError::DuplicateTransaction { tx_hash }); + } + + // Insert to account mapping. + let unexpected_existing_tx = self.txs_by_account.insert(tx_reference); + if unexpected_existing_tx.is_some() { + panic!( + "Transaction pool consistency error: transaction with hash {tx_hash} does not \ + appear in main mapping, but it appears in the account mapping", + ) + }; + + Ok(()) + } + + pub fn remove(&mut self, tx_hash: TransactionHash) -> MempoolResult { + // Remove from pool. + let tx = + self.tx_pool.remove(&tx_hash).ok_or(MempoolError::TransactionNotFound { tx_hash })?; + + // Remove from account mapping. + self.txs_by_account.remove(TransactionReference::new(&tx)).unwrap_or_else(|| { + panic!( + "Transaction pool consistency error: transaction with hash {tx_hash} appears in \ + main mapping, but does not appear in the account mapping" + ) + }); + + Ok(tx) + } + + pub fn remove_up_to_nonce(&mut self, address: ContractAddress, nonce: Nonce) { + let removed_txs = self.txs_by_account.remove_up_to_nonce(address, nonce); + + for TransactionReference { tx_hash, .. } in removed_txs { + self.tx_pool.remove(&tx_hash).unwrap_or_else(|| { + panic!( + "Transaction pool consistency error: transaction with hash {tx_hash} appears \ + in account mapping, but does not appear in the main mapping" + ); + }); + } + } + + pub fn get_by_tx_hash(&self, tx_hash: TransactionHash) -> MempoolResult<&ThinTransaction> { + self.tx_pool.get(&tx_hash).ok_or(MempoolError::TransactionNotFound { tx_hash }) + } + + pub fn get_by_address_and_nonce( + &self, + address: ContractAddress, + nonce: Nonce, + ) -> Option<&TransactionReference> { + self.txs_by_account.get(address, nonce) + } + + #[cfg(test)] + pub(crate) fn _tx_pool(&self) -> &HashToTransaction { + &self.tx_pool + } +} + +#[derive(Debug, Default, Eq, PartialEq)] +struct AccountTransactionIndex(HashMap>); + +impl AccountTransactionIndex { + /// If the transaction already exists in the mapping, the old value is returned. + fn insert(&mut self, tx: TransactionReference) -> Option { + self.0.entry(tx.sender_address).or_default().insert(tx.nonce, tx) + } + + fn remove(&mut self, tx: TransactionReference) -> Option { + let TransactionReference { sender_address, nonce, .. } = tx; + let account_txs = self.0.get_mut(&sender_address)?; + + let removed_tx = account_txs.remove(&nonce); + + if removed_tx.is_some() && account_txs.is_empty() { + self.0.remove(&sender_address); + } + + removed_tx + } + + fn get(&self, address: ContractAddress, nonce: Nonce) -> Option<&TransactionReference> { + self.0.get(&address)?.get(&nonce) + } + + fn remove_up_to_nonce( + &mut self, + address: ContractAddress, + nonce: Nonce, + ) -> Vec { + let Some(account_txs) = self.0.get_mut(&address) else { + return Vec::default(); + }; + + // Split the transactions at the given nonce. + let txs_with_higher_or_equal_nonce = account_txs.split_off(&nonce); + let txs_with_lower_nonce = std::mem::replace(account_txs, txs_with_higher_or_equal_nonce); + + if account_txs.is_empty() { + self.0.remove(&address); + } + + // Collect and return the transactions with lower nonces. + txs_with_lower_nonce.into_values().collect() + } +} diff --git a/crates/mempool/src/transaction_queue.rs b/crates/mempool/src/transaction_queue.rs new file mode 100644 index 00000000000..4ae982fc5d7 --- /dev/null +++ b/crates/mempool/src/transaction_queue.rs @@ -0,0 +1,95 @@ +use std::cmp::Ordering; +use std::collections::{BTreeSet, HashMap}; + +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::transaction::TransactionHash; + +use crate::mempool::TransactionReference; + +// Note: the derived comparison functionality considers the order guaranteed by the data structures +// used. +#[derive(Debug, Default, Eq, PartialEq)] +pub struct TransactionQueue { + // Priority queue of transactions with associated priority. + queue: BTreeSet, + // Set of account addresses for efficient existence checks. + address_to_tx: HashMap, +} + +impl TransactionQueue { + /// Adds a transaction to the mempool, ensuring unique keys. + /// Panics: if given a duplicate tx. + // TODO(Mohammad): Add test for two transactions from the same address, expecting specific + // assert. + pub fn insert(&mut self, tx: TransactionReference) { + assert_eq!( + self.address_to_tx.insert(tx.sender_address, tx), + None, + "Only a single transaction from the same contract class can be in the mempool at a \ + time." + ); + assert!( + self.queue.insert(tx.into()), + "Keys should be unique; duplicates are checked prior." + ); + } + + // TODO(gilad): remove collect + pub fn pop_chunk(&mut self, n_txs: usize) -> Vec { + let txs: Vec = + (0..n_txs).filter_map(|_| self.queue.pop_last().map(|tx| tx.0)).collect(); + for tx in &txs { + self.address_to_tx.remove(&tx.sender_address); + } + + txs.into_iter().map(|tx| tx.tx_hash).collect() + } + + /// Returns an iterator of the current eligible transactions for sequencing, ordered by their + /// priority. + pub fn iter(&self) -> impl Iterator { + self.queue.iter().rev().map(|tx| &tx.0) + } + + pub fn get_nonce(&self, address: ContractAddress) -> Option { + self.address_to_tx.get(&address).map(|tx| tx.nonce) + } + + /// Removes the transaction of the given account address from the queue. + /// This is well-defined, since there is at most one transaction per address in the queue. + pub fn remove(&mut self, address: ContractAddress) -> bool { + if let Some(tx) = self.address_to_tx.remove(&address) { + return self.queue.remove(&tx.into()); + } + false + } +} + +/// Encapsulates a transaction reference to assess its order (i.e., priority). +#[derive(Clone, Debug, derive_more::Deref, derive_more::From)] +struct QueuedTransaction(pub TransactionReference); + +/// Compare transactions based only on their tip, a uint, using the Eq trait. It ensures that two +/// tips are either exactly equal or not. +impl PartialEq for QueuedTransaction { + fn eq(&self, other: &QueuedTransaction) -> bool { + self.tip == other.tip && self.tx_hash == other.tx_hash + } +} + +/// Marks this struct as capable of strict equality comparisons, signaling to the compiler it +/// adheres to equality semantics. +// Note: this depends on the implementation of `PartialEq`, see its docstring. +impl Eq for QueuedTransaction {} + +impl Ord for QueuedTransaction { + fn cmp(&self, other: &Self) -> Ordering { + self.tip.cmp(&other.tip).then_with(|| self.tx_hash.cmp(&other.tx_hash)) + } +} + +impl PartialOrd for QueuedTransaction { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} diff --git a/crates/mempool_infra/Cargo.toml b/crates/mempool_infra/Cargo.toml new file mode 100644 index 00000000000..c65396a3cd4 --- /dev/null +++ b/crates/mempool_infra/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "starknet_mempool_infra" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[package.metadata.cargo-udeps.ignore] +normal = ["tokio"] + +[lints] +workspace = true + +[dependencies] +async-trait.workspace = true +bincode.workspace = true +hyper.workspace = true +rstest.workspace = true +serde.workspace = true +thiserror.workspace = true +tokio.workspace = true +tracing.workspace = true +tracing-subscriber = { workspace = true, features = ["env-filter"] } + +[dev-dependencies] +assert_matches.workspace = true +pretty_assertions.workspace = true diff --git a/crates/mempool_infra/src/component_client/definitions.rs b/crates/mempool_infra/src/component_client/definitions.rs new file mode 100644 index 00000000000..93cdbfa7d39 --- /dev/null +++ b/crates/mempool_infra/src/component_client/definitions.rs @@ -0,0 +1,21 @@ +use bincode::ErrorKind; +use hyper::{Error as HyperError, StatusCode}; +use thiserror::Error; + +use crate::component_definitions::ServerError; + +#[derive(Debug, Error)] +pub enum ClientError { + #[error("Communication error: {0}")] + CommunicationFailure(HyperError), + #[error("Could not deserialize server response: {0}")] + ResponseDeserializationFailure(Box), + #[error("Could not parse the response: {0}")] + ResponseParsingFailure(HyperError), + #[error("Got status code: {0}, with server error: {1}")] + ResponseError(StatusCode, ServerError), + #[error("Got an unexpected response type.")] + UnexpectedResponse, +} + +pub type ClientResult = Result; diff --git a/crates/mempool_infra/src/component_client/local_component_client.rs b/crates/mempool_infra/src/component_client/local_component_client.rs new file mode 100644 index 00000000000..2330f9fc897 --- /dev/null +++ b/crates/mempool_infra/src/component_client/local_component_client.rs @@ -0,0 +1,92 @@ +use tokio::sync::mpsc::{channel, Sender}; + +use crate::component_definitions::ComponentRequestAndResponseSender; + +/// The `LocalComponentClient` struct is a generic client for sending component requests and +/// receiving responses asynchronously. +/// +/// # Type Parameters +/// - `Request`: The type of the request. This type must implement both `Send` and `Sync` traits. +/// - `Response`: The type of the response. This type must implement both `Send` and `Sync` traits. +/// +/// # Fields +/// - `tx`: An asynchronous sender channel for transmitting +/// `ComponentRequestAndResponseSender` messages. +/// +/// # Example +/// ```rust +/// // Example usage of the LocalComponentClient +/// use tokio::sync::mpsc::Sender; +/// +/// use crate::starknet_mempool_infra::component_client::local_component_client::LocalComponentClient; +/// use crate::starknet_mempool_infra::component_definitions::ComponentRequestAndResponseSender; +/// +/// // Define your request and response types +/// struct MyRequest { +/// pub content: String, +/// } +/// +/// struct MyResponse { +/// content: String, +/// } +/// +/// #[tokio::main] +/// async fn main() { +/// // Create a channel for sending requests and receiving responses +/// let (tx, _rx) = tokio::sync::mpsc::channel::< +/// ComponentRequestAndResponseSender, +/// >(100); +/// +/// // Instantiate the client. +/// let client = LocalComponentClient::new(tx); +/// +/// // Instantiate a request. +/// let request = MyRequest { content: "Hello, world!".to_string() }; +/// +/// // Send the request; typically, the client should await for a response. +/// client.send(request); +/// } +/// ``` +/// +/// # Notes +/// - The `LocalComponentClient` struct is designed to work in an asynchronous environment, +/// utilizing Tokio's async runtime and channels. +pub struct LocalComponentClient +where + Request: Send + Sync, + Response: Send + Sync, +{ + tx: Sender>, +} + +impl LocalComponentClient +where + Request: Send + Sync, + Response: Send + Sync, +{ + pub fn new(tx: Sender>) -> Self { + Self { tx } + } + + // TODO(Tsabary, 1/5/2024): Consider implementation for messages without expected responses. + + pub async fn send(&self, request: Request) -> Response { + let (res_tx, mut res_rx) = channel::(1); + let request_and_res_tx = ComponentRequestAndResponseSender { request, tx: res_tx }; + self.tx.send(request_and_res_tx).await.expect("Outbound connection should be open."); + + res_rx.recv().await.expect("Inbound connection should be open.") + } +} + +// Can't derive because derive forces the generics to also be `Clone`, which we prefer not to do +// since it'll require transactions to be cloneable. +impl Clone for LocalComponentClient +where + Request: Send + Sync, + Response: Send + Sync, +{ + fn clone(&self) -> Self { + Self { tx: self.tx.clone() } + } +} diff --git a/crates/mempool_infra/src/component_client/mod.rs b/crates/mempool_infra/src/component_client/mod.rs new file mode 100644 index 00000000000..40b3fca5682 --- /dev/null +++ b/crates/mempool_infra/src/component_client/mod.rs @@ -0,0 +1,3 @@ +pub mod definitions; +pub mod local_component_client; +pub mod remote_component_client; diff --git a/crates/mempool_infra/src/component_client/remote_component_client.rs b/crates/mempool_infra/src/component_client/remote_component_client.rs new file mode 100644 index 00000000000..c908582c028 --- /dev/null +++ b/crates/mempool_infra/src/component_client/remote_component_client.rs @@ -0,0 +1,87 @@ +use std::marker::PhantomData; +use std::net::IpAddr; + +use bincode::{deserialize, serialize}; +use hyper::body::to_bytes; +use hyper::header::CONTENT_TYPE; +use hyper::{Body, Client, Request as HyperRequest, Response as HyperResponse, StatusCode, Uri}; +use serde::{Deserialize, Serialize}; + +use super::definitions::{ClientError, ClientResult}; +use crate::component_definitions::APPLICATION_OCTET_STREAM; + +pub struct RemoteComponentClient +where + Request: Serialize, + Response: for<'a> Deserialize<'a>, +{ + uri: Uri, + client: Client, + _req: PhantomData, + _res: PhantomData, +} + +impl RemoteComponentClient +where + Request: Serialize, + Response: for<'a> Deserialize<'a>, +{ + pub fn new(ip_address: IpAddr, port: u16) -> Self { + let uri = match ip_address { + IpAddr::V4(ip_address) => format!("http://{}:{}/", ip_address, port).parse().unwrap(), + IpAddr::V6(ip_address) => format!("http://[{}]:{}/", ip_address, port).parse().unwrap(), + }; + // TODO(Tsabary): Add a configuration for the maximum number of idle connections. + // TODO(Tsabary): Add a configuration for "keep-alive" time of idle connections. + let client = + Client::builder().http2_only(true).pool_max_idle_per_host(usize::MAX).build_http(); + Self { uri, client, _req: PhantomData, _res: PhantomData } + } + + pub async fn send(&self, component_request: Request) -> ClientResult { + let http_request = HyperRequest::post(self.uri.clone()) + .header(CONTENT_TYPE, APPLICATION_OCTET_STREAM) + .body(Body::from( + serialize(&component_request).expect("Request serialization should succeed"), + )) + .expect("Request building should succeed"); + + // Todo(uriel): Add configuration for controlling the number of retries. + let http_response = + self.client.request(http_request).await.map_err(ClientError::CommunicationFailure)?; + + match http_response.status() { + StatusCode::OK => get_response_body(http_response).await, + status_code => Err(ClientError::ResponseError( + status_code, + get_response_body(http_response).await?, + )), + } + } +} + +async fn get_response_body(response: HyperResponse) -> Result +where + T: for<'a> Deserialize<'a>, +{ + let body_bytes = + to_bytes(response.into_body()).await.map_err(ClientError::ResponseParsingFailure)?; + deserialize(&body_bytes).map_err(ClientError::ResponseDeserializationFailure) +} + +// Can't derive because derive forces the generics to also be `Clone`, which we prefer not to do +// since it'll require the generic Request and Response types to be cloneable. +impl Clone for RemoteComponentClient +where + Request: Serialize, + Response: for<'a> Deserialize<'a>, +{ + fn clone(&self) -> Self { + Self { + uri: self.uri.clone(), + client: self.client.clone(), + _req: PhantomData, + _res: PhantomData, + } + } +} diff --git a/crates/mempool_infra/src/component_definitions.rs b/crates/mempool_infra/src/component_definitions.rs new file mode 100644 index 00000000000..4585fdc8e1f --- /dev/null +++ b/crates/mempool_infra/src/component_definitions.rs @@ -0,0 +1,45 @@ +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use thiserror::Error; +use tokio::sync::mpsc::{Receiver, Sender}; + +#[async_trait] +pub trait ComponentRequestHandler { + async fn handle_request(&mut self, request: Request) -> Response; +} + +pub struct ComponentCommunication { + tx: Option>, + rx: Option>, +} + +impl ComponentCommunication { + pub fn new(tx: Option>, rx: Option>) -> Self { + Self { tx, rx } + } + + pub fn take_tx(&mut self) -> Sender { + self.tx.take().expect("Sender should be available, could be taken only once") + } + + pub fn take_rx(&mut self) -> Receiver { + self.rx.take().expect("Receiver should be available, could be taken only once") + } +} + +pub struct ComponentRequestAndResponseSender +where + Request: Send + Sync, + Response: Send + Sync, +{ + pub request: Request, + pub tx: Sender, +} + +pub const APPLICATION_OCTET_STREAM: &str = "application/octet-stream"; + +#[derive(Debug, Error, Deserialize, Serialize, Clone)] +pub enum ServerError { + #[error("Could not deserialize client request: {0}")] + RequestDeserializationFailure(String), +} diff --git a/crates/mempool_infra/src/component_runner.rs b/crates/mempool_infra/src/component_runner.rs new file mode 100644 index 00000000000..de8ab6b51d3 --- /dev/null +++ b/crates/mempool_infra/src/component_runner.rs @@ -0,0 +1,18 @@ +use async_trait::async_trait; + +#[derive(thiserror::Error, Debug, PartialEq, Clone)] +pub enum ComponentStartError { + #[error("Error in the component configuration.")] + ComponentConfigError, + #[error("An internal component error.")] + InternalComponentError, +} + +/// Interface to start components. +#[async_trait] +pub trait ComponentStarter { + /// Start the component. By default do nothing. + async fn start(&mut self) -> Result<(), ComponentStartError> { + Ok(()) + } +} diff --git a/crates/mempool_infra/src/component_server/definitions.rs b/crates/mempool_infra/src/component_server/definitions.rs new file mode 100644 index 00000000000..7aa54bb3cec --- /dev/null +++ b/crates/mempool_infra/src/component_server/definitions.rs @@ -0,0 +1,22 @@ +use async_trait::async_trait; +use tracing::{error, info}; + +use crate::component_runner::ComponentStarter; + +#[async_trait] +pub trait ComponentServerStarter: Send + Sync { + async fn start(&mut self); +} + +pub async fn start_component(component: &mut Component) -> bool +where + Component: ComponentStarter + Sync + Send, +{ + if let Err(err) = component.start().await { + error!("ComponentServer::start() failed: {:?}", err); + return false; + } + + info!("ComponentServer::start() completed."); + true +} diff --git a/crates/mempool_infra/src/component_server/empty_component_server.rs b/crates/mempool_infra/src/component_server/empty_component_server.rs new file mode 100644 index 00000000000..53b03b6bfda --- /dev/null +++ b/crates/mempool_infra/src/component_server/empty_component_server.rs @@ -0,0 +1,25 @@ +use async_trait::async_trait; + +use super::definitions::{start_component, ComponentServerStarter}; +use crate::component_runner::ComponentStarter; + +pub struct EmptyServer { + component: T, +} + +impl EmptyServer { + pub fn new(component: T) -> Self { + Self { component } + } +} + +#[async_trait] +impl ComponentServerStarter for EmptyServer { + async fn start(&mut self) { + start_component(&mut self.component).await; + } +} + +pub fn create_empty_server(component: T) -> EmptyServer { + EmptyServer::new(component) +} diff --git a/crates/mempool_infra/src/component_server/local_component_server.rs b/crates/mempool_infra/src/component_server/local_component_server.rs new file mode 100644 index 00000000000..19c0906acd2 --- /dev/null +++ b/crates/mempool_infra/src/component_server/local_component_server.rs @@ -0,0 +1,150 @@ +use async_trait::async_trait; +use tokio::sync::mpsc::Receiver; + +use super::definitions::{start_component, ComponentServerStarter}; +use crate::component_definitions::{ComponentRequestAndResponseSender, ComponentRequestHandler}; +use crate::component_runner::ComponentStarter; + +/// The `LocalComponentServer` struct is a generic server that handles requests and responses for a +/// specified component. It receives requests, processes them using the provided component, and +/// sends back responses. The server needs to be started using the `start` function, which runs +/// indefinitely. +/// +/// # Type Parameters +/// +/// - `Component`: The type of the component that will handle the requests. This type must implement +/// the `ComponentRequestHandler` trait, which defines how the component processes requests and +/// generates responses. +/// - `Request`: The type of requests that the component will handle. This type must implement the +/// `Send` and `Sync` traits to ensure safe concurrency. +/// - `Response`: The type of responses that the component will generate. This type must implement +/// the `Send` and `Sync` traits to ensure safe concurrency. +/// +/// # Fields +/// +/// - `component`: The component responsible for handling the requests and generating responses. +/// - `rx`: A receiver that receives incoming requests along with a sender to send back the +/// responses. This receiver is of type ` Receiver>`. +/// +/// # Example +/// ```rust +/// // Example usage of the LocalComponentServer +/// use std::sync::mpsc::{channel, Receiver}; +/// +/// use async_trait::async_trait; +/// use starknet_mempool_infra::component_runner::{ComponentStartError, ComponentStarter}; +/// use tokio::task; +/// +/// use crate::starknet_mempool_infra::component_definitions::{ +/// ComponentRequestAndResponseSender, ComponentRequestHandler, +/// }; +/// use crate::starknet_mempool_infra::component_server::local_component_server::LocalComponentServer; +/// use crate::starknet_mempool_infra::component_server::definitions::ComponentServerStarter; +/// +/// // Define your component +/// struct MyComponent {} +/// +/// #[async_trait] +/// impl ComponentStarter for MyComponent { +/// async fn start(&mut self) -> Result<(), ComponentStartError> { +/// Ok(()) +/// } +/// } +/// +/// // Define your request and response types +/// struct MyRequest { +/// pub content: String, +/// } +/// +/// struct MyResponse { +/// pub content: String, +/// } +/// +/// // Define your request processing logic +/// #[async_trait] +/// impl ComponentRequestHandler for MyComponent { +/// async fn handle_request(&mut self, request: MyRequest) -> MyResponse { +/// MyResponse { content: request.content.clone() + " processed" } +/// } +/// } +/// +/// #[tokio::main] +/// async fn main() { +/// // Create a channel for sending requests and receiving responses +/// let (tx, rx) = tokio::sync::mpsc::channel::< +/// ComponentRequestAndResponseSender, +/// >(100); +/// +/// // Instantiate the component. +/// let component = MyComponent {}; +/// +/// // Instantiate the server. +/// let mut server = LocalComponentServer::new(component, rx); +/// +/// // Start the server in a new task. +/// task::spawn(async move { +/// server.start().await; +/// }); +/// +/// // Ensure the server starts running. +/// task::yield_now().await; +/// +/// // Create the request and the response channel. +/// let (res_tx, mut res_rx) = tokio::sync::mpsc::channel::(1); +/// let request = MyRequest { content: "request example".to_string() }; +/// let request_and_res_tx = ComponentRequestAndResponseSender { request, tx: res_tx }; +/// +/// // Send the request. +/// tx.send(request_and_res_tx).await.unwrap(); +/// +/// // Receive the response. +/// let response = res_rx.recv().await.unwrap(); +/// assert!(response.content == "request example processed".to_string(), "Unexpected response"); +/// } +/// ``` +pub struct LocalComponentServer +where + Component: ComponentRequestHandler + ComponentStarter, + Request: Send + Sync, + Response: Send + Sync, +{ + component: Component, + rx: Receiver>, +} + +impl LocalComponentServer +where + Component: ComponentRequestHandler + ComponentStarter, + Request: Send + Sync, + Response: Send + Sync, +{ + pub fn new( + component: Component, + rx: Receiver>, + ) -> Self { + Self { component, rx } + } +} + +#[async_trait] +impl ComponentServerStarter + for LocalComponentServer +where + Component: ComponentRequestHandler + ComponentStarter + Send + Sync, + Request: Send + Sync, + Response: Send + Sync, +{ + async fn start(&mut self) { + if start_component(&mut self.component).await { + while let Some(request_and_res_tx) = self.rx.recv().await { + let request = request_and_res_tx.request; + let tx = request_and_res_tx.tx; + + let res = self.component.handle_request(request).await; + + tx.send(res).await.expect("Response connection should be open."); + } + } + } +} diff --git a/crates/mempool_infra/src/component_server/mod.rs b/crates/mempool_infra/src/component_server/mod.rs new file mode 100644 index 00000000000..dbb040d6738 --- /dev/null +++ b/crates/mempool_infra/src/component_server/mod.rs @@ -0,0 +1,4 @@ +pub mod definitions; +pub mod empty_component_server; +pub mod local_component_server; +pub mod remote_component_server; diff --git a/crates/mempool_infra/src/component_server/remote_component_server.rs b/crates/mempool_infra/src/component_server/remote_component_server.rs new file mode 100644 index 00000000000..3146b9d1eb4 --- /dev/null +++ b/crates/mempool_infra/src/component_server/remote_component_server.rs @@ -0,0 +1,97 @@ +use std::marker::PhantomData; +use std::net::{IpAddr, SocketAddr}; +use std::sync::Arc; + +use async_trait::async_trait; +use bincode::{deserialize, serialize}; +use hyper::body::to_bytes; +use hyper::header::CONTENT_TYPE; +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request as HyperRequest, Response as HyperResponse, Server, StatusCode}; +use serde::{Deserialize, Serialize}; +use tokio::sync::Mutex; + +use super::definitions::ComponentServerStarter; +use crate::component_definitions::{ + ComponentRequestHandler, ServerError, APPLICATION_OCTET_STREAM, +}; + +pub struct RemoteComponentServer +where + Component: ComponentRequestHandler + Send + 'static, + Request: for<'a> Deserialize<'a> + Send + 'static, + Response: Serialize + 'static, +{ + socket: SocketAddr, + component: Arc>, + _req: PhantomData, + _res: PhantomData, +} + +impl RemoteComponentServer +where + Component: ComponentRequestHandler + Send + 'static, + Request: for<'a> Deserialize<'a> + Send + 'static, + Response: Serialize + 'static, +{ + pub fn new(component: Component, ip_address: IpAddr, port: u16) -> Self { + Self { + component: Arc::new(Mutex::new(component)), + socket: SocketAddr::new(ip_address, port), + _req: PhantomData, + _res: PhantomData, + } + } + + async fn handler( + http_request: HyperRequest, + component: Arc>, + ) -> Result, hyper::Error> { + let body_bytes = to_bytes(http_request.into_body()).await?; + let http_response = match deserialize(&body_bytes) { + Ok(component_request) => { + // Acquire the lock for component computation, release afterwards. + let component_response = + { component.lock().await.handle_request(component_request).await }; + HyperResponse::builder() + .status(StatusCode::OK) + .header(CONTENT_TYPE, APPLICATION_OCTET_STREAM) + .body(Body::from( + serialize(&component_response) + .expect("Response serialization should succeed"), + )) + } + Err(error) => { + let server_error = ServerError::RequestDeserializationFailure(error.to_string()); + HyperResponse::builder().status(StatusCode::BAD_REQUEST).body(Body::from( + serialize(&server_error).expect("Server error serialization should succeed"), + )) + } + } + .expect("Response building should succeed"); + + Ok(http_response) + } +} + +#[async_trait] +impl ComponentServerStarter + for RemoteComponentServer +where + Component: ComponentRequestHandler + Send + 'static, + Request: for<'a> Deserialize<'a> + Send + Sync + 'static, + Response: Serialize + Send + Sync + 'static, +{ + async fn start(&mut self) { + let make_svc = make_service_fn(|_conn| { + let component = Arc::clone(&self.component); + async { + Ok::<_, hyper::Error>(service_fn(move |req| { + Self::handler(req, Arc::clone(&component)) + })) + } + }); + + Server::bind(&self.socket.clone()).serve(make_svc).await.unwrap(); + } +} diff --git a/crates/mempool_infra/src/lib.rs b/crates/mempool_infra/src/lib.rs new file mode 100644 index 00000000000..bdeea651d3b --- /dev/null +++ b/crates/mempool_infra/src/lib.rs @@ -0,0 +1,5 @@ +pub mod component_client; +pub mod component_definitions; +pub mod component_runner; +pub mod component_server; +pub mod trace_util; diff --git a/crates/mempool_infra/src/trace_util.rs b/crates/mempool_infra/src/trace_util.rs new file mode 100644 index 00000000000..057af5b98ed --- /dev/null +++ b/crates/mempool_infra/src/trace_util.rs @@ -0,0 +1,15 @@ +use tracing::metadata::LevelFilter; +use tracing_subscriber::prelude::*; +use tracing_subscriber::{fmt, EnvFilter}; + +const DEFAULT_LEVEL: LevelFilter = LevelFilter::INFO; + +pub fn configure_tracing() { + let fmt_layer = fmt::layer().compact().with_target(false); + let level_filter_layer = + EnvFilter::builder().with_default_directive(DEFAULT_LEVEL.into()).from_env_lossy(); + + // This sets a single subscriber to all of the threads. We may want to implement different + // subscriber for some threads and use set_global_default instead of init. + tracing_subscriber::registry().with(fmt_layer).with(level_filter_layer).init(); +} diff --git a/crates/mempool_infra/tests/common/mod.rs b/crates/mempool_infra/tests/common/mod.rs new file mode 100644 index 00000000000..57b5fabb453 --- /dev/null +++ b/crates/mempool_infra/tests/common/mod.rs @@ -0,0 +1,85 @@ +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use starknet_mempool_infra::component_client::definitions::ClientResult; +use starknet_mempool_infra::component_runner::ComponentStarter; + +pub(crate) type ValueA = u32; +pub(crate) type ValueB = u8; + +pub(crate) type ResultA = ClientResult; +pub(crate) type ResultB = ClientResult; + +// TODO(Tsabary): add more messages / functions to the components. + +#[derive(Serialize, Deserialize, Debug)] +pub enum ComponentARequest { + AGetValue, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum ComponentAResponse { + AGetValue(ValueA), +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum ComponentBRequest { + BGetValue, + BSetValue(ValueB), +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum ComponentBResponse { + BGetValue(ValueB), + BSetValue, +} + +#[async_trait] +pub(crate) trait ComponentAClientTrait: Send + Sync { + async fn a_get_value(&self) -> ResultA; +} + +#[async_trait] +pub(crate) trait ComponentBClientTrait: Send + Sync { + async fn b_get_value(&self) -> ResultB; + async fn b_set_value(&self, value: ValueB) -> ClientResult<()>; +} + +pub(crate) struct ComponentA { + b: Box, +} + +impl ComponentA { + pub fn new(b: Box) -> Self { + Self { b } + } + + pub async fn a_get_value(&self) -> ValueA { + let b_value = self.b.b_get_value().await.unwrap(); + b_value.into() + } +} + +#[async_trait] +impl ComponentStarter for ComponentA {} + +pub(crate) struct ComponentB { + value: ValueB, + _a: Box, +} + +impl ComponentB { + pub fn new(value: ValueB, a: Box) -> Self { + Self { value, _a: a } + } + + pub fn b_get_value(&self) -> ValueB { + self.value + } + + pub fn b_set_value(&mut self, value: ValueB) { + self.value = value; + } +} + +#[async_trait] +impl ComponentStarter for ComponentB {} diff --git a/crates/mempool_infra/tests/component_server_client_http_test.rs b/crates/mempool_infra/tests/component_server_client_http_test.rs new file mode 100644 index 00000000000..657039793ae --- /dev/null +++ b/crates/mempool_infra/tests/component_server_client_http_test.rs @@ -0,0 +1,251 @@ +mod common; + +use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + +use async_trait::async_trait; +use bincode::{deserialize, serialize}; +use common::{ + ComponentAClientTrait, ComponentARequest, ComponentAResponse, ComponentBClientTrait, + ComponentBRequest, ComponentBResponse, ResultA, ResultB, +}; +use hyper::body::to_bytes; +use hyper::header::CONTENT_TYPE; +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Client, Request, Response, Server, StatusCode, Uri}; +use rstest::rstest; +use serde::Serialize; +use starknet_mempool_infra::component_client::definitions::{ClientError, ClientResult}; +use starknet_mempool_infra::component_client::remote_component_client::RemoteComponentClient; +use starknet_mempool_infra::component_definitions::{ + ComponentRequestHandler, ServerError, APPLICATION_OCTET_STREAM, +}; +use starknet_mempool_infra::component_server::definitions::ComponentServerStarter; +use starknet_mempool_infra::component_server::remote_component_server::RemoteComponentServer; +use tokio::task; + +type ComponentAClient = RemoteComponentClient; +type ComponentBClient = RemoteComponentClient; + +use crate::common::{ComponentA, ComponentB, ValueA, ValueB}; + +const LOCAL_IP: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +const A_PORT_TEST_SETUP: u16 = 10000; +const B_PORT_TEST_SETUP: u16 = 10001; +const A_PORT_FAULTY_CLIENT: u16 = 10010; +const B_PORT_FAULTY_CLIENT: u16 = 10011; +const UNCONNECTED_SERVER_PORT: u16 = 10002; +const FAULTY_SERVER_REQ_DESER_PORT: u16 = 10003; +const FAULTY_SERVER_RES_DESER_PORT: u16 = 10004; +const MOCK_SERVER_ERROR: &str = "mock server error"; +const ARBITRARY_DATA: &str = "arbitrary data"; +// ServerError::RequestDeserializationFailure error message. +const DESERIALIZE_REQ_ERROR_MESSAGE: &str = "Could not deserialize client request"; +// ClientError::ResponseDeserializationFailure error message. +const DESERIALIZE_RES_ERROR_MESSAGE: &str = "Could not deserialize server response"; + +#[async_trait] +impl ComponentAClientTrait for RemoteComponentClient { + async fn a_get_value(&self) -> ResultA { + match self.send(ComponentARequest::AGetValue).await? { + ComponentAResponse::AGetValue(value) => Ok(value), + } + } +} + +#[async_trait] +impl ComponentRequestHandler for ComponentA { + async fn handle_request(&mut self, request: ComponentARequest) -> ComponentAResponse { + match request { + ComponentARequest::AGetValue => ComponentAResponse::AGetValue(self.a_get_value().await), + } + } +} + +#[async_trait] +impl ComponentBClientTrait for RemoteComponentClient { + async fn b_get_value(&self) -> ResultB { + match self.send(ComponentBRequest::BGetValue).await? { + ComponentBResponse::BGetValue(value) => Ok(value), + _ => Err(ClientError::UnexpectedResponse), + } + } + + async fn b_set_value(&self, value: ValueB) -> ClientResult<()> { + match self.send(ComponentBRequest::BSetValue(value)).await? { + ComponentBResponse::BSetValue => Ok(()), + _ => Err(ClientError::UnexpectedResponse), + } + } +} + +#[async_trait] +impl ComponentRequestHandler for ComponentB { + async fn handle_request(&mut self, request: ComponentBRequest) -> ComponentBResponse { + match request { + ComponentBRequest::BGetValue => ComponentBResponse::BGetValue(self.b_get_value()), + ComponentBRequest::BSetValue(value) => { + self.b_set_value(value); + ComponentBResponse::BSetValue + } + } + } +} + +async fn verify_response( + a_client: ComponentAClient, + b_client: ComponentBClient, + expected_value: ValueA, +) { + assert_eq!(a_client.a_get_value().await.unwrap(), expected_value); + let new_expected_value: ValueB = 222; + + assert!(b_client.b_set_value(new_expected_value).await.is_ok()); + assert_eq!(a_client.a_get_value().await.unwrap(), new_expected_value.into()); +} + +async fn verify_error( + a_client: impl ComponentAClientTrait, + expected_error_contained_keywords: &[&str], +) { + let Err(error) = a_client.a_get_value().await else { + panic!("Expected an error."); + }; + assert_error_contains_keywords(error.to_string(), expected_error_contained_keywords) +} + +fn assert_error_contains_keywords(error: String, expected_error_contained_keywords: &[&str]) { + for expected_keyword in expected_error_contained_keywords { + if !error.contains(expected_keyword) { + panic!("Expected keyword: '{expected_keyword}' is not in error: '{error}'.") + } + } +} + +async fn create_client_and_faulty_server(port: u16, body: T) -> ComponentAClient +where + T: Serialize + Send + Sync + 'static + Clone, +{ + task::spawn(async move { + async fn handler( + _http_request: Request, + body: T, + ) -> Result, hyper::Error> { + Ok(Response::builder() + .status(StatusCode::BAD_REQUEST) + .body(Body::from(serialize(&body).unwrap())) + .unwrap()) + } + + let socket = SocketAddr::new(LOCAL_IP, port); + let make_svc = make_service_fn(|_conn| { + let body = body.clone(); + async move { Ok::<_, hyper::Error>(service_fn(move |req| handler(req, body.clone()))) } + }); + Server::bind(&socket).serve(make_svc).await.unwrap(); + }); + + // Todo(uriel): Get rid of this + // Ensure the server starts running. + task::yield_now().await; + + ComponentAClient::new(LOCAL_IP, port) +} + +async fn setup_for_tests(setup_value: ValueB, a_port: u16, b_port: u16) { + let a_client = ComponentAClient::new(LOCAL_IP, a_port); + let b_client = ComponentBClient::new(LOCAL_IP, b_port); + + let component_a = ComponentA::new(Box::new(b_client)); + let component_b = ComponentB::new(setup_value, Box::new(a_client.clone())); + + let mut component_a_server = RemoteComponentServer::< + ComponentA, + ComponentARequest, + ComponentAResponse, + >::new(component_a, LOCAL_IP, a_port); + let mut component_b_server = RemoteComponentServer::< + ComponentB, + ComponentBRequest, + ComponentBResponse, + >::new(component_b, LOCAL_IP, b_port); + + task::spawn(async move { + component_a_server.start().await; + }); + + task::spawn(async move { + component_b_server.start().await; + }); + + // Todo(uriel): Get rid of this + task::yield_now().await; +} + +#[tokio::test] +async fn test_proper_setup() { + let setup_value: ValueB = 90; + setup_for_tests(setup_value, A_PORT_TEST_SETUP, B_PORT_TEST_SETUP).await; + let a_client = ComponentAClient::new(LOCAL_IP, A_PORT_TEST_SETUP); + let b_client = ComponentBClient::new(LOCAL_IP, B_PORT_TEST_SETUP); + verify_response(a_client, b_client, setup_value.into()).await; +} + +#[tokio::test] +async fn test_faulty_client_setup() { + // Todo(uriel): Find a better way to pass expected value to the setup + // 123 is some arbitrary value, we don't check it anyway. + setup_for_tests(123, A_PORT_FAULTY_CLIENT, B_PORT_FAULTY_CLIENT).await; + + struct FaultyAClient; + + #[async_trait] + impl ComponentAClientTrait for FaultyAClient { + async fn a_get_value(&self) -> ResultA { + let component_request = ARBITRARY_DATA.to_string(); + let uri: Uri = + format!("http://[{}]:{}/", LOCAL_IP, A_PORT_FAULTY_CLIENT).parse().unwrap(); + let http_request = Request::post(uri) + .header(CONTENT_TYPE, APPLICATION_OCTET_STREAM) + .body(Body::from(serialize(&component_request).unwrap())) + .unwrap(); + let http_response = Client::new().request(http_request).await.unwrap(); + let status_code = http_response.status(); + let body_bytes = to_bytes(http_response.into_body()).await.unwrap(); + let response: ServerError = deserialize(&body_bytes).unwrap(); + + Err(ClientError::ResponseError(status_code, response)) + } + } + let faulty_a_client = FaultyAClient; + let expected_error_contained_keywords = + [StatusCode::BAD_REQUEST.as_str(), DESERIALIZE_REQ_ERROR_MESSAGE]; + verify_error(faulty_a_client, &expected_error_contained_keywords).await; +} + +#[tokio::test] +async fn test_unconnected_server() { + let client = ComponentAClient::new(LOCAL_IP, UNCONNECTED_SERVER_PORT); + + let expected_error_contained_keywords = ["Connection refused"]; + verify_error(client, &expected_error_contained_keywords).await; +} + +#[rstest] +#[case::request_deserialization_failure( + create_client_and_faulty_server( + FAULTY_SERVER_REQ_DESER_PORT, + ServerError::RequestDeserializationFailure(MOCK_SERVER_ERROR.to_string()) + ).await, + &[StatusCode::BAD_REQUEST.as_str(),DESERIALIZE_REQ_ERROR_MESSAGE, MOCK_SERVER_ERROR], +)] +#[case::response_deserialization_failure( + create_client_and_faulty_server(FAULTY_SERVER_RES_DESER_PORT,ARBITRARY_DATA).await, + &[DESERIALIZE_RES_ERROR_MESSAGE], +)] +#[tokio::test] +async fn test_faulty_server( + #[case] client: ComponentAClient, + #[case] expected_error_contained_keywords: &[&str], +) { + verify_error(client, expected_error_contained_keywords).await; +} diff --git a/crates/mempool_infra/tests/component_server_client_test.rs b/crates/mempool_infra/tests/component_server_client_test.rs new file mode 100644 index 00000000000..38334c97375 --- /dev/null +++ b/crates/mempool_infra/tests/component_server_client_test.rs @@ -0,0 +1,115 @@ +mod common; + +use async_trait::async_trait; +use common::{ + ComponentAClientTrait, ComponentARequest, ComponentAResponse, ComponentBClientTrait, + ComponentBRequest, ComponentBResponse, ResultA, ResultB, +}; +use starknet_mempool_infra::component_client::definitions::{ClientError, ClientResult}; +use starknet_mempool_infra::component_client::local_component_client::LocalComponentClient; +use starknet_mempool_infra::component_definitions::{ + ComponentRequestAndResponseSender, ComponentRequestHandler, +}; +use starknet_mempool_infra::component_server::definitions::ComponentServerStarter; +use starknet_mempool_infra::component_server::local_component_server::LocalComponentServer; +use tokio::sync::mpsc::channel; +use tokio::task; + +use crate::common::{ComponentA, ComponentB, ValueA, ValueB}; + +type ComponentAClient = LocalComponentClient; +type ComponentBClient = LocalComponentClient; + +// TODO(Tsabary): send messages from component b to component a. + +#[async_trait] +impl ComponentAClientTrait for LocalComponentClient { + async fn a_get_value(&self) -> ResultA { + let res = self.send(ComponentARequest::AGetValue).await; + match res { + ComponentAResponse::AGetValue(value) => Ok(value), + } + } +} + +#[async_trait] +impl ComponentRequestHandler for ComponentA { + async fn handle_request(&mut self, request: ComponentARequest) -> ComponentAResponse { + match request { + ComponentARequest::AGetValue => ComponentAResponse::AGetValue(self.a_get_value().await), + } + } +} + +#[async_trait] +impl ComponentBClientTrait for LocalComponentClient { + async fn b_get_value(&self) -> ResultB { + let res = self.send(ComponentBRequest::BGetValue).await; + match res { + ComponentBResponse::BGetValue(value) => Ok(value), + _ => Err(ClientError::UnexpectedResponse), + } + } + + async fn b_set_value(&self, value: ValueB) -> ClientResult<()> { + match self.send(ComponentBRequest::BSetValue(value)).await { + ComponentBResponse::BSetValue => Ok(()), + _ => Err(ClientError::UnexpectedResponse), + } + } +} + +#[async_trait] +impl ComponentRequestHandler for ComponentB { + async fn handle_request(&mut self, request: ComponentBRequest) -> ComponentBResponse { + match request { + ComponentBRequest::BGetValue => ComponentBResponse::BGetValue(self.b_get_value()), + ComponentBRequest::BSetValue(value) => { + self.b_set_value(value); + ComponentBResponse::BSetValue + } + } + } +} + +async fn verify_response( + a_client: ComponentAClient, + b_client: ComponentBClient, + expected_value: ValueA, +) { + assert_eq!(a_client.a_get_value().await.unwrap(), expected_value); + let new_expected_value: ValueB = 222; + + assert!(b_client.b_set_value(new_expected_value).await.is_ok()); + assert_eq!(a_client.a_get_value().await.unwrap(), new_expected_value.into()); +} + +#[tokio::test] +async fn test_setup() { + let setup_value: ValueB = 30; + let expected_value: ValueA = setup_value.into(); + + let (tx_a, rx_a) = + channel::>(32); + let (tx_b, rx_b) = + channel::>(32); + + let a_client = ComponentAClient::new(tx_a.clone()); + let b_client = ComponentBClient::new(tx_b.clone()); + + let component_a = ComponentA::new(Box::new(b_client.clone())); + let component_b = ComponentB::new(setup_value, Box::new(a_client.clone())); + + let mut component_a_server = LocalComponentServer::new(component_a, rx_a); + let mut component_b_server = LocalComponentServer::new(component_b, rx_b); + + task::spawn(async move { + component_a_server.start().await; + }); + + task::spawn(async move { + component_b_server.start().await; + }); + + verify_response(a_client, b_client, expected_value).await; +} diff --git a/crates/mempool_node/Cargo.toml b/crates/mempool_node/Cargo.toml new file mode 100644 index 00000000000..a4b5626280a --- /dev/null +++ b/crates/mempool_node/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "starknet_mempool_node" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +anyhow.workspace = true +clap.workspace = true +const_format.workspace = true +futures.workspace = true +papyrus_config.workspace = true +serde.workspace = true +starknet_gateway = { path = "../gateway", version = "0.0" } +starknet_mempool = { path = "../mempool", version = "0.0" } +starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } +starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +tokio.workspace = true +tracing.workspace = true +validator.workspace = true + +[dev-dependencies] +assert-json-diff.workspace = true +assert_matches.workspace = true +colored.workspace = true +pretty_assertions.workspace = true +serde_json.workspace = true +mempool_test_utils = { path = "../mempool_test_utils" } diff --git a/crates/mempool_node/src/bin/dump_config.rs b/crates/mempool_node/src/bin/dump_config.rs new file mode 100644 index 00000000000..83ce80d970d --- /dev/null +++ b/crates/mempool_node/src/bin/dump_config.rs @@ -0,0 +1,10 @@ +use papyrus_config::dumping::SerializeConfig; +use starknet_mempool_node::config::{MempoolNodeConfig, DEFAULT_CONFIG_PATH}; + +/// Updates the default config file by: +/// cargo run --bin dump_config -q +fn main() { + MempoolNodeConfig::default() + .dump_to_file(&vec![], DEFAULT_CONFIG_PATH) + .expect("dump to file error"); +} diff --git a/crates/mempool_node/src/communication.rs b/crates/mempool_node/src/communication.rs new file mode 100644 index 00000000000..ea532e00794 --- /dev/null +++ b/crates/mempool_node/src/communication.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; + +use starknet_mempool_infra::component_definitions::ComponentCommunication; +use starknet_mempool_types::communication::{ + MempoolClientImpl, MempoolRequestAndResponseSender, SharedMempoolClient, +}; +use tokio::sync::mpsc::{channel, Receiver, Sender}; + +use crate::config::MempoolNodeConfig; + +pub struct MempoolNodeCommunication { + mempool_channel: ComponentCommunication, +} + +impl MempoolNodeCommunication { + pub fn take_mempool_tx(&mut self) -> Sender { + self.mempool_channel.take_tx() + } + pub fn take_mempool_rx(&mut self) -> Receiver { + self.mempool_channel.take_rx() + } +} + +pub fn create_node_channels() -> MempoolNodeCommunication { + const MEMPOOL_INVOCATIONS_QUEUE_SIZE: usize = 32; + let (tx_mempool, rx_mempool) = + channel::(MEMPOOL_INVOCATIONS_QUEUE_SIZE); + MempoolNodeCommunication { + mempool_channel: ComponentCommunication::new(Some(tx_mempool), Some(rx_mempool)), + } +} + +pub struct MempoolNodeClients { + mempool_client: Option, + // TODO (Lev 25/06/2024): Change to Option>. +} + +impl MempoolNodeClients { + pub fn get_mempool_client(&self) -> Option { + self.mempool_client.clone() + } +} + +pub fn create_node_clients( + config: &MempoolNodeConfig, + channels: &mut MempoolNodeCommunication, +) -> MempoolNodeClients { + let mempool_client: Option = match config.components.gateway.execute { + true => Some(Arc::new(MempoolClientImpl::new(channels.take_mempool_tx()))), + false => None, + }; + MempoolNodeClients { mempool_client } +} diff --git a/crates/mempool_node/src/components.rs b/crates/mempool_node/src/components.rs new file mode 100644 index 00000000000..9096d7584e5 --- /dev/null +++ b/crates/mempool_node/src/components.rs @@ -0,0 +1,29 @@ +use starknet_gateway::gateway::{create_gateway, Gateway}; +use starknet_mempool::mempool::Mempool; + +use crate::communication::MempoolNodeClients; +use crate::config::MempoolNodeConfig; + +pub struct Components { + pub gateway: Option, + pub mempool: Option, +} + +pub fn create_components(config: &MempoolNodeConfig, clients: &MempoolNodeClients) -> Components { + let gateway = if config.components.gateway.execute { + let mempool_client = + clients.get_mempool_client().expect("Mempool Client should be available"); + + Some(create_gateway( + config.gateway_config.clone(), + config.rpc_state_reader_config.clone(), + mempool_client, + )) + } else { + None + }; + + let mempool = if config.components.mempool.execute { Some(Mempool::empty()) } else { None }; + + Components { gateway, mempool } +} diff --git a/crates/mempool_node/src/config/config_test.rs b/crates/mempool_node/src/config/config_test.rs new file mode 100644 index 00000000000..a6a15da976f --- /dev/null +++ b/crates/mempool_node/src/config/config_test.rs @@ -0,0 +1,75 @@ +use std::env; +use std::fs::File; + +use assert_json_diff::assert_json_eq; +use assert_matches::assert_matches; +use colored::Colorize; +use mempool_test_utils::get_absolute_path; +use papyrus_config::dumping::SerializeConfig; +use papyrus_config::validators::{ParsedValidationError, ParsedValidationErrors}; +use validator::Validate; + +use crate::config::{ + ComponentConfig, ComponentExecutionConfig, MempoolNodeConfig, DEFAULT_CONFIG_PATH, +}; + +/// Test the validation of the struct ComponentConfig. +/// The validation validates at least one of the components is set with execute: true. +#[test] +fn test_components_config_validation() { + // Initialize an invalid config and check that the validator finds an error. + let mut component_config = ComponentConfig { + gateway: ComponentExecutionConfig { execute: false }, + mempool: ComponentExecutionConfig { execute: false }, + }; + + assert_matches!(component_config.validate().unwrap_err(), validation_errors => { + let parsed_errors = ParsedValidationErrors::from(validation_errors); + assert_eq!(parsed_errors.0.len(), 1); + let parsed_validation_error = &parsed_errors.0[0]; + assert_matches!( + parsed_validation_error, + ParsedValidationError { param_path, code, message, params} + if ( + param_path == "__all__" && + code == "Invalid components configuration." && + params.is_empty() && + *message == Some("At least one component should be allowed to execute.".to_string()) + ) + ) + }); + + // Update the config to be valid and check that the validator finds no errors. + for (gateway_component_execute, mempool_component_execute) in + [(true, false), (false, true), (true, true)] + { + component_config.gateway.execute = gateway_component_execute; + component_config.mempool.execute = mempool_component_execute; + + assert_matches!(component_config.validate(), Ok(())); + } +} + +/// Test the validation of the struct MempoolNodeConfig and that the default config file is up to +/// date. To update the default config file, run: +/// cargo run --bin dump_config -q +#[test] +fn default_config_file_is_up_to_date() { + let default_config = MempoolNodeConfig::default(); + assert_matches!(default_config.validate(), Ok(())); + let from_code: serde_json::Value = serde_json::to_value(default_config.dump()).unwrap(); + + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + let from_default_config_file: serde_json::Value = + serde_json::from_reader(File::open(DEFAULT_CONFIG_PATH).unwrap()).unwrap(); + + println!( + "{}", + "Default config file doesn't match the default NodeConfig implementation. Please update \ + it using the dump_config binary." + .purple() + .bold() + ); + println!("Diffs shown below."); + assert_json_eq!(from_default_config_file, from_code) +} diff --git a/crates/mempool_node/src/config/mod.rs b/crates/mempool_node/src/config/mod.rs new file mode 100644 index 00000000000..3533d6a81c7 --- /dev/null +++ b/crates/mempool_node/src/config/mod.rs @@ -0,0 +1,130 @@ +#[cfg(test)] +mod config_test; + +use std::collections::BTreeMap; +use std::fs::File; +use std::path::Path; + +use clap::Command; +use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; +use papyrus_config::loading::load_and_process_config; +use papyrus_config::{ConfigError, ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_gateway::config::{GatewayConfig, RpcStateReaderConfig}; +use validator::{Validate, ValidationError}; + +use crate::version::VERSION_FULL; + +// The path of the default configuration file, provided as part of the crate. +pub const DEFAULT_CONFIG_PATH: &str = "config/mempool_default_config.json"; + +/// The single crate configuration. +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +pub struct ComponentExecutionConfig { + pub execute: bool, +} + +impl SerializeConfig for ComponentExecutionConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ser_param( + "execute", + &self.execute, + "The component execution flag.", + ParamPrivacyInput::Public, + )]) + } +} + +impl Default for ComponentExecutionConfig { + fn default() -> Self { + Self { execute: true } + } +} + +/// The components configuration. +#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] +#[validate(schema(function = "validate_components_config"))] +pub struct ComponentConfig { + pub gateway: ComponentExecutionConfig, + pub mempool: ComponentExecutionConfig, +} + +impl SerializeConfig for ComponentConfig { + fn dump(&self) -> BTreeMap { + #[allow(unused_mut)] + let mut sub_configs = vec![ + append_sub_config_name(self.gateway.dump(), "gateway"), + append_sub_config_name(self.mempool.dump(), "mempool"), + ]; + + sub_configs.into_iter().flatten().collect() + } +} + +pub fn validate_components_config(components: &ComponentConfig) -> Result<(), ValidationError> { + if components.gateway.execute || components.mempool.execute { + return Ok(()); + } + + let mut error = ValidationError::new("Invalid components configuration."); + error.message = Some("At least one component should be allowed to execute.".into()); + Err(error) +} + +/// The configurations of the various components of the node. +#[derive(Debug, Deserialize, Default, Serialize, Clone, PartialEq, Validate)] +pub struct MempoolNodeConfig { + #[validate] + pub components: ComponentConfig, + #[validate] + pub gateway_config: GatewayConfig, + #[validate] + pub rpc_state_reader_config: RpcStateReaderConfig, +} + +impl SerializeConfig for MempoolNodeConfig { + fn dump(&self) -> BTreeMap { + #[allow(unused_mut)] + let mut sub_configs = vec![ + append_sub_config_name(self.components.dump(), "components"), + append_sub_config_name(self.gateway_config.dump(), "gateway_config"), + append_sub_config_name(self.rpc_state_reader_config.dump(), "rpc_state_reader_config"), + ]; + + sub_configs.into_iter().flatten().collect() + } +} + +impl MempoolNodeConfig { + /// Creates a config object. Selects the values from the default file and from resources with + /// higher priority. + fn load_and_process_config_file( + args: Vec, + config_file_name: Option<&str>, + ) -> Result { + let config_file_name = match config_file_name { + Some(file_name) => file_name, + None => DEFAULT_CONFIG_PATH, + }; + + let default_config_file = File::open(Path::new(config_file_name))?; + load_and_process_config(default_config_file, node_command(), args) + } + + pub fn load_and_process(args: Vec) -> Result { + Self::load_and_process_config_file(args, None) + } + pub fn load_and_process_file( + args: Vec, + config_file_name: &str, + ) -> Result { + Self::load_and_process_config_file(args, Some(config_file_name)) + } +} + +/// The command line interface of this node. +pub fn node_command() -> Command { + Command::new("Mempool") + .version(VERSION_FULL) + .about("Mempool is a Starknet mempool node written in Rust.") +} diff --git a/crates/mempool_node/src/lib.rs b/crates/mempool_node/src/lib.rs new file mode 100644 index 00000000000..1a31b0bf52c --- /dev/null +++ b/crates/mempool_node/src/lib.rs @@ -0,0 +1,5 @@ +pub mod communication; +pub mod components; +pub mod config; +pub mod servers; +pub mod version; diff --git a/crates/mempool_node/src/main.rs b/crates/mempool_node/src/main.rs new file mode 100644 index 00000000000..f54e926bd6f --- /dev/null +++ b/crates/mempool_node/src/main.rs @@ -0,0 +1,37 @@ +use std::env::args; +use std::process::exit; + +use papyrus_config::validators::config_validate; +use papyrus_config::ConfigError; +use starknet_mempool_infra::trace_util::configure_tracing; +use starknet_mempool_node::communication::{create_node_channels, create_node_clients}; +use starknet_mempool_node::components::create_components; +use starknet_mempool_node::config::MempoolNodeConfig; +use starknet_mempool_node::servers::{create_servers, run_component_servers}; +use tracing::{error, info}; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + configure_tracing(); + + let config = MempoolNodeConfig::load_and_process(args().collect()); + if let Err(ConfigError::CommandInput(clap_err)) = config { + clap_err.exit(); + } + + let config = config?; + if let Err(error) = config_validate(&config) { + error!("{}", error); + exit(1); + } + + let mut channels = create_node_channels(); + let clients = create_node_clients(&config, &mut channels); + let components = create_components(&config, &clients); + let servers = create_servers(&config, &mut channels, components); + + info!("Starting components!"); + run_component_servers(&config, servers).await?; + + Ok(()) +} diff --git a/crates/mempool_node/src/servers.rs b/crates/mempool_node/src/servers.rs new file mode 100644 index 00000000000..a8f87846a4e --- /dev/null +++ b/crates/mempool_node/src/servers.rs @@ -0,0 +1,91 @@ +use std::future::pending; +use std::pin::Pin; + +use futures::{Future, FutureExt}; +use starknet_gateway::communication::{create_gateway_server, GatewayServer}; +use starknet_mempool::communication::{create_mempool_server, MempoolServer}; +use starknet_mempool_infra::component_server::definitions::ComponentServerStarter; +use tracing::error; + +use crate::communication::MempoolNodeCommunication; +use crate::components::Components; +use crate::config::MempoolNodeConfig; + +pub struct Servers { + pub gateway: Option>, + pub mempool: Option>, +} + +pub fn create_servers( + config: &MempoolNodeConfig, + communication: &mut MempoolNodeCommunication, + components: Components, +) -> Servers { + let gateway_server = if config.components.gateway.execute { + Some(Box::new(create_gateway_server( + components.gateway.expect("Gateway is not initialized."), + ))) + } else { + None + }; + + let mempool_server = if config.components.mempool.execute { + Some(Box::new(create_mempool_server( + components.mempool.expect("Mempool is not initialized."), + communication.take_mempool_rx(), + ))) + } else { + None + }; + + Servers { gateway: gateway_server, mempool: mempool_server } +} + +pub async fn run_component_servers( + config: &MempoolNodeConfig, + servers: Servers, +) -> anyhow::Result<()> { + // Gateway server. + let gateway_future = + get_server_future("Gateway", config.components.gateway.execute, servers.gateway); + + // Mempool server. + let mempool_future = + get_server_future("Mempool", config.components.mempool.execute, servers.mempool); + + // Start servers. + let gateway_handle = tokio::spawn(gateway_future); + let mempool_handle = tokio::spawn(mempool_future); + + tokio::select! { + res = gateway_handle => { + error!("Gateway Server stopped."); + res? + } + res = mempool_handle => { + error!("Mempool Server stopped."); + res? + } + }; + error!("Servers ended with unexpected Ok."); + + Ok(()) +} + +pub fn get_server_future( + name: &str, + execute_flag: bool, + server: Option>, +) -> Pin + Send>> { + let server_future = match execute_flag { + true => { + let mut server = match server { + Some(server) => server, + _ => panic!("{} component is not initialized.", name), + }; + async move { server.start().await }.boxed() + } + false => pending().boxed(), + }; + server_future +} diff --git a/crates/mempool_node/src/version.rs b/crates/mempool_node/src/version.rs new file mode 100644 index 00000000000..b5ba9580f37 --- /dev/null +++ b/crates/mempool_node/src/version.rs @@ -0,0 +1,55 @@ +#[cfg(test)] +#[path = "version_test.rs"] +mod version_test; + +/// Major version component of the current release. +const VERSION_MAJOR: u32 = 0; + +/// Minor version component of the current release. +const VERSION_MINOR: u32 = 0; + +/// Patch version component of the current release. +const VERSION_PATCH: u32 = 0; + +/// Version metadata to append to the version string. +/// Expected values are `dev` and `stable`. +#[allow(dead_code)] +const VERSION_META: Metadata = Metadata::Dev; + +/// Textual version string. +pub const VERSION: &str = version_str(); +/// Textual version string including the metadata. +pub const VERSION_FULL: &str = full_version_str(); + +#[allow(dead_code)] +const DEV_VERSION_META: &str = "dev"; +#[allow(dead_code)] +const STABLE_VERSION_META: &str = "stable"; + +#[allow(dead_code)] +#[derive(PartialEq)] +enum Metadata { + Dev, + Stable, +} + +#[cfg_attr(coverage_nightly, coverage_attribute)] +const fn version_str() -> &'static str { + const_format::concatcp!(VERSION_MAJOR, ".", VERSION_MINOR, ".", VERSION_PATCH) +} + +#[cfg_attr(coverage_nightly, coverage_attribute)] +const fn full_version_str() -> &'static str { + match VERSION_META { + Metadata::Dev => const_format::concatcp!(VERSION, "-", DEV_VERSION_META), + Metadata::Stable => VERSION, + } +} + +#[allow(dead_code)] +const fn metadata_str(metadata: Metadata) -> &'static str { + match metadata { + Metadata::Dev => DEV_VERSION_META, + Metadata::Stable => STABLE_VERSION_META, + } +} diff --git a/crates/mempool_node/src/version_test.rs b/crates/mempool_node/src/version_test.rs new file mode 100644 index 00000000000..13afebce468 --- /dev/null +++ b/crates/mempool_node/src/version_test.rs @@ -0,0 +1,16 @@ +use pretty_assertions::assert_eq; + +#[test] +fn version() { + let expected_version = + format!("{}.{}.{}", super::VERSION_MAJOR, super::VERSION_MINOR, super::VERSION_PATCH); + assert_eq!(super::VERSION, expected_version); + + let expected_version_with_meta = match super::VERSION_META { + crate::version::Metadata::Dev => { + format!("{}-{}", expected_version, super::metadata_str(super::VERSION_META)) + } + crate::version::Metadata::Stable => expected_version, + }; + assert_eq!(super::VERSION_FULL, expected_version_with_meta); +} diff --git a/crates/mempool_test_utils/Cargo.toml b/crates/mempool_test_utils/Cargo.toml new file mode 100644 index 00000000000..4385ec6cdcc --- /dev/null +++ b/crates/mempool_test_utils/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "mempool_test_utils" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[features] + +[dependencies] +assert_matches.workspace = true +blockifier = { workspace = true, features = ["testing"] } +starknet-types-core.workspace = true +starknet_api.workspace = true +serde_json.workspace = true + + diff --git a/crates/mempool_test_utils/src/lib.rs b/crates/mempool_test_utils/src/lib.rs new file mode 100644 index 00000000000..860e758c536 --- /dev/null +++ b/crates/mempool_test_utils/src/lib.rs @@ -0,0 +1,15 @@ +use std::env; +use std::path::{Path, PathBuf}; + +pub mod starknet_api_test_utils; + +pub const TEST_FILES_FOLDER: &str = "crates/mempool_test_utils/test_files"; +pub const CONTRACT_CLASS_FILE: &str = "contract_class.json"; +pub const COMPILED_CLASS_HASH_OF_CONTRACT_CLASS: &str = + "0x01e4f1248860f32c336f93f2595099aaa4959be515e40b75472709ef5243ae17"; +pub const FAULTY_ACCOUNT_CLASS_FILE: &str = "faulty_account.sierra.json"; + +/// Returns the absolute path from the project root. +pub fn get_absolute_path(relative_path: &str) -> PathBuf { + Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../..").join(relative_path) +} diff --git a/crates/mempool_test_utils/src/starknet_api_test_utils.rs b/crates/mempool_test_utils/src/starknet_api_test_utils.rs new file mode 100644 index 00000000000..4f5cbce2115 --- /dev/null +++ b/crates/mempool_test_utils/src/starknet_api_test_utils.rs @@ -0,0 +1,532 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::env; +use std::fs::File; +use std::path::Path; +use std::rc::Rc; + +use assert_matches::assert_matches; +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::{create_trivial_calldata, CairoVersion, NonceManager}; +use serde_json::to_string_pretty; +use starknet_api::core::{ + calculate_contract_address, ClassHash, CompiledClassHash, ContractAddress, Nonce, +}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::rpc_transaction::{ + ContractClass, RPCDeclareTransactionV3, RPCDeployAccountTransaction, + RPCDeployAccountTransactionV3, RPCInvokeTransactionV3, RPCTransaction, ResourceBoundsMapping, +}; +use starknet_api::transaction::{ + AccountDeploymentData, Calldata, ContractAddressSalt, PaymasterData, ResourceBounds, Tip, + TransactionSignature, TransactionVersion, +}; +use starknet_api::{calldata, felt}; +use starknet_types_core::felt::Felt; + +use crate::{ + declare_tx_args, deploy_account_tx_args, get_absolute_path, invoke_tx_args, + COMPILED_CLASS_HASH_OF_CONTRACT_CLASS, CONTRACT_CLASS_FILE, TEST_FILES_FOLDER, +}; + +pub const VALID_L1_GAS_MAX_AMOUNT: u64 = 203484; +pub const VALID_L1_GAS_MAX_PRICE_PER_UNIT: u128 = 100000000000; +pub const TEST_SENDER_ADDRESS: u128 = 0x1000; + +// Utils. +pub enum TransactionType { + Declare, + DeployAccount, + Invoke, +} + +pub fn external_tx_for_testing( + tx_type: TransactionType, + resource_bounds: ResourceBoundsMapping, + calldata: Calldata, + signature: TransactionSignature, +) -> RPCTransaction { + match tx_type { + TransactionType::Declare => { + // Minimal contract class. + let contract_class = ContractClass { + sierra_program: vec![felt!(1_u32), felt!(3_u32), felt!(0_u32)], + ..Default::default() + }; + external_declare_tx(declare_tx_args!(resource_bounds, signature, contract_class)) + } + TransactionType::DeployAccount => external_deploy_account_tx(deploy_account_tx_args!( + resource_bounds, + constructor_calldata: calldata, + signature + )), + TransactionType::Invoke => { + external_invoke_tx(invoke_tx_args!(signature, resource_bounds, calldata)) + } + } +} + +pub const NON_EMPTY_RESOURCE_BOUNDS: ResourceBounds = + ResourceBounds { max_amount: 1, max_price_per_unit: 1 }; + +pub fn create_resource_bounds_mapping( + l1_resource_bounds: ResourceBounds, + l2_resource_bounds: ResourceBounds, +) -> ResourceBoundsMapping { + ResourceBoundsMapping { l1_gas: l1_resource_bounds, l2_gas: l2_resource_bounds } +} + +pub fn zero_resource_bounds_mapping() -> ResourceBoundsMapping { + create_resource_bounds_mapping(ResourceBounds::default(), ResourceBounds::default()) +} + +pub fn executable_resource_bounds_mapping() -> ResourceBoundsMapping { + create_resource_bounds_mapping( + ResourceBounds { + max_amount: VALID_L1_GAS_MAX_AMOUNT, + max_price_per_unit: VALID_L1_GAS_MAX_PRICE_PER_UNIT, + }, + ResourceBounds::default(), + ) +} + +/// Get the contract class used for testing. +pub fn contract_class() -> ContractClass { + env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Couldn't set working dir."); + let json_file_path = Path::new(CONTRACT_CLASS_FILE); + serde_json::from_reader(File::open(json_file_path).unwrap()).unwrap() +} + +/// Get the compiled class hash corresponding to the contract class used for testing. +pub fn compiled_class_hash() -> CompiledClassHash { + CompiledClassHash(felt!(COMPILED_CLASS_HASH_OF_CONTRACT_CLASS)) +} + +pub fn declare_tx() -> RPCTransaction { + let contract_class = contract_class(); + let compiled_class_hash = compiled_class_hash(); + + let account_contract = FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1); + let account_address = account_contract.get_instance_address(0); + let mut nonce_manager = NonceManager::default(); + let nonce = nonce_manager.next(account_address); + + external_declare_tx(declare_tx_args!( + signature: TransactionSignature(vec![Felt::ZERO]), + sender_address: account_address, + resource_bounds: executable_resource_bounds_mapping(), + nonce, + class_hash: compiled_class_hash, + contract_class, + )) +} + +// Convenience method for generating a single invoke transaction with trivial fields. +// For multiple, nonce-incrementing transactions, use the transaction generator directly. +pub fn invoke_tx(cairo_version: CairoVersion) -> RPCTransaction { + let default_account = FeatureContract::AccountWithoutValidations(cairo_version); + + MultiAccountTransactionGenerator::new_for_account_contracts([default_account]) + .account_with_id(0) + .generate_default_invoke() +} + +// TODO(Yael 18/6/2024): Get a final decision from product whether to support Cairo0. +pub fn deploy_account_tx() -> RPCTransaction { + let default_account = FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1); + + MultiAccountTransactionGenerator::new_for_account_contracts([default_account]) + .account_with_id(0) + .generate_default_deploy_account() +} + +// TODO: when moving this to Starknet API crate, move this const into a module alongside +// MultiAcconutTransactionGenerator. +type AccountId = usize; +type ContractInstanceId = u16; + +type SharedNonceManager = Rc>; + +/// Manages transaction generation for multiple pre-funded accounts, internally bumping nonces +/// as needed. +/// +/// **Currently supports:** +/// - Single contract type +/// - Only supports invokes, which are all a trivial method in the contract type. +/// +/// # Example +/// +/// ``` +/// use mempool_test_utils::starknet_api_test_utils::MultiAccountTransactionGenerator; +/// +/// let mut tx_generator = MultiAccountTransactionGenerator::new(2); // Initialize with 2 accounts. +/// let account_0_tx_with_nonce_0 = tx_generator.account_with_id(0).generate_default_invoke(); +/// let account_1_tx_with_nonce_0 = tx_generator.account_with_id(1).generate_default_invoke(); +/// let account_0_tx_with_nonce_1 = tx_generator.account_with_id(0).generate_default_invoke(); +/// ``` +// Note: when moving this to starknet api crate, see if blockifier's +// [blockifier::transaction::test_utils::FaultyAccountTxCreatorArgs] can be made to use this. +pub struct MultiAccountTransactionGenerator { + // Invariant: coupled with the nonce manager. + account_contracts: HashMap, + // Invariant: nonces managed internally thorugh `generate` API of the account transaction + // generator. + // Only used by single account transaction generators, but owning it here is preferable over + // only distributing the ownership among the account generators. + _nonce_manager: SharedNonceManager, +} + +impl MultiAccountTransactionGenerator { + pub fn new(n_accounts: usize) -> Self { + let default_account_contract = + FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1); + let accounts = std::iter::repeat(default_account_contract).take(n_accounts); + Self::new_for_account_contracts(accounts) + } + + pub fn new_for_account_contracts(accounts: impl IntoIterator) -> Self { + let mut account_contracts = HashMap::new(); + let mut account_type_to_n_instances = HashMap::new(); + let nonce_manager = SharedNonceManager::default(); + for (account_id, account) in accounts.into_iter().enumerate() { + let n_current_contract = account_type_to_n_instances.entry(account).or_insert(0); + account_contracts.insert( + account_id, + AccountTransactionGenerator { + account, + contract_instance_id: *n_current_contract, + nonce_manager: nonce_manager.clone(), + }, + ); + *n_current_contract += 1; + } + + Self { account_contracts, _nonce_manager: nonce_manager } + } + + pub fn account_with_id(&mut self, account_id: AccountId) -> &mut AccountTransactionGenerator { + self.account_contracts.get_mut(&account_id).unwrap_or_else(|| { + panic!( + "{account_id:?} not found! This number should be an index of an account in the \ + initialization array. " + ) + }) + } +} + +/// Manages transaction generation for a single account. +/// Supports faulty transaction generation via [AccountTransactionGenerator::generate_raw]. +/// +/// This struct provides methods to generate both default and fully customized transactions, +/// with room for future extensions. +/// +/// TODO: add more transaction generation methods as needed. +pub struct AccountTransactionGenerator { + account: FeatureContract, + contract_instance_id: ContractInstanceId, + nonce_manager: SharedNonceManager, +} + +impl AccountTransactionGenerator { + /// Generate a valid `RPCTransaction` with default parameters. + pub fn generate_default_invoke(&mut self) -> RPCTransaction { + let invoke_args = invoke_tx_args!( + sender_address: self.sender_address(), + resource_bounds: executable_resource_bounds_mapping(), + nonce: self.next_nonce(), + calldata: create_trivial_calldata(self.test_contract_address()), + ); + external_invoke_tx(invoke_args) + } + + pub fn generate_default_deploy_account(&mut self) -> RPCTransaction { + let nonce = self.next_nonce(); + assert_eq!(nonce, Nonce(Felt::ZERO)); + + let deploy_account_args = deploy_account_tx_args!( + nonce, + class_hash: self.account.get_class_hash(), + resource_bounds: executable_resource_bounds_mapping() + ); + external_deploy_account_tx(deploy_account_args) + } + + // TODO: support more contracts, instead of this hardcoded type. + pub fn test_contract_address(&mut self) -> ContractAddress { + let cairo_version = self.account.cairo_version(); + FeatureContract::TestContract(cairo_version).get_instance_address(0) + } + + /// Generates an `RPCTransaction` with fully custom parameters. + /// + /// Caller must manually handle bumping nonce and fetching the correct sender address via + /// [AccountTransactionGenerator::nonce] and [AccountTransactionGenerator::sender_address]. + /// See [AccountTransactionGenerator::generate_default] to have these filled up by default. + /// + /// Note: This is a best effort attempt to make the API more useful; amend or add new methods + /// as needed. + pub fn generate_raw(&mut self, invoke_tx_args: InvokeTxArgs) -> RPCTransaction { + external_invoke_tx(invoke_tx_args) + } + + pub fn sender_address(&mut self) -> ContractAddress { + self.account.get_instance_address(self.contract_instance_id) + } + + /// Retrieves the nonce for the current account, and __increments__ it internally. + pub fn next_nonce(&mut self) -> Nonce { + let sender_address = self.sender_address(); + self.nonce_manager.borrow_mut().next(sender_address) + } +} + +// TODO(Ayelet, 28/5/2025): Try unifying the macros. +// TODO(Ayelet, 28/5/2025): Consider moving the macros StarkNet API. +#[macro_export] +macro_rules! invoke_tx_args { + ($($field:ident $(: $value:expr)?),* $(,)?) => { + $crate::starknet_api_test_utils::InvokeTxArgs { + $($field $(: $value)?,)* + ..Default::default() + } + }; + ($($field:ident $(: $value:expr)?),* , ..$defaults:expr) => { + $crate::starknet_api_test_utils::InvokeTxArgs { + $($field $(: $value)?,)* + ..$defaults + } + }; +} + +#[macro_export] +macro_rules! deploy_account_tx_args { + ($($field:ident $(: $value:expr)?),* $(,)?) => { + $crate::starknet_api_test_utils::DeployAccountTxArgs { + $($field $(: $value)?,)* + ..Default::default() + } + }; + ($($field:ident $(: $value:expr)?),* , ..$defaults:expr) => { + $crate::starknet_api_test_utils::DeployAccountTxArgs { + $($field $(: $value)?,)* + ..$defaults + } + }; +} + +#[macro_export] +macro_rules! declare_tx_args { + ($($field:ident $(: $value:expr)?),* $(,)?) => { + $crate::starknet_api_test_utils::DeclareTxArgs { + $($field $(: $value)?,)* + ..Default::default() + } + }; + ($($field:ident $(: $value:expr)?),* , ..$defaults:expr) => { + $crate::starknet_api_test_utils::DeclareTxArgs { + $($field $(: $value)?,)* + ..$defaults + } + }; +} + +#[derive(Clone)] +pub struct InvokeTxArgs { + pub signature: TransactionSignature, + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub version: TransactionVersion, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce: Nonce, +} + +impl Default for InvokeTxArgs { + fn default() -> Self { + InvokeTxArgs { + signature: TransactionSignature::default(), + sender_address: ContractAddress::default(), + calldata: calldata![], + version: TransactionVersion::THREE, + resource_bounds: zero_resource_bounds_mapping(), + tip: Tip::default(), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + paymaster_data: PaymasterData::default(), + account_deployment_data: AccountDeploymentData::default(), + nonce: Nonce::default(), + } + } +} + +#[derive(Clone)] +pub struct DeployAccountTxArgs { + pub signature: TransactionSignature, + pub version: TransactionVersion, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, +} + +impl Default for DeployAccountTxArgs { + fn default() -> Self { + DeployAccountTxArgs { + signature: TransactionSignature::default(), + version: TransactionVersion::THREE, + resource_bounds: zero_resource_bounds_mapping(), + tip: Tip::default(), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + paymaster_data: PaymasterData::default(), + nonce: Nonce::default(), + class_hash: ClassHash::default(), + contract_address_salt: ContractAddressSalt::default(), + constructor_calldata: Calldata::default(), + } + } +} + +#[derive(Clone)] +pub struct DeclareTxArgs { + pub signature: TransactionSignature, + pub sender_address: ContractAddress, + pub version: TransactionVersion, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce: Nonce, + pub class_hash: CompiledClassHash, + pub contract_class: ContractClass, +} + +impl Default for DeclareTxArgs { + fn default() -> Self { + Self { + signature: TransactionSignature::default(), + sender_address: ContractAddress::default(), + version: TransactionVersion::THREE, + resource_bounds: zero_resource_bounds_mapping(), + tip: Tip::default(), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + paymaster_data: PaymasterData::default(), + account_deployment_data: AccountDeploymentData::default(), + nonce: Nonce::default(), + class_hash: CompiledClassHash::default(), + contract_class: ContractClass::default(), + } + } +} + +pub fn external_invoke_tx(invoke_args: InvokeTxArgs) -> RPCTransaction { + if invoke_args.version != TransactionVersion::THREE { + panic!("Unsupported transaction version: {:?}.", invoke_args.version); + } + + starknet_api::rpc_transaction::RPCTransaction::Invoke( + starknet_api::rpc_transaction::RPCInvokeTransaction::V3(RPCInvokeTransactionV3 { + resource_bounds: invoke_args.resource_bounds, + tip: invoke_args.tip, + calldata: invoke_args.calldata, + sender_address: invoke_args.sender_address, + nonce: invoke_args.nonce, + signature: invoke_args.signature, + nonce_data_availability_mode: invoke_args.nonce_data_availability_mode, + fee_data_availability_mode: invoke_args.fee_data_availability_mode, + paymaster_data: invoke_args.paymaster_data, + account_deployment_data: invoke_args.account_deployment_data, + }), + ) +} + +pub fn external_deploy_account_tx(deploy_tx_args: DeployAccountTxArgs) -> RPCTransaction { + if deploy_tx_args.version != TransactionVersion::THREE { + panic!("Unsupported transaction version: {:?}.", deploy_tx_args.version); + } + + starknet_api::rpc_transaction::RPCTransaction::DeployAccount( + starknet_api::rpc_transaction::RPCDeployAccountTransaction::V3( + RPCDeployAccountTransactionV3 { + resource_bounds: deploy_tx_args.resource_bounds, + tip: deploy_tx_args.tip, + contract_address_salt: deploy_tx_args.contract_address_salt, + class_hash: deploy_tx_args.class_hash, + constructor_calldata: deploy_tx_args.constructor_calldata, + nonce: deploy_tx_args.nonce, + signature: deploy_tx_args.signature, + nonce_data_availability_mode: deploy_tx_args.nonce_data_availability_mode, + fee_data_availability_mode: deploy_tx_args.fee_data_availability_mode, + paymaster_data: deploy_tx_args.paymaster_data, + }, + ), + ) +} + +pub fn external_declare_tx(declare_tx_args: DeclareTxArgs) -> RPCTransaction { + if declare_tx_args.version != TransactionVersion::THREE { + panic!("Unsupported transaction version: {:?}.", declare_tx_args.version); + } + + starknet_api::rpc_transaction::RPCTransaction::Declare( + starknet_api::rpc_transaction::RPCDeclareTransaction::V3(RPCDeclareTransactionV3 { + contract_class: declare_tx_args.contract_class, + signature: declare_tx_args.signature, + sender_address: declare_tx_args.sender_address, + resource_bounds: declare_tx_args.resource_bounds, + tip: declare_tx_args.tip, + nonce_data_availability_mode: declare_tx_args.nonce_data_availability_mode, + fee_data_availability_mode: declare_tx_args.fee_data_availability_mode, + paymaster_data: declare_tx_args.paymaster_data, + account_deployment_data: declare_tx_args.account_deployment_data, + nonce: declare_tx_args.nonce, + compiled_class_hash: declare_tx_args.class_hash, + }), + ) +} + +pub fn external_tx_to_json(tx: &RPCTransaction) -> String { + let mut tx_json = serde_json::to_value(tx) + .unwrap_or_else(|tx| panic!("Failed to serialize transaction: {tx:?}")); + + // Add type and version manually + let type_string = match tx { + RPCTransaction::Declare(_) => "DECLARE", + RPCTransaction::DeployAccount(_) => "DEPLOY_ACCOUNT", + RPCTransaction::Invoke(_) => "INVOKE", + }; + + tx_json + .as_object_mut() + .unwrap() + .extend([("type".to_string(), type_string.into()), ("version".to_string(), "0x3".into())]); + + // Serialize back to pretty JSON string + to_string_pretty(&tx_json).expect("Failed to serialize transaction") +} + +pub fn deployed_account_contract_address(deploy_tx: &RPCTransaction) -> ContractAddress { + let tx = assert_matches!( + deploy_tx, + RPCTransaction::DeployAccount(RPCDeployAccountTransaction::V3(tx)) => tx + ); + calculate_contract_address( + tx.contract_address_salt, + tx.class_hash, + &tx.constructor_calldata, + ContractAddress::default(), + ) + .unwrap() +} diff --git a/crates/mempool_test_utils/test_files/contract_class.json b/crates/mempool_test_utils/test_files/contract_class.json new file mode 100644 index 00000000000..1b876244df2 --- /dev/null +++ b/crates/mempool_test_utils/test_files/contract_class.json @@ -0,0 +1,2339 @@ +{ + "sierra_program": [ + "0x1", + "0x3", + "0x0", + "0x2", + "0x1", + "0x0", + "0x340", + "0xc0", + "0x61", + "0x53797374656d", + "0x0", + "0x556e696e697469616c697a6564", + "0x1", + "0x52616e6765436865636b", + "0x4761734275696c74696e", + "0x66656c74323532", + "0x4172726179", + "0x4", + "0x536e617073686f74", + "0x5", + "0x537472756374", + "0x2", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0x6", + "0x436f6e747261637441646472657373", + "0x3693aea200ee3080885d21614d01b9532a8670f69e658a94addaadd72e9aca", + "0x8", + "0x9", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x456e756d", + "0x3", + "0x28f184fd9e4406cc4475e4faaa80e83b54a57026386ee7d5fc4fa8f347e327d", + "0xa", + "0xb", + "0x7", + "0xc", + "0x16a4c8d7c05909052238a862d8cc3e7975bf05a07b3a69c6b28951083a6d672", + "0xe", + "0xc1f0cb41289e2f6a79051e9af1ead07112b46ff17a492a90b3944dc53a51c8", + "0xd", + "0xf", + "0x753332", + "0x9931c641b913035ae674b400b61a51476d506bbe8bba2ff8a6272790aba9e6", + "0x12", + "0x4275696c74696e436f737473", + "0x3e137c9814c9973ee88e7e31b65669af6715dd5b338041471bb870148eb7467", + "0xbe98964ad87fcd5b526713f42003cd42d2fe9444caf96ea1c7d50e6f2f96d3", + "0x15", + "0x17", + "0x25abf8fd76a01c7e2544d26b0a2e29212b05a36781e0330b46d878e43b307d1", + "0x18", + "0x74584e9f10ffb1a40aa5a3582e203f6758defc4a497d1a2d5a89f274a320e9", + "0x1b", + "0x45634f70", + "0x10203be321c62a7bd4c060d69539c1fbe065baa9e253c74d2cc48be163e259", + "0x1e", + "0x11c6d8087e00642489f92d2821ad6ebd6532ad1a3b6d12833da6d6810391511", + "0x17b6ecc31946835b0d9d92c2dd7a9c14f29af0371571ae74a1b228828b2242", + "0x22", + "0x34f9bd7c6cb2dd4263175964ad75f1ff1461ddc332fbfb274e0fb2a5d7ab968", + "0x23", + "0x506564657273656e", + "0x3288d594b9a45d15bb2fcb7903f06cdb06b27f0ba88186ec4cfaa98307cb972", + "0x26", + "0xa853c166304d20fb0711becf2cbdf482dee3cac4e9717d040b7a7ab1df7eec", + "0x27", + "0x16", + "0x2237f6c75cc19eaab0a790edb28366420422acf3a882aec9ff8279033111628", + "0x29", + "0x426f78", + "0x29d7d57c04a880978e7b3689f6218e507f3be17588744b58dc17762447ad0e7", + "0x2b", + "0x3e1934b18d91949ab9afdbdd1866a30ccca06c2b1e6581582c6b27f8b4f6555", + "0x2d", + "0x4e6f6e5a65726f", + "0x75313238", + "0x2e655a7513158873ca2e5e659a9e175d23bf69a2325cdd0397ca3b8d864b967", + "0x30", + "0x31", + "0x32", + "0x3508bb43f8880f8a37030d78eb1ac52d3a1abcccd991bf0258bdf64f81014ed", + "0x33", + "0x28f8d296e28032baef1f420f78ea9d933102ba47a50b1c5f80fc8a3a1041da", + "0x1a", + "0x215f8df46019a45bb1093d990dff0445a67e3bb8181daa58a4f70432ee33547", + "0xeeb47a92569029b2ce33588f9767315e3455bc29cde2bf05f293bae2681407", + "0x36", + "0xcc5e86243f861d2d64b08c35db21013e773ac5cf10097946fe0011304886d5", + "0x38", + "0xdcbd0e10f6a0d141f54f15717d7cd32aaf61ce9acceab121e2cb229b7cca73", + "0x18508a22cd4cf1437b721f596cd2277fc0a5e4dcd247b107ef2ef5fd2752cf7", + "0x3b", + "0x8416421239ce8805ed9d27e6ddae62a97ab5d01883bb8f5246b4742a44b429", + "0x3c", + "0x753634", + "0x3808c701a5d13e100ab11b6c02f91f752ecae7e420d21b56c90ec0a475cc7e5", + "0x3e", + "0x3f", + "0x19367431bdedfe09ea99eed9ade3de00f195dd97087ed511b8942ebb45dbc5a", + "0x40", + "0x41", + "0x42", + "0x38f4af6e44b2e0a6ad228a4874672855e693db590abc7105a5a9819dbbf5ba6", + "0x43", + "0x32cb17bdb0d0d053909169ec443a25462b7e27237007511f772a7d957ce924c", + "0x45", + "0x35", + "0x1f5d91ca543c7f9a0585a1c8beffc7a207d4af73ee640223a154b1da196a40d", + "0x48", + "0x3ae40d407f8074730e48241717c3dd78b7128d346cf81094e31806a3a5bdf", + "0x4a", + "0x53746f726167654261736541646472657373", + "0x53746f7261676541646472657373", + "0x90d0203c41ad646d024845257a6eceb2f8b59b29ce7420dd518053d2edeedc", + "0x2925a04fc391ada50284b6527eab1be251c753361f948dad28e02a8cc8d4d5", + "0x21198f4f6fc56c1abc7109da49418fd12318745c7ea52b22014e073544fbd8d", + "0x4f", + "0x3a", + "0x101dc0399934cc08fa0d6f6f2daead4e4a38cabeea1c743e1fc28d2d6e58e99", + "0xd23138f8285304c3ebd13660cfe5408fbdef3b446d1d9cb56bfc4e84571f6d", + "0x52", + "0x37", + "0x1827242a312e84b6be6528961d2bda00ea0f14f86a5ac6923a206845c53f991", + "0x54", + "0x3d37ad6eafb32512d2dd95a2917f6bf14858de22c27a1114392429f2e5c15d7", + "0x2c7badf5cd070e89531ef781330a9554b04ce4ea21304b67a30ac3d43df84a2", + "0x4563506f696e74", + "0x5a", + "0x248e8fae2f16a35027771ffd74d6a6f3c379424b55843563a18f566bba3d905", + "0x8a83d9ec9f9fb5df25481c17595a3c6e57e163e7dc6ebe15ba9f7fa94e666", + "0x5d", + "0x161ee0e6962e56453b5d68e09d1cabe5633858c1ba3a7e73fee8c70867eced0", + "0x45635374617465", + "0x19b", + "0x616c6c6f635f6c6f63616c", + "0x66696e616c697a655f6c6f63616c73", + "0x7265766f6b655f61705f747261636b696e67", + "0x77697468647261775f676173", + "0x6272616e63685f616c69676e", + "0x73746f72655f74656d70", + "0x66756e6374696f6e5f63616c6c", + "0x656e756d5f6d61746368", + "0x10", + "0x7374727563745f6465636f6e737472756374", + "0x61727261795f6c656e", + "0x736e617073686f745f74616b65", + "0x11", + "0x64726f70", + "0x7533325f636f6e7374", + "0x72656e616d65", + "0x7533325f6571", + "0x61727261795f6e6577", + "0x66656c743235325f636f6e7374", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x61727261795f617070656e64", + "0x7374727563745f636f6e737472756374", + "0x656e756d5f696e6974", + "0x13", + "0x6765745f6275696c74696e5f636f737473", + "0x14", + "0x77697468647261775f6761735f616c6c", + "0x73746f72655f6c6f63616c", + "0x19", + "0x1c", + "0x4f7574206f6620676173", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x1d", + "0x1f", + "0x21", + "0x24", + "0x20", + "0x25", + "0x28", + "0x2a", + "0x64697361626c655f61705f747261636b696e67", + "0x61727261795f736e617073686f745f706f705f66726f6e74", + "0x2c", + "0x6a756d70", + "0x756e626f78", + "0x2e", + "0x636f6e74726163745f616464726573735f746f5f66656c74323532", + "0x66656c743235325f737562", + "0x66656c743235325f69735f7a65726f", + "0x656e61626c655f61705f747261636b696e67", + "0x34", + "0x2f", + "0x100000000000000000000000000000001", + "0x4163636f756e743a20696e76616c69642074782076657273696f6e", + "0x4163636f756e743a20696e76616c69642063616c6c6572", + "0x647570", + "0x4163636f756e743a20696e76616c6964207369676e6174757265", + "0x56414c4944", + "0x39", + "0x3d", + "0x44", + "0x46", + "0x7533325f746f5f66656c74323532", + "0x49", + "0x47", + "0x4b", + "0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055", + "0x73746f726167655f626173655f616464726573735f636f6e7374", + "0x3b28019ccfdbd30ffc65951d94bb85c9e2b8434111a000b5afd533ce65f57a4", + "0x73746f726167655f616464726573735f66726f6d5f62617365", + "0x4d", + "0x73746f726167655f726561645f73797363616c6c", + "0x4e", + "0x4163636f756e743a20756e617574686f72697a6564", + "0x50", + "0x656d69745f6576656e745f73797363616c6c", + "0x51", + "0x53", + "0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd", + "0x55", + "0x57", + "0x56", + "0x6765745f657865637574696f6e5f696e666f5f73797363616c6c", + "0x58", + "0x61727261795f706f705f66726f6e74", + "0x61727261795f676574", + "0x496e646578206f7574206f6620626f756e6473", + "0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f", + "0x65635f706f696e745f66726f6d5f785f6e7a", + "0x5b", + "0x756e777261705f6e6f6e5f7a65726f", + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + "0x65635f706f696e745f7472795f6e65775f6e7a", + "0x65635f706f696e745f69735f7a65726f", + "0x65635f706f696e745f756e77726170", + "0x4c", + "0x5c", + "0x38f6a5b87c23cee6e7294bcc3302e95019f70f81586ff3cac38581f5ca96381", + "0xca58956845fecb30a8cb3efe23582630dbe8b80cc1fb8fd5d5e866b1356ad", + "0x73746f726167655f77726974655f73797363616c6c", + "0x5e", + "0x21adb5788e32c84f69a1863d85ef9394b7bf761a0ce1190f826984e5075c371", + "0x63616c6c5f636f6e74726163745f73797363616c6c", + "0x5f", + "0x65635f73746174655f696e6974", + "0x65635f73746174655f6164645f6d756c", + "0x60", + "0x65635f73746174655f7472795f66696e616c697a655f6e7a", + "0x65635f706f696e745f7a65726f", + "0x65635f73746174655f616464", + "0x65635f6e6567", + "0x2301a1ef5ee1980ed3866b2a9d4de903edb9e15fa6dc5fc692ddab87642f5cc", + "0x706564657273656e", + "0xad292db4ff05a993c318438c1b6c8a8303266af2da151aa28ccece6726f1f1", + "0x626f6f6c5f6e6f745f696d706c", + "0x102f", + "0xffffffffffffffff", + "0x89", + "0x81", + "0x71", + "0x62", + "0x59", + "0x63", + "0x64", + "0x65", + "0x66", + "0x67", + "0x68", + "0x69", + "0x6a", + "0x6b", + "0x6c", + "0x6d", + "0x6e", + "0x6f", + "0x70", + "0x72", + "0x73", + "0x74", + "0x75", + "0x76", + "0x77", + "0x78", + "0x79", + "0x7a", + "0x7b", + "0x7c", + "0x7d", + "0x7e", + "0x7f", + "0x80", + "0x82", + "0x83", + "0x113", + "0x10b", + "0xfb", + "0xc1", + "0xed", + "0xe5", + "0x1bd", + "0x1ac", + "0x1a3", + "0x192", + "0x154", + "0x182", + "0x17a", + "0x84", + "0x85", + "0x86", + "0x87", + "0x88", + "0x8a", + "0x8b", + "0x8c", + "0x8d", + "0x8e", + "0x8f", + "0x90", + "0x91", + "0x92", + "0x268", + "0x257", + "0x24e", + "0x23d", + "0x1ff", + "0x22d", + "0x225", + "0x2e7", + "0x2d7", + "0x29d", + "0x2c9", + "0x2c1", + "0x367", + "0x357", + "0x31b", + "0x348", + "0x340", + "0x3e7", + "0x3d7", + "0x39b", + "0x3c8", + "0x3c0", + "0x44b", + "0x415", + "0x43e", + "0x437", + "0x4bc", + "0x4ad", + "0x47d", + "0x49f", + "0x498", + "0x51f", + "0x4e9", + "0x512", + "0x50b", + "0x590", + "0x581", + "0x551", + "0x573", + "0x56c", + "0x637", + "0x627", + "0x617", + "0x607", + "0x5cd", + "0x5f9", + "0x5f1", + "0x6af", + "0x69f", + "0x66b", + "0x690", + "0x688", + "0x6c6", + "0x6cb", + "0x6e7", + "0x6e1", + "0x778", + "0x769", + "0x760", + "0x72c", + "0x739", + "0x750", + "0x749", + "0x79a", + "0x93", + "0x7db", + "0x94", + "0x7d3", + "0x95", + "0x7c8", + "0x96", + "0x97", + "0x98", + "0x99", + "0x9a", + "0x9b", + "0x7f1", + "0x7f6", + "0x800", + "0x9c", + "0x9d", + "0x9e", + "0x80f", + "0x814", + "0x830", + "0x9f", + "0x82a", + "0xa0", + "0xa1", + "0xa2", + "0xa3", + "0xa4", + "0x85a", + "0x84e", + "0x852", + "0xa5", + "0xa6", + "0xa7", + "0xa8", + "0xa9", + "0xaa", + "0x879", + "0xab", + "0xac", + "0xad", + "0xae", + "0xaf", + "0x888", + "0x88c", + "0x8ad", + "0xb0", + "0xb1", + "0xb2", + "0x8c3", + "0xb3", + "0xb4", + "0x908", + "0xb5", + "0xb6", + "0x900", + "0xb7", + "0xb8", + "0xb9", + "0x8f9", + "0xba", + "0xbb", + "0x8f3", + "0xbc", + "0xbd", + "0xbe", + "0xbf", + "0xc0", + "0x91e", + "0x934", + "0x94e", + "0x99c", + "0xc2", + "0x967", + "0xc3", + "0xc4", + "0xc5", + "0x994", + "0xc6", + "0xc7", + "0x98a", + "0xc8", + "0x984", + "0xc9", + "0xca", + "0x9bd", + "0xcb", + "0xcc", + "0xcd", + "0xce", + "0xcf", + "0xd0", + "0xd1", + "0xd2", + "0xd3", + "0x9d5", + "0xd4", + "0xd5", + "0xd6", + "0xd7", + "0xd8", + "0xd9", + "0xda", + "0xdb", + "0x9ef", + "0xdc", + "0xdd", + "0xde", + "0xa4d", + "0xdf", + "0xe0", + "0xa10", + "0xe1", + "0xe2", + "0xa15", + "0xe3", + "0xe4", + "0xa3f", + "0xe6", + "0xe7", + "0xa38", + "0xa32", + "0xa46", + "0xe8", + "0xe9", + "0xea", + "0xeb", + "0xa75", + "0xec", + "0xaa2", + "0xac0", + "0xee", + "0xab5", + "0xef", + "0xf0", + "0xaaa", + "0xf1", + "0xb03", + "0xadb", + "0xf2", + "0xaf9", + "0xaf3", + "0xf3", + "0xb24", + "0xf4", + "0xf5", + "0xf6", + "0xf7", + "0xb39", + "0xf8", + "0xf9", + "0xfa", + "0xb4e", + "0xfc", + "0xfd", + "0xb53", + "0xfe", + "0xff", + "0x100", + "0xb5e", + "0xb9d", + "0x101", + "0xb96", + "0x102", + "0x103", + "0xb89", + "0x104", + "0x105", + "0x106", + "0x107", + "0x108", + "0x109", + "0x10a", + "0x10c", + "0x10d", + "0x10e", + "0xbbe", + "0x10f", + "0x110", + "0xbc3", + "0x111", + "0x112", + "0xbce", + "0x114", + "0x115", + "0x116", + "0xbf8", + "0x117", + "0x118", + "0x119", + "0x11a", + "0xbf2", + "0x11b", + "0x11c", + "0x11d", + "0xc26", + "0x11e", + "0xc1e", + "0x11f", + "0x120", + "0x121", + "0xc6c", + "0x122", + "0xc62", + "0xc5a", + "0xc50", + "0x123", + "0x124", + "0x125", + "0x126", + "0x127", + "0x128", + "0x129", + "0x12a", + "0x12b", + "0xc7d", + "0x12c", + "0x12d", + "0xc82", + "0x12e", + "0x12f", + "0x130", + "0xc8d", + "0x131", + "0x132", + "0x133", + "0x134", + "0xcdb", + "0x135", + "0xc9f", + "0x136", + "0x137", + "0xca4", + "0xcd0", + "0x138", + "0x139", + "0x13a", + "0xcc6", + "0x13b", + "0x13c", + "0xcbf", + "0x13d", + "0x13e", + "0x13f", + "0x140", + "0x141", + "0x142", + "0xd05", + "0x143", + "0xd12", + "0x144", + "0x145", + "0x146", + "0x147", + "0x148", + "0xd2a", + "0x149", + "0xd3c", + "0xd4e", + "0x14a", + "0xdcb", + "0x14b", + "0x14c", + "0xdc0", + "0x14d", + "0x14e", + "0x14f", + "0xdb4", + "0x150", + "0x151", + "0x152", + "0xd72", + "0x153", + "0x155", + "0x156", + "0xd85", + "0xd98", + "0xd96", + "0x157", + "0xd9f", + "0xdae", + "0xdac", + "0x158", + "0x159", + "0x15a", + "0x15b", + "0x15c", + "0xded", + "0x15d", + "0xdfb", + "0xe13", + "0x15e", + "0x15f", + "0xe29", + "0x160", + "0x161", + "0xe34", + "0x162", + "0x163", + "0x164", + "0x165", + "0xe3f", + "0x166", + "0xe54", + "0xe59", + "0xe64", + "0x167", + "0x168", + "0x169", + "0x16a", + "0x16b", + "0xe86", + "0xe8b", + "0xe96", + "0x16c", + "0x16d", + "0xeb6", + "0x16e", + "0x16f", + "0x170", + "0x171", + "0x172", + "0xed0", + "0x173", + "0xec9", + "0x174", + "0x175", + "0x176", + "0x177", + "0xedc", + "0x178", + "0x179", + "0xeee", + "0x17b", + "0xef3", + "0x17c", + "0x17d", + "0x17e", + "0xefe", + "0xf40", + "0xf10", + "0xf15", + "0xf32", + "0xf2c", + "0xf39", + "0xf56", + "0xf66", + "0x17f", + "0x180", + "0x181", + "0xf61", + "0xf64", + "0x183", + "0x184", + "0x185", + "0xf6f", + "0xf75", + "0x186", + "0x187", + "0xf81", + "0xf84", + "0xf8c", + "0x188", + "0x189", + "0x18a", + "0x18b", + "0x18c", + "0xfc4", + "0xfb9", + "0xfbe", + "0x18d", + "0x18e", + "0x18f", + "0x190", + "0x191", + "0xfd0", + "0x193", + "0x194", + "0x195", + "0xffa", + "0xffe", + "0x1008", + "0x100d", + "0x101a", + "0x196", + "0x197", + "0x198", + "0x199", + "0x19a", + "0x1029", + "0x1cd", + "0x278", + "0x2f6", + "0x376", + "0x3f6", + "0x459", + "0x4ca", + "0x52d", + "0x59e", + "0x646", + "0x6be", + "0x6f1", + "0x6f5", + "0x780", + "0x7a0", + "0x7e4", + "0x7ea", + "0x807", + "0x83a", + "0x862", + "0x881", + "0x896", + "0x8b5", + "0x8c9", + "0x910", + "0x924", + "0x93a", + "0x956", + "0x9ab", + "0x9c3", + "0x9db", + "0x9f6", + "0xa02", + "0xa5d", + "0xaca", + "0xb12", + "0xb41", + "0xb64", + "0xba3", + "0xbd5", + "0xbff", + "0xc30", + "0xc76", + "0xc93", + "0xceb", + "0xd0b", + "0xd1d", + "0xdd5", + "0xdf5", + "0xe01", + "0xe19", + "0xe1c", + "0xe39", + "0xe45", + "0xe6b", + "0xe9d", + "0xebe", + "0xed6", + "0xee2", + "0xf04", + "0xf4f", + "0xf69", + "0xf86", + "0xf94", + "0xf9e", + "0xfca", + "0xfd6", + "0xfe0", + "0xfea", + "0xfed", + "0x1023", + "0x8be4", + "0xe0080d0300b0100402809010040200201c0201802014020100400c0200400", + "0x205815050020100c04c040100802c040240404804044020240c0081003c04", + "0xb0101d01014008160301c008040301b0101a0101400816030190101801017", + "0x240800408c04088020581506804050020340c008210800407c040780205815", + "0x290081605428010140080d0301a0100402027010260080d030250080403002", + "0x2d080040b0040ac02058150640402c04050020580c0a0040100a080040a804", + "0x90103000816054090100400c200102f0102e0081605409010140080d03002", + "0x40d0040cc02058150c80406804050020580c0640402c040c4020581506404", + "0x2001039010380081605437010140080d03019010190103600816054020d420", + "0x40f80205815024040103d080040f0040ec0205815064040e804050020580c", + "0x120300210c09010041082001041010400081605412010140080d030190103f", + "0x4050020340c118040103d0240402404024040680411404048040240411002", + "0x4e0104d0080d0304c008040304b0104a0080d0302001049010480081605447", + "0x4148020581502404144020340c080041400413c020581506404050020340c", + "0x57008090300215820010550105400816054530101a01014008160301901013", + "0x3d02404048040480411c0416c041680203c0c164040103d048041600416004", + "0x28010180101400809030200105f0105e008160545d010140080d0305c01004", + "0x41900418c0205815068040103d18804010030800418404180020581506404", + "0x90106900816054021a00219c200106601065008160543f010140080d03019", + "0xc02c04064041b802058151b4041b0041ac0205815024041a8020340c02c04", + "0x160541901071010140081603020010700106f0081605419010270101400816", + "0x4174041d4020581506404048041d002058150480401003080041cc041c802", + "0x4e01014008160300b0103701078008160547701004108021d813010040f40b", + "0x2010041f87d0087c02c04068041ec0205815080041e8041e4020581506404", + "0x8507c16010840680401083058040108303404010830088200881008800087f", + "0x422c8a0100422409010042201a0100421c1b010042141f0100421c8601004", + "0x83060040108b010040108b0088e2280401083228040108d0080d0108c22804", + "0x4248090100420c9103404240090100423c190100422c1d058042100201004", + "0x4010830089625404010830100d25404034940800401093074040109302404", + "0x420c3a0100420c3a0100422c3a010042243a0100424c270100424c0226097", + "0x40108b0a004010890a8040108726804010850080401099080160108406004", + "0xb010042242c0100421c9b0100421486058042100b0100420c4b0100420c28", + "0x40108b2700d010900080d254040349408c0401093068040109302c040108b", + "0x9010042242f0100421c9f010042148a058042109e0100420c9d034042401a", + "0x84024040109928004010852541601084024040107e08c1601084024040108b", + "0x420ca20100422c27058042103201004214340100421ca1010042149705804", + "0x4010830dc040108b0dc04010890e4040108729004010850e8160108428c04", + "0x3c0100422ca5010042144b058042109a058042102a05804210280580421037", + "0x830080d2a0040349402404010a7008a6278160108426c16010840b01601084", + "0x42a8a80100421404034a80100d250190100424c022a4a80100420c0f01004", + "0x830080d218040349407c04010930bc160108404c040108f024040108d02404", + "0x42149f05804210190100420c040341b0100d25004034860100d2508601004", + "0x401085008af2881601084008ae008ad0080d01090008ac10404010872ac04", + "0x403404240450100422c120100422c460100421c46010042a8490100421cb0", + "0x4010830080d26804034940a8040109328016010842c80d010902c4040108b", + "0x42101a010042204b010042d4b403404240b303404240040349a0100d2509a", + "0x830080d26c04034940b004010930d01601084188040108318804010930c816", + "0x9f0100d250b6034042403701004214a105804210040349b0100d2509b01004", + "0xd28004034940080d27c04034940bc04010932dc0d0109027c04010830100d", + "0x2034a10100d250340100424ca30580421004034a00100d250a00100420c02", + "0x891c4040109313804010930100d0c804034940100d28404034942840401083", + "0x2034a40100d250390100424c3705804210710100420c710100422c7101004", + "0x160108409c04010830e804010870dc040108d0100d29004034942900401083", + "0x6d0100420c6d0100424c2701004224500100422cb801004214a40580421039", + "0x4010830080d29404034940f0040109329416010840f004010870f01601084", + "0x20341b0100d25009010042d43f05804210270100422c04034a50100d250a5", + "0x85104160108404c040109214c040108515404010872e404010852a01601084", + "0x424c470100422c5b0100422c5c0100421c5c010042a85f0100421cba01004", + "0x40349412404010930100d2ac04034942ac04010830080d2ac040349410404", + "0xab05804210280100420c1a0100423c04034b00100d250b00100420c02034b0", + "0x40349406804010a71880401087188040107e008bc18404010872ec0401085", + "0x1a010042a8bd01004214620100426404034bd0100d250bd0100420c02034bd", + "0xd0dc04034940340d0108c06804010b52f8040108b188040108b2c41601084", + "0x320100d25046058042100403404230660100421cbf01004214450580421002", + "0xc111c160108413804010831c404010870100d0dc04034943000d010900080d", + "0xc60100d250c60100420c02034c60100d25002314c40100420c0230cc203404", + "0x401093048040108d04804010892c016010841241601084318040108d0100d", + "0x620580421004034b80100d250c703404240b80100420c02034b80100d25050", + "0x830080d3280403494008c913816010843200401083320040108b3200401089", + "0x5005804210500100421c7105804210ca0100423404034ca0100d250ca01004", + "0x843300d010902e016010841b004010831b004010931c0040108732c0401085", + "0x4264ce01004214530580421012010041f8730100422ccd010042146d05804", + "0x4010830080d2e4040349415404010930080d14c040349404c040109304804", + "0x2034d10100d25002340cf0100422c04034b90100d25004034530100d250b9", + "0x40349417c04010931541601084344040108d0100d34404034943440401083", + "0x530100420c13010042a8130100434804034ba0100d250ba0100420c02034ba", + "0x941840401093068040109208c040108725404010852e4160108404c0401083", + "0x434c58058042101a0100423404034bb0100d250bb0100420c02034bb0100d", + "0xd2fc04034943500d010902fc04010830080d2fc0403494198040109302404", + "0x236cda03404240d9034042407701004360d70100420c02358d50340424004", + "0x8416c16010841dc04010b5008dd1dc040108b008dc16416010841dc0401083", + "0x4214ba05804210df010042345f05804210de0100420c5d058042105c05804", + "0x843840d0109018416010843800d0109032004010850100d320040349431804", + "0x420c02034cb0100d250700100424c02388ca010042140b01004234bb05804", + "0x931e8040108738c040108519016010842f816010840100d32c040349432c04", + "0xce0100d2500239004034cd0100d250cd0100420c02034cd0100d2507301004", + "0x403494008e504c040108734404010850100d338040349433804010830080d", + "0x23a00239cbd05804210e60100423404034e60100d250e60100420c02034e6", + "0x8b008ed008ec35c040108b1dc040108d278040108d008eb008ea3a40401083", + "0xd250df0100420c02034df0100d250023c4023c0023bcee034042404e01004", + "0x4010890080d32004034941b404010871b0040108737c04010850100d37c04", + "0xe60100421404034e30100d250e30100420c02034e30100d2507a0100424c4e", + "0x40080d05802008f30100203402008f3010020100202c043cc0400802008f2", + "0xf0081f010f30100f0100b008023cc0400809008130480d3d01a03c0d3cc0d", + "0x19060163cc040801d07c1604802080043cc040580406802074043cc0406804", + "0xd3cc042180406002008f30100202402228043d486010f30341b010130081b", + "0xf3010230101b008023cc040080900827010f625c043cc0d254040640225423", + "0xf30102a010200089a0a80d3cc040a004074020a0043cc040e80407c020e804", + "0x2008f30102c010200089b0b00d3cc0412c040740212c043cc040088600802", + "0x950089e010f30109e010230082f010f30109b0108a0089e010f30109a0108a", + "0x9701027008023cc0402c0425c02008f301002024020083f008f30342f2780d", + "0x4288040a8022889f034f3010a001028008a0010f30100d0103a008023cc04", + "0x20d0043cc040d0040b0020d0043cc040084b00832010f30100226802008f3", + "0x20dc043cc04284a30342f008a3010f30100227802284043cc040d0320349b", + "0x3a0083c010f3010190100f008a4010f3010180100b00839010f3010370109f", + "0xf301002024020fca50f0a4024040fc043cc040e40428802294043cc0427c04", + "0xd3cc0d2a019060160d0022a0043cc042a0040c8022a0043cc04008a000802", + "0xf301046010a300846010f30100228402008f30100202402114b1034f72ac41", + "0x43cc041040402c02008f30104901039008b01240d3cc0411c040dc0211c04", + "0x53010f3010b0010a40086d010f30100d0103a008b8010f3010ab0100f00850", + "0x3f008710244e188093cc04154531b4b81400b29402154043cc0425c040f002", + "0x2008f301002024021600435cb9010f303471010a800809010f30100902c0d", + "0xb10085d1700d3cc04164042ac0216c043cc040089a00859010f3010b901041", + "0x5d01045008be010f30104e0100f008bb010f3010620100b008023cc0417004", + "0x612e85f058f3010bd190be2ec0911c022f4043cc0416c0411802190043cc04", + "0xde034f301066010b0008023cc0400809008bf01073198043cc0d1840412402", + "0x2008f3010c60104e0086c3180d3cc043780418802008f3010c40102a008c4", + "0xb00870010f3010ca010b8008ca010f3010c801050008c8010f30106c01071", + "0x428802334043cc04024040e8021cc043cc042e80403c0232c043cc0417c04", + "0xce010f3010bf0109f008023cc0400809008cf3347332c09010cf010f301070", + "0x21dc043cc04024040e8023e0043cc042e80403c02344043cc0417c0402c02", + "0xf3010580109f008023cc0400809008d71dcf834409010d7010f3010ce010a2", + "0x43cc04024040e80238c043cc041380403c021e8043cc041880402c0237c04", + "0xb01097008023cc0400809008e9398e31e809010e9010f3010df010a2008e6", + "0x23dc043cc040086d00800010f30100226802008f30109701027008023cc04", + "0x2f008fa010f301002278023e4043cc043dc000349b008f7010f3010f70102c", + "0xf008fd010f3010b10100b008fc010f3010fb0109f008fb010f3010f93e80d", + "0xfd02404400043cc043f004288023fc043cc04034040e8023f8043cc0411404", + "0x53008023cc0402c0425c02008f3010270102a008023cc0400809009003fcfe", + "0xf3011020102c00902010f30100215402404043cc040089a008023cc0408c04", + "0xf3011034100d0bc02410043cc040089e00903010f3011024040d26c0240804", + "0x43cc040640403c023d8043cc040600402c02418043cc044140427c0241404", + "0x900909421073d80901109010f301106010a200908010f30100d0103a00907", + "0xf3010180100b0090a010f30108a0109f008023cc0402c0425c02008f301002", + "0x43cc044280428802434043cc04034040e802430043cc040640403c0242c04", + "0x40580414c02008f30100b01097008023cc04008090090e4350c42c090110e", + "0x2440043cc04440040b002440043cc040086d0090f010f30100226802008f3", + "0x244c043cc04445120342f00912010f30100227802444043cc044410f0349b", + "0x3a008f5010f3010130100f00915010f3010120100b00914010f3011130109f", + "0xf3010020340245d163d5150240445c043cc044500428802458043cc0403404", + "0xb0100b008023cc0400809008120680d4600f02c0d3cc0d034020341600802", + "0x1f06c1604802074043cc04024040680207c043cc0403c0403c0206c043cc04", + "0x2008f301002024022180446420010f303419010130081906013058f30101d", + "0x23cc0400809008970111a254043cc0d08c040640208c8a034f30102001018", + "0x1d0083a010f3010270101f00827010f30108a0101b008023cc042540409c02", + "0x9a0101d0089a010f30100221802008f301028010200082a0a00d3cc040e804", + "0x40b0042280226c043cc040a80422802008f30104b010200082c12c0d3cc04", + "0x4008090080246c023cc0d2789b034950089b010f30109b010230089e010f3", + "0xf30109f0102a0089f0bc0d3cc04288040a002288043cc04058040e802008f3", + "0x9b00832010f3010320102c00832010f30100212c02280043cc040089a00802", + "0x9f008a3010f3010342840d0bc02284043cc040089e00834010f3010322800d", + "0x403c02290043cc04010042e4020e4043cc0404c0402c020dc043cc0428c04", + "0xa40e40b0103f010f301037010a2008a5010f30102f0103a0083c010f301018", + "0x22a0043cc042a0040c8022a0043cc04008a0008023cc04008090083f2943c", + "0xf30100228402008f30100202402114b10351c2ac41034f3034a80601305834", + "0xf30104901039008b01240d3cc0411c040dc0211c043cc041180428c0211804", + "0x55010f3010ab0100f00853010f301004010b90086d010f3010410100b00802", + "0x4160b9154531b40b16002160043cc042c004290022e4043cc04058040e802", + "0x2008f3010020240216c0447459010f3034b801059008b8140711386202cf3", + "0x5d008ba17c0d3cc041700417002174043cc040089a0085c010f3010590105b", + "0xbe0345f00864010f30105d01046008be010f3010ba0102c008023cc0417c04", + "0x413802198bd034f30106101062008023cc042ec040a8022ec61034f301064", + "0x4378042e002378043cc042fc04140022fc043cc04198041c402008f3010bd", + "0xf3010710100f0086c010f30104e010b9008c6010f3010620100b008c4010f3", + "0x70328c81b0c602c041c0043cc043100428802328043cc04140040e80232004", + "0x42e4021cc043cc041880402c0232c043cc0416c0427c02008f30100202402", + "0xcb010a2008ce010f3010500103a008cf010f3010710100f008cd010f30104e", + "0x23e0043cc040089a008023cc0400809008d1338cf3347302c04344043cc04", + "0x9e008d7010f3010773e00d26c021dc043cc041dc040b0021dc043cc040086d", + "0x402c0238c043cc041e80427c021e8043cc0435cdf0342f008df010f301002", + "0x160103a00800010f3010450100f008e9010f301004010b9008e6010f3010b1", + "0x23cc0400809008f93dc003a4e602c043e4043cc0438c04288023dc043cc04", + "0x400855008fa010f30100226802008f30108a01053008023cc0425c040a802", + "0xf301002278023f0043cc043ecfa0349b008fb010f3010fb0102c008fb010f3", + "0xf3010130100b008ff010f3010fe0109f008fe010f3010fc3f40d0bc023f404", + "0x43cc04058040e802408043cc040600403c02404043cc04010042e40240004", + "0x427c02008f3010020240241103409014000b01104010f3010ff010a200903", + "0x180100f008f6010f301004010b900906010f3010130100b00905010f301086", + "0x1073d90602c04424043cc044140428802420043cc04058040e80241c043cc04", + "0x21b402428043cc040089a008023cc040240414c02008f3010020240242508", + "0x40089e0090c010f30110b4280d26c0242c043cc0442c040b00242c043cc04", + "0x40680402c0243c043cc044380427c02438043cc044310d0342f0090d010f3", + "0xf3010160103a00912010f3010120100f00911010f301004010b900910010f3", + "0x203c043cc04008ba0091444d124451002c04450043cc0443c042880244c04", + "0x1804c0d478120680d3cc0d0340203416008023cc040080d008023cc0400804", + "0xb0081b0640d3cc0407c041840207c043cc040240406802008f30100202402", + "0xb008023cc04008090081d0111f02c043cc0d06c042ec02068043cc0406804", + "0xd2f80225c043cc040640406802254043cc040480403c0208c043cc0406804", + "0x43cc0d228042f40222886080163cc0425c9508c161900202c043cc0402c0f", + "0xf30342a010bf0082a0a00d3cc0409c0419802008f301002024020e80448027", + "0xf30102c0101f0082c010f3010280101b008023cc04008090084b0112126804", + "0x9f010f30100221802008f30109e010200082f2780d3cc0426c040740226c04", + "0x20c8043cc040bc0422802008f3010a201020008a02880d3cc0427c0407402", + "0x2488023cc0d0d0320349500832010f3010320102300834010f3010a00108a", + "0x4058040e802008f30100b0105d008023cc042680413802008f30100202402", + "0x43cc040089a008023cc0428c040a80228ca1034f3010370102800837010f3", + "0x3c010f3010a40e40d26c02290043cc04290040b002290043cc040084b00839", + "0x22a0043cc040fc0427c020fc043cc040f0a50342f008a5010f30100227802", + "0x3a008b1010f3010860100f008ab010f301004010b900841010f3010200100b", + "0x40080900846114b12ac4102c04118043cc042a00428802114043cc0428404", + "0xf303447218200583400847010f3010470103200847010f30100228002008f3", + "0x41c40428c021c4043cc04008a1008023cc04008090084e1880d48cb01240d", + "0xf3010490100b008023cc042e0040e4021b4b8034f3010500103700850010f3", + "0x43cc04058040e802174043cc042c00403c02170043cc04010042e40216c04", + "0xbb010f30109a0104600861010f30100b0102c008ba010f30106d010a40085f", + "0x43cc0d1640416402164582e45514c0b3cc042ec612e85f1745c16c1a37802", + "0x66010f301002268022f4043cc042f80416c02008f3010020240219004490be", + "0x21b0043cc04378040b002008f3010bf0105d008de2fc0d3cc042f40417002", + "0x2008f3010c60102a008c63100d3cc043206c0345f008c8010f30106601046", + "0x50008cb010f30107001071008023cc0432804138021c0ca034f3010c401062", + "0x42e40233c043cc0414c0402c02334043cc041cc042e0021cc043cc0432c04", + "0xcd010a2008f8010f3010580103a008d1010f3010b90100f008ce010f301055", + "0xd7010f3010640109f008023cc0400809008773e0d1338cf02c041dc043cc04", + "0x238c043cc042e40403c021e8043cc04154042e40237c043cc0414c0402c02", + "0x2024023a4e638c7a37c0b010e9010f3010d7010a2008e6010f3010580103a", + "0x2000043cc040089a008023cc0402c0417402008f30109a0104e008023cc04", + "0x9e008f9010f3010f70000d26c023dc043cc043dc040b0023dc043cc040086d", + "0x402c023f0043cc043ec0427c023ec043cc043e4fa0342f008fa010f301002", + "0x160103a008ff010f30104e0100f008fe010f301004010b9008fd010f301062", + "0x23cc040080900901400ff3f8fd02c04404043cc043f00428802400043cc04", + "0x40089a008023cc0402c0417402008f30102801053008023cc0412c040a802", + "0xf3011034080d26c0240c043cc0440c040b00240c043cc040085500902010f3", + "0x43cc044180427c02418043cc04411050342f00905010f3010022780241004", + "0x109010f3010860100f00908010f301004010b900907010f3010200100b008f6", + "0x90090b429094210702c0442c043cc043d80428802428043cc04058040e802", + "0xf3010200100b0090c010f30103a0109f008023cc0402c0417402008f301002", + "0x43cc04058040e80243c043cc042180403c02438043cc04010042e40243404", + "0x40a802008f301002024024451043d0e4340b01111010f30110c010a200910", + "0x112010f30100226802008f30100f010c4008023cc040640414c02008f30101d", + "0x2450043cc0444d120349b00913010f3011130102c00913010f30100215402", + "0xb00916010f3010f50109f008f5010f3011144540d0bc02454043cc040089e", + "0x40e802498043cc040480403c02494043cc04010042e40245c043cc0406804", + "0xf301002024024a1274992545c0b01128010f301116010a200927010f301016", + "0x21b4024a4043cc040089a008023cc0403c0431002008f3010090105300802", + "0x40089e0092a010f3010f44a40d26c023d0043cc043d0040b0023d0043cc04", + "0x404c0402c024b4043cc044b00427c024b0043cc044a92b0342f0092b010f3", + "0xf3010160103a00930010f3010180100f0092f010f301004010b90092e010f3", + "0x203c043cc04008ba009324c5304bd2e02c044c8043cc044b404288024c404", + "0x1804c0d4cc120680d3cc0d0340203416008023cc040080d008023cc0400804", + "0xb0081b0640d3cc0407c041840207c043cc040240406802008f30100202402", + "0xb008023cc04008090081d0113402c043cc0d06c042ec02068043cc0406804", + "0xd2f80225c043cc040640406802254043cc040480403c0208c043cc0406804", + "0x43cc0d228042f40222886080163cc0425c9508c161900202c043cc0402c0f", + "0xf30342a010bf0082a0a00d3cc0409c0419802008f301002024020e8044d427", + "0xf30102c0101f0082c010f3010280101b008023cc04008090084b0113626804", + "0x9f010f30100221802008f30109e010200082f2780d3cc0426c040740226c04", + "0x20c8043cc040bc0422802008f3010a201020008a02880d3cc0427c0407402", + "0x24dc023cc0d0d0320349500832010f3010320102300834010f3010a00108a", + "0x4058040e802008f30100b0105d008023cc042680413802008f30100202402", + "0x43cc040089a008023cc0428c040a80228ca1034f3010370102800837010f3", + "0x3c010f3010a40e40d26c02290043cc04290040b002290043cc040084b00839", + "0x22a0043cc040fc0427c020fc043cc040f0a50342f008a5010f30100227802", + "0x3a008b1010f3010860100f008ab010f301004010b900841010f3010200100b", + "0x40080900846114b12ac4102c04118043cc042a00428802114043cc0428404", + "0xf303447218200583400847010f3010470103200847010f30100228002008f3", + "0x41c40428c021c4043cc04008a1008023cc04008090084e1880d4e0b01240d", + "0xf3010490100b008023cc042e0040e4021b4b8034f3010500103700850010f3", + "0x43cc04058040e802174043cc042c00403c02170043cc04010042e40216c04", + "0xbb010f30109a0104600861010f30100b0102c008ba010f30106d010a40085f", + "0x43cc0d1640416402164582e45514c0b3cc042ec612e85f1745c16c1a37802", + "0x66010f301002268022f4043cc042f80416c02008f30100202402190044e4be", + "0x21b0043cc04378040b002008f3010bf0105d008de2fc0d3cc042f40417002", + "0x2008f3010c60102a008c63100d3cc043206c0345f008c8010f30106601046", + "0x50008cb010f30107001071008023cc0432804138021c0ca034f3010c401062", + "0x42e40233c043cc0414c0402c02334043cc041cc042e0021cc043cc0432c04", + "0xcd010a2008f8010f3010580103a008d1010f3010b90100f008ce010f301055", + "0xd7010f3010640109f008023cc0400809008773e0d1338cf02c041dc043cc04", + "0x238c043cc042e40403c021e8043cc04154042e40237c043cc0414c0402c02", + "0x2024023a4e638c7a37c0b010e9010f3010d7010a2008e6010f3010580103a", + "0x2000043cc040089a008023cc0402c0417402008f30109a0104e008023cc04", + "0x9e008f9010f3010f70000d26c023dc043cc043dc040b0023dc043cc040086d", + "0x402c023f0043cc043ec0427c023ec043cc043e4fa0342f008fa010f301002", + "0x160103a008ff010f30104e0100f008fe010f301004010b9008fd010f301062", + "0x23cc040080900901400ff3f8fd02c04404043cc043f00428802400043cc04", + "0x40089a008023cc0402c0417402008f30102801053008023cc0412c040a802", + "0xf3011034080d26c0240c043cc0440c040b00240c043cc040085500902010f3", + "0x43cc044180427c02418043cc04411050342f00905010f3010022780241004", + "0x109010f3010860100f00908010f301004010b900907010f3010200100b008f6", + "0x90090b429094210702c0442c043cc043d80428802428043cc04058040e802", + "0xf3010200100b0090c010f30103a0109f008023cc0402c0417402008f301002", + "0x43cc04058040e80243c043cc042180403c02438043cc04010042e40243404", + "0x40a802008f301002024024451043d0e4340b01111010f30110c010a200910", + "0x112010f30100226802008f30100f010c4008023cc040640414c02008f30101d", + "0x2450043cc0444d120349b00913010f3011130102c00913010f30100215402", + "0xb00916010f3010f50109f008f5010f3011144540d0bc02454043cc040089e", + "0x40e802498043cc040480403c02494043cc04010042e40245c043cc0406804", + "0xf301002024024a1274992545c0b01128010f301116010a200927010f301016", + "0x21b4024a4043cc040089a008023cc0403c0431002008f3010090105300802", + "0x40089e0092a010f3010f44a40d26c023d0043cc043d0040b0023d0043cc04", + "0x404c0402c024b4043cc044b00427c024b0043cc044a92b0342f0092b010f3", + "0xf3010160103a00930010f3010180100f0092f010f301004010b90092e010f3", + "0x16008023cc040080d009324c5304bd2e02c044c8043cc044b404288024c404", + "0x43cc040240406802008f301002024020481a0353a03c0b034f30340d0080d", + "0x43cc0d060042ec0202c043cc0402c0402c0206013034f3010190106100819", + "0x1d010f3010130101b008023cc0406c0417402008f3010020240207c044ec1b", + "0x2008f301086010200088a2180d3cc040800407402080043cc040740407c02", + "0x422802008f30109501020008972540d3cc0408c040740208c043cc0400886", + "0x270349500827010f301027010230083a010f3010970108a00827010f30108a", + "0x4268040a002268043cc04058040e802008f301002024020093c008f30343a", + "0x2c010f30100212c0212c043cc040089a008023cc040a8040a8020a828034f3", + "0x2278043cc040089e0089b010f30102c12c0d26c020b0043cc040b0040b002", + "0x2288043cc0402c0402c0227c043cc040bc0427c020bc043cc0426c9e0342f", + "0xa200834010f3010280103a00832010f30100f0100f008a0010f301004010b9", + "0x43cc04008a0008023cc0400809008a10d032280a202c04284043cc0427c04", + "0x20f0a40353d0e437034f3034a303c0b05834008a3010f3010a301032008a3", + "0x40fc040dc020fc043cc042940428c02294043cc04008a1008023cc0400809", + "0xf301004010b900849010f3010370100b008023cc042a0040e402104a8034f3", + "0x43cc041040429002138043cc04058040e802188043cc040e40403c022c004", + "0x50010f3034470105900847118452c4ab02cf301071138622c04902c5800871", + "0x214c043cc040089a0086d010f3010500105b008023cc0400809008b80113e", + "0x460085b010f3010b90102c008023cc0415404174022e455034f30106d0105c", + "0x62008023cc04164040a80216458034f30105c16c0d17c02170043cc0414c04", + "0x4140022e8043cc0417c041c402008f30105d0104e0085f1740d3cc0416004", + "0xb1010b9008be010f3010ab0100b008bb010f301061010b800861010f3010ba", + "0x42ec0428802198043cc04118040e8022f4043cc041140403c02190043cc04", + "0x2378043cc042e00427c02008f301002024022fc662f4642f80b010bf010f3", + "0x3a0086c010f3010450100f008c6010f3010b1010b9008c4010f3010ab0100b", + "0x400809008ca3206c318c402c04328043cc043780428802320043cc0411804", + "0x232c043cc0432c040b00232c043cc040086d00870010f30100226802008f3", + "0x233c043cc041cccd0342f008cd010f301002278021cc043cc0432c700349b", + "0xf008f8010f301004010b9008d1010f3010a40100b008ce010f3010cf0109f", + "0xd102c0437c043cc04338042880235c043cc04058040e8021dc043cc040f004", + "0x2008f30101301053008023cc0407c040a802008f3010020240237cd71dcf8", + "0x7a0349b008e3010f3010e30102c008e3010f301002154021e8043cc040089a", + "0x109f00800010f3010e63a40d0bc023a4043cc040089e008e6010f3010e3", + "0x403c0403c023e8043cc04010042e4023e4043cc0402c0402c023dc043cc04", + "0xfc3ecfa3e40b010fd010f3010f7010a2008fc010f3010160103a008fb010f3", + "0x40086d008fe010f30100226802008f30100901053008023cc0400809008fd", + "0xf30100227802400043cc043fcfe0349b008ff010f3010ff0102c008ff010f3", + "0xf30101a0100b00903010f3011020109f00902010f3011004040d0bc0240404", + "0x43cc04058040e802418043cc040480403c02414043cc04010042e40241004", + "0xd05802008f3010020340241cf6419054100b01107010f301103010a2008f6", + "0x19010f3010090101a008023cc0400809008120680d4fc0f02c0d3cc0d03404", + "0x1b010f303418010bb0080b010f30100b0100b0081804c0d3cc040640418402", + "0x20010f30101d0101f0081d010f3010130101b008023cc04008090081f01140", + "0x1d00823010f30100221802008f301086010200088a2180d3cc040800407402", + "0x42280209c043cc042280422802008f30109501020008972540d3cc0408c04", + "0x900802504023cc0d0e8270349500827010f301027010230083a010f301097", + "0xf30109a010280089a010f3010160103a008023cc0406c0417402008f301002", + "0x20b0043cc040084b0084b010f30100226802008f30102a0102a0082a0a00d", + "0x2f0089e010f3010022780226c043cc040b04b0349b0082c010f30102c0102c", + "0xb008a2010f301002010c60089f010f30102f0109f0082f010f30109b2780d", + "0x4288020d0043cc040a0040e8020c8043cc0403c0403c02280043cc0402c04", + "0xa3010f30100228002008f30100202402284340c8a02880b010a1010f30109f", + "0x90083c2900d508390dc0d3cc0d28c0f02c160d00228c043cc0428c040c802", + "0xf30103f010370083f010f3010a5010a3008a5010f30100228402008f301002", + "0x43cc040e40403c02124043cc040dc0402c02008f3010a801039008412a00d", + "0x71010f301041010a40084e010f3010160103a00862010f301002010c6008b0", + "0x47118452c4ab02cf3010501c44e188b01240f1b002140043cc0406c040b002", + "0x53010f3010b8010ca008023cc04008090086d011432e0043cc0d11c0432002", + "0x73008023cc042e40432c02160b9034f3010530107000855010f30100226802", + "0x216c59034f30105d1700d33402174043cc041540411802170043cc0416004", + "0x41c402008f30105f0104e008ba17c0d3cc041640418802008f30105b0102a", + "0x45010c6008be010f3010bb010b8008bb010f3010610105000861010f3010ba", + "0x4118040e802198043cc042c40403c022f4043cc042ac0402c02190043cc04", + "0x2008f30100202402378bf198bd1900b010de010f3010be010a2008bf010f3", + "0xf0086c010f3010ab0100b008c6010f301045010c6008c4010f30106d0109f", + "0xc602c041c0043cc043100428802328043cc04118040e802320043cc042c404", + "0x232c043cc040089a008023cc0406c0417402008f301002024021c0ca3206c", + "0x9e008cd010f30107332c0d26c021cc043cc041cc040b0021cc043cc040086d", + "0x431802344043cc043380427c02338043cc04334cf0342f008cf010f301002", + "0x160103a008d7010f30103c0100f00877010f3010a40100b008f8010f301002", + "0x23cc04008090087a37cd71dcf802c041e8043cc04344042880237c043cc04", + "0x400855008e3010f30100226802008f30101301053008023cc0407c040a802", + "0xf301002278023a4043cc04398e30349b008e6010f3010e60102c008e6010f3", + "0xf301002010c6008f9010f3010f70109f008f7010f3010e90000d0bc0200004", + "0x43cc04058040e8023f0043cc0403c0403c023ec043cc0402c0402c023e804", + "0x414c02008f301002024023f8fd3f0fb3e80b010fe010f3010f9010a2008fd", + "0x43cc04400040b002400043cc040086d008ff010f30100226802008f301009", + "0x43cc04405020342f00902010f30100227802404043cc04400ff0349b00900", + "0x106010f30101a0100b00905010f301002010c600904010f3011030109f00903", + "0x4420043cc04410042880241c043cc04058040e8023d8043cc040480403c02", + "0x1a0354403c0b034f30340d0100d05802008f30100203402421073d9064140b", + "0x206013034f3010190106100819010f3010090101a008023cc040080900812", + "0x2008f3010020240207c045141b010f303418010bb0080b010f30100b0100b", + "0x222886034f3010200101d00820010f30101d0101f0081d010f3010130101b", + "0x40800225c95034f3010230101d00823010f30100221802008f30108601020", + "0x409c0408c020e8043cc0425c042280209c043cc042280422802008f301095", + "0xf30101b0105d008023cc040080900802518023cc0d0e8270349500827010f3", + "0x23cc040a8040a8020a828034f30109a010280089a010f3010160103a00802", + "0xd26c020b0043cc040b0040b0020b0043cc040084b0084b010f30100226802", + "0x427c020bc043cc0426c9e0342f0089e010f3010022780226c043cc040b04b", + "0xf0100f008a0010f30100b0100b008a2010f301002010c60089f010f30102f", + "0x32280a202c04284043cc0427c04288020d0043cc040a0040e8020c8043cc04", + "0x34008a3010f3010a301032008a3010f30100228002008f3010020240228434", + "0x43cc04008a1008023cc04008090083c2900d51c390dc0d3cc0d28c0f02c16", + "0x23cc042a0040e402104a8034f30103f010370083f010f3010a5010a3008a5", + "0x2188043cc0400804318022c0043cc040e40403c02124043cc040dc0402c02", + "0xcf00850010f30101b0102c00871010f301041010a40084e010f3010160103a", + "0x4520b8010f303447010c800847118452c4ab02cf3010501c44e188b01240f", + "0x41c002154043cc040089a00853010f3010b8010ca008023cc04008090086d", + "0x55010460085c010f30105801073008023cc042e40432c02160b9034f301053", + "0x5901062008023cc0416c040a80216c59034f30105d1700d33402174043cc04", + "0x41840414002184043cc042e8041c402008f30105f0104e008ba17c0d3cc04", + "0xf3010ab0100b00864010f301045010c6008be010f3010bb010b8008bb010f3", + "0x43cc042f804288022fc043cc04118040e802198043cc042c40403c022f404", + "0x431802310043cc041b40427c02008f30100202402378bf198bd1900b010de", + "0x460103a008c8010f3010b10100f0086c010f3010ab0100b008c6010f301045", + "0x23cc040080900870328c81b0c602c041c0043cc043100428802328043cc04", + "0x730102c00873010f3010021b40232c043cc040089a008023cc0406c0417402", + "0xcd33c0d0bc0233c043cc040089e008cd010f30107332c0d26c021cc043cc04", + "0x42900402c023e0043cc040080431802344043cc043380427c02338043cc04", + "0xf3010d1010a2008df010f3010160103a008d7010f30103c0100f00877010f3", + "0x414c02008f30101f0102a008023cc04008090087a37cd71dcf802c041e804", + "0x43cc04398040b002398043cc0400855008e3010f30100226802008f301013", + "0x43cc043a4000342f00800010f301002278023a4043cc04398e30349b008e6", + "0xfb010f30100b0100b008fa010f301002010c6008f9010f3010f70109f008f7", + "0x43f8043cc043e404288023f4043cc04058040e8023f0043cc0403c0403c02", + "0x43cc040089a008023cc040240414c02008f301002024023f8fd3f0fb3e80b", + "0x101010f3011003fc0d26c02400043cc04400040b002400043cc040086d008ff", + "0x2410043cc0440c0427c0240c043cc04405020342f00902010f30100227802", + "0x3a008f6010f3010120100f00906010f30101a0100b00905010f301002010c6", + "0x40080d0090841cf64190502c04420043cc04410042880241c043cc0405804", + "0x406c02008f301002024020680f0354902c09034f3034040080d05802008f3", + "0x40800206418034f3010130101d00813010f3010120101f00812010f301016", + "0x407c04080020741f034f30101b0101d0081b010f30100221802008f301018", + "0x43cc040800408c02218043cc040740422802080043cc040640422802008f3", + "0x23cc040080900802528023cc0d218200349500809010f3010090100b00820", + "0x2008f3010230102a008232280d3cc04254040a002254043cc04034040e802", + "0x970349b00827010f3010270102c00827010f30100212c0225c043cc040089a", + "0x2a0109f0082a010f30103a0a00d0bc020a0043cc040089e0083a010f301027", + "0x4228040e8020b0043cc0402c0403c0212c043cc040240402c02268043cc04", + "0xa0008023cc04008090089e26c2c12c090109e010f30109a010a20089b010f3", + "0x14b2889f034f30342f02c09058340082f010f30102f010320082f010f301002", + "0x2284043cc040d00428c020d0043cc04008a1008023cc0400809008322800d", + "0x3a008a5010f3010a20100f008023cc0428c040e4020dca3034f3010a101037", + "0xa40e4163cc042a03f29416338022a0043cc040dc04290020fc043cc0403404", + "0xf301002024022ac0453041010f30343c010590089f010f30109f0100b0083c", + "0x471180d3cc042c40417002114043cc040089a008b1010f3010410105b00802", + "0x5f0084e010f3010450104600862010f3010470102c008023cc041180417402", + "0x214071034f30104901062008023cc042c0040a8022c049034f30104e1880d", + "0x42e0021b4043cc042e004140022e0043cc04140041c402008f3010710104e", + "0xa40103a008b9010f3010390100f00855010f30109f0100b00853010f30106d", + "0x2008f30100202402164582e45502404164043cc0414c0428802160043cc04", + "0x3a0085d010f3010390100f0085c010f30109f0100b0085b010f3010ab0109f", + "0xf301002024022e85f1745c024042e8043cc0416c042880217c043cc0429004", + "0x9b008bb010f3010bb0102c008bb010f3010021b402184043cc040089a00802", + "0x9f008bd010f3010be1900d0bc02190043cc040089e008be010f3010bb1840d", + "0x40e802378043cc040c80403c022fc043cc042800402c02198043cc042f404", + "0x23cc0400809008c6310de2fc09010c6010f301066010a2008c4010f30100d", + "0xc80102c008c8010f3010021b4021b0043cc040089a008023cc040580414c02", + "0xca1c00d0bc021c0043cc040089e008ca010f3010c81b00d26c02320043cc04", + "0x40680403c02334043cc0403c0402c021cc043cc0432c0427c0232c043cc04", + "0xd1338cf33409010d1010f301073010a2008ce010f30100d0103a008cf010f3", + "0xf301002024020680f0354d02c09034f3034040080d05802008f30100203402", + "0x43cc040240402c0204c12034f3010180106100818010f3010160101a00802", + "0x43cc040480406c02008f3010020240206c0453819010f303413010bb00809", + "0x23cc04080040800221820034f30101d0101d0081d010f30101f0101f0081f", + "0x8a008023cc0408c040800225423034f30108a0101d0088a010f30100221802", + "0xd2540225c043cc0425c0408c0209c043cc04254042280225c043cc0421804", + "0x4034040e802008f3010190105d008023cc04008090080253c023cc0d09c97", + "0x43cc040089a008023cc040a0040a8020a03a034f30102a010280082a010f3", + "0x2c010f30104b2680d26c0212c043cc0412c040b00212c043cc040084b0089a", + "0x20bc043cc042780427c02278043cc040b09b0342f0089b010f30100227802", + "0xa2008a0010f30103a0103a008a2010f30100b0100f0089f010f3010090100b", + "0x34010f30100228002008f301002024020c8a02889f024040c8043cc040bc04", + "0x9008390dc0d540a32840d3cc0d0d00b024160d0020d0043cc040d0040c802", + "0xf3010a30100f0083c010f3010a4010a3008a4010f30100228402008f301002", + "0x43cc04064040b0022c4043cc040f004290022ac043cc04034040e80210404", + "0x43e002284043cc042840402c022a03f294163cc04114b12ac41024d100845", + "0x40089a008023cc04118041dc02008f3010020240211c0454446010f3034a8", + "0xf30106201071008023cc042c00413802188b0034f3010490106200849010f3", + "0x43cc042840402c02140043cc041c4042e0021c4043cc04138041400213804", + "0x55010f301050010a200853010f30103f0103a0086d010f3010a50100f008b8", + "0x42840402c022e4043cc0411c0427c02008f30100202402154531b4b802404", + "0xf3010b9010a20085b010f30103f0103a00859010f3010a50100f00858010f3", + "0x40089a008023cc040640417402008f301002024021705b164580240417004", + "0xf30105f1740d26c0217c043cc0417c040b00217c043cc040086d0085d010f3", + "0x43cc042ec0427c022ec043cc042e8610342f00861010f301002278022e804", + "0x66010f30100d0103a008bd010f3010390100f00864010f3010370100b008be", + "0x406c040a802008f301002024022fc662f464024042fc043cc042f80428802", + "0x2c008c4010f30100215402378043cc040089a008023cc040480414c02008f3", + "0xd0bc021b0043cc040089e008c6010f3010c43780d26c02310043cc0431004", + "0x403c021c0043cc040240402c02328043cc043200427c02320043cc043186c", + "0xcb1c009010cd010f3010ca010a200873010f30100d0103a008cb010f30100b", + "0x21b40233c043cc040089a008023cc040580414c02008f3010020240233473", + "0x40089e008d1010f3010ce33c0d26c02338043cc04338040b002338043cc04", + "0x403c0402c0235c043cc041dc0427c021dc043cc04344f80342f008f8010f3", + "0xf3010d7010a2008e3010f30100d0103a0087a010f30101a0100f008df010f3", + "0x15202c09034f3034040080d05802008f30100203402398e31e8df0240439804", + "0x13010f3010120101f00812010f3010160101b008023cc04008090081a03c0d", + "0x1d0081b010f30100221802008f30101801020008190600d3cc0404c0407402", + "0x422802080043cc040640422802008f30101f010200081d07c0d3cc0406c04", + "0x200349500809010f3010090100b00820010f3010200102300886010f30101d", + "0x4254040a002254043cc04034040e802008f3010020240200953008f303486", + "0x27010f30100212c0225c043cc040089a008023cc0408c040a80208c8a034f3", + "0x20a0043cc040089e0083a010f30102725c0d26c0209c043cc0409c040b002", + "0x212c043cc040240402c02268043cc040a80427c020a8043cc040e8280342f", + "0x90109e010f30109a010a20089b010f30108a0103a0082c010f30100b0100f", + "0x2f010f30102f010320082f010f30100228002008f301002024022789b0b04b", + "0x4008a1008023cc0400809008322800d550a227c0d3cc0d0bc0b024160d002", + "0x428c040e4020dca3034f3010a101037008a1010f301034010a300834010f3", + "0x43cc040dc04290020fc043cc04034040e802294043cc042880403c02008f3", + "0x3c010590089f010f30109f0100b0083c29039058f3010a80fca5058d7008a8", + "0x40089a008b1010f3010410105b008023cc0400809008ab01155104043cc0d", + "0xf3010470102c008023cc04118041740211c46034f3010b10105c00845010f3", + "0x42c0040a8022c049034f30104e1880d17c02138043cc04114041180218804", + "0x43cc04140041c402008f3010710104e008501c40d3cc041240418802008f3", + "0x55010f30109f0100b00853010f30106d010b80086d010f3010b801050008b8", + "0x4164043cc0414c0428802160043cc04290040e8022e4043cc040e40403c02", + "0xf30109f0100b0085b010f3010ab0109f008023cc040080900859160b915409", + "0x43cc0416c042880217c043cc04290040e802174043cc040e40403c0217004", + "0xf3010021b402184043cc040089a008023cc0400809008ba17c5d17009010ba", + "0x43cc040089e008be010f3010bb1840d26c022ec043cc042ec040b0022ec04", + "0x43cc042800402c02198043cc042f40427c022f4043cc042f8640342f00864", + "0xc6010f301066010a2008c4010f30100d0103a008de010f3010320100f008bf", + "0x43cc040089a008023cc040580414c02008f30100202402318c4378bf02404", + "0xca010f3010c81b00d26c02320043cc04320040b002320043cc040086d0086c", + "0x21cc043cc0432c0427c0232c043cc04328700342f00870010f30100227802", + "0xa2008ce010f30100d0103a008cf010f30101a0100f008cd010f30100f0100b", + "0xf3034040080d05802008f30100203402344ce33ccd02404344043cc041cc04", + "0x180106100818010f3010160101a008023cc04008090081a03c0d5580b0240d", + "0x206c0455c19010f303413010bb00809010f3010090100b008130480d3cc04", + "0x1d0101d0081d010f30101f0101f0081f010f3010120101b008023cc0400809", + "0xf30108a0101d0088a010f30100221802008f30102001020008860800d3cc04", + "0x43cc04254042280225c043cc042180422802008f301023010200089508c0d", + "0x23cc040080900802560023cc0d09c970349500897010f3010970102300827", + "0x20a03a034f30102a010280082a010f30100d0103a008023cc040640417402", + "0x412c040b00212c043cc040084b0089a010f30100226802008f3010280102a", + "0x40b09b0342f0089b010f301002278020b0043cc0412c9a0349b0084b010f3", + "0xf30100b0100f0089f010f3010090100b0082f010f30109e0109f0089e010f3", + "0x20c8a02889f024040c8043cc040bc0428802280043cc040e8040e80228804", + "0xb024160d0020d0043cc040d0040c8020d0043cc04008a0008023cc0400809", + "0xa3008a4010f30100228402008f301002024020e4370355928ca1034f303434", + "0x4290022ac043cc04034040e802104043cc0428c0403c020f0043cc0429004", + "0x3f294163cc04114b12ac41024df00845010f3010190102c008b1010f30103c", + "0xf3010020240211c0456846010f3034a8010f8008a1010f3010a10100b008a8", + "0x2188b0034f3010490106200849010f30100226802008f3010460107700802", + "0x42e0021c4043cc041380414002138043cc04188041c402008f3010b00104e", + "0x3f0103a0086d010f3010a50100f008b8010f3010a10100b00850010f301071", + "0x2008f30100202402154531b4b802404154043cc04140042880214c043cc04", + "0x3a00859010f3010a50100f00858010f3010a10100b008b9010f3010470109f", + "0xf301002024021705b1645802404170043cc042e4042880216c043cc040fc04", + "0x40b00217c043cc040086d0085d010f30100226802008f3010190105d00802", + "0x610342f00861010f301002278022e8043cc0417c5d0349b0085f010f30105f", + "0x390100f00864010f3010370100b008be010f3010bb0109f008bb010f3010ba", + "0x662f464024042fc043cc042f80428802198043cc04034040e8022f4043cc04", + "0x40089a008023cc040480414c02008f30101b0102a008023cc0400809008bf", + "0xf3010c43780d26c02310043cc04310040b002310043cc0400855008de010f3", + "0x43cc043200427c02320043cc043186c0342f0086c010f3010022780231804", + "0x73010f30100d0103a008cb010f30100b0100f00870010f3010090100b008ca", + "0x40580414c02008f301002024023347332c7002404334043cc043280428802", + "0x2338043cc04338040b002338043cc040086d008cf010f30100226802008f3", + "0x21dc043cc04344f80342f008f8010f30100227802344043cc04338cf0349b", + "0x3a0087a010f30101a0100f008df010f30100f0100b008d7010f3010770109f", + "0xf30100203402398e31e8df02404398043cc0435c042880238c043cc0403404", + "0x90101a008023cc0400809008120680d56c0f02c0d3cc0d034020341600802", + "0x18010bb0080b010f30100b0100b0081804c0d3cc040640418402064043cc04", + "0x404c0406802008f30101b0105d008023cc04008090081f0115c06c043cc0d", + "0x9008230115d228043cc0d080042ec020801d034f3010860106100886010f3", + "0xf3010270106100827010f30101d0101a008023cc042280417402008f301002", + "0x40e80417402008f301002024020a0045783a010f303497010bb008972540d", + "0xd3cc042680407402268043cc040a80407c020a8043cc042540406c02008f3", + "0x2f2780d3cc0426c040740226c043cc0400886008023cc0412c04080020b04b", + "0x23008a2010f30102f0108a0089f010f30102c0108a008023cc042780408002", + "0x40e802008f301002024020095f008f3034a227c0d2540227c043cc0427c04", + "0x40089a008023cc040c8040a8020c8a0034f3010340102800834010f301016", + "0xf3010a32840d26c0228c043cc0428c040b00228c043cc040084b008a1010f3", + "0x43cc042900427c02290043cc040dc390342f00839010f301002278020dc04", + "0xa8010f30100f0100f0083f010f301004010b9008a5010f30100b0100b0083c", + "0x9008ab104a80fca502c042ac043cc040f00428802104043cc04280040e802", + "0xb103c0b05834008b1010f3010b101032008b1010f30100228002008f301002", + "0x428c022c0043cc04008a1008023cc04008090084911c0d580461140d3cc0d", + "0x450100b008023cc04138040e4021c44e034f3010620103700862010f3010b0", + "0x4058040e802164043cc041180403c02160043cc04010042e4022e4043cc04", + "0x6d2e05002cf30105c16c59160b902c580085c010f301071010a40085b010f3", + "0xf30105d0105b008023cc04008090085f01161174043cc0d154041640215453", + "0x23cc042ec04174022f8bb034f3010ba0105c00861010f301002268022e804", + "0x64034f3010bf1980d17c022fc043cc041840411802198043cc042f8040b002", + "0x2008f3010de0104e008c43780d3cc041900418802008f3010bd0102a008bd", + "0xb008c8010f30106c010b80086c010f3010c601050008c6010f3010c401071", + "0x40e80232c043cc041b40403c021c0043cc042e0042e402328043cc0414004", + "0xf301002024023347332c703280b010cd010f3010c8010a200873010f301053", + "0xd1010f3010b8010b9008ce010f3010500100b008cf010f30105f0109f00802", + "0x435c043cc0433c04288021dc043cc0414c040e8023e0043cc041b40403c02", + "0x43cc040086d008df010f30100226802008f3010020240235c773e0d13380b", + "0xe6010f3010022780238c043cc041e8df0349b0087a010f30107a0102c0087a", + "0xf7010f3010470100b00800010f3010e90109f008e9010f3010e33980d0bc02", + "0x23ec043cc04058040e8023e8043cc041240403c023e4043cc04010042e402", + "0x40a0040a802008f301002024023f0fb3e8f93dc0b010fc010f301000010a2", + "0x2c008fe010f301002154023f4043cc040089a008023cc042540414c02008f3", + "0xd0bc02400043cc040089e008ff010f3010fe3f40d26c023f8043cc043f804", + "0x42e40240c043cc0402c0402c02408043cc044040427c02404043cc043fd00", + "0x102010a200906010f3010160103a00905010f30100f0100f00904010f301004", + "0x2008f3010230102a008023cc0400809008f6419054110302c043d8043cc04", + "0x4420040b002420043cc040085500907010f30100226802008f30101d01053", + "0x44250a0342f0090a010f30100227802424043cc04421070349b00908010f3", + "0xf301004010b90090d010f30100b0100b0090c010f30110b0109f0090b010f3", + "0x43cc044300428802440043cc04058040e80243c043cc0403c0403c0243804", + "0x1301053008023cc0407c040a802008f301002024024451043d0e4340b01111", + "0x113010f3011130102c00913010f30100215402448043cc040089a008023cc04", + "0xf5010f3011144540d0bc02454043cc040089e00914010f3011134480d26c02", + "0x2494043cc04010042e40245c043cc0402c0402c02458043cc043d40427c02", + "0xb01128010f301116010a200927010f3010160103a00926010f30100f0100f", + "0x129010f30100226802008f30100901053008023cc04008090092849d2649517", + "0x24a8043cc043d1290349b008f4010f3010f40102c008f4010f3010021b402", + "0xb0092d010f30112c0109f0092c010f30112a4ac0d0bc024ac043cc040089e", + "0x40e8024c0043cc040480403c024bc043cc04010042e4024b8043cc0406804", + "0xf301002034024c9314c12f4b80b01132010f30112d010a200931010f301016", + "0x90101a008023cc0400809008120680d5880f02c0d3cc0d034040341600802", + "0x18010bb0080b010f30100b0100b0081804c0d3cc040640418402064043cc04", + "0x1d0101f0081d010f3010130101b008023cc04008090081f0116306c043cc0d", + "0xf30100221802008f301086010200088a2180d3cc040800407402080043cc04", + "0x43cc042280422802008f30109501020008972540d3cc0408c040740208c04", + "0x23cc0d0e8270349500827010f301027010230083a010f3010970108a00827", + "0x280089a010f3010160103a008023cc0406c0417402008f3010020240200964", + "0x40084b0084b010f30100226802008f30102a0102a0082a0a00d3cc0426804", + "0xf3010022780226c043cc040b04b0349b0082c010f30102c0102c0082c010f3", + "0xf301002010c60089f010f30102f0109f0082f010f30109b2780d0bc0227804", + "0x43cc040a0040e8020c8043cc0403c0403c02280043cc0402c0402c0228804", + "0x228002008f30100202402284340c8a02880b010a1010f30109f010a200834", + "0xd594390dc0d3cc0d28c0f02c160d00228c043cc0428c040c80228c043cc04", + "0xb0083f010f3010a5010a3008a5010f30100228402008f301002024020f0a4", + "0x40e802124043cc04008043180211c043cc040e40403c02118043cc040dc04", + "0x4603c7a0084e010f30101b0102c00862010f30103f010a4008b0010f301016", + "0x21400459871010f303445010f8008452c4ab104a802cf30104e188b012447", + "0xf3010b801062008b8010f30100226802008f30107101077008023cc0400809", + "0x43cc041540414002154043cc0414c041c402008f30106d0104e008531b40d", + "0x5b010f3010a80100b00859010f3010ab010c600858010f3010b9010b8008b9", + "0x417c043cc041600428802174043cc042c4040e802170043cc041040403c02", + "0x42ac04318022e8043cc041400427c02008f3010020240217c5d1705b1640b", + "0xf3010b10103a008be010f3010410100f008bb010f3010a80100b00861010f3", + "0x5d008023cc0400809008bd190be2ec6102c042f4043cc042e8042880219004", + "0xf3010bf0102c008bf010f3010021b402198043cc040089a008023cc0406c04", + "0xf3010de3100d0bc02310043cc040089e008de010f3010bf1980d26c022fc04", + "0x43cc042900402c02320043cc0400804318021b0043cc043180427c0231804", + "0x73010f30106c010a2008cb010f3010160103a00870010f30103c0100f008ca", + "0x404c0414c02008f30101f0102a008023cc04008090087332c70328c802c04", + "0x233c043cc0433c040b00233c043cc0400855008cd010f30100226802008f3", + "0x23e0043cc04338d10342f008d1010f30100227802338043cc0433ccd0349b", + "0xf008df010f30100b0100b008d7010f301002010c600877010f3010f80109f", + "0xd702c04398043cc041dc042880238c043cc04058040e8021e8043cc0403c04", + "0x23a4043cc040089a008023cc040240414c02008f30100202402398e31e8df", + "0x9e008f7010f3010003a40d26c02000043cc04000040b002000043cc040086d", + "0x4318023ec043cc043e80427c023e8043cc043dcf90342f008f9010f301002", + "0x160103a008fe010f3010120100f008fd010f30101a0100b008fc010f301002", + "0x23cc04008e3009003fcfe3f4fc02c04400043cc043ec04288023fc043cc04", + "0xf3010020240203c0459c0b0240d3cc0d0580439802058043cc040340406c02", + "0x13010f30101a010f700812010f301009010000081a010f30100b010e900802", + "0xf301018010fb00818010f3010023e802008f3010020240200968010023e402", + "0x43cc04048041c40204c043cc04064043dc02048043cc0403c040000206404", + "0xf30100202402074045a41f010f303413010fc0081b010f30101b0101a0081b", + "0x2228043cc04008ff00886010f301020010fe00820010f30101f010fd00802", + "0x3c00828010f30101b0101a0083a010f3010040100f00827010f3010020100b", + "0x163cc042682a0a03a09c0b40002268043cc04218040b0020a8043cc0422804", + "0x412c0406002008f301002024020b0045a84b010f303497010130089725423", + "0x230100b0089f010f30102f011020082f010f30109e26c0d404022789b034f3", + "0x32280a2058040c8043cc0427c0440c02280043cc042540403c02288043cc04", + "0x403c02284043cc0408c0402c020d0043cc040b00441002008f30100202402", + "0x2008f301002024020dca32841601037010f30103401103008a3010f301095", + "0x1b03501008a4010f3010390110500839010f3010023e802008f30101d0102a", + "0x40100f0083f010f3010020100b008a5010f30103c011020083c010f3010a4", + "0x2010043cc04008fa008412a03f05804104043cc042940440c022a0043cc04", + "0x23cc04008e3008160340d01016010f301004011060080d010f3010020103a", + "0xf600813010f30100d0103a00812010f3010040100f008023cc04058040e402", + "0xf30100202402064045ac18010f30341a011070081a03c0b058f3010130480d", + "0x1d034f30101f0105c0081f010f30101b011090081b010f3010180110800802", + "0x208c8a034f3010860105c00886010f30100242802008f30101d0105d00820", + "0xd42c0225c043cc0408c043f802254043cc04080043f802008f30108a0105d", + "0x20e8045b0023cc0d09c044300209c043cc0409c040b00209c043cc0425c95", + "0x4b0350d0082c010f30100f0103a0084b010f30100b0100f008023cc0400809", + "0x2278045b49b010f30349a0110f008023cc040090e0089a0a828058f30102c", + "0x9f011120089f010f30102f011110082f010f30109b01110008023cc0400809", + "0x2008f30103201114008023cc042800444c020dca3284340c8a02881a3cc04", + "0x40dc0417402008f3010a30105d008023cc042840417402008f30103401053", + "0xd3cc040f004170020f0043cc0400915008a40e40d3cc042880417002008f3", + "0x41034f3010a80105c008a8010f3010a4010fe008023cc0429404174020fca5", + "0x461140d3cc042c404170022c4043cc040fc043f802008f3010410105d008ab", + "0x2c00849010f301046010fe00847010f3010ab010fe008023cc041140417402", + "0x2c008b0010f3010b00102c008b0010f30104911c0d42c0211c043cc0411c04", + "0x417402008f30100202402188045b8023cc0d2c004430020e4043cc040e404", + "0x5c008023cc04188043d402008f301002024020096f010023e402008f301039", + "0x500105c00850010f30100245802008f30104e0105d008711380d3cc040e404", + "0x41b4043f80214c043cc041c4043f802008f3010b80105d0086d2e00d3cc04", + "0xd2e404430022e4043cc042e4040b0022e4043cc04154530350b00855010f3", + "0x5f010f3010020100b008023cc04008e3008023cc04008090085801170008f3", + "0x22ec043cc04024040f002184043cc040a8040e8022e8043cc040a00403c02", + "0x2190045c4be010f30345d010a80085d1705b164093cc042ec612e85f02517", + "0x660112600866010f3010bd01125008bd010f3010be01041008023cc0400809", + "0x4170040e802310043cc0416c0403c02378043cc041640402c022fc043cc04", + "0x128008023cc04008090086c318c4378090106c010f3010bf01127008c6010f3", + "0x40e8021c0043cc0416c0403c02328043cc041640402c02320043cc0419004", + "0x23cc04008090087332c703280901073010f3010c801127008cb010f30105c", + "0xf30100226802008f30100901027008023cc04160043d402008f30100238c02", + "0x43cc0433ccd0349b008cf010f3010cf0102c008cf010f3010024a40233404", + "0x77010f3010f801128008f8010f3010ce3440d0bc02344043cc040089e008ce", + "0x21e8043cc040a8040e80237c043cc040a00403c0235c043cc040080402c02", + "0x23cc04008e3008023cc0400809008e31e8df35c09010e3010f30107701127", + "0xf008e9010f3010020100b008e6010f30109e01128008023cc040240409c02", + "0xe9024043e4043cc043980449c023dc043cc040a8040e802000043cc040a004", + "0x9a008023cc040240409c02008f30103a010f5008023cc0400809008f93dc00", + "0xfb3e80d26c023ec043cc043ec040b0023ec043cc04008f4008fa010f301002", + "0x43f8044a0023f8043cc043f0fd0342f008fd010f301002278023f0043cc04", + "0xf30100f0103a00901010f30100b0100f00900010f3010020100b008ff010f3", + "0x409c02008f3010020240240d02405000240440c043cc043fc0449c0240804", + "0x402c0403c02414043cc040080402c02410043cc04064044a002008f301009", + "0x1073d9064140901107010f30110401127008f6010f30100f0103a00906010f3", + "0x1d00809010f30100b0112b0080b0340d3cc04034044a802008f30100238c02", + "0x411802060043cc040680408c02008f30100f010200081a03c0d3cc0402404", + "0x44b402008f3010130102a008130480d3cc04064180352c00819010f301016", + "0x1b0112e0088a010f3010040100f00886010f3010020100b0081b010f30100d", + "0x200741f058f30109508c8a218094bc02254043cc04048041180208c043cc04", + "0x3a034f301097010b0008023cc0400809008270117225c043cc0d0800412402", + "0x2268043cc040a83a035300082a010f3010023e802008f3010280102a00828", + "0x1320089b010f30101d0100f0082c010f30101f0100b0084b010f30109a01131", + "0x2f010f30102701173008023cc04008090089e26c2c05804278043cc0412c04", + "0x4280043cc040bc044c802288043cc040740403c0227c043cc0407c0402c02", + "0x130480d4340204c043cc04058040e802048043cc040340403c02280a227c16", + "0x110008023cc04008090081901174060043cc0d0680443c020680f02c163cc04", + "0x8a218200741a3cc0407c044480207c043cc0406c044440206c043cc0406004", + "0x2008f30108601114008023cc040800444c02008f30101d0105d0089725423", + "0x4010b90084b010f3010020100b008023cc0425c0417402008f3010950105d", + "0x40240429002278043cc0403c040e80226c043cc0402c0403c020b0043cc04", + "0x9b0b04b06975008a2010f30108a0101a0089f010f3010230102c0082f010f3", + "0x90083201176280043cc0d26804320022682a0a03a09c0b3cc042889f0bc9e", + "0x9008a301178284043cc0d0d0045dc020d0043cc042800432802008f301002", + "0x39010f3010025e4020dc043cc040089a008023cc04284040a802008f301002", + "0x20f0043cc040089e008a4010f3010390dc0d26c020e4043cc040e4040b002", + "0x22a0043cc0409c0402c020fc043cc04294045e802294043cc042903c0342f", + "0x17b008b1010f30102a0103a008ab010f3010280100f00841010f30103a010b9", + "0xf3010a30102a008023cc0400809008452c4ab104a802c04114043cc040fc04", + "0x2124043cc0411c045f80211c043cc04118045f402118043cc040097c00802", + "0x3a0084e010f3010280100f00862010f30103a010b9008b0010f3010270100b", + "0x400809008501c44e188b002c04140043cc04124045ec021c4043cc040a804", + "0x43cc040e8042e4021b4043cc0409c0402c022e0043cc040c8045e802008f3", + "0x58010f3010b80117b008b9010f30102a0103a00855010f3010280100f00853", + "0x4064045e802008f30100901039008023cc0400809008582e45514c6d02c04", + "0xf30100b0100f0085c010f301004010b90085b010f3010020100b00859010f3", + "0xba17c5d1705b02c042e8043cc04164045ec0217c043cc0403c040e80217404", + "0x2024043cc04008fa00816010f30100d0100d26c02034043cc04008043f802", + "0xf3010020101b0080f02c0d0100f010f301009011060080b010f30101601046", + "0x4058043a402008f30100202402024045fc160340d3cc0d010043980201004", + "0x260004008f90081a010f30100b010f70080f010f30100d010000080b010f3", + "0x90100000813010f301012010fb00812010f3010023e802008f30100202402", + "0x40600406802060043cc0403c041c402068043cc0404c043dc0203c043cc04", + "0x4064043f402008f3010020240206c0460419010f30341a010fc00818010f3", + "0xf3010180101a00820010f30101d011820081d010f30101f010fe0081f010f3", + "0x406c040a802008f301002024022288603404228043cc040800460c0221804", + "0x97010f3010180101a00895010f3010230118400823010f3010023e802008f3", + "0x43cc040340406c02008f30100238c0209c970340409c043cc042540460c02", + "0xf30100b010e9008023cc04008090080f0118502c09034f303416010e600816", + "0x200986010023e40204c043cc04068043dc02048043cc04024040000206804", + "0x403c0400002064043cc04060043ec02060043cc04008fa008023cc0400809", + "0xf30101b0101a0081b010f3010120107100813010f301019010f700812010f3", + "0xf30101f010fd008023cc04008090081d0118707c043cc0d04c043f00206c04", + "0x27010f3010020100b0088a010f30100226802218043cc04080043f80208004", + "0x20a8043cc0422804118020a0043cc0406c04068020e8043cc040100403c02", + "0x97010bd0089725423058f30109a0a8280e82702d880089a010f3010860102c", + "0xd628022789b034f30104b01066008023cc04008090082c0118912c043cc0d", + "0x403c02288043cc0408c0402c0227c043cc040bc0462c020bc043cc042789b", + "0x2008f301002024020c8a02881601032010f30109f0118c008a0010f301095", + "0x18c008a3010f3010950100f008a1010f3010230100b00834010f30102c0118d", + "0x2008f30101d0102a008023cc04008090083728ca1058040dc043cc040d004", + "0x18b0083c010f3010a406c0d62802290043cc040e404638020e4043cc04008fa", + "0x4630022a0043cc040100403c020fc043cc040080402c02294043cc040f004", + "0xf30101a0104e008120680d3cc0403c0418802104a80fc1601041010f3010a5", + "0x86010f301004010b900820010f3010020100b00813010f3010120107100802", + "0x2254043cc04024042900208c043cc04058040e802228043cc040340403c02", + "0x2725c9508c8a218200697500827010f3010130101a00897010f30100b0102c", + "0x23cc0400809008280118f0e8043cc0d07404320020741f06c190600b3cc04", + "0x23cc04008090084b01190268043cc0d0a8045dc020a8043cc040e80432802", + "0x23e40226c043cc040b0040b0020b0043cc040090a008023cc04268040a802", + "0x2c0089e010f3010025f002008f30104b0102a008023cc04008090080264404", + "0x402c0227c043cc040bc045f8020bc043cc0426c045f40226c043cc0427804", + "0x1f0103a00832010f30101b0100f008a0010f301019010b9008a2010f301018", + "0x23cc0400809008a10d032280a202c04284043cc0427c045ec020d0043cc04", + "0x20e4043cc04064042e4020dc043cc040600402c0228c043cc040a0045e802", + "0xb010a5010f3010a30117b0083c010f30101f0103a008a4010f30101b0100f", + "0xf30100f011930080f010f30100264802008f30100901039008a50f0a40e437", + "0x43cc040080402c02008f30101201195008130480d3cc04068046500206804", + "0x23010f3010160103a0088a010f30100d010c600886010f3010040100f00820", + "0x9725423228860800f65c0225c043cc0402c040b002254043cc0404c0465802", + "0x23cc04008090083a0119809c043cc0d07404320020741f06c190600b3cc04", + "0x2268043cc040a804668020a8043cc040a004664020a0043cc0409c0432802", + "0x3a0089b010f30101b010c60082c010f3010190100f0084b010f3010180100b", + "0x4008090082f2789b0b04b02c040bc043cc042680466c02278043cc0407c04", + "0x43cc040640403c02288043cc040600402c0227c043cc040e80467002008f3", + "0xa1010f30109f0119b00834010f30101f0103a00832010f30101b010c6008a0", + "0x467816010f30340d011770080d010f3010020119d008a10d032280a202c04", + "0xb0102c0080b010f30100242802008f3010160102a008023cc040080900809", + "0x115008023cc04024040a802008f301002024020099f010023e40203c043cc04", + "0x41740204c12034f30100f0105c0080f010f30101a0102c0081a010f301002", + "0x1f06c0d17c0207c043cc04010041180206c043cc0404c043f802008f301012", + "0xf301018010460081d010f3010023e802008f3010190102a008190600d3cc04", + "0x400992008023cc04024040e4022182003404218043cc04074044180208004", + "0x4048046540204c12034f30101a011940081a010f30100f011930080f010f3", + "0x43cc040340431802218043cc040100403c02080043cc040080402c02008f3", + "0x97010f30100b0102c00895010f3010130119600823010f3010160103a0088a", + "0x27010f30341d010c80081d07c1b0641802cf30109725423228860800f65c02", + "0x2a010f3010280119900828010f301027010ca008023cc04008090083a011a0", + "0x20b0043cc040640403c0212c043cc040600402c02268043cc040a80466802", + "0xb0102f010f30109a0119b0089e010f30101f0103a0089b010f30101b010c6", + "0xf3010180100b0089f010f30103a0119c008023cc04008090082f2789b0b04b", + "0x43cc0407c040e8020c8043cc0406c0431802280043cc040640403c0228804", + "0x2058043cc040340468402284340c8a02880b010a1010f30109f0119b00834", + "0x1a300813010f301016011a200812010f3010040103a0081a010f3010020100f", + "0x40080900819011a4060043cc0d03c041640203c0b024163cc0404c1206816", + "0x43cc0407c045f80207c043cc0406c045f40206c043cc040600416c02008f3", + "0x8a010f30101d0117b00886010f30100b0103a00820010f3010090100f0081d", + "0xf3010090100f00823010f3010190117a008023cc04008090088a2182005804", + "0xf0082725c950580409c043cc0408c045ec0225c043cc0402c040e80225404", + "0xf02c09058f3010120680d69402048043cc04010040e802068043cc0400804", + "0x2008f301013011a8008023cc040080900818011a704c043cc0d03c0469802", + "0x2228043cc040240403c0207c1b034f301019011a900819010f30100d011a1", + "0x1d058f30109508c8a059a300895010f30101f011a200823010f30100b0103a", + "0xf3010970105b008023cc040080900827011aa25c043cc0d218041640221820", + "0x43cc040740403c020a8043cc0406c0428c020a0043cc040e8046ac020e804", + "0x9f010f301028011ac0082f010f30102a010a40089e010f3010200103a0089b", + "0x2280046b8a2010f30342c010f80082c12c9a058f30109f0bc9e26c096b402", + "0x9a0100f008023cc040d0040a8020d032034f3010a2011af008023cc0400809", + "0x4058040b0020f0043cc040c80429002290043cc0412c040e8020e4043cc04", + "0x1b10fc043cc0d0dc043e0020dca3284163cc042943c29039025b0008a5010f3", + "0x2008f3010ab0102a008ab1040d3cc040fc046bc02008f301002024022a004", + "0xf00846010f301045011b300845010f3010b11040d6c8022c4043cc04008fa", + "0x47058042c0043cc04118046d002124043cc0428c040e80211c043cc0428404", + "0x2138043cc042840403c02188043cc042a0046d402008f301002024022c049", + "0xf30100202402140711381601050010f301062011b400871010f3010a30103a", + "0x21b4043cc042680403c022e0043cc04280046d402008f3010160105d00802", + "0xf30100202402154531b41601055010f3010b8011b400853010f30104b0103a", + "0xf008b9010f301027011b5008023cc0406c046d802008f3010160105d00802", + "0x580580416c043cc042e4046d002164043cc04080040e802160043cc0407404", + "0x46d402008f30100d01039008023cc040580417402008f3010020240216c59", + "0x5c011b40085f010f30100b0103a0085d010f3010090100f0085c010f301018", + "0x1a010f3010020100f00816010f30100d011a1008ba17c5d058042e8043cc04", + "0x163cc0404c120681668c0204c043cc040580468802048043cc04010040e802", + "0x40600416c02008f30100202402064046dc18010f30340f010590080f02c09", + "0xf3010090100f0081d010f30101f0117e0081f010f30101b0117d0081b010f3", + "0x90088a2182005804228043cc04074045ec02218043cc0402c040e80208004", + "0x402c040e802254043cc040240403c0208c043cc04064045e802008f301002", + "0x2068043cc040080403c0209c972541601027010f3010230117b00897010f3", + "0xd100818010f3010160102c00813010f30100d010a400812010f3010040103a", + "0x20240206c046e019010f30340f010f80080f02c09058f30101804c1206809", + "0x43cc04008fa008023cc04074040a8020741f034f301019011af008023cc04", + "0x43cc040240403c02228043cc04218046cc02218043cc040801f035b200820", + "0x20240225c9508c1601097010f30108a011b400895010f30100b0103a00823", + "0xf30100b0103a0083a010f3010090100f00827010f30101b011b5008023cc04", + "0xf00819010f3010020100b0082a0a03a058040a8043cc0409c046d0020a004", + "0x429002074043cc04058040e80207c043cc04034043180206c043cc0401004", + "0xb3cc04218200741f06c1903d1b00886010f30100b0102c00820010f301009", + "0x46bc02008f3010020240208c046e48a010f303418010f80081804c120680f", + "0x272540d6c80209c043cc04008fa008023cc0425c040a80225c95034f30108a", + "0x40680403c020a8043cc0403c0402c020a0043cc040e8046cc020e8043cc04", + "0xf301028011b40082c010f3010130103a0084b010f301012010c60089a010f3", + "0xb0089e010f301023011b5008023cc04008090089b0b04b2682a02c0426c04", + "0x40e802288043cc04048043180227c043cc040680403c020bc043cc0403c04", + "0xf30100238c020c8a02889f0bc0b01032010f30109e011b4008a0010f301013", + "0xd3cc0d02c04008160d00202c043cc0402c040c80202c043cc04008a000802", + "0xf0100b008180240d3cc04024046ec02008f3010020240204c12035ba0680f", + "0x40240417402008f30100202402064046f0023cc0d060044300203c043cc04", + "0xf30101f011020081f010f30101b0340d4040206c043cc04058046f402008f3", + "0x43cc040740440c02218043cc040680403c02080043cc0403c0402c0207404", + "0xf30100f0100b008023cc04064043d402008f3010020240222886080160108a", + "0x40a03a09c166f8020a0043cc0403404068020e8043cc040680403c0209c04", + "0x470402008f30100202402268047002a010f303497011bf0089725423058f3", + "0x1c4008023cc04008090089e011c326c043cc0d0b004708020b04b034f30102a", + "0xb008a2010f30109f0240d42c0227c043cc04009150082f010f30109b0580d", + "0x40f0020dc043cc0412c040680228c043cc042540403c02284043cc0408c04", + "0xa0058f3010a40e43728ca102d00008a4010f3010a20102c00839010f30102f", + "0xf30103c01018008023cc0400809008a5011c50f0043cc0d0d00404c020d032", + "0x42800402c022ac043cc041040440802104043cc042a03f03501008a80fc0d", + "0x2118452c41601046010f3010ab0110300845010f3010320100f008b1010f3", + "0x320100f00849010f3010a00100b00847010f3010a501104008023cc0400809", + "0x5d008023cc0400809008622c04905804188043cc0411c0440c022c0043cc04", + "0x4e12c0d40402138043cc042780441402008f30101601027008023cc0402404", + "0x42540403c022e0043cc0408c0402c02140043cc041c404408021c4043cc04", + "0x417402008f3010020240214c6d2e01601053010f301050011030086d010f3", + "0xf3010230100b00855010f30109a01104008023cc040580409c02008f301009", + "0x900859160b905804164043cc041540440c02160043cc042540403c022e404", + "0x23cc040340414c02008f30101601027008023cc040240417402008f301002", + "0xd26c02170043cc04170040b002170043cc040086d0085b010f30100226802", + "0x4410022e8043cc041745f0342f0085f010f30100227802174043cc041705b", + "0x6101103008be010f3010130100f008bb010f3010120100b00861010f3010ba", + "0xf010f3010040103a0080b010f3010020100f008642f8bb05804190043cc04", + "0x202402048047201a010f303409011c7008090580d058f30100f02c0d71802", + "0xf301018011cb00818010f301013011ca00813010f30101a011c9008023cc04", + "0x40740444c02008f30101b011cd008023cc0406404730020801d07c1b0640b", + "0x8a010f301086011cf00886010f30101f011ce008023cc040800417402008f3", + "0x425c043cc042280474002254043cc04058040e80208c043cc040340403c02", + "0x43cc040340403c0209c043cc040480474402008f3010020240225c9508c16", + "0x403c020a8280e8160102a010f301027011d000828010f3010160103a0083a", + "0x202416034163cc0403c0b035c60080f010f3010040103a0080b010f301002", + "0x204c043cc040680472402008f30100202402048047481a010f303409011c7", + "0xf301019011cc008200741f06c1902cf301018011cb00818010f301013011ca", + "0x474c02008f3010200105d008023cc040740444c02008f30101f0111300802", + "0x160103a00823010f30100d0100f0088a010f301086011d400886010f30101b", + "0x1d6008023cc040080900897254230580425c043cc042280475402254043cc04", + "0x4754020a0043cc04058040e8020e8043cc040340403c0209c043cc0404804", + "0xb00809010f30100275c02008f30100238c020a8280e8160102a010f301027", + "0x40f002064043cc04034040e802060043cc040100403c0204c043cc0400804", + "0xb024f30101f06c190601302dd90081f010f301009011d80081b010f301016", + "0x40740477002008f301002024020800476c1d010f303412011da008120680f", + "0xf30108a01125008023cc0408c040a802008f301086010270082322886058f3", + "0x43cc0403c0403c0209c043cc0402c0402c0225c043cc04254044980225404", + "0x90082a0a03a09c090102a010f3010970112700828010f30101a0103a0083a", + "0x403c0403c0212c043cc0402c0402c02268043cc04080044a002008f301002", + "0x9e26c2c12c090109e010f30109a011270089b010f30101a0103a0082c010f3", + "0xb0240d3cc040580417002058043cc040340477402034043cc040080422802", + "0x5f00813010f3010040104600812010f30100b0102c008023cc040240417402", + "0x411802060043cc04008fa008023cc04068040a8020680f034f3010130480d", + "0x202c043cc04009de0081b0640d0101b010f3010180110600819010f30100f", + "0x4008160d00203c043cc0403c040c80203c043cc04008a0008023cc0400804", + "0x2064043cc040340478002008f3010020240206013035df0481a034f30340f", + "0x23cc04008090081d011e207c1b034f303419011e10081a010f30101a0100b", + "0x2228043cc040800479002218043cc0406c0411402080043cc0407c0478c02", + "0x43cc0408c047980208c043cc04008fa008023cc04008090080279404008f9", + "0x9010f3010860112d0088a010f301095011e400886010f30101d0104500895", + "0x97010f30348a0111d00809010f30100902c0d79c02024043cc04024044b802", + "0xb0083a010f301097011e9008023cc04008e3008023cc040080900827011e8", + "0x41180226c043cc040e804068020b0043cc040480403c0212c043cc0406804", + "0x43cc0d26804124022682a0a0163cc042789b0b04b025ea0089e010f301016", + "0xf3010a00102a008a02880d3cc040bc042c002008f3010020240227c047ac2f", + "0x39010f3010090112e00837010f30102a0100f008a3010f3010280100b00802", + "0xa101049008a10d032058f3010a40e43728c094bc02290043cc042880411802", + "0x40a8022a03f034f30103c010b0008023cc0400809008a5011ec0f0043cc0d", + "0x40fc04118022ac043cc040d00403c02104043cc040c80402c02008f3010a8", + "0xb00845010f3010a501173008023cc0400809008027b404008f9008b1010f3", + "0x4605804124043cc04114044c80211c043cc040d00403c02118043cc040c804", + "0xb008b0010f30109f01173008023cc04024047b802008f3010020240212447", + "0x62058041c4043cc042c0044c802138043cc040a80403c02188043cc040a004", + "0x9011ee008023cc0409c040a802008f30100238c02008f301002024021c44e", + "0xf30101601046008ab010f3010120100f00841010f30101a0100b008023cc04", + "0x43cc042e0044c4022e0043cc04140b10353000850010f3010023e8022c404", + "0xb9010f30106d0113200855010f3010ab0100f00853010f3010410100b0086d", + "0x2008f30100b011ef008023cc04008e3008023cc0400809008b91545305804", + "0xf3010021b402160043cc040089a008023cc04034047b802008f3010160104e", + "0x43cc040089e0085b010f3010591600d26c02164043cc04164040b00216404", + "0x43cc0404c0402c0217c043cc04174045cc02174043cc0416c5c0342f0085c", + "0x47c0022ec612e816010bb010f30105f0113200861010f3010180100f008ba", + "0x40740204c043cc040480407c02048043cc040680406c020680f034f30100f", + "0x406c040740206c043cc04009f1008023cc04060040800206418034f301013", + "0xf30101d0108a00820010f3010190108a008023cc0407c04080020741f034f3", + "0xf30100202402009f2008f3034860800d25402080043cc040800408c0221804", + "0x23e802008f30100901039008023cc0403c0414c02008f30100b0105d00802", + "0x4010042e402254043cc040080402c0208c043cc04228047cc02228043cc04", + "0xf301023010730083a010f3010160103a00827010f30100d0100f00897010f3", + "0x403c020a8043cc040240468402008f30100202402009f4010023e4020a004", + "0x9b059a30082f010f30102a011a20089e010f3010160103a0089b010f30100d", + "0x23cc0400809008a2011f527c043cc0d0b004164020b04b268163cc040bc9e", + "0x34010f3010320101b0083203c0d3cc0403c047c002280043cc0427c0416c02", + "0x23008a4010f3010340100000839010f3010020100b008a1010f30100221802", + "0xa5010f303437011f60083728c0d3cc040f0a40e416470020f0043cc0428404", + "0x41010f3010a8010fd008a8010f3010a5011f8008023cc04008090083f011f7", + "0xb00845010f3010027e4022c4043cc0403c0406c022ac043cc04104043f802", + "0x1647002188043cc041140408c022c0043cc042c40400002124043cc0428c04", + "0x1fa138043cc0d11c047d8022ac043cc042ac040b00211c46034f3010622c049", + "0x22e0043cc04140043f402140043cc04138047e002008f301002024021c404", + "0x2c00859010f301004010b900858010f3010460100b0086d010f3010b8010fe", + "0x40b002174043cc042ac040b002170043cc04280040b00216c043cc0402c04", + "0x414c0402c022e45514c163cc0417c5d1705b1645803dfb0085f010f30106d", + "0xf30104b0103a00827010f30109a0100f00897010f301055010b900895010f3", + "0x43cc042e804668022e8043cc040a004664020a0043cc042e4041cc020e804", + "0x64010f3010270100f008be010f301097010b9008bb010f3010950100b00861", + "0x9008662f4642f8bb02c04198043cc041840466c022f4043cc040e8040e802", + "0x23cc0402c0417402008f3010a00105d008023cc042ac0417402008f301002", + "0x2310043cc04010042e402378043cc041180402c022fc043cc041c40467002", + "0xb010c8010f3010bf0119b0086c010f30104b0103a008c6010f30109a0100f", + "0x23cc042800417402008f30100f01053008023cc0400809008c81b0c6310de", + "0xb900870010f3010a30100b008ca010f30103f0119c008023cc0402c0417402", + "0x466c02334043cc0412c040e8021cc043cc042680403c0232c043cc0401004", + "0x23cc0403c0414c02008f3010020240233ccd1cccb1c00b010cf010f3010ca", + "0xb9008d1010f3010020100b008ce010f3010a20119c008023cc0402c0417402", + "0x466c0235c043cc0412c040e8021dc043cc042680403c023e0043cc0401004", + "0xb010f30100228002008f30100238c0237cd71dcf83440b010df010f3010ce", + "0x9008130480d7f01a03c0d3cc0d02c04008160d00202c043cc0402c040c802", + "0x180110c0080f010f30100f0100b008180240d3cc04024046ec02008f301002", + "0xf301016011fe008023cc040240417402008f30100202402064047f4023cc0d", + "0xf30100f0100b0081d010f30101f0118b0081f010f30101b0340d6280206c04", + "0x90088a2182005804228043cc040740463002218043cc040680403c0208004", + "0xf3010970106100897010f30100d0101a008023cc04064043d402008f301002", + "0x270580d26c02008f301002024020e8047fc27010f303495010bb0089508c0d", + "0x403c0402c02268043cc040a8090350b0082a010f301002454020a0043cc04", + "0xf301028010460089f010f3010230101a0082f010f30101a0100f0089e010f3", + "0x226c2c12c163cc04280a227c2f2780b62002280043cc04268040b00228804", + "0xa32840d3cc040c80419802008f301002024020d00480032010f30349b010bd", + "0xa4010f30104b0100b00839010f3010370118b00837010f3010a32840d62802", + "0x400809008a50f0a405804294043cc040e404630020f0043cc040b00403c02", + "0x43cc040b00403c022a0043cc0412c0402c020fc043cc040d00463402008f3", + "0x40240417402008f301002024022ac412a016010ab010f30103f0118c00841", + "0x43cc042c4230358a008b1010f30103a0118e008023cc040580413802008f3", + "0x49010f30101a0100f00847010f30100f0100b00846010f3010450118b00845", + "0xf3010090105d008023cc0400809008b012447058042c0043cc041180463002", + "0x21b402188043cc040089a008023cc040340414c02008f3010160104e00802", + "0x40089e00871010f30104e1880d26c02138043cc04138040b002138043cc04", + "0x40480402c021b4043cc042e004634022e0043cc041c4500342f00850010f3", + "0x22e45514c16010b9010f30106d0118c00855010f3010130100f00853010f3", + "0x2068043cc0403c120350b0081202c0d3cc0402c046ec0203c043cc0400a01", + "0x5d008023cc04008090081301202008f30341a0110c0081a010f30101a0102c", + "0xf3010180120300818010f3010023e802008f30100901195008023cc0402c04", + "0x43cc040080402c0207c043cc0406c046680206c043cc04064046640206404", + "0x8a010f3010160103a00886010f30100d010c600820010f3010040100f0081d", + "0x13010f5008023cc040080900823228860801d02c0408c043cc0407c0466c02", + "0xf3010040100f0089a010f3010020100b00895010f30100901204008023cc04", + "0x43cc04254048140226c043cc04058040e8020b0043cc04034043180212c04", + "0x280e82725c0b3cc040bc9e26c2c12c9a03e060082f010f30100b0102c0089e", + "0x43cc0427c0432802008f301002024022880481c9f010f30342a010c80082a", + "0xa1010f3010970100b00834010f3010320119a00832010f3010a001199008a0", + "0x20e4043cc040a0040e8020dc043cc040e8043180228c043cc0409c0403c02", + "0x42880467002008f30100202402290390dca32840b010a4010f3010340119b", + "0xf30103a010c60083f010f3010270100f008a5010f3010970100b0083c010f3", + "0xab104a80fca502c042ac043cc040f00466c02104043cc040a0040e8022a004", + "0x221802024043cc040580482402058043cc0400a08008023cc04034046d802", + "0x40080946802024043cc04024048280202c043cc0402c0408c0202c043cc04", + "0xf3010120120c008023cc0400809008190601305a0b0481a03c163cc0d0240b", + "0x43cc0406c0483402074043cc04068040e80207c043cc0403c0403c0206c04", + "0x130100f00886010f3010190120f008023cc04008090080283804008f900820", + "0x40800484002080043cc042180483402074043cc04060040e80207c043cc04", + "0x20240225c0484895010f30348a010590088a010f3010230121100823010f3", + "0xf30103a0117e0083a010f3010270117d00827010f3010950105b008023cc04", + "0x43cc040a0045ec02268043cc04074040e8020a8043cc0407c0403c020a004", + "0x407c0403c020b0043cc0425c045e802008f3010020240212c9a0a8160104b", + "0x20bc9e26c160102f010f30102c0117b0089e010f30101d0103a0089b010f3", + "0x16034163cc0403c0b034f60080f010f3010040103a0080b010f3010020100f", + "0x43cc040680442002008f301002024020480484c1a010f3034090110700809", + "0x163cc040741f036140081d010f3010160103a0081f010f30100d0100f00813", + "0x40800442002008f301002024022180485420010f30341b011070081b06418", + "0xf30101301216008023cc0408c0444c0225423034f30108a012160088a010f3", + "0x43cc040e804424020e8043cc042540485c02008f301097011130082725c0d", + "0x4b010f30102701217008023cc040a804174022682a034f3010280105c00828", + "0x2008f30109b0105d0089e26c0d3cc040b004170020b0043cc0412c0442402", + "0x2288043cc0427c2f0350b0089f010f30109e010fe0082f010f30109a010fe", + "0xfa008023cc0400809008a001218008f3034a20110c008a2010f3010a20102c", + "0x180100f008a1010f3010340121a00834010f3010320121900832010f301002", + "0x390dca3058040e4043cc042840486c020dc043cc04064040e80228c043cc04", + "0xf30100287002290043cc040089a008023cc04280043d402008f30100202402", + "0x43cc040089e008a5010f30103c2900d26c020f0043cc040f0040b0020f004", + "0x43cc040600403c02104043cc042a004874022a0043cc042943f0342f0083f", + "0x202402114b12ac1601045010f3010410121b008b1010f3010190103a008ab", + "0x43cc040600403c02118043cc042180487402008f30101301113008023cc04", + "0x2024022c04911c16010b0010f3010460121b00849010f3010190103a00847", + "0xf3010160103a0084e010f30100d0100f00862010f3010120121d008023cc04", + "0x21e0080b010f301016011ac008501c44e05804140043cc041880486c021c404", + "0x40240487c02068043cc040089a0080f010f30100226802024043cc0402c04", + "0xf30100f010460081f010f30101301220008023cc04048044640204c12034f3", + "0x40a80206c19060163cc040801d07c1688402080043cc04068041180207404", + "0x4228041c402008f3010860104e0088a2180d3cc040600418802008f30101b", + "0xf30109701071008023cc04254041380225c95034f3010190106200823010f3", + "0x2708c04008098880209c043cc0409c040680208c043cc0408c040680209c04", + "0x2240082c010f3010023e802008f3010020240212c9a0a81688c280e80d3cc0d", + "0x4894020bc043cc040a0040e802278043cc040e80403c0226c043cc040b004", + "0xa2010f30104b01227008023cc04008090080289804008f90089f010f30109b", + "0x227c043cc0428804894020bc043cc04268040e802278043cc040a80403c02", + "0x48a434010f3034a0011a6008a0010f3010320111800832010f30109f01228", + "0x20dc043cc0428c0d035b2008a3010f3010340122a008023cc0400809008a1", + "0x1b40083c010f30102f0103a008a4010f30109e0100f00839010f301037011b3", + "0x2008f30100d01039008023cc0400809008a50f0a405804294043cc040e404", + "0x1b400841010f30102f0103a008a8010f30109e0100f0083f010f3010a1011b5", + "0xf3010020100f00809010f30100d011a1008ab104a8058042ac043cc040fc04", + "0xd3cc04058046ec02060043cc04024046880204c043cc04010040e80204804", + "0x22c0081a03c0b058f30101906013048098ac02064043cc04064040b00206416", + "0x20801d034f30101b0122e008023cc04008090081f0122d06c043cc0d06804", + "0x403c02228043cc040740428c02218043cc04058048bc02008f3010200102a", + "0x860123000828010f30108a010a40083a010f30100f0103a00827010f30100b", + "0x9a010f303497010f80089725423058f30102a0a03a09c098c4020a8043cc04", + "0x23cc0426c040a80226c2c034f30109a011af008023cc04008090084b01232", + "0x227c043cc040bc046cc020bc043cc042782c035b20089e010f3010023e802", + "0x1601032010f30109f011b4008a0010f3010950103a008a2010f3010230100f", + "0xa1010f3010230100f00834010f30104b011b5008023cc040080900832280a2", + "0x4008090083728ca1058040dc043cc040d0046d00228c043cc04254040e802", + "0xa4010f30100b0100f00839010f30101f011b5008023cc040580417402008f3", + "0x400992008a50f0a405804294043cc040e4046d0020f0043cc0403c040e802", + "0x43cc040080402c02048043cc0400a330081a010f30100f011930080f010f3", + "0x8a010f3010160103a00886010f30100d010c600820010f3010040100f0081d", + "0x9508c8a218200740f8d002254043cc04048040b00208c043cc040680465802", + "0x23cc0400809008270123625c043cc0d07c048d40207c1b0641804c0b3cc04", + "0xa40084b010f30101b0103a0089a010f3010180100f008023cc0425c048dc02", + "0x3a058f30109b0b04b268096c00226c043cc0402c040b0020b0043cc0402404", + "0xf30109e011af008023cc04008090082f01238278043cc0d0a8043e0020a828", + "0x43cc042809f035b2008a0010f3010023e802008f3010a20102a008a227c0d", + "0xa3010f30103a0100f008a1010f3010130100b00834010f301032011b300832", + "0x4290043cc040d0046d0020e4043cc040a0040e8020dc043cc040640431802", + "0x404c0402c020f0043cc040bc046d402008f30100202402290390dca32840b", + "0xf3010280103a008a8010f301019010c60083f010f30103a0100f008a5010f3", + "0x5d008023cc0400809008ab104a80fca502c042ac043cc040f0046d00210404", + "0x404c0402c022c4043cc0409c046d402008f30100901039008023cc0402c04", + "0xf30101b0103a00847010f301019010c600846010f3010180100f00845010f3", + "0x2024043cc04008ba008b0124471184502c042c0043cc042c4046d00212404", + "0x43cc040080402c02008f30100238c02008f3010020100203c043cc0400a39", + "0xd04c048ec0204c12068163cc04064180363a00819010f30100d0101a00818", + "0x40800418402080043cc040480406802008f3010020240206c048f00b010f3", + "0x2218048f816010f30341d010bb0080b010f30100b03c0d8f4020741f034f3", + "0x1f0101a00827010f3010040100f00897010f30101a0100b008023cc0400809", + "0x9508c8a058f30103a09c970586400816010f3010160240d2f8020e8043cc04", + "0x9a034f30102801066008023cc04008090082a0123f0a0043cc0d254042f402", + "0x40b01602c1690402008f3010020240226c049002c010f30344b010bf0084b", + "0x427c049100227c043cc040bc9a036430082f010f30109e012420089e010f3", + "0xf3010a20124500832010f3010230100f008a0010f30108a0100b008a2010f3", + "0x40580417402008f30100b01113008023cc0400809008340c8a0058040d004", + "0xf3010a301244008a3010f3010a12680d90c02284043cc0426c0491802008f3", + "0x43cc040dc0491402290043cc0408c0403c020e4043cc042280402c020dc04", + "0xf30100b01113008023cc040580417402008f301002024020f0a40e4160103c", + "0xa8010f3010230100f0083f010f30108a0100b008a5010f30102a0124700802", + "0xf30100b01113008023cc0400809008412a03f05804104043cc042940491402", + "0xb1010f3010ab07c0d90c022ac043cc042180491802008f301009010c400802", + "0x211c043cc040100403c02118043cc040680402c02114043cc042c40491002", + "0x23cc040240431002008f30100202402124471181601049010f30104501245", + "0x2188043cc042c01203643008b0010f30101b01246008023cc0403c0492002", + "0x24500850010f3010040100f00871010f30101a0100b0084e010f30106201244", + "0xb05a4a02416034163cc0d0100203649008b814071058042e0043cc0413804", + "0x204c043cc040340403c02048043cc040240492c02008f301002024020680f", + "0x4008090080293404008f900819010f3010120124c00818010f3010160103a", + "0x43cc0403c040e80204c043cc0402c0403c0206c043cc040680493802008f3", + "0x1f010f30101d012500081d010f3010190124f00819010f30101b0124c00818", + "0x8a010f301020011c9008023cc04008090088601251080043cc0d07c0471c02", + "0x225c043cc0404c0403c02254043cc0408c0494c0208c043cc042280494802", + "0xf301002024020e82725c160103a010f3010950125400827010f3010180103a", + "0x9a010f3010180103a0082a010f3010130100f00828010f3010860125500802", + "0x402c040c80202c043cc04008a00084b2682a0580412c043cc040a00495002", + "0x2008f3010020240204c12036560680f034f30340b01002058340080b010f3", + "0x23cc04008090081b0125806418034f303416012570080f010f30100f0100b", + "0x2080043cc04060040f002074043cc0407c049080207c043cc040640496402", + "0x43cc04008fa008023cc04008090080296c04008f900886010f30101d0125a", + "0x86010f3010230125a00820010f30101b0103c00823010f30108a012460088a", + "0x2a010f30101a0100f008023cc0400809008970125c254043cc0d2180470802", + "0x163cc0412c9a0a8169780212c043cc042540497402268043cc04034040e802", + "0xf30100238c02008f3010020240226c049802c010f3034280125f008280e827", + "0x43cc0403c0402c020bc043cc0427809036620089e010f30102c0126100802", + "0x37010f3010200103c008a3010f30103a0103a008a1010f3010270100f00834", + "0x1da00832280a227c093cc040e43728ca10d00b764020e4043cc040bc0476002", + "0xa80fca5058f3010a4011dc008023cc04008090083c01263290043cc0d0c804", + "0x43cc0427c0402c022ac043cc041040499402104043cc042a03f2941699002", + "0x47010f3010ab0126600846010f3010a00103a00845010f3010a20100f008b1", + "0x427c0402c02124043cc040f00499c02008f3010020240211c46114b102404", + "0xf301049012660084e010f3010a00103a00862010f3010a20100f008b0010f3", + "0x40800409c02008f30100238c02008f301002024021c44e188b0024041c404", + "0xb8010f30100f0100b00850010f30109b01267008023cc04024042c402008f3", + "0x4154043cc04140049980214c043cc040e8040e8021b4043cc0409c0403c02", + "0x2008f3010970102a008023cc04008e3008023cc04008090085514c6d2e009", + "0x2164043cc041600499402160043cc042e40908016990022e4043cc04008fa", + "0x2660085d010f30100d0103a0085c010f30101a0100f0085b010f30100f0100b", + "0x2008f30100238c02008f3010020240217c5d1705b0240417c043cc0416404", + "0xf3010021b4022e8043cc040089a008023cc04024042c402008f30101601027", + "0x43cc040089e008bb010f3010612e80d26c02184043cc04184040b00218404", + "0x43cc040480402c022f4043cc041900499c02190043cc042ecbe0342f008be", + "0xc4010f3010bd01266008de010f30100d0103a008bf010f3010130100f00866", + "0x901268008090340d3cc04034047c002008f30100238c02310de2fc6602404", + "0x40680407402068043cc0403c0407c0203c043cc0402c0406c0202c043cc04", + "0xf301016010460081b010f30101301023008023cc04048040800204c12034f3", + "0xf30100d01268008023cc04064040a80206418034f30101f06c0d4b00207c04", + "0x43cc040740406802254043cc040100403c0208c043cc040080402c0207404", + "0x41240222886080163cc0409c97254230266900827010f3010180104600897", + "0x1300089a0a80d3cc040e8042c002008f301002024020a0049a83a010f30348a", + "0xf0089b010f3010200100b0082c010f30104b011310084b010f30109a0a80d", + "0x23cc04008090082f2789b058040bc043cc040b0044c802278043cc0421804", + "0x2280043cc042180403c02288043cc040800402c0227c043cc040a0045cc02", + "0x49b0090580d3cc0d03404008169ac020c8a02881601032010f30109f01132", + "0xb0081a010f30100f0126e0080f010f3010090126d008023cc04008090080b", + "0x2008f3010020240204c120340404c043cc04068049bc02048043cc0405804", + "0x180349b00819010f3010190102c00819010f3010029c002060043cc040089a", + "0x1d012710081d010f30101b07c0d0bc0207c043cc040089e0081b010f301019", + "0x22288603404228043cc04080049bc02218043cc0402c0402c02080043cc04", + "0x2008f30100202402068049c8023cc0d03c044300203c0b034f30100b011bb", + "0x40580417402008f3010090105d008023cc040340417402008f30100b0105d", + "0x18010f3010020100b00813010f301012011f300812010f3010023e802008f3", + "0x4008090081b064180580406c043cc0404c041cc02064043cc04010042e402", + "0x2002c0d3cc0402c046ec0207c043cc0400a73008023cc04068043d402008f3", + "0x274008f30341d0110c0081d010f30101d0102c0081d010f30101f0800d42c02", + "0x417402008f30100d0105d008023cc0402c0417402008f3010020240221804", + "0x43cc04228047cc02228043cc04008fa008023cc040580417402008f301009", + "0x27010f3010230107300897010f301004010b900895010f3010020100b00823", + "0x3a010f3010029cc02008f301086010f5008023cc04008090082725c9505804", + "0x43cc040a0040b0020a0043cc040e82a0350b0082a0240d3cc04024046ec02", + "0x2008f30100b0105d008023cc04008090089a01275008f3034280110c00828", + "0xf3010023e802008f3010160105d008023cc040240417402008f30100d0105d", + "0x43cc04010042e40226c043cc040080402c020b0043cc0412c047cc0212c04", + "0x4268043d402008f301002024020bc9e26c160102f010f30102c010730089e", + "0xa201278008023cc0400809008a0012772889f034f3034160080d9d802008f3", + "0x9f03676008340240d3cc04024046ec020c8043cc04288049e402288043cc04", + "0x279008a3010f3010a301278008023cc0400809008370127a28ca1034f303434", + "0x4290040b0020f0043cc0400a7c008a4010f3010029ec020e4043cc0428c04", + "0xd0f0a40367d008a1010f3010a10100b0083c010f30103c0102c008a4010f3", + "0xf3010a501279008a5010f3010a501278008023cc0400809008029f8a5010f3", + "0x43cc0402c040b0022c4043cc040e4049fc022ac043cc04010042e4020fc04", + "0x20240211804a08023cc0d10404a0402104a8034f3010452c4ab05a8000845", + "0x2008f30100d0105d008023cc040240417402008f30103201283008023cc04", + "0xa10100b00849010f301047011f300847010f3010023e802008f30103f01283", + "0x4e188b005804138043cc04124041cc02188043cc042a0042e4022c0043cc04", + "0x42e402008f3010500105d008501c40d3cc041180448802008f30100202402", + "0x5305a80008b9010f30100d0102c00855010f30103f0127f00853010f3010a8", + "0x2c0085c010f3010320127f0085b010f3010b8010b90086d2e00d3cc042e455", + "0x6d034f30106d01284008591600d3cc041745c16c16a0002174043cc0402404", + "0x43cc04184049fc0218459034f30105901284008ba010f3010ba0127f008ba", + "0xf301002024022ec04a18023cc0d17c04a040217c043cc04184ba0368500861", + "0x417402190be034f3010bb01122008023cc040080900802a1c04008f900802", + "0x40b0022f4043cc04198be0350b008661c40d3cc041c4046ec02008f301064", + "0x710105d008023cc0400809008bf01288008f3034bd0110c008bd010f3010bd", + "0x2378043cc04008fa008023cc041b404a0c02008f30105901283008023cc04", + "0x730086c010f301058010b9008c6010f3010a10100b008c4010f3010de01203", + "0x2008f3010bf010f5008023cc0400809008c81b0c605804320043cc0431004", + "0x2328043cc0432c7003689008cb010f3010590127f00870010f30106d0127f", + "0x23e402008f3010710105d008023cc0400809008730128a008f3034ca01281", + "0x23cc0433c041740233ccd034f30107301122008023cc040080900802a2c04", + "0x28c008f3034ce0110c008ce010f3010ce0102c008ce010f3010713340d42c02", + "0xb00877010f3010f801203008f8010f3010023e802008f3010020240234404", + "0xd7058041e8043cc041dc041cc0237c043cc04160042e40235c043cc0428404", + "0x47cc0238c043cc04008fa008023cc04344043d402008f301002024021e8df", + "0xe60107300800010f301058010b9008e9010f3010a10100b008e6010f3010e3", + "0x417402008f30103201283008023cc0400809008f7000e9058043dc043cc04", + "0x23cc040e404a0c02008f30100b0105d008023cc040340417402008f301009", + "0xb9008fb010f3010a10100b008fa010f3010f9011f3008f9010f3010023e802", + "0x23cc0400809008fd3f0fb058043f4043cc043e8041cc023f0043cc0401004", + "0xd0105d008023cc040240417402008f30103201283008023cc0402c0417402", + "0x43cc040dc0402c023fc043cc043f8047cc023f8043cc04008fa008023cc04", + "0x202402409014001601102010f3010ff0107300901010f301004010b900900", + "0x2008f3010090105d008023cc040340417402008f30100b0105d008023cc04", + "0x42e402414043cc042800402c02410043cc0440c047cc0240c043cc04008fa", + "0x43cc040080402c023d90641416010f6010f3011040107300906010f301004", + "0x1b010f30100b0102c00819010f3010090120500818010f30100d010c600813", + "0x40100403c0207c043cc0400886008120680f058f30101b0641804c09a3402", + "0xf3010120128e00895010f30101f0102300823010f3010160103a0088a010f3", + "0x2910083a010f30108601290008860801d058f3010972542322809a3c0225c04", + "0xca008023cc04008090082a012920a0043cc0d09c043200209c043cc040e804", + "0x402c020b0043cc0412c046680212c043cc042680466402268043cc040a004", + "0x200103a0082f010f30101a010c60089e010f30101d0100f0089b010f30100f", + "0x23cc0400809008a227c2f2789b02c04288043cc040b00466c0227c043cc04", + "0x20d0043cc040740403c020c8043cc0403c0402c02280043cc040a80467002", + "0xb01037010f3010a00119b008a3010f3010200103a008a1010f30101a010c6", + "0x45f402008f3010020240203404a5004010f303402012930083728ca10d032", + "0x202c040100b010f3010090117b00809010f3010160117e00816010f301004", + "0x1a0117a0081a010f30100d03c0d0bc0203c043cc040089e008023cc0400809", + "0x3a0080b010f3010020100f008130100404c043cc04048045ec02048043cc04", + "0x1a010f303409011c7008090580d058f30100f02c0d7180203c043cc0401004", + "0x18010f301013011ca00813010f30101a011c9008023cc04008090081201295", + "0xf30101b011cd008023cc0406404730020801d07c1b0640b3cc040600472c02", + "0x1cf00886010f30101d011ce008023cc040800417402008f30101f0111300802", + "0x474002254043cc04058040e80208c043cc040340403c02228043cc0421804", + "0x209c043cc040480474402008f3010020240225c9508c1601097010f30108a", + "0x160102a010f301027011d000828010f3010160103a0083a010f30100d0100f", + "0x4a5c02034040100d010f3010040122000804010f301002012960082a0a03a", + "0xb0102c0080b010f301002a6402008f3010020240202404a6016010f303402", + "0xf0104600818010f301016012300080f010f30100b0100d26c0202c043cc04", + "0x204c12068163cc0406c1906016a680206c043cc040340411802064043cc04", + "0x23e402074043cc04048041180207c043cc040680411802008f3010130102a", + "0x2080043cc04080040b002080043cc0400a9c008023cc040080900802a6c04", + "0x209c043cc04218041180225c043cc04024046b002218043cc04080040349b", + "0xf3010950102a0089508c8a058f30103a09c9705a9d0083a010f30100d01046", + "0x20a0043cc04008fa0081d010f301023010460081f010f30108a0104600802", + "0x160104b010f301028011060089a010f30101d0129e0082a010f30101f0129e", + "0x40100486402008f3010020240203404a8004010f3034020129f0084b2682a", + "0x20240202c040100b010f3010090121b00809010f3010160121a00816010f3", + "0xf30101a0121d0081a010f30100d03c0d0bc0203c043cc040089e008023cc04", + "0x46d80202c09034f30100d011a9008130100404c043cc040480486c0204804", + "0x43cc04008860081a010f30100f012090080f010f30100282002008f30100b", + "0x16068120100202ea10081a010f30101a0120a00812010f3010120102300812", + "0x2240081d010f3010023e802008f3010020240207c1b06416a881804c0d3cc0d", + "0x489402228043cc04060040e802218043cc0404c0403c02080043cc0407404", + "0x95010f30101f01227008023cc040080900802a8c04008f900823010f301020", + "0x208c043cc042540489402228043cc0406c040e802218043cc040640403c02", + "0x4a903a010f303497011a600897010f3010270111800827010f30102301228", + "0x2268043cc040a809036a50082a010f30103a0122a008023cc040080900828", + "0x2a70089b010f30108a0103a0082c010f3010860100f0084b010f30109a012a6", + "0x2008f301009011b6008023cc04008090089e26c2c05804278043cc0412c04", + "0x2a7008a2010f30108a0103a0089f010f3010860100f0082f010f301028012a8", + "0xf30100b012a90080b010f30101601230008a02889f05804280043cc040bc04", + "0x130480d3cc040240487c02068043cc040089a0080f010f3010022680202404", + "0x460081d010f30100f010460081f010f30101301220008023cc040480446402", + "0x23cc0406c040a80206c19060163cc040801d07c1688402080043cc0406804", + "0x208c043cc04228041c402008f3010860104e0088a2180d3cc040600418802", + "0x1a00827010f30109701071008023cc04254041380225c95034f30101901062", + "0x3a034f30342708c04008098880209c043cc0409c040680208c043cc0408c04", + "0xf30102c012240082c010f3010023e802008f3010020240212c9a0a816aa828", + "0x43cc0426c04894020bc043cc040a0040e802278043cc040e80403c0226c04", + "0x2a0100f008a2010f30104b01227008023cc040080900802aac04008f90089f", + "0x427c048a00227c043cc0428804894020bc043cc04268040e802278043cc04", + "0x20240228404ab034010f3034a0011a6008a0010f3010320111800832010f3", + "0x40dc046cc020dc043cc0428c0d035b2008a3010f3010340122a008023cc04", + "0xf301039011b40083c010f30102f0103a008a4010f30109e0100f00839010f3", + "0x4284046d402008f30100d01039008023cc0400809008a50f0a40580429404", + "0xf30103f011b400841010f30102f0103a008a8010f30109e0100f0083f010f3", + "0x481002068043cc0403c0480c0203c043cc04008fa008ab104a8058042ac04", + "0xd010c600820010f3010040100f0081d010f3010020100b00812010f301009", + "0x402c040b00208c043cc040480481402228043cc04058040e802218043cc04", + "0x1302cf30109725423228860801d06aad00897010f30101a0107300895010f3", + "0x27012b0008023cc04008090083a012af09c043cc0d07c04ab80207c1b06418", + "0xf3010023e802268043cc040a00464c02008f30102a0102a0082a0a00d3cc04", + "0xf3010130100b0089b010f30102c012b20082c010f30104b2680dac40212c04", + "0x43cc0406c040e80227c043cc0406404318020bc043cc040600403c0227804", + "0x4ad002008f30100202402280a227c2f2780b010a0010f30109b012b3008a2", + "0x19010c6008a1010f3010180100f00834010f3010130100b00832010f30103a", + "0xa32843402c040e4043cc040c804acc020dc043cc0406c040e80228c043cc04", + "0xf303416010bb008160340d3cc040240418402024043cc0401004068020e437", + "0x204c04adc120680d3cc0d02c02036b6008023cc04008090080f012b502c04", + "0xd0101a00819010f30101a0100b00818010f301012012b8008023cc0400809", + "0xfa008023cc04008090081f06c190580407c043cc0406004ae40206c043cc04", + "0xd0101a00886010f3010130100b00820010f30101d012ba0081d010f301002", + "0x2ba008023cc040080900823228860580408c043cc0408004ae402228043cc04", + "0x4ae40209c043cc04034040680225c043cc040080402c02254043cc0403c04", + "0x4008090080d012bc010043cc0d00804aec020e82725c160103a010f301095", + "0x43cc040240495002024043cc040580494c02058043cc040100494802008f3", + "0x43cc040340f0342f0080f010f30100227802008f3010020240202c040100b", + "0x403404af40204c0401013010f3010120125400812010f30101a012550081a", + "0x1a01071008023cc0403c04138020680f034f30100b010620080b02416058f3", + "0x1804c163cc0d04809058040080baf802048043cc040480406802048043cc04", + "0x404c0403c02080043cc040640449002008f301002024020741f06c16afc19", + "0x2b0404008f900823010f301020012c00088a010f3010180103a00886010f3", + "0x40e802218043cc0406c0403c02254043cc0407404b0802008f30100202402", + "0x27012c400827010f301023012c300823010f301095012c00088a010f30101f", + "0x3a01261008023cc040080900828012c50e8043cc0d25c0497c0225c043cc04", + "0x42180403c0212c043cc04268042e002268043cc040a804140020a8043cc04", + "0x22789b0b0160109e010f30104b010a20089b010f30108a0103a0082c010f3", + "0x8a0103a0089f010f3010860100f0082f010f3010280109f008023cc0400809", + "0x2024043cc04008a0008a02889f05804280043cc040bc0428802288043cc04", + "0x2024020481a036c603c0b034f303409010020583400809010f30100901032", + "0xf303413010e60080b010f30100b0100b00813010f30100d0101b008023cc04", + "0x4060040000207c043cc04064043a402008f3010020240206c04b1c190600d", + "0xfa008023cc040080900802b2004008f900820010f30101f010f70081d010f3", + "0x8a010f70081d010f30101b010000088a010f301086010fb00886010f301002", + "0xd080043f00208c043cc0408c040680208c043cc04074041c402080043cc04", + "0x43cc04254043f402008f30100238c02008f3010020240225c04b2495010f3", + "0xd3cc042682a0345f0089a010f301016010460082a010f3010270102c00827", + "0x2f010f30100f0100f0089e010f30100b0100b008023cc040a0040a8020a03a", + "0xf3010a227c2f278099a402288043cc040e8041180227c043cc0408c0406802", + "0xa0010b0008023cc040080900832012ca280043cc0d26c041240226c2c12c16", + "0x40b00403c0228c043cc0412c0402c02008f3010a10102a008a10d00d3cc04", + "0x173008023cc040080900802b2c04008f900839010f3010340104600837010f3", + "0x44c802294043cc040b00403c020f0043cc0412c0402c02290043cc040c804", + "0x40a802008f30100238c02008f301002024020fca50f0160103f010f3010a4", + "0xf30100f0100f008a3010f30100b0100b008023cc0408c0414c02008f301097", + "0x43cc042a03903530008a8010f3010023e8020e4043cc0405804118020dc04", + "0x45010f3010370100f008b1010f3010a30100b008ab010f3010410113100841", + "0x23cc04008e3008023cc040080900846114b105804118043cc042ac044c802", + "0x40086d00847010f30100226802008f3010160104e008023cc040340414c02", + "0xf301002278022c0043cc04124470349b00849010f3010490102c00849010f3", + "0xf30101a0100b00871010f30104e011730084e010f3010b01880d0bc0218804", + "0x2840086d2e050058041b4043cc041c4044c8022e0043cc040480403c0214004", + "0x5d008023cc040080900809012cc008f30341601281008160100d3cc0401004", + "0x4008f90080f010f3010040127f0080b010f301002010b9008023cc0403404", + "0x9b3c02068043cc0400ace008023cc0401004a0c02008f3010020240200acd", + "0x12010f301012010b900813010f301013012d0008130480d3cc040240d06802", + "0x2064043cc04060049e402008f3010020240200ad1060043cc0d04c0448c02", + "0x43cc0400ad3008023cc040080900802b4804008f90081b010f3010190127f", + "0xf010f30101b0127f0080b010f301012010b90081b010f30101f0127f0081f", + "0x400804a10020801d03404080043cc0403c04b5402074043cc0402c04b5002", + "0x400804a0c02008f3010020240205804b58023cc0d03404a040203402034f3", + "0xf30340401281008023cc04008090080901004024043cc04010049fc02008f3", + "0xf010f3010020127f008023cc0405804b6002008f3010020240202c04b5c02", + "0x2d90081a010f301002b3802008f30100201283008023cc04008090080f01004", + "0x204c043cc0402c12036d900812010f301012012d000812010f3010160680d", + "0x279008023cc040080900802b6818010f3034130112300813010f301013012d0", + "0xf3010020240200adb010023e40206c043cc04064049fc02064043cc0406004", + "0x4074043cc0406c04b540206c043cc0407c049fc0207c043cc0400ad300802", + "0x40080900816012dc008f30340d012810080d0100d3cc0401004a100207404", + "0xf301002024020240401009010f3010020127f008023cc0401004a0c02008f3", + "0x2068043cc04008049fc0202c043cc0401004b7402008f301016012d800802", + "0x404c043cc0403c04b540203c043cc040481a0368500812010f30100b0127f", + "0x2024043cc04024040b002024043cc0400adf008023cc0403404b780204c04", + "0xf30100f0080db840203c043cc0403c040b00203c0b034f3010160240405ae0", + "0xf3010120128e00818010f30100b010c600813010f30101a0100b008120680d", + "0x163cc0d0240d010020251a00809010f3010160120900819060130580406404", + "0x5d0081b0640d3cc040680417002008f301002024020601304816b881a03c0b", + "0x1d0105d008200740d3cc0407c041700207c043cc040090a008023cc0406404", + "0x4228041740208c8a034f3010860105c00886010f30101b010fe008023cc04", + "0xf3010970105d0082725c0d3cc042540417002254043cc04080043f802008f3", + "0x3a010f30103a0102c00828010f301027010fe0083a010f301023010fe00802", + "0xb010f30100b0100f0082a010f30102a0102c0082a010f3010280e80d42c02", + "0x2008f3010020240226804b8c023cc0d0a8044300203c043cc0403c040e802", + "0x23e40226c043cc040b0041cc020b0043cc0412c0480c0212c043cc04008fa", + "0x1f30089e010f3010023e802008f30109a010f5008023cc040080900802b9004", + "0x4b980227c043cc0426c04b940226c043cc040bc041cc020bc043cc0427804", + "0xa2012e700832010f30100f0103a008a0010f30100b0100f008a2010f30109f", + "0xf008a1010f301018012e8008023cc0400809008340c8a0058040d0043cc04", + "0xa3058040e4043cc0428404b9c020dc043cc0404c040e80228c043cc0404804", + "0xf30100401199008023cc04008090080d012ea010043cc0d00804ba4020e437", + "0x4008090080b0100402c043cc040240466c02024043cc04058046680205804", + "0x43cc040680467002068043cc040340f0342f0080f010f30100227802008f3", + "0x4058040b002058043cc04008044840204c0401013010f3010120119b00812", + "0xb0102a0080b0240d3cc040680f0345f0081a010f30100d010460080f010f3", + "0x43cc04024041180204c043cc040100411802048043cc04008fa008023cc04", + "0x40b002058043cc0400804bac020641804c1601019010f3010120110600818", + "0x2a0080b0240d3cc040680f0345f0081a010f30100d010460080f010f301016", + "0x4024041180204c043cc040100411802048043cc04008fa008023cc0402c04", + "0x2010043cc0400804bb0020641804c1601019010f3010120110600818010f3", + "0xf3010020100b008120680d3cc0402404bb402034040100d010f30100401220", + "0x43cc0402c040b002074043cc04048048140207c043cc04034043180206c04", + "0xf0117700886010f301002218020641804c163cc040801d07c1b0268d00820", + "0xf30100242802008f30108a0102a008023cc040080900823012ee228043cc0d", + "0x40a802008f3010020240200aef010023e40225c043cc04254040b00225404", + "0xf3010190120900897010f3010270102c00827010f30100245402008f301023", + "0x16bc02a0a00d3cc0d25c3a218160100ba8402218043cc042180408c020e804", + "0x2278043cc0426c048900226c043cc04008fa008023cc04008090082c12c9a", + "0xf9008a2010f30109e012250089f010f30102a0103a0082f010f3010280100f", + "0x43cc042680403c02280043cc040b00489c02008f3010020240200af101002", + "0x34010f3010a201228008a2010f3010a0012250089f010f30104b0103a0082f", + "0x23cc0400809008a3012f2284043cc0d0c804698020c8043cc040d00446002", + "0xa4010f301039012f400839010f3010370680dbcc020dc043cc04284048a802", + "0x20fc043cc040600431802294043cc040bc0403c020f0043cc0404c0402c02", + "0x202402104a80fca50f00b01041010f3010a4012f5008a8010f30109f0103a", + "0x43cc0404c0402c022ac043cc0428c04bd802008f30101a012de008023cc04", + "0x47010f30109f0103a00846010f301018010c600845010f30102f0100f008b1", + "0x4be004010f303402012f70084911c46114b102c04124043cc042ac04bd402", + "0xa200809010f301016010b800816010f30100401050008023cc04008090080d", + "0xd0bc0203c043cc040089e008023cc04008090080b0100402c043cc0402404", + "0x130100404c043cc040480428802048043cc040680427c02068043cc040340f", + "0x9e0340b068020589e0340b0081603404008950081603409068020580d02466", + "0x160340400895008162780d02c1a008162780d02d7b02416034040089500816", + "0x20589e0340bbe4090580d01002254020589e0340b068020589e0340b8f409", + "0x9500816034a302c1a00816034a302efa024160340400895008162780d02c1a", + "0x9bf0090580d01002254020580d28c0b068020580d28c0bbec090580d01002", + "0x2254020580d0241a0081603409bf41603404008950081603409068020580d", + "0x9068020580d026ff0580d01002254020580d0241a0081603409bf81603404", + "0x160340400895008162780d02c1a008162780d02f000580d01002254020580d", + "0x160681603416c08090580d01002254020580d28c0b068020580d28c0bc0409", + "0x9a00816034090603a008160340bc100206402034020130303404008860580d", + "0x20589e0340bc1816034040089b0580d0580b12c1603409c14090580d01002", + "0xd06804c20040081902c0d02c090370702416034040089f008162780d02c3a", + "0xb02c090e8020589e0341ac280d0100228416034160681603416c24022801a", + "0x228c160340b0243a008a30580d03f0b03c0b02416034040089f008162780d", + "0xb0243a008a30580d03f0d010020640b0340b0dc0dc300b0241603404008a4", + "0x9c3c0d0100227c02058160e80205816c380b0241603404008a4008a30580d", + "0x311034040089f008160583a0081605b100580d0100229402058160243a00816", + "0xa30580d02c090e80228c160340fc481603404008a500816058090e80205809", + "0x3140241603404008860580d058090601a0580d02f1302c090580d0100229402", + "0x180081603409c5804008b000816058020580dc5404008ab00816058020580d", + "0x1602c620580d02718010020640b0340b2280dc5c16034040089a0081603409", + "0xd01002290020589e0340b068090e8020589e0341ac6416034040089b0580d", + "0xa30580d03f1b0241603404008a10580d0580902c1a0580d02f1a03c0b02416", + "0x227c020581609c0205816c700b0241603404008a4008a30580d02c091c402", + "0xd0100229402058161b43a008160271e010022e00205816008160371d03404", + "0xd02c090e80228c160340fc801603404008a500816058090e80205809c7c16", + "0x160372203404008b90580d0581a0580d05b2102c090580d010022940228c16", + "0x3240241603404008bb00816034090a018008160340bc8c04008ba0081605802", + "0x32603404008bf0340d2280f03416c9416034040089b0580d0580b0681603409", + "0x91380228c160340fc9c0b0241603404008372780d05809024090249e0340f", + "0x20581600816037290089f010c60132802c090580d010022900228c160340b", + "0x432804cb00d010020640b02c1602c0b32016cac02320041b404ca804008ab", + "0x2058161b03a008160272e0580d0100232c020581602427008160272d008b8", + "0xb0241603404008cd008a30580d02c091c40228c160340fcbc1603404008a5", + "0x9500816058130081605b32008ba010d101331010023381a034160680d03730", + "0x772780d0247727816cd016034040089b0580d0580b0681603409ccc0d01002", + "0x9138a303409cdc0400877010771dc0dcd80400877010771dc0dcd40d01002", + "0xdf013390580d0100237c02058163788a00816027380580d01002378a303416", + "0x20640b02c1602c0b1b416cec0d010020640b02c1602c0b1b016ce80229004", + "0x4008e3008a30580d02c370244e008a30580d06b3d008c80106c0133c03404", + "0xcfc022540439804cf80f02c090580d" + ], + "contract_class_version": "0.1.0", + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "function_idx": 12, + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ], + "EXTERNAL": [ + { + "function_idx": 10, + "selector": "0xbc0eb87884ab91e330445c3584a50d7ddf4b568f02fbeb456a6242cce3f5d9" + }, + { + "function_idx": 5, + "selector": "0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283" + }, + { + "function_idx": 0, + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad" + }, + { + "function_idx": 1, + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775" + }, + { + "function_idx": 7, + "selector": "0x1a35984e05126dbecb7c3bb9929e7dd9106d460c59b1633739a5c733a5fb13b" + }, + { + "function_idx": 9, + "selector": "0x1a6c6a0bdec86cc645c91997d8eea83e87148659e3e61122f72361fd5e94079" + }, + { + "function_idx": 3, + "selector": "0x213dfe25e2ca309c4d615a09cfc95fdb2fc7dc73fbcad12c450fe93b1f2ff9e" + }, + { + "function_idx": 2, + "selector": "0x28420862938116cb3bbdbedee07451ccc54d4e9412dbef71142ad1980a30941" + }, + { + "function_idx": 4, + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3" + }, + { + "function_idx": 6, + "selector": "0x29e211664c0b63c79638fbea474206ca74016b3e9a3dc4f9ac300ffd8bdf2cd" + }, + { + "function_idx": 8, + "selector": "0x2e3e21ff5952b2531241e37999d9c4c8b3034cccc89a202a6bf019bdf5294f9" + }, + { + "function_idx": 11, + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895" + } + ], + "L1_HANDLER": [] + }, + "abi": "[{\"type\": \"constructor\", \"name\": \"constructor\", \"inputs\": []}, {\"type\": \"function\", \"name\": \"test\", \"inputs\": [{\"name\": \"arg\", \"type\": \"core::felt252\"}, {\"name\": \"arg1\", \"type\": \"core::felt252\"}, {\"name\": \"arg2\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_read\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_write\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}, {\"name\": \"value\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_get_execution_info\", \"inputs\": [{\"name\": \"block_number\", \"type\": \"core::felt252\"}, {\"name\": \"block_timestamp\", \"type\": \"core::felt252\"}, {\"name\": \"sequencer_address\", \"type\": \"core::felt252\"}, {\"name\": \"version\", \"type\": \"core::felt252\"}, {\"name\": \"account_address\", \"type\": \"core::felt252\"}, {\"name\": \"max_fee\", \"type\": \"core::felt252\"}, {\"name\": \"chain_id\", \"type\": \"core::felt252\"}, {\"name\": \"nonce\", \"type\": \"core::felt252\"}, {\"name\": \"caller_address\", \"type\": \"core::felt252\"}, {\"name\": \"contract_address\", \"type\": \"core::felt252\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_event\", \"inputs\": [{\"name\": \"keys\", \"type\": \"core::array::Array::\"}, {\"name\": \"data\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_send_message_to_l1\", \"inputs\": [{\"name\": \"to_address\", \"type\": \"core::felt252\"}, {\"name\": \"payload\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_simple_event\", \"inputs\": [{\"name\": \"argument\", \"type\": \"core::felt252\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\"}, {\"name\": \"another_argument\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_call_contract\", \"inputs\": [{\"name\": \"contract_address\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_library_call\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"assert_eq\", \"inputs\": [{\"name\": \"x\", \"type\": \"core::felt252\"}, {\"name\": \"y\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_segment_arena\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"enum\", \"name\": \"core::bool\", \"variants\": [{\"name\": \"False\", \"type\": \"()\"}, {\"name\": \"True\", \"type\": \"()\"}]}, {\"type\": \"function\", \"name\": \"test_deploy\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"contract_address_salt\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}, {\"name\": \"deploy_from_zero\", \"type\": \"core::bool\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_replace_class\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"struct\", \"members\": [{\"name\": \"argument\", \"type\": \"core::felt252\", \"kind\": \"data\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::Event\", \"kind\": \"enum\", \"variants\": [{\"name\": \"simple_event\", \"type\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"nested\"}]}]" +} \ No newline at end of file diff --git a/crates/mempool_test_utils/test_files/faulty_account.sierra.json b/crates/mempool_test_utils/test_files/faulty_account.sierra.json new file mode 100644 index 00000000000..e832b549efd --- /dev/null +++ b/crates/mempool_test_utils/test_files/faulty_account.sierra.json @@ -0,0 +1,1224 @@ +{ + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x4", + "0x3", + "0x1de", + "0x22", + "0x35", + "0x52616e6765436865636b", + "0x800000000000000100000000000000000000000000000000", + "0x426f78", + "0x800000000000000700000000000000000000000000000001", + "0x1", + "0xa", + "0x4172726179", + "0x800000000000000300000000000000000000000000000001", + "0x9", + "0x456e756d", + "0x800000000000000300000000000000000000000000000003", + "0x0", + "0xfeece2ea7edbbbebeeb5f270b77f64c680a68a089b794478dd9eca75e0196a", + "0x2", + "0x753634", + "0x800000000000000700000000000000000000000000000000", + "0x436f6e747261637441646472657373", + "0x537472756374", + "0x800000000000000700000000000000000000000000000004", + "0x3808c701a5d13e100ab11b6c02f91f752ecae7e420d21b56c90ec0a475cc7e5", + "0x4", + "0x5", + "0x6", + "0x1d", + "0x66656c74323532", + "0x800000000000000700000000000000000000000000000006", + "0x7d4d99e9ed8d285b5c61b493cedb63976bc3d9da867933d829f49ce838b5e7", + "0x7", + "0x8", + "0x800000000000000700000000000000000000000000000002", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x800000000000000f00000000000000000000000000000001", + "0x16a4c8d7c05909052238a862d8cc3e7975bf05a07b3a69c6b28951083a6d672", + "0xc", + "0x2ca39cde64b91db1514d78c135ee79d71b3b57fffee52f1a3ef96618a34d8c8", + "0xb", + "0xd", + "0x90d0203c41ad646d024845257a6eceb2f8b59b29ce7420dd518053d2edeedc", + "0x536e617073686f74", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0x10", + "0x161ee0e6962e56453b5d68e09d1cabe5633858c1ba3a7e73fee8c70867eced0", + "0x11", + "0x4e6f6e5a65726f", + "0x14", + "0x3ae40d407f8074730e48241717c3dd78b7128d346cf81094e31806a3a5bdf", + "0x15", + "0x1b", + "0x17", + "0x1597b831feeb60c71f259624b79cf66995ea4f7e383403583674ab9c33b9cec", + "0x18", + "0x75313238", + "0x3342418ef16b3e2799b906b1e4e89dbb9b111332dd44f72458ce44f9895b508", + "0x1a", + "0x753332", + "0x80000000000000070000000000000000000000000000000e", + "0x348a62b7a38c0673e61e888d83a3ac1bf334ee7361a8514593d3d9532ed8b39", + "0x19", + "0x1c", + "0xa36a0a15af8cf1727a3a4fd9137671f23256b1f42299af56605a6910c522ce", + "0x1e", + "0x800000000000000700000000000000000000000000000003", + "0x29d7d57c04a880978e7b3689f6218e507f3be17588744b58dc17762447ad0e7", + "0x20", + "0x29a02530bac70a6d5878fc0c5cb42f1926cd91d9162685c15f1be12819caf78", + "0x800000000000000f00000000000000000000000000000003", + "0x22", + "0xab150493414b66aee0a7b751a581ec565ab30639d18606b5bc9ef09ebaad6f", + "0x23", + "0x17b6ecc31946835b0d9d92c2dd7a9c14f29af0371571ae74a1b228828b2242", + "0x25", + "0x34f9bd7c6cb2dd4263175964ad75f1ff1461ddc332fbfb274e0fb2a5d7ab968", + "0x26", + "0x3d37ad6eafb32512d2dd95a2917f6bf14858de22c27a1114392429f2e5c15d7", + "0x556e696e697469616c697a6564", + "0x800000000000000200000000000000000000000000000001", + "0x3288d594b9a45d15bb2fcb7903f06cdb06b27f0ba88186ec4cfaa98307cb972", + "0x2d7b9ba5597ffc180f5bbd030da76b84ecf1e4f1311043a0a15295f29ccc1b0", + "0x2b", + "0x10203be321c62a7bd4c060d69539c1fbe065baa9e253c74d2cc48be163e259", + "0x2e", + "0x4275696c74696e436f737473", + "0x53797374656d", + "0x9931c641b913035ae674b400b61a51476d506bbe8bba2ff8a6272790aba9e6", + "0x2d", + "0x11c6d8087e00642489f92d2821ad6ebd6532ad1a3b6d12833da6d6810391511", + "0x4761734275696c74696e", + "0xc9", + "0x7265766f6b655f61705f747261636b696e67", + "0x77697468647261775f676173", + "0x6272616e63685f616c69676e", + "0x73746f72655f74656d70", + "0x66756e6374696f6e5f63616c6c", + "0x3", + "0x656e756d5f6d61746368", + "0x33", + "0x64726f70", + "0x7374727563745f6465636f6e737472756374", + "0x61727261795f6c656e", + "0x736e617073686f745f74616b65", + "0x7533325f636f6e7374", + "0x72656e616d65", + "0x7533325f6571", + "0x61727261795f6e6577", + "0x66656c743235325f636f6e7374", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x61727261795f617070656e64", + "0x7374727563745f636f6e737472756374", + "0x656e756d5f696e6974", + "0x32", + "0x34", + "0x31", + "0x6765745f6275696c74696e5f636f737473", + "0x30", + "0x77697468647261775f6761735f616c6c", + "0x2f", + "0x4f7574206f6620676173", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x2c", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x616c6c6f635f6c6f63616c", + "0x66696e616c697a655f6c6f63616c73", + "0x28", + "0x73746f72655f6c6f63616c", + "0x27", + "0x29", + "0x2a", + "0xe", + "0xf", + "0x24", + "0x61727261795f736e617073686f745f706f705f66726f6e74", + "0x21", + "0x6a756d70", + "0x756e626f78", + "0x1f", + "0x12", + "0x16", + "0x647570", + "0x66656c743235325f737562", + "0x66656c743235325f69735f7a65726f", + "0x56414c4944", + "0x13", + "0x494e56414c4944", + "0x496e76616c6964207363656e6172696f", + "0x21adb5788e32c84f69a1863d85ef9394b7bf761a0ce1190f826984e5075c371", + "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d", + "0x63616c6c5f636f6e74726163745f73797363616c6c", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x7536345f636f6e7374", + "0x6765745f626c6f636b5f686173685f73797363616c6c", + "0x7536345f746f5f66656c74323532", + "0x636f6e74726163745f616464726573735f746f5f66656c74323532", + "0x53455155454e4345525f4d49534d41544348", + "0x424c4f434b5f54494d455354414d505f4d49534d41544348", + "0x424c4f434b5f4e554d4245525f4d49534d41544348", + "0x556e6b6e6f776e207363656e6172696f", + "0x626f6f6c5f6e6f745f696d706c", + "0x64697361626c655f61705f747261636b696e67", + "0x73656e645f6d6573736167655f746f5f6c315f73797363616c6c", + "0x61727261795f676574", + "0x496e646578206f7574206f6620626f756e6473", + "0x6765745f657865637574696f6e5f696e666f5f76325f73797363616c6c", + "0x6fb", + "0xffffffffffffffff", + "0x61", + "0x52", + "0x45", + "0x3e", + "0x36", + "0x37", + "0x38", + "0x39", + "0x3a", + "0x3b", + "0x3c", + "0x3d", + "0x3f", + "0x40", + "0x41", + "0x42", + "0x43", + "0x104", + "0xf5", + "0xe5", + "0xd4", + "0x9a", + "0xc4", + "0xbd", + "0x44", + "0x46", + "0x47", + "0x48", + "0x49", + "0x4a", + "0x4b", + "0x4c", + "0x4d", + "0x4e", + "0x4f", + "0x50", + "0x51", + "0x53", + "0x54", + "0x55", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x1bd", + "0x1ac", + "0x19b", + "0x192", + "0x181", + "0x147", + "0x171", + "0x16a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x62", + "0x63", + "0x26d", + "0x25c", + "0x24b", + "0x242", + "0x231", + "0x202", + "0x221", + "0x2bb", + "0x299", + "0x2ae", + "0x327", + "0x318", + "0x2ea", + "0x30a", + "0x303", + "0x33c", + "0x341", + "0x34b", + "0x511", + "0x509", + "0x64", + "0x65", + "0x66", + "0x67", + "0x385", + "0x68", + "0x69", + "0x6a", + "0x6b", + "0x6c", + "0x6d", + "0x3b2", + "0x3a4", + "0x6e", + "0x6f", + "0x70", + "0x71", + "0x408", + "0x72", + "0x401", + "0x73", + "0x3f3", + "0x74", + "0x75", + "0x3db", + "0x76", + "0x77", + "0x3e0", + "0x78", + "0x79", + "0x7a", + "0x3ec", + "0x7b", + "0x7c", + "0x7d", + "0x433", + "0x7e", + "0x7f", + "0x80", + "0x41b", + "0x81", + "0x82", + "0x420", + "0x83", + "0x84", + "0x42c", + "0x85", + "0x86", + "0x87", + "0x88", + "0x89", + "0x8a", + "0x8b", + "0x8c", + "0x8d", + "0x8e", + "0x8f", + "0x90", + "0x4fa", + "0x91", + "0x92", + "0x93", + "0x94", + "0x95", + "0x96", + "0x97", + "0x98", + "0x99", + "0x4f2", + "0x9b", + "0x9c", + "0x9d", + "0x9e", + "0x9f", + "0xa0", + "0xa1", + "0xa2", + "0xa3", + "0xa4", + "0x4e9", + "0xa5", + "0xa6", + "0xa7", + "0xa8", + "0xa9", + "0xaa", + "0xab", + "0xac", + "0xad", + "0xae", + "0xaf", + "0x4e0", + "0xb0", + "0xb1", + "0xb2", + "0xb3", + "0xb4", + "0xb5", + "0xb6", + "0x4d6", + "0xb7", + "0xb8", + "0xb9", + "0xba", + "0xbb", + "0xbc", + "0xbe", + "0xbf", + "0xc0", + "0xc1", + "0xc2", + "0xc3", + "0xc5", + "0xc6", + "0xc7", + "0xc8", + "0xca", + "0xcb", + "0x4c4", + "0xcc", + "0xcd", + "0xce", + "0xcf", + "0xd0", + "0xd1", + "0xd2", + "0xd3", + "0xd5", + "0x4b4", + "0xd6", + "0xd7", + "0xd8", + "0xd9", + "0xda", + "0xdb", + "0xdc", + "0xdd", + "0xde", + "0xdf", + "0x4a6", + "0xe0", + "0xe1", + "0xe2", + "0xe3", + "0xe4", + "0xe6", + "0xe7", + "0xe8", + "0xe9", + "0xea", + "0xeb", + "0xec", + "0xed", + "0xee", + "0xef", + "0xf0", + "0xf1", + "0xf2", + "0xf3", + "0xf4", + "0xf6", + "0xf7", + "0xf8", + "0xf9", + "0xfa", + "0xfb", + "0xfc", + "0xfd", + "0xfe", + "0xff", + "0x100", + "0x101", + "0x524", + "0x529", + "0x54f", + "0x545", + "0x54a", + "0x567", + "0x56b", + "0x576", + "0x586", + "0x59f", + "0x598", + "0x5ad", + "0x5b2", + "0x5ce", + "0x5c8", + "0x5e6", + "0x5ea", + "0x5f8", + "0x60d", + "0x611", + "0x625", + "0x629", + "0x630", + "0x63c", + "0x641", + "0x65b", + "0x668", + "0x679", + "0x685", + "0x692", + "0x697", + "0x6a1", + "0x6e0", + "0x6b8", + "0x6d6", + "0x6d0", + "0x6f5", + "0x112", + "0x1cd", + "0x27d", + "0x2c9", + "0x335", + "0x352", + "0x518", + "0x51d", + "0x556", + "0x58d", + "0x5a5", + "0x5d8", + "0x5ff", + "0x614", + "0x617", + "0x649", + "0x661", + "0x673", + "0x67f", + "0x68b", + "0x6a7", + "0x6ef", + "0x3bfb", + "0x501813090402210078380a0502834180b050240a08038180a04018080200", + "0x142c050e81438050d83034120806430050200c2e050200c2c050a8142a05", + "0x900a230602c140e028880a1f0602c24210608024050287c181e090240a16", + "0x14560515030160a14814500c0f0481c050209c1c05048144c0c058284a05", + "0xc00a08038940a2f028b8180b050b40a1f06078240902810060902810580e", + "0x307012080dc6c050a81412051a8302612080d06605190303c12188140827", + "0xac0a3b028ec0a2b028d80a3a028240a09028240a2b028d80a16028240a39", + "0x488005168147e0c1f0283e0c100484a051e814780c058283a050f8303c12", + "0x1000a0e02918180b050940a4502910180b051000a430287c1842091041820", + "0x14984b200142c05250307c0a12814920524030160a2381456050f8301612", + "0xac0a1f0607824400293c0a4e060f81440029000a4d060f81416029309609", + "0x284a052a814a80c058280453081484a0528814a00c0582812050f8303c12", + "0x140a5c0b9780a5d158140a5c0616c185a06164b0022b9000a0902958183e", + "0x14ca3b02814c23b02814c80902814c62b02814c40902814c26002814be0c", + "0x140a6b048140a5c350380a69048140a680619c760502970760502998180e", + "0x1b80a052e1c00a052e1bc0a052e0141c6e02838da2502814d82202814d809", + "0x140a5c048140a64288140a623a0140a5f0e1780a5d061cce405029701871", + "0x38da5502814d82b02814d80e02814c20e02814c84002814c21d2f014ba0e", + "0x140a613b8140a5f049780a5d3b0380a69158140a613a8380a6906038dc05", + "0x14d27807014d2062f014ba4f02814b84302814c24302814c84302814d84f", + "0x140a7d0b0140a7d3e0140a5f121780a5d061ec1205029e82c05029e8f20e", + "0x14ba1602814b81602814c24702814be4902814c47e02814be222f014ba09", + "0x18506050297c525e02975045e02975025e02975000502984fe05029844a5e", + "0x1000a05360310c8502814b82902814b80c072140a0e368240a05421140a05", + "0x140a5c06038c005071b4120502998120502a1d0a050297c0a0e428141c6d", + "0x600a05310600a05438f40a05312200a052f8acbc052e8141c6002838da60", + "0x140a62450140a5f449780a5d148140a66158140a641d0140a611b0140a61", + "0x301c7402838da5102814d88e07014d20c46831180902815160c07014d22f", + "0x1a40a0e3a0141c6d488380a69480380a69028380a69478140a613a0140a5c", + "0x38da8902814b80c072240a0e36831289307014d20c490141c05328381c05", + "0x380a962f0380a694a8380a692a8140a61370140a5f479780a5d028391205", + "0xb4bc052e8141c8202838da8202814b80c072080a0e368312e1502814b80c", + "0x140a62408140a5f179780a5d2f0380a65070380a650a8380a69288140a61", + "0x31301702814c417028150e1c02814b81d02814c20602814c406028150e24", + "0x389e05071b53a0e029a5380e029a42a0502985360e029a5340e029a41899", + "0x14c805071dc0a0e369dc0a052e0301c7702838da0c4f0301c4f02838da05", + "0x27c0a0e3e0141c6d3e0140a5c06038f805071b49e05029989e050297c9e05", + "0x38da05071f80a0e369f80a052e0301c7e02838da4902814d88a2f014ba0c", + "0x1840a0e418141c6d418140a5c060390605071b48a05029b018a0028388e05", + "0x240a05508141c8802838da8802814b80c072200a0e368f40a05360700a05", + "0x140a5f028391405071b5440e029a5140502970180e450141c6d178140a6c", + "0xc4bc052e8141c5e02838da5e02814b80c071780a0e36831468202814be89", + "0x17c180e238141c6d028390205071b5020502970180e408141c6d120140a6c", + "0x301c0c0e05c1ca60b0541ca507014180e0283018a502830180c521780a05", + "0x154a050a8142c0c048741ca5029780a15061780aa5029780a5e060314a05", + "0x74180c528140c050e03018a5028301c0c120154e0602a941c090285c1815", + "0x2040a2406209020e528144a05030304a05528144405048304405528143a05", + "0x3018a5028ac0a2406224560e528145205030305205528141822060314a05", + "0x23c1c820623c0aa502a3c0a81060b40aa502a240a250623c0aa502a080a25", + "0x31140552814182b060bc0aa502830520c062940a0c070301885062941c2d", + "0xcc1c2f060cc0aa5028305a0c188154a05450bc1c8f062280aa502a280a89", + "0x2940a16028c4181502a940a1502858183602a940a3a02a28183a02a940a31", + "0x301c0c1b0382c150a8146c05528146c051d0301c05528141c05198302c05", + "0x394a0e180582a5e1d8306005528146005180306005528141836060314a05", + "0x154a050c014620c1d8154a051d8142c0c062940a0c07031103d072a0303b", + "0x388a051e8308a43429002aa502838303b2f060180e02a940a0e028cc1818", + "0x1f80aa502a0c0a88061240aa502830520c062940a0c070308e0554a0c0aa5", + "0x150a0c3f8154a053f815120c062940a7c02870187f3e0394a053f014800c", + "0x1500054183018a50293c0a450613d000e52814927f0710c184902a940a49", + "0x1d00aa5029440a7e061440aa5029540a49060314a053b8148e0c2a9dc1ca5", + "0x14660c428154a0542814620c200154a05200142c0c390154a053a014f80c", + "0x228180c52814180e061c88685200540a7202a940a72028e8184302a940a43", + "0x148605198310a05528150a051883080055281480050b030e005528148e05", + "0x141829060314a0506038187021a148015029c00aa5029c00a3a0610c0aa5", + "0x1bc0aa502980dc0e47830c00552814c00544830c00552814187f061b80aa5", + "0x142c0c558154a0555015140c550154a05378001c2f060000aa5028305a0c", + "0x2940aab028e8180e02a940a0e028cc188802a940a88028c4183d02a940a3d", + "0x2940a1d02a00180c5281448052283018a5028301c0c55839103d0a8155605", + "0x2b01c8f062b40aa502ab40a89062b40aa5028309e0c560154a05060a4180c", + "0x2940ab002a2818b002a940aae578385e0c578154a05060b418ae02a940aad", + "0x301c05528141c05198302c05528142c05188302a05528142a050b0316205", + "0x3018a5029780a80060314a050603818b1070582a1502ac40aa502ac40a3a", + "0x1564a90723c18b202a940ab202a2418b202a940a0c3f8315205528141829", + "0x2d80aa502ad40a8a062d40aa502acd680e17831680552814182d062cc0aa5", + "0x14740c070154a0507014660c0e0154a050e014620c0b8154a050b8142c0c", + "0x582a0e528380a0c07014180c52814180c062d81c1c0b8540ab602a940ab6", + "0x243a0e52814bc050a830bc0552814bc052f03018a5028301c0c0e05c1cb7", + "0x178180c52814180e060900ab8030154a0e048142e0c0a8154a050a8142c0c", + "0x3104055ca040aa5070940a1706094440e528143a050a8303a05528143a05", + "0x3856052a8305629072940a22029dc182202a940a2202978180c52814180e", + "0x154a0516814120c168154a05148143a0c062940a0c070311e055d2240aa5", + "0x140c0c198154a0506088180c52815140512030628a072940a2f02818182f", + "0x2940a3602894183002a940a3102894180c528147405120306c3a072940a33", + "0x3018a5028301c0c062ec18a5070ec600e410306005528146005408307605", + "0x600aa502830520c062940a0602870180c5281502050e03018a502a240a51", + "0x305a0c440154a051e8601c8f060f40aa5028f40a89060f40aa502830560c", + "0x2940a1502858184302a940a8502a28188502a940a88200385e0c200154a05", + "0x1486055281486051d0301c05528141c05198302c05528142c05188302a05", + "0x308a05528148a05180308a05528141836060314a05060381843070582a15", + "0x1f00aa502830e80c062940a0c07030fc49072f08e83072941c450b054bc3b", + "0x14620c418154a05418142c0c062940a7f029c018803f8394a053e014e40c", + "0x2940a8102a24180602a940a0602a24180e02a940a0e028cc184702a940a47", + "0x144aa77278554a0544a040c800711d061c300311205528151205370310205", + "0x15100c380154a05060a4180c52814180e061c80abd3a0154a0e288147a0c", + "0x2940a6f02a24180c52814c0050e030de60072940a6e02900186e02a940a74", + "0x314a05550148a0c550001ca5029c0de0e21830e00552814e00542830de05", + "0x14fc0c568154a0556014920c062940aab0291c18ac558394a0500015060c", + "0x2940a77028c4184f02a940a4f0285818af02a940aae029f018ae02a940aad", + "0x301c0c57954ee4f0a8155e05528155e051d030aa0552814aa0519830ee05", + "0x1dc0aa5029dc0a310613c0aa50293c0a16062c00aa5029c80a8a060314a05", + "0x2940a0c0703160553b93c2a05580154a0558014740c2a8154a052a814660c", + "0x2940a0c1483018a5028180a1c060314a0540814380c062940a8902944180c", + "0x3164055281552b10723c18a902a940aa902a2418a902a940a0c3f8316205", + "0x1240a16062d40aa502ad00a8a062d00aa502ac9660e17831660552814182d", + "0x154a055a814740c070154a0507014660c3f0154a053f014620c248154a05", + "0x314a0514815000c062940a8f02914180c52814180e062d41c7e248540ab5", + "0x154a05061bc18b602a940a0c1483018a5028180a1c060314a0540814380c", + "0xbc18bf02a940a0c168315005528157cb60723c18be02a940abe02a2418be", + "0x580a31060540aa5028540a16063040aa502b000a8a063000aa502aa17e0e", + "0x31820e0b0542a05608154a0560814740c070154a0507014660c0b0154a05", + "0x3018a5028880a80060314a0503014380c062940a8202914180c52814180e", + "0x1586c20723c18c302a940ac302a2418c302a940a0c000318405528141829", + "0x31c0aa502b180a8a063180aa502b118a0e178318a0552814182d063100aa5", + "0x14740c070154a0507014660c0b0154a050b014620c0a8154a050a8142c0c", + "0x15000c062940a2402914180c52814180e0631c1c160a8540ac702a940ac7", + "0x31920552815920544831920552814184f063200aa502830520c062940a1d", + "0x15140c658154a056529c1c2f0629c0aa5028305a0c650154a0564b201c8f", + "0x2940a0e028cc181602a940a16028c4181502a940a150285818cc02a940acb", + "0x14bc054003018a5028301c0c660382c150a81598055281598051d0301c05", + "0x391e0c670154a0567015120c670154a05061fc18cd02a940a0c1483018a5", + "0x15a20545031a205528159ed0070bc18d002a940a0c168319e05528159ccd", + "0x380aa5028380a33060700aa5028700a310605c0aa50285c0a16063480aa5", + "0x154a05062ac181602a940a0c55031a40e0e05c2a05690154a0569014740c", + "0x900c0e698243a0e528380a0c07014180c52814180c060314a05062b0181c", + "0x1783a0e56830bc0552814bc052f0303a05528143a050b03018a5028301c0c", + "0x940a5e060314a0506038188202b502a05528390205570310225111794a05", + "0x3856050b8302a05528142a16072bc182b148394a05128142a0c128154a05", + "0x154a0504814620c110154a05110142c0c062940a0c0703112056a85c0aa5", + "0x1794a0514824445e588302e05528142e1c072c0182902a940a29029781809", + "0x394a0545015640c062940a0c0703062056b2280aa5070bc0aa9060bc5a8f", + "0xec0aa5028cc0a1d060314a0506038183002b5c6c05528387405598307433", + "0x30440c062940a3d0289018881e8394a050c0140c0c0c0154a051d814120c", + "0x154a05440144a0c062940a85028901843428394a05200140c0c200154a05", + "0x31b00c52839064507208184502a940a4502a04188302a940a43028941845", + "0x314a050a815680c062940a1702870180c528146c052383018a5028301c0c", + "0x1248e0e47830920552814920544830920552814182b0611c0aa502830520c", + "0x154a053f815140c3f8154a053f1f01c2f061f00aa5028305a0c3f0154a05", + "0xe8180e02a940a0e028cc182d02a940a2d028c4188f02a940a8f028581880", + "0xc0184f02a940a0c1b03018a5028301c0c400385a8f0a8150005528150005", + "0x314a0506038187428839b2553b8394a0e278b51e5e1d8309e05528149e05", + "0x1dc0a16060314a0538014e00c371c01ca5029c80a72061c80aa502830e80c", + "0x154a050a8156a0c070154a0507014660c2a8154a052a814620c3b8154a05", + "0xd82e1537038aa770e2d8183602a940a3602a14181702a940a1702a241815", + "0x30520c062940a0c0703158056d2ac0aa5072a80a3d062a8006f300554a05", + "0x2940aaf0287018b0578394a0557014800c570154a0555815100c568154a05", + "0x2a5620e528155ab00710c18ad02a940aad02a1418b002a940ab002a24180c", + "0x2cc0a49060314a05590148e0c59ac81ca502ac40a83060314a05548148a0c", + "0x154a05300142c0c5b0154a055a814f80c5a8154a055a014fc0c5a0154a05", + "0x540ab602a940ab6028e8180002a940a00028cc186f02a940a6f028c41860", + "0x30c00552814c0050b0317c055281558054503018a5028301c0c5b000de60", + "0x1bcc01502af80aa502af80a3a060000aa5028000a33061bc0aa5029bc0a31", + "0x142a055a03018a50285c0a1c060314a051b0148e0c062940a0c070317c00", + "0x391e0c5f8154a055f815120c5f8154a05061fc18a802a940a0c1483018a5", + "0x1584054503184055281580c1070bc18c102a940a0c168318005528157ea8", + "0x380aa5028380a33061d00aa5029d00a31061440aa5029440a160630c0aa5", + "0x314a05180148a0c062940a0c07031860e3a1442a05618154a0561814740c", + "0x154a05060a4180c528142a055a03018a50285c0a1c060314a0519815000c", + "0xb418c602a940ac5620391e0c628154a0562815120c628154a05061bc18c4", + "0x151e050b0319205528159005450319005528158cc7070bc18c702a940a0c", + "0x3240aa502b240a3a060380aa5028380a33060b40aa5028b40a310623c0aa5", + "0x3018a50285c0a1c060314a050a815680c062940a0c07031920e16a3c2a05", + "0x380a33060b40aa5028b40a310623c0aa502a3c0a16063280aa5028c40a8a", + "0x148a0c062940a0c07031940e16a3c2a05650154a0565014740c070154a05", + "0xa4180c5281438055f03018a5028a40a80060314a050a815680c062940a89", + "0x2940acb538391e0c658154a0565815120c658154a050600018a702a940a0c", + "0x319e05528159c05450319c055281598cd070bc18cd02a940a0c168319805", + "0x33c0a3a060380aa5028380a33060240aa5028240a31060880aa5028880a16", + "0x940a80060314a05410148a0c062940a0c070319e0e048882a05678154a05", + "0x309e0c680154a05060a4180c528142c055403018a5028700abe060314a05", + "0x154a05060b418d202a940ad1680391e0c688154a0568815120c688154a05", + "0x3044055281444050b031ba0552815b80545031b80552815a4db070bc18db", + "0x24441502b740aa502b740a3a060380aa5028380a33060240aa5028240a31", + "0x1438055f03018a5029780a80060314a050b015500c062940a0c07031ba0e", + "0x391e0c6f8154a056f815120c6f8154a05061fc18de02a940a0c1483018a5", + "0x15c20545031c20552815c0a6070bc18a602a940a0c16831c00552815bede", + "0x380aa5028380a33060900aa5028900a31060180aa5028180a16063880aa5", + "0x154a05062ac181602a940a0c55031c40e120182a05710154a0571014740c", + "0x900c0e718243a0e528380a0c07014180c52814180c060314a05062b0181c", + "0x1783a0e56830bc0552814bc052f0303a05528143a050b03018a5028301c0c", + "0x940a5e060314a0506038188202b902a05528390205570310225111794a05", + "0x3856050b8302a05528142a16072bc182b148394a05128142a0c128154a05", + "0x154a0504814620c110154a05110142c0c062940a0c0703112057285c0aa5", + "0x1794a0514824445e588302e05528142e1c072c0182902a940a29029781809", + "0x394a0545015640c062940a0c070306205732280aa5070bc0aa9060bc5a8f", + "0xec0aa5028cc0a1d060314a0506038183002b9c6c05528387405598307433", + "0x30440c062940a3d0289018881e8394a050c0140c0c0c0154a051d814120c", + "0x154a05440144a0c062940a85028901843428394a05200140c0c200154a05", + "0x31d00c52839064507208184502a940a4502a04188302a940a43028941845", + "0x314a050a815680c062940a1702870180c528146c052383018a5028301c0c", + "0x1248e0e47830920552814920544830920552814182b0611c0aa502830520c", + "0x154a053f815140c3f8154a053f1f01c2f061f00aa5028305a0c3f0154a05", + "0xe8180e02a940a0e028cc182d02a940a2d028c4188f02a940a8f028581880", + "0xc0184f02a940a0c1b03018a5028301c0c400385a8f0a8150005528150005", + "0x314a0506038187428839d2553b8394a0e278b51e5e1d8309e05528149e05", + "0x1540a31060314a0538014e00c371c01ca5029c80a72061c80aa502830e80c", + "0x154a050b815120c0a8154a050a8156a0c070154a0507014660c2a8154a05", + "0x30520c001bcc05e528146c170a9b81c550bafc183602a940a3602a141817", + "0x154a0556015120c062940aab0287018ac558394a0500014800c550154a05", + "0x3018a502ab80a45062b95a0e5281554ac0710c18aa02a940aaa02a1418ac", + "0x2c40a7e062c40aa502ac00a49060314a05578148e0c582bc1ca502ab40a83", + "0x154a0530014620c3b8154a053b8142c0c590154a0554814f80c548154a05", + "0x14180e062c8de603b8540ab202a940ab2028e8186f02a940a6f028cc1860", + "0x141829060314a050a815680c062940a1702870180c528146c052383018a5", + "0x2d40aa502ad1660e47831680552815680544831680552814187f062cc0aa5", + "0x142c0c540154a055f015140c5f0154a055aad81c2f062d80aa5028305a0c", + "0x2940aa8028e8180e02a940a0e028cc187402a940a74028c4185102a940a51", + "0x2940a3302a00180c5281460052283018a5028301c0c54038e8510a8155005", + "0x2940a0c378317e05528141829060314a050a815680c062940a1702870180c", + "0x31840552814182d063040aa502b017e0e478318005528158005448318005", + "0x14620c478154a05478142c0c620154a0561815140c618154a0560b081c2f", + "0x3101c2d478540ac402a940ac4028e8180e02a940a0e028cc182d02a940a2d", + "0x154a0518815140c062940a1702870180c528142a055a03018a5028301c0c", + "0xe8180e02a940a0e028cc182d02a940a2d028c4188f02a940a8f0285818c5", + "0x2d0180c5281512052283018a5028301c0c628385a8f0a8158a05528158a05", + "0x318c05528141829060314a050e0157c0c062940a2902a00180c528142a05", + "0x14182d063200aa502b1d8c0e478318e05528158e05448318e05528141800", + "0x154a05110142c0c538154a0565015140c650154a05643241c2f063240aa5", + "0x540aa702a940aa7028e8180e02a940a0e028cc180902a940a09028c41822", + "0x157c0c062940a2502a00180c5281504052283018a5028301c0c538381222", + "0x22418cc02a940a0c278319605528141829060314a050b015500c062940a1c", + "0x3359c0e178319c0552814182d063340aa502b31960e478319805528159805", + "0x154a0504814620c110154a05110142c0c680154a0567815140c678154a05", + "0x14180e063401c09110540ad002a940ad0028e8180e02a940a0e028cc1809", + "0x141829060314a050e0157c0c062940a5e02a00180c528142c055403018a5", + "0x36c0aa502b49a20e47831a40552815a40544831a40552814187f063440aa5", + "0x142c0c6f0154a056e815140c6e8154a056db701c2f063700aa5028305a0c", + "0x2940ade028e8180e02a940a0e028cc182402a940a24028c4180602a940a06", + "0x5c1cea0b0541ca507014180e0283018a502830180c6f03848060a815bc05", + "0x240a06060240aa5028740a09060740aa5029780a1d060314a0506038181c", + "0x941ca5028880a06060880aa502830440c062940a06028901824030394a05", + "0x15020c148154a05408144a0c410154a05120144a0c062940a25028901881", + "0x14180e06031d60c52838528207208181502a940a1502858188202a940a82", + "0x391e0c448154a0544815120c448154a05060ac182b02a940a0c1483018a5", + "0x145e05450305e05528151e2d070bc182d02a940a0c168311e0552815122b", + "0x380aa5028380a33060580aa5028580a31060540aa5028540a16062280aa5", + "0xc40aa5028306c0c062940a0c07031140e0b0542a05450154a0545014740c", + "0x14180e060c06c0e760e8660e5283862160a978760c188154a0518814600c", + "0x300180c528143005380307a18072940a3b029c8183b02a940a0c3a03018a5", + "0x394a0520015060c200154a05060a4180c528151005228311005528147a05", + "0x1f0188302a940a45029f8184502a940a4302924180c528150a05238308685", + "0x141c051983074055281474051883066055281466050b0308e05528150605", + "0x141829060314a05060381847070e866150291c0aa50291c0a3a060380aa5", + "0x1f00aa5029f8920e47830fc0552814fc0544830fc0552814187f061240aa5", + "0x142c0c278154a0540015140c400154a053e1fc1c2f061fc0aa5028305a0c", + "0x2940a4f028e8180e02a940a0e028cc183002a940a30028c4183602a940a36", + "0x154a05060a4180c52814bc054003018a5028301c0c2783860360a8149e05", + "0xb4185102a940a553b8391e0c2a8154a052a815120c2a8154a05061fc1877", + "0x142e050b030e00552814e40545030e40552814a274070bc187402a940a0c", + "0x1c00aa5029c00a3a060380aa5028380a33060700aa5028700a310605c0aa5", + "0x303817073b42c15072941c05060380a0c062940a0c06030e00e0e05c2a05", + "0x142a050b030121d072940a5e029dc185e02a940a5e02978180c52814180e", + "0x154a050e8143a0c062940a0c070304805770180aa5070240a55060540aa5", + "0x88180c528150205120310481072940a2502818182502a940a22028241822", + "0x2940a8202894180c52814560512031122b072940a2902818182902a940a0c", + "0x3bc18a5070b51e0e410311e05528151e05408305a05528151205128311e05", + "0x154a05060ac182f02a940a0c1483018a5028180a51060314a0506038180c", + "0xbc183302a940a0c16830620552815142f0723c188a02a940a8a02a24188a", + "0x580a31060540aa5028540a16060d80aa5028e80a8a060e80aa5028c4660e", + "0x306c0e0b0542a051b0154a051b014740c070154a0507014660c0b0154a05", + "0x3860160a978760c180154a0518014600c180154a05060d8180c52814180e", + "0x2940a3b02858184002a940a0c3a03018a5028301c0c440f41cf00c0ec1ca5", + "0x300c05528140c05370301c05528141c05198303005528143005188307605", + "0x38184902bc48e0552839060561031064521a142aa502818800e0c0ec2cc1", + "0x1fcf80e52814fc0541830fc05528141829060314a0523815860c062940a0c", + "0x13c0a7c0613c0aa502a000a7e062000aa5029fc0a49060314a053e0148e0c", + "0x154a0522814660c218154a0521814620c428154a05428142c0c3b8154a05", + "0x2940a4902a28180c52814180e061dc8a43428540a7702a940a77028e81845", + "0x308a05528148a05198308605528148605188310a05528150a050b030aa05", + "0x3018a5028180a51060314a050603818552290d0a15029540aa5029540a3a", + "0x14e8510723c187402a940a7402a24187402a940a0c3f830a205528141829", + "0x1800aa5029b80a8a061b80aa5029c8e00e17830e00552814182d061c80aa5", + "0x14740c070154a0507014660c440154a0544014620c1e8154a051e8142c0c", + "0x15000c062940a2402914180c52814180e061801c881e8540a6002a940a60", + "0x30000552814000544830000552814184f061bc0aa502830520c062940a1d", + "0x15140c560154a05552ac1c2f062ac0aa5028305a0c550154a05001bc1c8f", + "0x2940a0e028cc181602a940a16028c4181502a940a150285818ad02a940aac", + "0x14bc054003018a5028301c0c568382c150a8155a05528155a051d0301c05", + "0x391e0c578154a0557815120c578154a05061fc18ae02a940a0c1483018a5", + "0x1552054503152055281560b1070bc18b102a940a0c168316005528155eae", + "0x380aa5028380a33060700aa5028700a310605c0aa50285c0a16062c80aa5", + "0x380a05620300a055281418050e831640e0e05c2a05590154a0559014740c", + "0x2940a0e02b18181602a940a5e02b14180c52814180e060540af22f0381ca5", + "0x2940a0c6483018a5028301c0c063cc0a0c640303805528142c05638302e05", + "0x303805528141205638302e05528142a05630301205528143a05650303a05", + "0x3044057a0900aa5070700aa7060180aa5028180a5e060180aa50285c0a49", + "0x2940a8102b34188102a940a2502b30182502a940a2402b2c180c52814180e", + "0x2940a0c070310406070150405528150405670300c05528140c052f0310405", + "0x180a5e060ac0aa5028a40acf060a40aa502831920c062940a2202914180c", + "0x14660c028154a0502814620c158181c05158154a05158159c0c030154a05", + "0x700af50b8154a0e0b015a20c0b054bc5e528141c0507340180e02a940a0e", + "0x1412056e0301205528143a056d8303a05528142e056903018a5028301c0c", + "0x1448055a03018a5028180a1c062285e2d47a245629412044a22120184aa5", + "0xa40a1c060314a0541014380c062940a8102870180c5281444056e83018a5", + "0x14480c062940a8f02a00180c5281512056e83018a5028ac0ade060314a05", + "0xcc620e528144a056f83018a502a280a80060314a0517814480c062940a2d", + "0x300a16060c00aa5028d80ae0060d80aa5028cc0a1d060e80aa502830440c", + "0x147430061794c0c1d0154a051d015020c180154a05180158c0c060154a05", + "0x14180e062200af61e8154a0e0c015c20c188154a0518814bc0c0c0ec1ca5", + "0x308605528150a05660310a05528148005658308005528147a057103018a5", + "0x20c1cf90620c860e5281486057c0308605528148605448308a055281418f7", + "0x14180e061240afb062941c4702be8184702a940a4702a24184702a940a45", + "0x1f80afd061f80aa502831f80c062940a4302870180c5281462054003018a5", + "0x154a052f014620c1d8154a051d8142c0c3f8154a053e015fc0c3e0154a05", + "0x14180e061fc2a5e1d8540a7f02a940a7f02bfc181502a940a15028cc185e", + "0x3e4184f218394a0521815f00c400154a0506404180c5281492058003018a5", + "0x38185502c0818a5071dc0afa061dc0aa5029dc0a89061dc0aa502a009e0e", + "0x100185102a940a0c7b83018a50290c0a1c060314a0518815000c062940a0c", + "0x2940a7002900187002a940a0c8083018a5029d00a1c061c8e80e52814a205", + "0x30000552814c00566030de0552814e4056603018a5029b80a1c06180dc0e", + "0x15f40c550154a0555015120c550154a05001bc1cf9061bc0aa5029bc0a89", + "0x154a0556015fa0c560154a0506410180c52814180e062ac0b03062941caa", + "0xcc185e02a940a5e028c4183b02a940a3b0285818ae02a940aad02bf818ad", + "0x3018a5028301c0c57054bc3b0a8155c05528155c057f8302a05528142a05", + "0x154a0558015120c580154a050641418af02a940a0c1483018a502aac0b00", + "0x3164055281562a9070bc18a902a940a0c1683162055281560af0723c18b0", + "0x540a33061780aa5029780a31060ec0aa5028ec0a16062cc0aa502ac80b06", + "0x16000c062940a0c0703166152f0ec2a05598154a0559815fe0c0a8154a05", + "0x2940ab45a839f20c5a90c1ca50290c0af8062d00aa5028320e0c062940a55", + "0x3018a5028301c0c5f016100c528396c057d0316c05528156c05448316c05", + "0x2940a0c8483018a502aa00a80062fd500e5281462056f83018a50290c0a1c", + "0x3076055281476050b0318405528158205700318205528157e050e8318005", + "0x3188c3072940ac0610ecbca6063000aa502b000a81063080aa502b080ac6", + "0x15960c638154a0562815c40c062940a0c070318c05853140aa5073100ae1", + "0x154a0565015120c650154a0564015980c648154a05060a418c802a940ac7", + "0x394a0564815060c062940a0c0703198058632d4e0e5283994c30742c18ca", + "0x15120c680154a0567014920c678154a0506434180c528159a05238319ccd", + "0x32c2a5e0b43818a702a940aa70285818d002a940ad00297818cf02a940acf", + "0x37c0aa502b6c0b10060314a050603818de6eb70bd0f6db49a25e52839a0cf", + "0x31900c708154a056f816220c530154a0569014660c700154a0568814620c", + "0xcc18e002a940adc028c418e202a940ade02c4c180c52814180e060322405", + "0x39ee058a831ee0552815c2058a031c20552815c405888314c0552815ba05", + "0x31f4055281418fc060314a057c0162e0c062940a0c07031f2058b3e00aa5", + "0x3800a310629c0aa502a9c0a16063f40aa502bf00afe063f00aa502be80afd", + "0x31faa67029c2a057e8154a057e815fe0c530154a0553014660c700154a05", + "0x2940ae0028c418a702a940aa70285818fe02a940af902c18180c52814180e", + "0x301c0c7f299c0a70a815fc0552815fc057f8314c05528154c0519831c005", + "0x15120c800154a050646018ff02a940a0c1483018a502b240a47060314a05", + "0x160304070bc190402a940a0c1683202055281600ff0723c190002a940b00", + "0x1780aa5029780a31063300aa502b300a16064180aa502c140b06064140aa5", + "0x2940a0c070320c152f3302a05830154a0583015fe0c0a8154a050a814660c", + "0xcc185e02a940a5e028c418c302a940ac302858190702a940ac602c18180c", + "0x3018a5028301c0c83854bcc30a8160e05528160e057f8302a05528142a05", + "0x426160e7c8321643072940a4302be0190902a940a0c8c83018a502af80b00", + "0x2940a0c070321c058d0314a0e86815f40c868154a0586815120c868154a05", + "0x1620058e032200552814191b060314a0521814380c062940a3102a00180c", + "0x3018a5028301c0c8c45e2a5e8f45227112f2941d100a978bd1d064400aa5", + "0x4640b20064700aa502c4c0a330646c0aa502c440a31064640aa502c500b1f", + "0x14620c8f8154a058c016440c062940a0c07030192102831900c8e8154a05", + "0x2940b1d02c8c191d02a940b1f02c80191c02a940b17028cc191b02a940b15", + "0x3018a502c880b25060314a0506038192302c9244055283a40051e8324005", + "0x1476050b0324e05528164c057f0324c05528164a057e8324a055281418fc", + "0x49c0aa502c9c0aff064700aa502c700a330646c0aa502c6c0a31060ec0aa5", + "0x154a051d8142c0c940154a05918160c0c062940a0c070324f1c8d8ec2a05", + "0x540b2802a940b2802bfc191c02a940b1c028cc191b02a940b1b028c4183b", + "0x325529072940a4302900180c528161c058003018a5028301c0c94472363b", + "0x1658050e0325b2c072940b2b02900192b02a940a0c9303018a502ca40a1c", + "0x4c00aa502cbe5c0e7c8325e05528165a05660325c055281654056603018a5", + "0x15be0c062940a0c070326405988314a0e98015f40c980154a0598015120c", + "0x2940b3602b80193602a940b3402874193502a940a0c848326933072940a31", + "0x326a05528166a05408326e05528166e056303076055281476050b0326e05", + "0x314a050603818bb02cee74055283a7205708327338072940b359b8ecbca6", + "0x49c193f9f0394a0599815be0c9e8154a059e015960c9e0154a059d015c40c", + "0x2940b3802858194202a940b4102b80194102a940b3f02874194002a940a0c", + "0x394a05a050a705e530328005528168005408328405528168405630327005", + "0x314a0506038194702d1a8a055283a8805708327a05528167a05448328943", + "0x200194ba50394a059f015be0ca48154a05a4015960ca40154a05a2815c40c", + "0x154a05a6815c00ca68154a05a58143a0ca60154a05064a0180c528169405", + "0x298194c02a940b4c02a04194e02a940b4e02b18194302a940b4302858194e", + "0x16a55102a941d5002b84194902a940b4902a241950a78394a05a653a865e", + "0x1780a31065540aa502d500acb065500aa502d440ae2060314a05060381953", + "0x5540a8906562af562f2940a152f03a520c0a8154a050a814660c2f0154a05", + "0x2940b5902cac180c52814180e0656c0b5aac8154a0eac016540caa8154a05", + "0x16be0597032c2bdb057ebc1652816ba0596832ba0552816b80596032b805", + "0x5780b2f060314a05b0814380c062940abd02ad0180c52816c0055a03018a5", + "0x16c60599832cb64b19794a05b1016640cb10154a05af016600caf0154a05", + "0x314a05b3814380cb459c1ca502d980a40062f00aa502cf40acc065980aa5", + "0x15980c2c0154a05b4015980c062940b6902870196ab48394a055e014800c", + "0x16d80544832d80552816d658073e4185802a940a5802a24196b02a940b6a", + "0x5b418a5075b00afa065940aa502d940ab5065900aa502d900b1c065b00aa5", + "0x14800cb80154a05a4815980cb78154a05b2016660c062940a0c07032dc05", + "0x16e6050e032e973072940b7002900180c52816e2050e032e571072940b6f", + "0x5d80aa502aeaea0e7c831740552816e80566032ea0552816e4056603018a5", + "0x16680c062940a0c07032f005bb8314a0ebb015f40cbb0154a05bb015120c", + "0x16f6050e032f97b072940b7902900197a02a940b5502b30197902a940b65", + "0x32fe0552816f8056603018a502df40a1c065fafa0e52816f4052003018a5", + "0x15f40cc08154a05c0815120cc08154a05c05fc1cf9066000aa502df80acc", + "0x154a05c2015fa0cc20154a05063f0180c52814180e0660c0b82062941d81", + "0xcc195602a940b56028c4194f02a940b4f02858198602a940b8502bf81985", + "0x3018a5028301c0cc355ead4f0a8170c05528170c057f832ae0552816ae05", + "0x154a055c815120c5c8154a05064d4198702a940a0c1483018a502e0c0b00", + "0x331405528171189070bc198902a940a0c1683310055281573870723c18b9", + "0x55c0a33065580aa502d580a310653c0aa502d3c0a160662c0aa502e280b06", + "0x16000c062940a0c070331757ab53c2a05c58154a05c5815fe0cab8154a05", + "0x4d8198c02a940a0c1483018a502d940ab4060314a05aa814380c062940b78", + "0x2940a0c168331c05528171b8c0723c198d02a940b8d02a24198d02a940a0c", + "0x53c0aa502d3c0a16066440aa502e400b06066400aa502e3b1e0e178331e05", + "0x53c2a05c88154a05c8815fe0cab8154a05ab814660cab0154a05ab014620c", + "0x5940ab4060314a05aa814380c062940b6e02c00180c52814180e06646af56", + "0x32700cc90154a05060a4180c52816c8059b83018a502d240a1c060314a05", + "0x154a05060b4199402a940b93c90391e0cc98154a05c9815120cc98154a05", + "0x329e05528169e050b0317005528172c05830332c05528172995070bc1995", + "0x55a9e1502ae00aa502ae00aff0655c0aa502d5c0a33065580aa502d580a31", + "0x1692050e03018a502cf40a1c060314a05aa814380c062940a0c070317157", + "0x32ac0552816ac05188329e05528169e050b0332e0552816b6058303018a5", + "0x314a05060381997abd5a9e1502e5c0aa502e5c0aff0655c0aa502d5c0a33", + "0x169e050b033300552816a6058303018a502cf40a1c060314a05a4814380c", + "0x6600aa502e600aff060540aa5028540a33061780aa5029780a310653c0aa5", + "0x3018a502cf40a1c060314a059f015000c062940a0c0703330152f53c2a05", + "0x540a33061780aa5029780a310650c0aa502d0c0a16066640aa502d1c0b06", + "0x15000c062940a0c0703332152f50c2a05cc8154a05cc815fe0c0a8154a05", + "0x154a052f014620c9c0154a059c0142c0ccd0154a055d8160c0c062940b33", + "0x14180e066682a5e9c0540b9a02a940b9a02bfc181502a940a15028cc185e", + "0x1419390666c0aa502830520c062940a3102a00180c5281664058003018a5", + "0x6780aa5028305a0cce8154a05ce66c1c8f066700aa502e700a89066700aa5", + "0xc4183b02a940a3b0285819a002a940b9f02c18199f02a940b9dcf0385e0c", + "0x54bc3b0a81740055281740057f8302a05528142a0519830bc0552814bc05", + "0x1476050b03342055281510058303018a5028c40a80060314a050603819a0", + "0x6840aa502e840aff060540aa5028540a33061780aa5029780a31060ec0aa5", + "0x154a05060142c0cd10154a050e0160c0c062940a0c0703342152f0ec2a05", + "0x540ba202a940ba202bfc181502a940a15028cc185e02a940a5e028c4180c", + "0x154a0506324185e02a940a0e028391e0c070154a0506015980cd1054bc0c", + "0x2941c0502b10180502a940a0c0287418152f0380a5e02a940a5e02a141815", + "0x154a05070158c0c0b0154a052f0158a0c062940a0c070302a05d19781c0e", + "0x154a0506324180c52814180e06033480506320181c02a940a1602b1c1817", + "0x124181c02a940a0902b1c181702a940a1502b18180902a940a1d02b28181d", + "0x38182202e944805528383805538300c05528140c052f0300c05528142e05", + "0x394a0540814800c408154a0512815980c128154a0512015960c062940a0c", + "0x70188f448394a0515814800c158154a05063dc180c5281504050e0305282", + "0x145e050e031142f072940a2d02900182d02a940a2902b30180c528151205", + "0x3018a5028cc0a1c060e8660e528146205200306205528151e056603018a5", + "0xd81cf9060d80aa5028d80a89060c00aa5028e80acc060d80aa502a280acc", + "0x14180e060600ba6062941c3b02be8183b02a940a3b02a24183b02a940a30", + "0x320184002a940a88029b8188802a940a3d02ce8183d02a940a0c6483018a5", + "0x15760c428154a0506324180c5281430058003018a5028301c0c0669c0a0c", + "0x2940a4502cf4184502a940a4002cf0184002a940a43029b8184302a940a85", + "0x2940a0c0703106060701506055281506059f0300c05528140c052f0310605", + "0x180a5e061240aa50291c0b3f0611c0aa502831920c062940a2202914180c", + "0x540a1c060314a052f014e00c248181c05248154a05248167c0c030154a05", + "0x3018a5028700a5106074380e528142e05a003018a5028580a1c060314a05", + "0x900a5106088480e528140c05a00300c055281412055d83012055281418c9", + "0x2940a0c070310205d40940aa5070740b41060880aa5028880a6e060314a05", + "0x14dc0c148154a0541016780c410154a0511016840c062940a2502914180c", + "0x16840c062940a8102914180c52814180e06033520506320182b02a940a29", + "0x301c0c16817548f02a941c2b02d04182b02a940a89029b8188902a940a22", + "0x3f8188a02a940a2f02bf4182f02a940a0c7e03018a502a3c0a45060314a05", + "0x141c05198300a05528140a051883018055281418050b0306205528151405", + "0xb40a45060314a05060381831070141815028c40aa5028c40aff060380aa5", + "0x380aa5028380a33060140aa5028140a31060300aa5028300a16060314a05", + "0x301c0c0c017563b02a941c30028f418301b0e86615528141c0506178300c", + "0x1000aa502a200afe062200aa5028f40afd060f40aa5028ec0a88060314a05", + "0x15fe0c1b0154a051b014660c1d0154a051d014620c198154a05198142c0c", + "0x58188502a940a1802c18180c52814180e061006c3a198540a4002a940a40", + "0x150a057f8306c05528146c05198307405528147405188306605528146605", + "0x30bc0e072940a0502854180502a940a050297818851b0e8661502a140aa5", + "0x6b43817072941c150603a160c062940a0c070302c05d60540aa5071780a17", + "0x14bc0c0b8154a050b8142c0c048154a050e016860c062940a0c070303a05", + "0x31920c062940a0c07030120e0b9780a0902a940a0902d10180e02a940a0e", + "0x154a0507014bc0c0e8154a050e8142c0c120154a05030168a0c030154a05", + "0x154a050b0168a0c062940a0c07030480e0e9780a2402a940a2402d10180e", + "0x1780a2202a940a2202d10180e02a940a0e02978180c02a940a0c028581822", + "0x6b82c15072941c5e02b10185e02a940a0e02874180c528141947060881c0c", + "0x158e0c0e8154a050a8158c0c0e0154a050b0158a0c062940a0c070302e05", + "0x15940c030154a0506324180c52814180e060335e0506320180902a940a1c", + "0x2940a1d02924180902a940a2402b1c181d02a940a1702b18182402a940a06", + "0x314a0506038188102ec04a055283812055383044055281444052f0304405", + "0x300a16060ac0aa502a080acc060a40aa502830520c410154a0512815960c", + "0x154a05148150a0c110154a0511014bc0c028154a0502814620c060154a05", + "0xb40aa9060b51e892f2940a2b148880a0c0b520182b02a940a2b02a241829", + "0xcc620ea48306631072940a2f02ac8180c52814180e062280bb1178154a0e", + "0x154a0547814620c448154a05448142c0c1b0154a051d016940c1d0154a05", + "0x154a0545016980c062940a0c070306c8f449780a3602a940a3602d2c188f", + "0x1780a3002a940a3002d2c188f02a940a8f028c4188902a940a89028581830", + "0xec0b4d060ec0aa502831920c062940a8102914180c52814180e060c11e89", + "0x2940a0c02858188802a940a3d02d28183d02a940a181103a920c0c0154a05", + "0x1780a70062200a0c2f0151005528151005a58300a05528140a05188301805", + "0x15060c0e0154a05063dc180c528142c050e03018a5028540ab4060314a05", + "0x2940a1c02a24180602a940a0902924180c528143a0523830121d072940a17", + "0x20902252f6c84424072941c060e0380a15a70300c05528140c052f0303805", + "0x6cc0a0c6403056055281444051983052055281448051883018a5028301c0c", + "0x150205198305205528144a051883018a502a080a47060314a0506038180c", + "0xac0aa5028ac0a33060a40aa5028a40a31060300aa5028300a16060ac0aa5", + "0x301c0c18817688a02a941c2f028f4182f16a3d121552814562906178300c", + "0xd80aa5028e80afe060e80aa5028cc0afd060cc0aa502a280a88060314a05", + "0x15fe0c168154a0516814660c478154a0547814620c448154a05448142c0c", + "0x58183002a940a3102c18180c52814180e060d85a8f448540a3602a940a36", + "0x1460057f8305a05528145a05198311e05528151e05188311205528151205", + "0x540a1c060314a052f015680c062940a0e029c0183016a3d1215028c00aa5", + "0x3018a5028700a4706074380e528142c05418302e055281418f7060314a05", + "0x302b4e060240aa5028240a5e0605c0aa50285c0a89060240aa5028740a49", + "0x2080aa5028180a31060314a0506038188112888bdb5120181ca5070242e05", + "0x314a05408148e0c062940a0c0703019b602831900c148154a0512014660c", + "0xac0a89060ac0aa502831f80c148154a0512814660c410154a0511014620c", + "0x300a05028140aa502831920c062940a0c029c0182b14a08bc05158154a05", + "0x1438059d03038055281418c9060314a050b014a20c0b8581ca5028540b40", + "0x180aa5028180a6e060314a0504814a20c030241ca5028740b40060740aa5", + "0x16840c062940a2402914180c52814180e060880bb7120154a0e0b816820c", + "0x33700506320188202a940a81029b8188102a940a2502cf0182502a940a06", + "0x2940a29029b8182902a940a0602d08180c5281444052283018a5028301c0c", + "0x3018a5028ac0a45060314a0506038188902ee45605528390405a08310405", + "0x1418c8060bc0aa5028380a33060b40aa5028140a310623c0aa5028300a16", + "0x140a31060300aa5028300a16060314a05448148a0c062940a0c0703019ba", + "0xf4183a198c51415528141c0506178300c070154a0507014660c028154a05", + "0x1514050b03018a5028d80b25060314a0506038183002eec6c05528387405", + "0x3076055281418c9060bc0aa5028cc0a33060b40aa5028c40a310623c0aa5", + "0x23c2a051e8154a051e816a20c1e8154a050c016a00c0c0154a051d9781d4f", + "0x142c0c440154a0518016a60c062940a5e029c0180c52814180e060f45e2d", + "0x2940a8802d44183302a940a33028cc183102a940a31028c4188a02a940a8a", + "0x3a520c028154a0502814660c060154a0506014620c440cc628a0a8151005", + "0x4ac180c52814180e0605c0bbc0b0154a0e0a816540c0a9781c5e528140a0c", + "0x304a22120181216528143a05968303a05528143805960303805528142c05", + "0x314a0512814380c062940a2202ad0180c5281448055a03018a5028240b54", + "0x14660c070154a0507014620c410154a0540816ac0c408154a0503016aa0c", + "0x16b00c062940a0c07031045e071780a8202a940a8202d5c185e02a940a5e", + "0x2940a2902d5c185e02a940a5e028cc180e02a940a0e028c4182902a940a17", + "0x314a0506038181602ef42a5e072941c0e02830bd59060a4bc0e2f0145205", + "0x16ba0c2f0154a052f0142c0c0e0154a050b816b80c0b8154a050a816b60c", + "0x2940a0caf0303a05528141829060314a0506038181c2f0380a1c02a940a1c", + "0x30480552814182d060180aa5028243a0e478301205528141205448301205", + "0x16ba0c0b0154a050b0142c0c128154a0511016be0c110154a05030901c2f", + "0x3018a5028301c0c070177c0502a941c0c02d8018250b0380a2502a940a25", + "0x302a05028540aa5028540a3a060540aa5029780a7c061780aa5028140a7e", + "0x2940a1702a28181702a940a0e0b0385e0c0b0154a05060b4180c52814180e", + "0x301c0c070177e0502a941c0c02af4181c0281438055281438051d0303805", + "0x540aa5028540aff060540aa5029780afe061780aa5028140afd060314a05", + "0x418181702a940a0e0b0385e0c0b0154a05060b4180c52814180e060540a05", + "0x1781c5e528380a0c07584181c0281438055281438057f8303805528142e05", + "0x154a0507014620c0e8154a050a816c40c062940a0c0703038170b17b8015", + "0x14180e06033820506320182402a940a1d02d8c180602a940a5e028cc1809", + "0x300c05528142e05198301205528142c05188304405528143805b203018a5", + "0x310405e12040aa5070940b2a060940aa5028900b65060900aa5028880b63", + "0x2940a2b02af0182b02a940a2902d98182902a940a8102cac180c52814180e", + "0x151205528151205b38300c05528140c05198301205528141205188311205", + "0x301205528141205188311e05528150405b403018a5028301c0c44818125e", + "0x3018a5028328e0c47818125e02a3c0aa502a3c0b67060180aa5028180a33", + "0x3b861c0b8394a0e0b014185e1d8302c05528142c05180302c05528141836", + "0x3e8181702a940a170285818060a8394a050a815f00c062940a0c07030121d", + "0x2940a5e02da4180c528142a050e03018a5028301c0c12017880c528380c05", + "0x5c0aa50285c0a16062040aa5028940b4a060940aa5028881c0ea48304405", + "0x314a050603818810e05cbc05408154a0540816960c0e0154a050e014620c", + "0x142e0c14a081ca5028380a15060380aa5028380a5e060314a0512016000c", + "0x1419010623c0aa5028acbc0e4783018a5028301c0c448178a2b02a941c29", + "0x154a050e014620c0b8154a050b8142c0c178154a05168541cf9060b40aa5", + "0x520182f02a940a2f02a24188f02a940a8f02a14188202a940a8202978181c", + "0x14180e060d80bc61d0154a0e19815520c198c5145e528145e8f410702e16", + "0x154a050c016940c0c0154a051d8c01d49060ec600e5281474055903018a5", + "0x1780a3d02a940a3d02d2c183102a940a31028c4188a02a940a8a02858183d", + "0xc4188a02a940a8a02858188802a940a3602d30180c52814180e060f4628a", + "0x70180c52814180e06220628a2f0151005528151005a58306205528146205", + "0x2940a404103a920c200154a05448169a0c062940a5e0291c180c528142a05", + "0x303805528143805188302e05528142e050b0308605528150a05a50310a05", + "0x11c180c528142a050e03018a5028301c0c218702e5e0290c0aa50290c0b4b", + "0x31060552814187f061140aa502830520c062940a0e02a00180c52814bc05", + "0x1241c2f061240aa5028305a0c238154a05419141c8f0620c0aa502a0c0a89", + "0x2940a09028c4181d02a940a1d02858187c02a940a7e02d30187e02a940a47", + "0x301c05e38140aa5070300b6a061f0121d2f014f80552814f805a58301205", + "0x2940a1502d9c181502a940a5e02af0185e02a940a0502d98180c52814180e", + "0x5c0aa5028382c0e178302c0552814182d060314a05060381815028142a05", + "0x302a2b381bc1815198700a050e0154a050e016ce0c0e0154a050b816d00c", + "0x1c0de0c0ac14bc0e02830dc70378302a2b381bc1815061781c05061b8e06f", + "0x57925e07014186e381bc1815159c0de0c0af20bc0e02830dc70378302a2b", + "0x380a0c371c0de0c0a8ace06f06057945e07014186e381bc1815159c0de0c", + "0x381c0e0483b9a0e02830e870378302a7037830bdcc06180560e15817965e", + "0x380a0c3a1c0de0c0a93c1209219c0de0c0e73c1877158385605e70141840", + "0x7481c05061f8de0c2f0acde0c2f7440a0c3e0ac185e158301dd00b8582a5e", + "0x242c43381bc2fd30b8582a5e070141874381bc1815070242c43381bc181c", + "0x1bc18152790ce06f0605baa0c200148605ea0582a5e070141809381bcbc0e", + "0x14188a0603876290617bae0506220e06f2f1c0de0eeb054bc0e028310670", + "0x1bc1816ed8141881381bcbc703783bb40c3a0150405ec830dc0544817b00e", + "0x7741881029780bdc0a9781c05061f8de0c2f0241c2b" + ], + "sierra_program_debug_info": { + "type_names": [], + "libfunc_names": [], + "user_func_names": [] + }, + "contract_class_version": "0.1.0", + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "function_idx": 3 + }, + { + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "function_idx": 2 + }, + { + "selector": "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d", + "function_idx": 4 + }, + { + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "function_idx": 0 + }, + { + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "function_idx": 1 + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 5 + } + ] + }, + "abi": [ + { + "type": "function", + "name": "__validate_declare__", + "inputs": [ + { + "name": "class_hash", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "function", + "name": "__validate_deploy__", + "inputs": [ + { + "name": "class_hash", + "type": "core::felt252" + }, + { + "name": "contract_address_salt", + "type": "core::felt252" + }, + { + "name": "validate_constructor", + "type": "core::bool" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "__validate__", + "inputs": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "calldata", + "type": "core::array::Array::" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "__execute__", + "inputs": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "calldata", + "type": "core::array::Array::" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "constructor", + "name": "constructor", + "inputs": [ + { + "name": "validate_constructor", + "type": "core::bool" + } + ] + }, + { + "type": "function", + "name": "foo", + "inputs": [], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "event", + "name": "account_faulty::account_faulty::Account::Event", + "kind": "enum", + "variants": [] + } + ] +} \ No newline at end of file diff --git a/crates/mempool_types/Cargo.toml b/crates/mempool_types/Cargo.toml new file mode 100644 index 00000000000..3bad738b071 --- /dev/null +++ b/crates/mempool_types/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "starknet_mempool_types" +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + +[lints] +workspace = true + +[dependencies] +async-trait.workspace = true +mockall.workspace = true +starknet_api.workspace = true +starknet_mempool_infra = { path = "../mempool_infra" } +thiserror.workspace = true diff --git a/crates/mempool_types/src/communication.rs b/crates/mempool_types/src/communication.rs new file mode 100644 index 00000000000..d19405a8b03 --- /dev/null +++ b/crates/mempool_types/src/communication.rs @@ -0,0 +1,75 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use mockall::predicate::*; +use mockall::*; +use starknet_mempool_infra::component_client::definitions::ClientError; +use starknet_mempool_infra::component_client::local_component_client::LocalComponentClient; +use starknet_mempool_infra::component_definitions::ComponentRequestAndResponseSender; +use thiserror::Error; + +use crate::errors::MempoolError; +use crate::mempool_types::{MempoolInput, ThinTransaction}; + +pub type MempoolClientImpl = LocalComponentClient; +pub type MempoolResult = Result; +pub type MempoolClientResult = Result; +pub type MempoolRequestAndResponseSender = + ComponentRequestAndResponseSender; +pub type SharedMempoolClient = Arc; + +/// Serves as the mempool's shared interface. Requires `Send + Sync` to allow transferring and +/// sharing resources (inputs, futures) across threads. +#[automock] +#[async_trait] +pub trait MempoolClient: Send + Sync { + async fn add_tx(&self, mempool_input: MempoolInput) -> MempoolClientResult<()>; + async fn get_txs(&self, n_txs: usize) -> MempoolClientResult>; +} + +#[derive(Debug)] +pub enum MempoolRequest { + AddTransaction(MempoolInput), + GetTransactions(usize), +} + +#[derive(Debug)] +pub enum MempoolResponse { + AddTransaction(MempoolResult<()>), + GetTransactions(MempoolResult>), +} + +#[derive(Debug, Error)] +pub enum MempoolClientError { + #[error(transparent)] + ClientError(#[from] ClientError), + #[error(transparent)] + MempoolError(#[from] MempoolError), +} + +#[async_trait] +impl MempoolClient for MempoolClientImpl { + async fn add_tx(&self, mempool_input: MempoolInput) -> MempoolClientResult<()> { + let request = MempoolRequest::AddTransaction(mempool_input); + let response = self.send(request).await; + match response { + MempoolResponse::AddTransaction(Ok(response)) => Ok(response), + MempoolResponse::AddTransaction(Err(response)) => { + Err(MempoolClientError::MempoolError(response)) + } + _ => Err(MempoolClientError::ClientError(ClientError::UnexpectedResponse)), + } + } + + async fn get_txs(&self, n_txs: usize) -> MempoolClientResult> { + let request = MempoolRequest::GetTransactions(n_txs); + let response = self.send(request).await; + match response { + MempoolResponse::GetTransactions(Ok(response)) => Ok(response), + MempoolResponse::GetTransactions(Err(response)) => { + Err(MempoolClientError::MempoolError(response)) + } + _ => Err(MempoolClientError::ClientError(ClientError::UnexpectedResponse)), + } + } +} diff --git a/crates/mempool_types/src/errors.rs b/crates/mempool_types/src/errors.rs new file mode 100644 index 00000000000..ebe6ad50d51 --- /dev/null +++ b/crates/mempool_types/src/errors.rs @@ -0,0 +1,13 @@ +use starknet_api::transaction::TransactionHash; +use thiserror::Error; + +#[derive(Clone, Debug, Error, PartialEq, Eq)] +pub enum MempoolError { + #[error("Duplicate transaction, with hash: {tx_hash}")] + DuplicateTransaction { tx_hash: TransactionHash }, + #[error("Transaction with hash: {tx_hash} not found")] + TransactionNotFound { tx_hash: TransactionHash }, + // TODO(Mohammad): Consider using `StarknetApiError` once it implements `PartialEq`. + #[error("Out of range.")] + FeltOutOfRange, +} diff --git a/crates/mempool_types/src/lib.rs b/crates/mempool_types/src/lib.rs new file mode 100644 index 00000000000..0a1f5bb3c38 --- /dev/null +++ b/crates/mempool_types/src/lib.rs @@ -0,0 +1,3 @@ +pub mod communication; +pub mod errors; +pub mod mempool_types; diff --git a/crates/mempool_types/src/mempool_types.rs b/crates/mempool_types/src/mempool_types.rs new file mode 100644 index 00000000000..08ff1716b65 --- /dev/null +++ b/crates/mempool_types/src/mempool_types.rs @@ -0,0 +1,33 @@ +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::transaction::{Tip, TransactionHash}; + +use crate::errors::MempoolError; + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct ThinTransaction { + pub sender_address: ContractAddress, + pub tx_hash: TransactionHash, + pub tip: Tip, + pub nonce: Nonce, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct AccountState { + pub nonce: Nonce, + // TODO: add balance field when needed. +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Account { + // TODO(Ayelet): Consider removing this field as it is duplicated in ThinTransaction. + pub sender_address: ContractAddress, + pub state: AccountState, +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub struct MempoolInput { + pub tx: ThinTransaction, + pub account: Account, +} + +pub type MempoolResult = Result; diff --git a/crates/papyrus_base_layer/Cargo.toml b/crates/papyrus_base_layer/Cargo.toml new file mode 100644 index 00000000000..b5bfba2b215 --- /dev/null +++ b/crates/papyrus_base_layer/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "papyrus_base_layer" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[dependencies] +async-trait.workspace = true +ethers.workspace = true +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +rustc-hex.workspace = true +serde.workspace = true +serde_json.workspace = true +starknet_api.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +url.workspace = true + +[dev-dependencies] +ethers-core = { version = "2.0.3" } +pretty_assertions.workspace = true +starknet_api = { workspace = true, features = ["testing"] } +starknet-types-core.workspace = true +tar = { version = "0.4.38" } +tempfile.workspace = true +test-with = { version = "0.9.3", default-features = false, features = [ + "executable", +] } diff --git a/crates/papyrus_base_layer/resources/ganache-db.tar b/crates/papyrus_base_layer/resources/ganache-db.tar new file mode 100644 index 00000000000..f9a64daef43 Binary files /dev/null and b/crates/papyrus_base_layer/resources/ganache-db.tar differ diff --git a/crates/papyrus_base_layer/src/base_layer_test.rs b/crates/papyrus_base_layer/src/base_layer_test.rs new file mode 100644 index 00000000000..6cbfa347b8a --- /dev/null +++ b/crates/papyrus_base_layer/src/base_layer_test.rs @@ -0,0 +1,81 @@ +use std::fs::File; +use std::process::Command; + +use ethers::utils::{Ganache, GanacheInstance}; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::felt; +use tar::Archive; +use tempfile::{tempdir, TempDir}; + +use crate::ethereum_base_layer_contract::{EthereumBaseLayerConfig, EthereumBaseLayerContract}; +use crate::BaseLayerContract; + +type EthereumContractAddress = String; +type TestEthereumNodeHandle = (GanacheInstance, TempDir); + +// Returns a Ganache instance, preset with a Starknet core contract and some state updates: +// Starknet contract address: 0xe2aF2c1AE11fE13aFDb7598D0836398108a4db0A +// Ethereum block number starknet block number starknet block hash +// 10 100 0x100 +// 20 200 0x200 +// 30 300 0x300 +// The blockchain is at Ethereum block number 31. +// Note: Requires Ganache@7.4.3 installed. +fn get_test_ethereum_node() -> (TestEthereumNodeHandle, EthereumContractAddress) { + const SN_CONTRACT_ADDR: &str = "0xe2aF2c1AE11fE13aFDb7598D0836398108a4db0A"; + // Verify correct Ganache version. + let ganache_version = String::from_utf8_lossy( + &Command::new("ganache") + .arg("--version") + .output() + .expect("Failed to get Ganache version, check if it is installed.") + .stdout, + ) + .to_string(); + // TODO(yair): Consider relaxing the version requirement. + assert!( + ganache_version.starts_with("ganache v7.4.3"), + "Wrong Ganache version, please install v7.4.3" + ); + const DB_NAME: &str = "ganache-db"; + let db_archive_path = format!("resources/{DB_NAME}.tar"); + + // Unpack the Ganache db tar file into a temporary dir. + let mut archive = Archive::new(File::open(db_archive_path).expect("Ganache db not found.")); + let ganache_db = tempdir().unwrap(); + archive.unpack(ganache_db.path()).unwrap(); + + // Start Ganache instance. This will panic if Ganache is not installed. + let db_path = ganache_db.path().join(DB_NAME); + let ganache = Ganache::new().args(["--db", db_path.to_str().unwrap()]).spawn(); + + ((ganache, ganache_db), SN_CONTRACT_ADDR.to_owned()) +} + +#[test_with::executable(ganache)] +#[tokio::test] +// Note: the test requires ganache-cli installed, otherwise it is ignored. +async fn latest_proved_block_ethereum() { + let (node_handle, starknet_contract_address) = get_test_ethereum_node(); + let config = + EthereumBaseLayerConfig { node_url: node_handle.0.endpoint(), starknet_contract_address }; + let contract = EthereumBaseLayerContract::new(config).unwrap(); + + let first_sn_state_update = (BlockNumber(100), BlockHash(felt!("0x100"))); + let second_sn_state_update = (BlockNumber(200), BlockHash(felt!("0x200"))); + let third_sn_state_update = (BlockNumber(300), BlockHash(felt!("0x300"))); + + type Scenario = (Option, Option<(BlockNumber, BlockHash)>); + let scenarios: Vec = vec![ + (None, Some(third_sn_state_update)), + (Some(5), Some(third_sn_state_update)), + (Some(15), Some(second_sn_state_update)), + (Some(25), Some(first_sn_state_update)), + (Some(1000), None), + ]; + for (scenario, expected) in scenarios { + let latest_block = contract.latest_proved_block(scenario).await.unwrap(); + assert_eq!(latest_block, expected); + } +} diff --git a/crates/papyrus_base_layer/src/core_contract_latest_block.abi b/crates/papyrus_base_layer/src/core_contract_latest_block.abi new file mode 100644 index 00000000000..e8c65974990 --- /dev/null +++ b/crates/papyrus_base_layer/src/core_contract_latest_block.abi @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "stateBlockNumber", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stateBlockHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs b/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs new file mode 100644 index 00000000000..ed902849ee1 --- /dev/null +++ b/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs @@ -0,0 +1,118 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + +use async_trait::async_trait; +use ethers::abi::{Abi, AbiEncode}; +use ethers::contract::Contract; +use ethers::prelude::{AbiError, Address, ContractError, Http, Middleware, Provider}; +use ethers::providers::ProviderError; +use ethers::types::{I256, U256}; +use papyrus_config::dumping::{ser_param, ser_required_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializationType, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::hash::StarkHash; +use starknet_api::StarknetApiError; +use url::ParseError; + +use crate::BaseLayerContract; + +#[derive(thiserror::Error, Debug)] +pub enum EthereumBaseLayerError { + #[error(transparent)] + FromHex(#[from] rustc_hex::FromHexError), + #[error(transparent)] + Abi(#[from] AbiError), + #[error(transparent)] + Url(#[from] ParseError), + #[error(transparent)] + Serde(#[from] serde_json::Error), + #[error(transparent)] + Provider(#[from] ProviderError), + #[error(transparent)] + BadContract(#[from] ContractError>), + #[error(transparent)] + StarknetApi(#[from] StarknetApiError), +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +pub struct EthereumBaseLayerConfig { + // TODO(yair): consider using types. + pub node_url: String, + pub starknet_contract_address: String, +} + +impl SerializeConfig for EthereumBaseLayerConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_required_param( + "node_url", + SerializationType::String, + "Ethereum node URL. A schema to match to Infura node: https://mainnet.infura.io/v3/, but any other node can be used.", + ParamPrivacyInput::Private, + ), + ser_param( + "starknet_contract_address", + &self.starknet_contract_address, + "Starknet contract address in ethereum.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl Default for EthereumBaseLayerConfig { + fn default() -> Self { + Self { + node_url: "https://mainnet.infura.io/v3/".to_string(), + starknet_contract_address: "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4".to_string(), + } + } +} + +pub struct EthereumBaseLayerContract { + contract: Contract>, +} + +impl EthereumBaseLayerContract { + pub fn new(config: EthereumBaseLayerConfig) -> Result { + let address = config.starknet_contract_address.parse::
()?; + let client: Provider = Provider::::try_from(config.node_url)?; + // The solidity contract was pre-compiled, and only the relevant functions were kept. + let abi: Abi = serde_json::from_str::(include_str!("core_contract_latest_block.abi"))?; + Ok(Self { contract: Contract::new(address, abi, Arc::new(client)) }) + } +} + +#[async_trait] +impl BaseLayerContract for EthereumBaseLayerContract { + type Error = EthereumBaseLayerError; + + async fn latest_proved_block( + &self, + min_confirmations: Option, + ) -> Result, Self::Error> { + let ethereum_block_number = self + .contract + .client() + .get_block_number() + .await? + .checked_sub(min_confirmations.unwrap_or(0).into()); + let Some(ethereum_block_number) = ethereum_block_number else { + return Ok(None); + }; + + let call_state_block_number = + self.contract.method::<_, I256>("stateBlockNumber", ())?.block(ethereum_block_number); + let call_state_block_hash = + self.contract.method::<_, U256>("stateBlockHash", ())?.block(ethereum_block_number); + let (state_block_number, state_block_hash) = + tokio::try_join!(call_state_block_number.call(), call_state_block_hash.call())?; + + Ok(Some(( + BlockNumber(state_block_number.as_u64()), + // TODO: use safe conversion. + BlockHash(StarkHash::from_hex_unchecked(state_block_hash.encode_hex().as_str())), + ))) + } +} diff --git a/crates/papyrus_base_layer/src/lib.rs b/crates/papyrus_base_layer/src/lib.rs new file mode 100644 index 00000000000..d582f758d01 --- /dev/null +++ b/crates/papyrus_base_layer/src/lib.rs @@ -0,0 +1,20 @@ +use async_trait::async_trait; +use starknet_api::block::{BlockHash, BlockNumber}; + +#[cfg(test)] +mod base_layer_test; + +pub mod ethereum_base_layer_contract; + +/// Interface for getting data from the Starknet base contract. +#[async_trait] +pub trait BaseLayerContract { + type Error; + + /// Get the latest Starknet block that is proved on the base layer. + /// Optionally, require minimum confirmations. + async fn latest_proved_block( + &self, + min_confirmations: Option, + ) -> Result, Self::Error>; +} diff --git a/crates/papyrus_common/Cargo.toml b/crates/papyrus_common/Cargo.toml new file mode 100644 index 00000000000..601987082ab --- /dev/null +++ b/crates/papyrus_common/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "papyrus_common" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Common utils and objects for a Starknet node." + +[dependencies] +cairo-lang-starknet-classes.workspace = true +hex.workspace = true +itertools.workspace = true +lazy_static.workspace = true +serde.workspace = true +serde_json.workspace = true +sha3.workspace = true +starknet_api.workspace = true +starknet-types-core = { workspace = true, features = ["hash"] } +thiserror.workspace = true +rand.workspace = true +indexmap.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +pretty_assertions.workspace = true +serde_json = { workspace = true, features = ["arbitrary_precision"]} +test_utils = { path = "../test_utils" } diff --git a/crates/papyrus_common/resources/block_hash.json b/crates/papyrus_common/resources/block_hash.json new file mode 100644 index 00000000000..f3ee974f235 --- /dev/null +++ b/crates/papyrus_common/resources/block_hash.json @@ -0,0 +1,37654 @@ +{ + "header": { + "block_hash": "0x395daa726c74f1a96119796725d82b6b72452200cb62055c28e04202e07136f", + "parent_hash": "0x55f803cd7af981ed03d1ede9d52e5f5ba48cefb24e26ce181baeec3ae45c9dc", + "block_number": 183862, + "l1_gas_price": { + "price_in_fri": "0x0", + "price_in_wei": "0x41ab3fdb5" + }, + "l1_data_gas_price": { + "price_in_fri": "0x1", + "price_in_wei": "0x1" + }, + "state_root": "0x6c4171ece740d153a40106b18545f147d62c513a9cb67eb7b06f83a2508b3a4", + "sequencer": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "timestamp": 1693484880, + "l1_da_mode": "CALLDATA", + "transaction_commitment": "0x03ef487dcb7c114e91ffba49b91567a5719a188abe7a03466943588a4b06c453", + "event_commitment": "0x04ca88a5447b4885563a074af8316c6cd0e4e8949ba8f532f08770d2f986fc91", + "state_diff_commitment": "0x0", + "n_transactions": 332, + "n_events": 1561, + "starknet_version": "0.12.1" + }, + "body": { + "transactions": [ + { + "Invoke": { + "V1": { + "max_fee": "0x21ce72cd9cfd2", + "signature": [ + "0x254e1341fff2e81dec012208fd0a908d2a494af2052a0af24174877bfe7de45", + "0x71ed17005c723caba2e36534de7dfbcd9b7d2424cc8ea64a5c252cdf569589a" + ], + "nonce": "0x1a", + "sender_address": "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x853a0d2313c000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x853a0d2313c000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x1fb58f10b0acb295aff3863cfcdca5121392c4a6b05db20f3428c5d445579b3", + "0x7f4f70c316e16c7f1ad3fff96f5d213d391cf793b50f4fdcb2e15de818552a8" + ], + "nonce": "0xa", + "sender_address": "0x26ca87088efb5de3fb30bc2985d16330eda9faaa84f7b9af8c2a043cbef83cf", + "calldata": [ + "0x1", + "0x1b22f7a9d18754c994ae0ee9adb4628d414232e3ebd748c386ac286f86c3066", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x3a2fc8b0db9a9ef748227ef61ed254897cb40ad39575a9bde734dc78073f779", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2cce42cab7de6", + "signature": [ + "0x270e2a8f40e11e5ffed43c3bbd69972889e15867e3889e650b771faa0901b25", + "0x64a13b39842045871cfe438d8bb71a75409ce1057c41e7d2a63255aa577695e" + ], + "nonce": "0x6", + "sender_address": "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "calldata": [ + "0x2", + "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xb69b4361a8bcfea4e074bd844f59471180e9e07bd42a66ff4906186a9f2628", + "0x3", + "0x7", + "0xa", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x309e2082", + "0x0", + "0x1", + "0x309e2082", + "0x0", + "0x1a96079df3a8", + "0x0", + "0xc376", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x780da51c4000", + "signature": [ + "0x3b1243d8f48e6ca55895fe2c9ba74c3d92f9245e1f65f153356d098e5429aed", + "0x4450ec8b2e9e58ad3aa5de3353c97b70388a7442da918bc43c211d16632829" + ], + "nonce": "0x7", + "sender_address": "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x0", + "0x1", + "0x1", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x46f93bd68f539acdd84acfd6387dbabae04ac3e03004f40c1134e8bc55fbfc8", + "0x3bcd5645f911207cd48e3c9dd620377699ee06e3af87b1847999211241fc36e" + ], + "nonce": "0x6", + "sender_address": "0x4af558b8506186e8202ec994d711d523cf379717284ff44ef8d4d9089f8782", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x626f6c6f6265696b696b40646d61696c2e6169", + "0x626f6c6f2067616d6573" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x14bfec3ee0254", + "signature": [ + "0x7c8c459ba5cb670b78001d1ba92e4515c594ee27684b69109404552ce762749", + "0x258ce0cc6e6cc9ba2828140182857ba63bf6c51b76712fc652155891fa424c1" + ], + "nonce": "0xad", + "sender_address": "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x39d1cc435aba4b7727e32d1d8c6874f419df6432f3c1fd27d4e29d104abf", + "0x3", + "0xa", + "0xd", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2d4a98c3e9e887a", + "0x0", + "0x2d4a98c3e9e887a", + "0x0", + "0x143953d3", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x0", + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "0x64f09523" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x30a1e87c5490e", + "signature": [ + "0x51101aa5299c7fe3fc5e13c0046aa612d29a92a01670e8f4e8743f1e40d134f", + "0x1ee5f7f51764c4be3c2726af9058ff442eede9d3dd8e05397c7aa983ed7be6a" + ], + "nonce": "0xc", + "sender_address": "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2cfb12ff9e08412ec5009c65ea06e727119ad948d25c8a8cc2c86fec4adee70", + "0x6", + "0xa", + "0x10", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x54fd2a84932", + "0x0", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2710", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x54fd2a84932", + "0x0", + "0x534a05d3d7d", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2710", + "0x0", + "0x2648", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x52f680682f89c7066975ab8edfff1fd2dd1ab336b7ed8e436e77f11df5999e2", + "0x29b3d67fb66b22bc1b3ca838dc333aa3e996f17616bbe7a9ce0ad654ed9b71b" + ], + "nonce": "0x5", + "sender_address": "0x25d336ddc196a08e24d95d645cdc98738d57d8a78d502ba3bf60ef09fe302f1", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x4572657a757240676d61696c2e636f6d", + "0x65667320" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f012fae98cd", + "signature": [ + "0x28ae431412fa106c472581fe59de8d81b07f0ef3df4eebb2810d51c8aeaefa3", + "0x3ee8ce9723a2df7bc255df4197cb3b1a189d31a9f130ced2e7b2cbfc789d428" + ], + "nonce": "0x17", + "sender_address": "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1f1ed841f1d8360", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1f1ed841f1d8360" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x2e3cf2ca02de9c393581d71d68e0d08b448e36f7a215e6a471d2610ce1fdf43", + "0x25826a0ece4f9843d7be2d4131878d6cddbff53ac1a6147dd5598e16c33902b" + ], + "nonce": "0x817e6", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x36daa4935168fbfadf18f592e24de6b12a8862605a749fc43226f2a7efda030", + "0x20f81c5f840000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2df68a6bd2586", + "signature": [ + "0x3e8032af90d0dd19c743e6d65ec8b811af55484f13eceb5802beec5a814040c", + "0x41db7c9d6db77d5b7cbe7cede81eddecebdd73ad21da5feb5d0086be8a02575" + ], + "nonce": "0x3", + "sender_address": "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x2386f26fc10000", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0xf4240", + "0x2", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x2386f26fc10000", + "0x0", + "0x101af9a", + "0x0", + "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x129a06429b954", + "signature": [ + "0x300b2a9c8813c1e37aed07b61c75ab96a0ee889608dbbd0f999b78610515498", + "0x8fe56ea0e975be1bbd3898fbea038eb1ebfc73f1ae63ad7b46757b24e28a06" + ], + "nonce": "0x3", + "sender_address": "0x56938b103be20e69464936717788d42cd68c313978b3c49eddae482fdfdd12b", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x9e4cfa86c0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x5a41350b93bb", + "signature": [ + "0x1082d4fb04b6cee5a419001db526b809abaf8b3b61b691f4728daff5a72ea34", + "0x3b8ef088ee760fca4b6e9e3a20cbccc2a70f129c55964a1d0633683d87ec001" + ], + "nonce": "0x9", + "sender_address": "0x320de87ba71dd30890e2936910b6d5f583a09f46b9ae154dda6b6074d7675d9", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x7fb762ee4568f7b699adabf9f995462fea9e359cb679e8b32b9871468746bfc", + "0x60556bf9800", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1ff973cafa7fff", + "signature": [ + "0x5a9c3ebae6323701f8d2cc4f2768456611d1f3bc6b70c1a68d53a6cb33cd0d0", + "0x6ab665dd4da60230e5b51362a363f6b602069e5afc367482754e92bb0f53cac" + ], + "nonce": "0x22c92", + "sender_address": "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x2dbb492d8957b672dbff9840c4a2da5d1800d2f8df222fd51bcb40d8f493a8d", + "0x489156ba2ea001", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x255cc106e8190", + "signature": [ + "0x6e7c52b0c4ddde5385d7ccdb215da21846eb7aee388f46d5785bd564ab974eb", + "0x4047e1789c79d559b6e24f2cfb9f305635d9ebe4d10525e3dc7e6a6f56b4a6c" + ], + "nonce": "0x16", + "sender_address": "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc301e9394861", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xc301e9394861", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21c5fbba61b7c", + "signature": [ + "0xd31b78bd48e4f74ff2656a1078b97a7690ccc231a39b14a286f4cb7e3ed9b5", + "0x13dbfdf37678b5c751170be7754662cf32870e983e525f9c857007c5ee7ff84" + ], + "nonce": "0x2", + "sender_address": "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x944df26381000", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x944df26381000", + "0x0", + "0x429985", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10ff05cc9b000", + "signature": [ + "0x2e36ac5185d2b4a5dd7d1a1ce30ecd6b47d63345d9435f162c986472763ea5b", + "0x5d8b31c1840df2e78f9a34d052b284613b6f385a71861c8ef2f2a6ef1f8ad8" + ], + "nonce": "0x14", + "sender_address": "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x64acfe", + "0x0", + "0x64acfe", + "0x0", + "0xd5fc2eef6ad04", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "0x64f0947e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21c07121509f8", + "signature": [ + "0x69ee599ca5b302913bb7f0ec1e1d574f64a8fdd9887c573a03e655ca2fdf0ea", + "0x268154117b33b39233dc47805141e02a8bdce59148ff2bdbd0d0c5644e51ce" + ], + "nonce": "0x3", + "sender_address": "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x652e68bb34000", + "0x0", + "0x652e68bb34000", + "0x0", + "0x2d9706", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "0x64f32a16" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x379eae4072d956e75a8fe800abe6e575c706321f972ad95e806c09c1d866e80", + "0x46dfc90e8e56cc8af30491e99791ba47514633c1cb6d14e1ab63aea458f637b" + ], + "nonce": "0x817e7", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x7c1930a3fb0fdd9ea02fcadd27c45110e0063e29ebea9259714cf7e4c12ab25", + "0x54b3849164000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0xd66fc49d251fd6a5a88781fc19f929d0787fb7d3db815803130b33c797f4fe", + "0x78083f0f2b3601c82981937693a78ffcb2c743c383754e50db01ad9b4860bda" + ], + "nonce": "0x24", + "sender_address": "0x7cbb7403055ae474991ee3c8e00ea4b14424a6a727405c1285e3341fd70e89b", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x7a73757370656837383640676d61696c2e636f6d", + "0x48656c6c6f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x255cc106e8190", + "signature": [ + "0x3ac8ca1854249131ba465d9c4ad6592103cda319b23b4459a72e292667b7508", + "0x79a455ad740e8a54fe087f9ed223fc6b9721d211539ff6986c931d77fefc8d7" + ], + "nonce": "0x17", + "sender_address": "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x650ba08366996", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x650ba08366996", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1705869225000", + "signature": [ + "0x622d2532b09f663b40763aa5bae660e22967c31bb5f9f0db1290702a4bfd3ff", + "0x1938605cfae4cc05236dc0327762b9b7a94bb9e724711ce2db46a620cdd642f" + ], + "nonce": "0x1e", + "sender_address": "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x17d3f1", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xf4240", + "0x2", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x17d3f1", + "0x0", + "0x331bf0425d264", + "0x0", + "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2c6d4bee6e0a4", + "signature": [ + "0x18ac807a5ef88a57c88485463a3519ed5ffacc6099b1c1d630bcd78a7210445", + "0x9c46fc7778560af69f28e0e619e81dec7858acc59f7988ff94624855e31209" + ], + "nonce": "0x53", + "sender_address": "0x384e48629dd2808efd905c59ea9b3503446fb98687f11947543ee27428325b0", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x18d8d30643fdec6d9b8c21279f66988c66f43a2ff74851262f13f6eff0b2ea5", + "0x28e8f53df9dc0f229dadc4916536a1bc6d274412ec0849e66ca32fada58dae0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x23101fa869470", + "signature": [ + "0xdd86739e646c0941a6e8b78c31278dd876ccef23731c4228799b74c086b67e", + "0x3ac1c070b3f3e3e378295199aa6cce3074fc00f5fb2c47e7eca7a09dafbc71c" + ], + "nonce": "0x9", + "sender_address": "0x19336580bcb8886ce323d54d299c542e67b8567f70f43d93f643cf1133c657d", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5276e66c4675c8f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x415eb84b34a83e497735c4e2309e3ecab493d442cbeb919a41fb0c73cf8a544", + "0x4835936e003e97239e96790eee8db30dcf4d272129569ccc4a46c7faf954d58" + ], + "nonce": "0x3", + "sender_address": "0x173a1ebdd285d50ed9c2296cd2d71bbb978817cd59db9af17c51e96718fbf6", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x9016d1f519" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x16ae36d43f000", + "signature": [ + "0x28466a831130e1fbbe9ae25be174658fe693779cb3a408c00fa46a5b6e59c", + "0x386e07fed79262a494ba370fb18c0e85c18b8ef62b80d87c5a6b26a9c7f2d9e" + ], + "nonce": "0xa", + "sender_address": "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2cfb12ff9e08412ec5009c65ea06e727119ad948d25c8a8cc2c86fec4adee70", + "0x6", + "0xc", + "0x12", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x7ce9909b17f9", + "0x0", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x395f8", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x7ce9909b17f9", + "0x0", + "0x395f8", + "0x0", + "0x7a6a03794592", + "0x0", + "0x3839c", + "0x0", + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x3cdbed656bfc0697e06a7a8665d37c3f2b48097fe05870e161056f1c4979fcf", + "0x36eb5c19c5ff367dad69e584c5210183eea35c6c363dbd0229eb168d1f6f1d5" + ], + "nonce": "0x17", + "sender_address": "0x3fe27c102924cb4578d1adb1048db2005337dbf92259b374866c0fd2a646c98", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6f736e6f766e6f79373140646d61696c2e6169", + "0x422435441442" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x3236d34d0c4b08ea75c8781354afe7d8418e75b86c30ca4ee67c5a3fc17224d", + "0x39feed585bb22c375e91c254be02909e1b059763edd61296d794e7c2e7c9bf" + ], + "nonce": "0x817e8", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x392dd78035901bf189312ae7135fd1a3b63b5622bedec774a9e58745081815c", + "0x1835d5603d6c00", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x5af3107a4000", + "signature": [ + "0x27cdddec9576b5d6be854249004c3c72102b04ffee83844c267bd766bb2512a", + "0x4e782fa691917acf926e459c97b090b38533e4aa5925a9ae3b36cc47db3aa4d" + ], + "nonce": "0x14", + "sender_address": "0x528c925e7b695fd2f5167ececd8dcd5f458cf14c37eb909a98fc58142a4955c", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x3", + "0x364847c4f39b869760a8b213186b5b553127e9420e594075d13d1ce8a1d9157", + "0x7bb0f7b0800", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x22153f6e756f6", + "signature": [ + "0x58216881f1fcc1f65fead0ea4b940e4fa8e1574681acb699c284890ad34c35c", + "0x4c037d866aee0eea4f1e548589501f47faff2888acb6032881a8689ad60fc20" + ], + "nonce": "0x30", + "sender_address": "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xbde7b90", + "0x0", + "0xbde7b90", + "0x0", + "0x19790a007c06320", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "0x64f094fb" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x258bc74c86276", + "signature": [ + "0x2e2bca7ce89c6415e348734be29cd475d9fba078d30cf3e208f1e5a4660ecce", + "0x6f7ec9dc72c7c55cca44f9f7f53832e4f1cfbe210c7775b89eafe9820d8ed2b" + ], + "nonce": "0x16", + "sender_address": "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9764aa4a6f55", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x9764aa4a6f55", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x6f8fee9922304b629ca337cc083e143dfb668ac9129d61bdf609dd72fe5755", + "0x533856802c5964266d5c83722df16fa7f1ec583305dd771244e4a5eafa125e0" + ], + "nonce": "0x13", + "sender_address": "0x2bdc13afc019b08ccbb816b2fd91b296dbc6a351bec4434013536be58d370de", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x20bce99026300", + "signature": [ + "0x5ddcb602992c8e512a02df1aaeb58bf53ec37fa42b4f2bd07c0a2ba014e2bee", + "0x7d6b39724ac74505ff76482e8a1b97905d2c475c79ec31c292adf51622246d9" + ], + "nonce": "0x2", + "sender_address": "0x6f410bc0b9048455ef06252168cdbfa30f2c66e9f16871848746edf421da90e", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xa590f8b670" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x71fd4d48f4c6ade7a47a9865e1d3311fb760575f39a1ee5320c6e372bb7cfa2", + "0x33e2dcbf6c11f20bd9f29cbc410fd3c841d9d421a969408a7c9144df27ec16e" + ], + "nonce": "0xe", + "sender_address": "0x6081507ddd07a260d08d938cb667aa0d22e6c5cdf23e719ec99c0622c5491ae", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x225fe5180bbb4", + "signature": [ + "0x79b617efb98890683a94509c9cd0af09823d3c6c2de343fe15e6ba6af41177e", + "0x6a93978c6d4cfa55f4e171782fcd92c575ffa5407da780471b8ed16a5b90402" + ], + "nonce": "0x20", + "sender_address": "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x775f05a074000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x775f05a074000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x36d14c", + "0x0", + "0x3644f6", + "0x0", + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x12edc9ab5d000", + "signature": [ + "0x2a4cf7611b1178791a5ad28aa904eaf760337d5f4e30fdc9f1a88f4e88ec67d", + "0x328e9b28bfa3ae4033899aec595d067427005c1c0791921bda98313161642fa" + ], + "nonce": "0x24", + "sender_address": "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x16cc063b8338363cf388ce7fe1df408bf10f16cd51635d392e21d852fafb683", + "0x0", + "0x3", + "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "0x21b1db2234725d861dc258c6b852ebf8553dd1040720969790d8e6020d2bee4", + "0x3", + "0x19", + "0x1c", + "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "0x44364c5bb0000", + "0x0", + "0x44364c5bb0000", + "0x0", + "0x3e8", + "0x0", + "0x1", + "0x6b03ff460e78a39768340bb909ff8e9e9c507994ecbf6dd0e30aeba34df0452", + "0x76503062d78f4481be03c9145022d6a4a71ec0719aa07756f79a2384dc7ef16", + "0x1", + "0x44364c5bb0000", + "0x0", + "0x2eabab", + "0x0", + "0x1", + "0x0", + "0x12f3e256a78d411730c30d4ace443e31a59b1d48340d888d7aa198a2c4311f8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x0", + "0x39289ce5cffb918a0caff194a4ee12f7cea245aaccfab04b26832de8a789e4e", + "0x64f073d6", + "0x64f9af79", + "0x3e8", + "0x0", + "0x2", + "0x6c8dae8a2938ea90c0eca0c7847f7c96eafb5411e0dddc489d519c437252732", + "0x354f4ba758fb4ddeb988fe80de64dd2ad3512d24f83657376c8a2dae702d78c" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x166bbf6fd95ad", + "signature": [ + "0x488a8dc0e0116544d3f73a28dce49baca261f7fa2d7af9afbf6ddef5b8da3dc", + "0x5502fc72e0bff8b3e1845f61c2301278daf7b8b50d1351337f042b911014a23" + ], + "nonce": "0x3", + "sender_address": "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "calldata": [ + "0x2", + "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xb69b4361a8bcfea4e074bd844f59471180e9e07bd42a66ff4906186a9f2628", + "0x3", + "0x7", + "0xa", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xbea1317d47", + "0x0", + "0x1", + "0xbea1317d47", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x65366b946494f50818e1567071b63fdde2e153a139713e69c7d53015c7d8352", + "0x736e6e65024dd7bcf0ef7fe08d2241f5380da26e9fa2dc4981ee46e8739e65e" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x491fdf59535ebe73a642ac067a01cc65b5a8fe302006af023c58005f553e0b8", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x491fdf59535ebe73a642ac067a01cc65b5a8fe302006af023c58005f553e0b8", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x111c20613d000", + "signature": [ + "0x3933f91c16646bf8989b1fa63213d7340f15a88d34b95893f8dfd7bc5765eee", + "0x722d9f0b50d13705564dacad296a41ee62f8ab3bd58a5acb43e7fbbed10e94f" + ], + "nonce": "0x4", + "sender_address": "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2e2f6e5e148000", + "0x0", + "0x2e2f6e5e148000", + "0x0", + "0x14c34a3", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb3faf8e37322", + "signature": [ + "0x41d396c5f14cdc5c6a32bbd9604056e6e8eb59c9e0f61f826ca186fe98b1dd", + "0x2f53444dce24c44abc90dfc655671ca5740bc182d7c2e14ab0380db206e0306" + ], + "nonce": "0xb", + "sender_address": "0x2e1ddb85493a97793de29d38006c598b948e1b03878bc8dc634500c00efe27d", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x6845b38126c7ce2118b0088b82c738c47a6da100d562097358dea2c25e0431f", + "0x3afc3904c5e0091", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x4c39796f9d923deea176ddfa19d22d0f54c656975149fd82a70ebd94fc7c85e", + "0x71ba767df024be7adcf315bbef2b1afe4d7c93cf6b798bf75dc4cbac4719104" + ], + "nonce": "0x15", + "sender_address": "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x63616765696e6d796d696e6440676d61696c2e636f6d", + "0x63616765696e6d796d696e6440676d61696c2e636f6d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x20c44d232c710cd37d3ee9c64866c761843fbc0f84f13386a3af32731981aae", + "0x77227012ce2a555ccd7b98bb7eee0ef854af83824c433fbd9818a67646b9b05" + ], + "nonce": "0x1", + "sender_address": "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x676a686764406d61696c2e7275", + "0x6666647720667765776566" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x30ee11237d910c833b717ba6ee089257b3cdaf3c6da09f9a22c49e9caba8f7c", + "0x3890fd71d3f7fbb99abe6ac73380dc8739de47d97fbeb802ac0d2fbc6f0aeed" + ], + "nonce": "0x21", + "sender_address": "0x6e28706aa59de87c577af87df1b6b253534a82d48e0b1e9f1038ea9ad9f832e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x686868757967697540646d61696c2e6169", + "0x5265706c793a205265706c793a205265706c793a205265706c793a205265706" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xcee23da44be4", + "signature": [ + "0x94a03a88a312e662e5b262dbd9091b7a67382ae3c979d5894bfe92e0b03096", + "0x818cd7b3d2c046234f0d501a022f077e622358e8aaaf6fa8cf7ea247821471" + ], + "nonce": "0x16", + "sender_address": "0x465d17a4b9c37242556ea13db90332211a68ac5b4841806ef6c3b222bbaa5b1", + "calldata": [ + "0x1", + "0x60582df2cd4ad2c988b11fdede5c43f56a432e895df255ccd1af129160044b8", + "0x19ea78dfeefee473cead0f17e6cea7018f57abbf524110c3d3a369b248c7ce0", + "0x0", + "0x1", + "0x1", + "0x465d17a4b9c37242556ea13db90332211a68ac5b4841806ef6c3b222bbaa5b1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x3ede9cb57ca3f09e60be7bdf4d2734208f90a4ccd5f8ad7e0259b8bb955cc8a", + "0x375b3c01b63cb04c2ded600341970fb45156544fcd1f0c3e77e6174b246518f" + ], + "nonce": "0x817e9", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x76c9a967632f9fd33e271d61b93b0aa49f0106cde18d2dc5c3ece8b6a0b9b96", + "0x38d7ea4c68000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x12d0af16bb000", + "signature": [ + "0xaf13fe1666d915be02cdbf650dba2fa93351a1ccb20466dd4ec45cafc0e033", + "0x486fcd58577d02b67d621c3a8df9a4ecbe638340c04c768c0b215c0be0d2237" + ], + "nonce": "0x3", + "sender_address": "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5af3107a4000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5af3107a4000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x17d68148cf33f", + "signature": [ + "0x22f526e58d7979fa3bf7c3f9300e94e20494e2317efd94255c03ab003a8474b", + "0x71dcdd3962b09368fd92c31c76402eead19dd3ad1767a31d17239cf5eb9adaa" + ], + "nonce": "0x10", + "sender_address": "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "calldata": [ + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x717e", + "0x0", + "0x717e", + "0x0", + "0x0", + "0x0", + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "0x64f08863" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x9513eaaeb6d4", + "signature": [ + "0x4499e5cf65837ebb5d849a5ef9d675a58a20c2b2d0c2866fe62f6fb2ca3e956", + "0x2e21589b3dd70ee437592029c44f19dde4f41048ba0a994cf3d0cb556127cf3" + ], + "nonce": "0x10", + "sender_address": "0x226b0fdfbce6e933f1db111c6e6dad24bb05d15a0ef8565a97eeadd6b109439", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xdf6d70ccac" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x11393af5df000", + "signature": [ + "0x5f7c1491b8a4c5d0d062ecaa94cba932d963c8dd6b424863845242925e04dfe", + "0x2d19b0905c44abd635571a7f9f472996e6eef9ea7f5ce744da464c5299cefa5" + ], + "nonce": "0x27", + "sender_address": "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2386f26fc10000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2386f26fc10000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x10508c2", + "0x0", + "0x1026c82", + "0x0", + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10a667519ebb0", + "signature": [ + "0x7b9fedee10a0698798fbe35098103adc950b102d917f77447bc1bbeb2b73347", + "0x4f537401edd15342d52c96153db99b0feccdbecb754170ca5240635fc8b4789" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x53366a7258e5572f9ba5cd03e9378f10a41a2dea84c1797080ce1f14da5aea", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x53366a7258e5572f9ba5cd03e9378f10a41a2dea84c1797080ce1f14da5aea", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xbb5b1cd2e000", + "signature": [ + "0x1ca24d4afddfcb819597618684a49c5eb0e447fc86e2f158b6f402d4636a361", + "0x5f409b658f85f898749ce3c99b01c23938b373ecb747f92d230120b6ed72b2e" + ], + "nonce": "0x19", + "sender_address": "0x76a56a5fb9001d6af903dffab7b70b515522a970a74dfdaad09e2f5fa2353b", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x3f01d80498096f7929858b5fc97cdfbd676b5d2ee673407df0c957d6a0fef5f", + "0x0", + "0x1", + "0x1", + "0x7300100008000000000000000000000000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x1705c245135e82f617edde53149e5c882de6df34cbf01d02ba2fcb96c4b2041", + "0x49ec8cbda5b8f4ea52e00a125c5d82e370886540ea622c83f9ccaa7b5db8eb1" + ], + "nonce": "0xa", + "sender_address": "0x5f03d40dbf0cc25e17eae47060f09d277e07d1629e09fd8e63620e7e647367a", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xd9804cc437" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x1ae72ab721a888dc8bd1bc85cf8cb0d4d8be8945524495c742c032a309fbb6d", + "0x43fe72e73a72d4687c4c813699a2c872a4172f4fb5940fd250d543b7c72bf0f" + ], + "nonce": "0xd", + "sender_address": "0x854d0cbf46d77a1bb0ec14ac70e943afab2cb628f4c74882d4221d47ce427a", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x73817de2f000", + "signature": [ + "0x12fcb9d703e841c584e9214c9754365a8985a3fe693827e7c698c8ca085eff2", + "0x31763cfb6b4ff199aefac3493878a9bcd42dcce90a22d28932af4d6f01b951a" + ], + "nonce": "0x0", + "class_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9", + "contract_address_salt": "0x3a5bf647cbad631ea5a24cd784b70d5620aaa0e4e7dcd77fc75c92943687ec5", + "constructor_calldata": [ + "0x309c042d3729173c7f2f91a34f04d8c509c1b292d334679ef1aabf8da0899cc", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x3a5bf647cbad631ea5a24cd784b70d5620aaa0e4e7dcd77fc75c92943687ec5", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x4369ea5e574cb05e0c971ad40814959e8725b487f947b5d8aa2f802825c456c", + "0x185feecdb4297599f3cb3c76e5faf4e012f248ba7b1407c39973f23813f6e0e" + ], + "nonce": "0x4", + "sender_address": "0x69f39cf408157b2ff6b01935f1313d3f48c16b832ef96fee7da6e53b51110b0", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x98dea72e7e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf075803c3100", + "signature": [ + "0x6b25f7c66b24c1617307d0bebfb9e76af245c684378f98df2057e7016c24118", + "0x3807433d6b314ce80a79c7b65f6430c605ef073b7a4a70cb9c78018f382ad04" + ], + "nonce": "0x1", + "sender_address": "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x73817de2f000", + "signature": [ + "0x634636e4fb271219ff872e700a951c9bbef5e336e43a738444e99a9d56b1f70", + "0x48065d9f8f7162597ec69ced8a7a980ad82b35b1d8ce459ad56bab7cf0ce320" + ], + "nonce": "0x0", + "class_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9", + "contract_address_salt": "0x2a50b77a01d3c5f0f80f0517fc06767e8be82d146d8a6993371721c206f2c60", + "constructor_calldata": [ + "0x309c042d3729173c7f2f91a34f04d8c509c1b292d334679ef1aabf8da0899cc", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x2a50b77a01d3c5f0f80f0517fc06767e8be82d146d8a6993371721c206f2c60", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x258bc74c86276", + "signature": [ + "0x207067a0a24b834b7e684672b38331b5eb66e950546b15135d57e14c983003f", + "0x68e29bdf2c2c8674a0ae4fdfd4351bbae444733978f3e2483959ddd4edf5fa1" + ], + "nonce": "0x8", + "sender_address": "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5b09cd3e5e90000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5b09cd3e5e90000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x85dae0193801", + "signature": [ + "0x7dd525306fc4b83218702205c2f1be8d61852975c13649f99fb74e2a96fe51a", + "0x3266a410e38ef87bd9576ae153da04237a272620bfc3b4ded2325f16776590" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x407798b20e5cbdeb6aaade02defb04630af5b8da449444673452bd2ef722251", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x407798b20e5cbdeb6aaade02defb04630af5b8da449444673452bd2ef722251", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x73817de2f000", + "signature": [ + "0x6528e1f8b17b000b3d2aeefc0f53a4e018dc7b7434f88730a0e2e988a7bb49d", + "0x1139fff66c2e1fcb9dabdc62488f6a81087c7823be0ffcb41912767540e9461" + ], + "nonce": "0x0", + "class_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9", + "contract_address_salt": "0x52d0cd65e537ffd80239806de2b489930aca7f927dded19f52a8e711808f2c7", + "constructor_calldata": [ + "0x309c042d3729173c7f2f91a34f04d8c509c1b292d334679ef1aabf8da0899cc", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x52d0cd65e537ffd80239806de2b489930aca7f927dded19f52a8e711808f2c7", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0xe31c19c83b3a461abcd2b6740eb9ed3b63430d2d3f16a75904ec20bab74228", + "0x2755edf44f0badfe852c13bbb1f7fc08e8745336ef8097dfe4b4e0b22a7b0de" + ], + "nonce": "0x1c", + "sender_address": "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a0922657e550ba1ef76531454cb6d203d4d168153a0f05671492982c2f7741", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a0922657e550ba1ef76531454cb6d203d4d168153a0f05671492982c2f7741", + "0xbd75889095000", + "0x0", + "0xbd75889095000", + "0x0", + "0x549802", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "0x64f1d8a9" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb3faf8e37322", + "signature": [ + "0x61617baae4a42f789fb2e7046993c0eea37ee6a957b72b227ef7523fc0dc84f", + "0x4b6ebe24ddc2d1ec3d0895d6176fd76327d4e80d2a1eb860152c82bc7a4fd8" + ], + "nonce": "0xa", + "sender_address": "0x19961e608b5d0d51b9f8c76862f7231541e215ad9be1c1b3f67adaad7d23184", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x70a3a50e70e7a004b5e643ad03d01a270ea7d08839df454c03a56ffede2602a", + "0x27f7d0bdb920000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1130550ce5a6a", + "signature": [ + "0x65e97e36573b9c077b83e9917f1fbcbee1f66c724c0719f80fd29216ac8b54b", + "0x25be4c7ff97ab1589a6c9f525dd7b750d9e2992d6bec70656c6480486850c4f" + ], + "nonce": "0x22", + "sender_address": "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1bda703f0a0000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bda703f0a0000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xc28939", + "0x0", + "0xb8cf29", + "0x0", + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x167401aafb000", + "signature": [ + "0x6e648178117083c4a528c373b10847e2145d1f1df07604f67167b749e53fef2", + "0x1b69238cd2a331cd3f6210d42c9310fc48e9ca0400d91fc047e235d25f05990" + ], + "nonce": "0x5", + "sender_address": "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "calldata": [ + "0x2", + "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xb69b4361a8bcfea4e074bd844f59471180e9e07bd42a66ff4906186a9f2628", + "0x3", + "0x7", + "0xa", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x385944bc69", + "0x0", + "0x4", + "0x385944bc69", + "0x0", + "0x1da1d1e61e90cb", + "0x0", + "0xd8e9e6", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x1fc81f1ac1a3042b52e16a417a7e83c7d2815bd4bde90a121d2098ae084d14a", + "0xa9e898fae34a3e8d526d75f63ece6676f8587c2067ca8e5f28a6b600d0193" + ], + "nonce": "0x817ea", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0xf7069f39bc298e0e293d4e9ee511120964b623a90c6a2576d91e35b692d22c", + "0xe35fa931a0000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2216047035014", + "signature": [ + "0x7853841a15db91b722307bc8c209311ee13a3da615238710190e52c6cdb9bbd", + "0x6955aa3cb6ed6a78980f0c67684dae8841b9566ced19c6154b725d585019468" + ], + "nonce": "0x6", + "sender_address": "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1717b72f0a4000", + "0x0", + "0x1717b72f0a4000", + "0x0", + "0xa61d24", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x23ee86a1ad06f", + "signature": [ + "0x3d6f581835e5852a47de783fa0ad1889cc138d8b58bfd67d8b4801dbb5f7c6", + "0x53a1c2fff70435d431ef93a081ff0c5327833e55dbd9bd1d72fb7f9f55bfec6" + ], + "nonce": "0x474", + "sender_address": "0x32ff0324a913f56b666d6b1ec00c7ed5c1a277fab8fca29edf274838779337f", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x14", + "0x17", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x9ea563fa6bf6bb3f0", + "0x0", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x9ea563fa6bf6bb3f0", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x17e5a0a74eb59a0", + "0x0", + "0x17e5a0a74eb59a0", + "0x0", + "0x32ff0324a913f56b666d6b1ec00c7ed5c1a277fab8fca29edf274838779337f", + "0x0", + "0x0", + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x225fe5180bbb4", + "signature": [ + "0x5201965d2747a39db31a9328c2c72f8204f791b64f1a761890b99044164d2fe", + "0x2dd4dda916772b3468acdd41ebf2c5e5fcf4a40c8f1cf9b6539c2befff4bf34" + ], + "nonce": "0x9", + "sender_address": "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x146d98337560000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x146d98337560000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x961560c", + "0x0", + "0x94952a0", + "0x0", + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2a54ea2bd9b3e", + "signature": [ + "0x515720c4812f71f4e408cd69f69f9c64dfbf18a39aecad0684cdf697c470eb6", + "0x6de50544d5478fa018e317366da5cad127703d93112a40fabbffc915f190a8d" + ], + "nonce": "0x44", + "sender_address": "0x707766f45fb32682ac74df9145af9bf22dc9cb7e6e3e13cd5486b7d97cc34f5", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x23c34600" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x15ff641b292c4f85aaf5f4fc06dff2a05ce308d5cf85016af53100df3d751ac", + "0x7fef83e6cd462ade71af81887e519ec41434d5074a99856ad6d9e12b5d06587" + ], + "nonce": "0xf", + "sender_address": "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x71afd498d0000", + "0x0", + "0x3329e5", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x64f32a36" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x73817de2f000", + "signature": [ + "0x15f03ed795b1be1acd0b2c33de83642dfb3a6066f3969527987fcbcf0738186", + "0x2d55a7a433c4978e5d5a9a89a0b5eb184c9c76da7c655e099c0b1455cbc36d7" + ], + "nonce": "0x0", + "class_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9", + "contract_address_salt": "0x4f87a1b68dc6d0e838eaf1a18b7d06848b37408508174ff807be333188f876b", + "constructor_calldata": [ + "0x309c042d3729173c7f2f91a34f04d8c509c1b292d334679ef1aabf8da0899cc", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4f87a1b68dc6d0e838eaf1a18b7d06848b37408508174ff807be333188f876b", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1565541babf62", + "signature": [ + "0xfd0575342d99d328b787efdde8567a75cbe945d451c93b803e28c36254f459", + "0x7126c5c559fbfcf01a5edd2d2c7226ca5885b4a0066a720cb312539551f5583" + ], + "nonce": "0x638", + "sender_address": "0x7644743cf33d50422c7edb85177d23363e67e1295e7c157b8385ec6a083d8dd", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x14904840", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x14904840", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2cddcb197db3ce0", + "0x0", + "0x2cddcb197db3ce0", + "0x0", + "0x7644743cf33d50422c7edb85177d23363e67e1295e7c157b8385ec6a083d8dd", + "0x0", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2294398eee7f0", + "signature": [ + "0x411075f5f8c40c87e5424bcf10943019b5debca5b977c1e6faccbe20304d532", + "0x2220959e7cfd8d0a9bfe02257405a59103fe210534c229e0c7ce8f616bef6c" + ], + "nonce": "0x28", + "sender_address": "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x243f3bbee6ca000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x243f3bbee6ca000", + "0x0", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x109777ba", + "0x0", + "0x106cfe35", + "0x0", + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3093495b1cbc0", + "signature": [ + "0x5edd76cbaa2e15e94141c49b6361ea11ec1e96f6be711c5407fbbb52eaf0423", + "0x35a068804fb981ef8b89932b35c692f6af810ab7d868887d4a620967abaaaa5" + ], + "nonce": "0xb", + "sender_address": "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "calldata": [ + "0x4", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x3", + "0x1", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x2d88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc", + "0x4", + "0x6", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x2d01c9f1ed8d814a32aac4171c6cc5a66828d7f97a5da83a6bb6b6f064a0ee2", + "0xa", + "0x2", + "0xc", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0", + "0x307c3d542c", + "0x307c3d542c", + "0x27ce62e5e340", + "0x16d", + "0x0", + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x0", + "0x1", + "0x27ce62e5e340" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2418da01d5618", + "signature": [ + "0x31f6ff9aba7c81b1073c90d368a135e6ba4d47672751e37e7460327fb769e22", + "0x4c435ed30d3653a0ca42a0d741d833e9a061ac2c4834805a30f64441ca57e05" + ], + "nonce": "0x22", + "sender_address": "0x1d81237fd277baceaf255a1c663f754b8b5642612082f2ad6c65dba4f593df7", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1601be86ace47cec" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x129a06429b954", + "signature": [ + "0x4540a534122d91fedc7b321d664ab2b9f89ca5d09e1128dd82a6c757c85525a", + "0x24d1607617e10902510bb75668d6ea4296b98b5c2f865b88e86007c47063cd7" + ], + "nonce": "0x4", + "sender_address": "0x1be8bb665504cf62d6c2ad4c3074060dc8dff71e2c471c479736593d4af7929", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x58e8269ca1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x187152d40e000", + "signature": [ + "0x194d4fcc3641ed532bb607170a5ae1aedf2475db27a6c4537a8d73297f4b5e2", + "0x1e19a9456bec258b345e0fcc6dae41b7c0fcdf831d1cecc4177bc3a1d4c663b" + ], + "nonce": "0x36", + "sender_address": "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "calldata": [ + "0x2", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x147fd8f7d12de6da66feedc6d64a11bd371e5471ee1018f11f9072ede67a0fa", + "0x3", + "0xa", + "0xd", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x102038513c", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x102038513c", + "0x0", + "0x88711de874c61", + "0x0", + "0x3eab6c", + "0x0", + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x64f32a2b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x3ed38acd94ee5eec9b54fafaa5059694a3e2a2a8a7759ed435b63e46b90dd1", + "0x34ac3e47e4b97a009fdd3c0eccc33cb0991318d1da40aa5060bb67bfff571c6" + ], + "nonce": "0xe", + "sender_address": "0x5b9543e2656b0b7bee6bcd769d3590dccb859142266a501016ca94951538b0", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x16828ef54c000", + "signature": [ + "0x2d544822f775d03355591689f91e340fa0f95c2fd0f92386bb5a9d5a4b91961", + "0xa856b2bcdfbcf31de90226853fb4f18885495cae29abcf5c09b19dc08d8244" + ], + "nonce": "0x2c", + "sender_address": "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "calldata": [ + "0x3", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9851ff", + "0x0", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x9851ff", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x73817de2f000", + "signature": [ + "0xabd4cf1d5c201a68ce492330791714f38e9ba099d65b8d3c3ff3f9315366f0", + "0x7804157bf24a4182a2a44f206f711085ab4a10d2f9b732fc17795cc7da51d14" + ], + "nonce": "0x0", + "class_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9", + "contract_address_salt": "0x5e68470f58ffdf2395b3db8842788d89c316fa1f27c154d627d38dff902fca1", + "constructor_calldata": [ + "0x309c042d3729173c7f2f91a34f04d8c509c1b292d334679ef1aabf8da0899cc", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x5e68470f58ffdf2395b3db8842788d89c316fa1f27c154d627d38dff902fca1", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x4004104f83298bbb1585cf9ac14e1bd6f0f3901094180cd27ef7473dc57289", + "0x1c4dd37a73c88bf166c5669778e0aee3badfe30a7fc9433e65a2d43e31cd83b" + ], + "nonce": "0x817eb", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x1029379fd69f67a123b5487a71c23e988239a8597aec643ca829a4f203f27d2", + "0x3e2d15c04e9800", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x20a7bc32da0372b1ea965dff0aeb909fa6f4630c958e9b6cdacf3166805e062", + "0x76c35e29712ecaa5366af582cd3e35348c2201027824d0ecc9a304423091cce" + ], + "nonce": "0x12", + "sender_address": "0x3502b7ab0b9bd201aaa37bac6b4329557bee7d57796eac7d056f58a3f5c333e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x307831623532363934383736616361353935323435626136643933623734336", + "0x5265706c793a203531383620ff0c736b203036ff1b2054c854c8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x14a8f2f4a97a4", + "signature": [ + "0x7b029c378db182ff8dc5de7ee7109cadf024e12af34db1635b5f67e4c43262", + "0x2e5db0f2c132eaecc85dbeb1ddcf49e543147587cdce7946f9234a3bcdb39da" + ], + "nonce": "0x3f8", + "sender_address": "0x1383eb2872e594ffda60114a8a6a151505a083629f9eead70bb082bcd3f213e", + "calldata": [ + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x470d9", + "0x0", + "0x470d9", + "0x0", + "0x4c80ae0", + "0x0", + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1383eb2872e594ffda60114a8a6a151505a083629f9eead70bb082bcd3f213e", + "0x667ee5ed" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x8ed869518f42abdfc89b8bf5e96fae01c6bdef5fe5a4211f67cbff6b919434", + "0x7167a9e4387c35e509de0dff501a8ae46f5c48b69411d08e1d1ba3aa472df8" + ], + "nonce": "0x1e", + "sender_address": "0x7a70e197c312275cddc355c9996e75baf768fe94f35694d138b33713d5175c0", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x61706874686f6e677332303232403136332e636f6d", + "0x61706874686f6e677332303232403136332e636f6d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10e2fddd30dbe", + "signature": [ + "0x7e707491f6ff3eaaae049bebb76dd0fdd949b84f1a3f9a0e2d7d82db621f4fe", + "0x75d79501154fc44ac8daaaaa734f584b19735a49d67732ecdd0597e43372a2b" + ], + "nonce": "0x2", + "sender_address": "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4ed58b9570cf", + "0x0", + "0x4", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x4ed58b9570cf", + "0x0", + "0x233d3", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21ce72cd9cfd2", + "signature": [ + "0x71fcc59bee79ead56263fbf90248100d2a7cdfcfa0f930a31a30e3a94997db6", + "0x3f4a22343d752c60e785d505fb366dece9ed507627cffbc24ab21a78720053c" + ], + "nonce": "0x18", + "sender_address": "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x8d6d7882642dce", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x8d6d7882642dce" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2ccf07cc77706", + "signature": [ + "0x60eb9f7a62908c95f131c61e7869418011d0d325ecb25cc48d7b0aeaff4ab15", + "0x35ea0a37e7624701637ef90216260673e275e7ba7ba4a252f9b16d7e3788cc3" + ], + "nonce": "0x19", + "sender_address": "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2f87bb821a1c1ad3c2c226efac39b9d415c9b34020d1a50d145bb3ef7248ce4", + "0x3", + "0x1", + "0x4", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x970dca9f", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x3418c1f49aaca35334e684fbc420bc64a63e5b7a055880e8cf19f9772c19c29", + "0x25d61ae9043697064d8c410ae8b39863a1c33225a7206a7f8367029b9b4ead" + ], + "nonce": "0x817ec", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x489d8f2840456c0488589dcc9d1a3a08025740c29de78bbf5c51f2a3f262a61", + "0xaa87bee538000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x18f1b1335b440", + "signature": [ + "0x3c50fee5e2fe7ba71728c9c86f358397efeef7c527cf139c75c36a1326ca0c1", + "0xf63c03348c640039ebaa4c3d56e9d92b0e6f8d72c84873a7b6b1b38ef221f6" + ], + "nonce": "0x2b", + "sender_address": "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3a6a860649d92cb2c2e1068e013c8ab63b36c6155658861e544a3f477c9691b", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x4bdb62a680400", + "0x0", + "0x21e4e5", + "0x0", + "0x4bdb62a680400", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "0x64f09544" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2593e41f6b4d0", + "signature": [ + "0x3b4f5c0396858ff2ac05876a13a35c6535cd9327fa7792185aed2e605b441ec", + "0x56fb337c53761f41c4dfc767dbbd2d70325e51189814027ae62f8f2ac9bc3fa" + ], + "nonce": "0x6", + "sender_address": "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x8f6d6", + "0x0", + "0x8f6d6", + "0x0", + "0x1312b3fd39be1", + "0x0", + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "0x64f094c4" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x9513eaaeb6d4", + "signature": [ + "0x262927ac2e5545594f977dec9180118cd1a7b6eab2ce15daf7ca082ab9123d2", + "0x61837fbd18128647abd739709babe68963f65d80a16f6b34214c36927f9dfd3" + ], + "nonce": "0x19", + "sender_address": "0x5b4051fe17a5917afd5f2c60be97e35f0a9f2e6f5ffc350db48dbfc4e2c9da5", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x8383e7f2ec" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x6cdf218621c8c24a9e335c34f5c748bdd5bc4093b2c088f2dd8c99df7e46366", + "0x6e4ebc20844d8a4d3d440b34fe22bf853091775e133bd204a89879a375c7d01", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x2b39ba3678268a6bf04bbf750f4b32a87052cc4059a38859bf626a8bab1dfe6", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x2b39ba3678268a6bf04bbf750f4b32a87052cc4059a38859bf626a8bab1dfe6" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x258bc74c86276", + "signature": [ + "0x563b7f66059361e2a3c4b968385067b222620a5e501604bd89500c73126c04e", + "0x1592d6ed7b5f17566e49da8d17e9236e1aae48da665b7c4cb9d9bb1b64888b2" + ], + "nonce": "0x16", + "sender_address": "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xeb6a0c8e2b24", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xeb6a0c8e2b24", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2df68a6bd2586", + "signature": [ + "0x32648bddc3a0164a0394e2942ffc54527cb9e99333a231b020eae563ce31777", + "0x7d8a271dc2e8338305ed4832740469838ea28619a9a131c41e28b9453ffd5c1" + ], + "nonce": "0x2", + "sender_address": "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd7ec0b", + "0x0", + "0x1", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xf4240", + "0x2", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xd7ec0b", + "0x0", + "0x1cfe2bf2aed5d3", + "0x0", + "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2cd77edfb2b5a", + "signature": [ + "0x6465be410e1e70af9794c395693e086d1dd9f6ccc8cc6596aafa6dbd181b3fe", + "0x635daddc41880a352c5eb86d60f2b8fdad5a5579b50afb532eb5ea65a46291c" + ], + "nonce": "0x4", + "sender_address": "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "calldata": [ + "0x2", + "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xb69b4361a8bcfea4e074bd844f59471180e9e07bd42a66ff4906186a9f2628", + "0x3", + "0x7", + "0xa", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x172116a720", + "0x0", + "0x4", + "0x172116a720", + "0x0", + "0xc2449a4fd8825", + "0x0", + "0x5930d5", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x85dae0193801", + "signature": [ + "0x84adf42cdefdd4edffadf486312eed87fdf040e203c461c3442668bb1785ea", + "0x1a5469e7b82b68385da9b5346bd6d3b80533240e648a31d594e8ad0b83ba2eb" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x404c9752eccc53c8a4164358d82eef2fd8f9055eb76ee188d3f435bdb26f254", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x404c9752eccc53c8a4164358d82eef2fd8f9055eb76ee188d3f435bdb26f254", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x776b8e3dc02f1d1f5cd60542e51722b1592ac39ef1a1805da801304dff1e9c8", + "0x345f5d27705a73450f55b427b152f3e30734898aeac36553baaf9b0bdd74464", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x1a735a288f631ed09a0b2bbcd5ab6d5b40df2d7c77e358d4fd752d60f0d30d7", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x1a735a288f631ed09a0b2bbcd5ab6d5b40df2d7c77e358d4fd752d60f0d30d7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf1ecf382a000", + "signature": [ + "0x4469ee9dfdfdcf80e7ff08c09e170f0b072e9dc2a4545e06d2a002b07d3b9b9", + "0x3687ec6c18fd316f5aea76fa2139922c55febef65003360184f8b0e244b12a4" + ], + "nonce": "0x8", + "sender_address": "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xad257770e86a03742ebe0a615fb19503d9c891d118daa82163867444c08680", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xe9ccbccb8a46f", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xe9ccbccb8a46f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x14810662e90eea172e01d1b1d6c7a6581b63066e0a23582c50153973c76da4b", + "0x36fa1bb34cfbf774417093cfeba1e3eb4a55c0e768a21c7477ba33afd224144" + ], + "nonce": "0x25", + "sender_address": "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x8d18cad", + "0x0", + "0x8d18cad", + "0x0", + "0x12b844243dc4eba", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "0x64f32a36" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x33f6280a3d94905279689b9690c9fd320f10e91fadab52647782ff3d3d526e9", + "0x85119c9270401cb18e3d80b17308fa34a617de34f60286e9de8a645cb0bb1d", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x4880c6b60137ef3ccc9f159e1e2d46fc7dcae4650fec40903675ffb82af4846", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x4880c6b60137ef3ccc9f159e1e2d46fc7dcae4650fec40903675ffb82af4846" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21ca99c4df236", + "signature": [ + "0x418121f2237163fb81e8f1c44f4378f23cfd9f81fb57d0602f84fed9792518c", + "0x28a574efb7093042baa66341781d6454c40ed32ab1f814fa60a8c77097faefa" + ], + "nonce": "0x7", + "sender_address": "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x795ccd008cdad2e2611e4244faeab72dd68107fdd3c1e7a9b7c5431178e1666", + "0x4bd9948db23134cc8772cec5040d101873a2f4dd79cfa6d0e04c15d5c052ef4" + ], + "nonce": "0x15", + "sender_address": "0x40d8b68d4cb322fc69be5cd974df5d4a98744040735c6694ecc0b3da7c4a9f3", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x676466676466676466676440676d61696c2e636f6d", + "0x666573667365667365" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf0018141ea42", + "signature": [ + "0x5e6f183518d221988ea2a00c91b6849686e9df694c5b816ce3d209de610eeb5", + "0x4ae63d2401a3269de3da520ef954a80982685634e025ee50f6d8378feb44454" + ], + "nonce": "0x1c", + "sender_address": "0x5845060531ca6bd2679c3c4c7dd6f2e8d7db4665e348adf96ed799e3e8cf30e", + "calldata": [ + "0x1", + "0x173f81c529191726c6e7287e24626fe24760ac44dae2a1f7e02080230f8458b", + "0x68bcbdba7cc8cac2832d23e2c32e9eec39a9f1d03521eff5dff800a62725fa", + "0x0", + "0x5", + "0x5", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x18bea16edc7336", + "0x0", + "0x9c3c725560c1edbfbf5d00132777b92d58a6495a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x6b171016a8a44722f01dd7e8ab9208c0c5b271977bdfe6f75ba251ecc64a825", + "0x39bafcc38ff346996d6a853cfaaaddc2334f78c96b45a1958b916bc7bc852a" + ], + "nonce": "0x1", + "sender_address": "0x32ec531e21017143b0992dfe578562a2edfe4a516eb4a9bd2bb733068fe8c83", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xc530ac5b04" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x129a06429b954", + "signature": [ + "0x367036aca33cd3f7322d53d0e295d5709a4582252b323bd5d4956a620d52bde", + "0x3938da090dbef8c2af47c9c772456971298eecc3c2752cd85694615a98d0ab6" + ], + "nonce": "0x15", + "sender_address": "0x5dc9ac78471a66c0e8d71d72987878ff4f6024c478e10f4948a88f760a73e1b", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xdfc078fe2d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xbae1e0919802", + "signature": [ + "0x280d357bd6f5741e4f5cc91b4eb4382dccc100ad4e27651e287ddb5a834edeb", + "0x4a042f66c35207e558ad7ef01406f5530849d9ddab1cf0e4fc89eabf0ff2087" + ], + "nonce": "0x18", + "sender_address": "0x49fccdd4f0d252b0431b20a618c3b7babfb2e206569d7fd9507cb9b88aa65cb", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x3f01d80498096f7929858b5fc97cdfbd676b5d2ee673407df0c957d6a0fef5f", + "0x0", + "0x1", + "0x1", + "0x7300100008000000000000000000000000" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x53bbabdf26f03f73bb65adde0dc1ec7e130b47ae3385c133bed796d52af12e5", + "0x46610bbb246d5813ff21ed55ff215b97675f058085dec766d72ed81e39432e2", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x3458fdba97b689461cd2497df1178e8b5107f001078d3637cd4c74fe75d7473", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x3458fdba97b689461cd2497df1178e8b5107f001078d3637cd4c74fe75d7473" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x109ebee38c820", + "signature": [ + "0x164e06a866ccacbdb82097373f68bb14925c84e011f38da7fca3f3deca61093", + "0x7a58e90b579e32c966b552518298b0978270711b5d97f43a51aa9175243f288" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x3ed14e213ebb97a5b132348ddd6b79a7a803ec0b93ece9da03857433cd5d4c0", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x3ed14e213ebb97a5b132348ddd6b79a7a803ec0b93ece9da03857433cd5d4c0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x1ebc690f537eedd0bdd6a1378bfe4d01337bf8a648fed665f7957c0bcd15acd", + "0x3f6c338ccbb12107e1fa39af41fb0298e46c6058d0c29ade8fd2118c8c8f30d" + ], + "nonce": "0x15", + "sender_address": "0x1655d596876c1c5c1492411cb8e4c308eaa7308a67a4bb8492091c1ec910ce7", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x646d61696c7465616d40646d61696c2e6169", + "0x5265706c793a2057656c636f6d6520746f20446d61696c204e6574776f726b2" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21bcbfa566e08", + "signature": [ + "0x24bdf16091275a37d95531606ca00272198a548906c8732fd8405c52618ec92", + "0x3b89e865236f48ab84f8bd09a350bdb52452ecf1ea58427408cf5b11b3165cb" + ], + "nonce": "0x2", + "sender_address": "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x18880c1a1aba000", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x18880c1a1aba000", + "0x0", + "0xb0344e6", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x5e12ad996438d89db62b3e036652f709077a5279abc6fccf5b6ef7fda7bb348", + "0x31f884475f7445efe24eedad7b098d8ec86fa083c5f6d57c09d17b0ac760664" + ], + "nonce": "0x18", + "sender_address": "0x616e036a09afc3374e8dcfda106b4cd7ffca06e3bd0faf201f81b8b9d97c51e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6b617964656e696e64656e40646d61696c2e6169", + "0x7478" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x330129bd02737744d1c8f59bf49b60ae4c253e382beb3604e7b6d7a0d8db709", + "0x5b430c5e975bd6ac2586b45dfeb3ea82a1072a5a3f0b62b18f35368998db56b" + ], + "nonce": "0x43", + "sender_address": "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x7768697465736f636b7340646d61696c2e6169", + "0x637a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1bd6d5871ab5f", + "signature": [ + "0x62c81058e303d2bfd53bb4c1b50594a0520f2fedf096b5c6704792eb34cf77", + "0x23bebbaa410a1268cdb3920f62657dd1aced9f662851fdb1d95bef9f082bf2" + ], + "nonce": "0x1e", + "sender_address": "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "calldata": [ + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa2", + "0x0", + "0xaa2", + "0x0", + "0x0", + "0x0", + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "0x64f08867" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x14a2d29c9ae64", + "signature": [ + "0x48686c002a7d83e633c86f47f9f4acdf7b25194c16f5f4b47717108acd085ea", + "0x6f6c226d10820a5e591cde958fd659c220a780c316cf27b3520ecfbd33846fb" + ], + "nonce": "0x730", + "sender_address": "0x1ae80d66cc58dc4250a95a019a8c6dcb11f2bd0053ae6e9136c03b01be59a88", + "calldata": [ + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xa4dcc", + "0x0", + "0xa4dcc", + "0x0", + "0xb05ac88", + "0x0", + "0x2", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1ae80d66cc58dc4250a95a019a8c6dcb11f2bd0053ae6e9136c03b01be59a88", + "0x667ee5ed" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x21f82dd723913ae954aeea5ed94f38cea1448b413d9921803e76f5a72588d96", + "0x2df335513d8b14f89597fd11bbea735c306bdd5bc19cb93171c97886c43b8e9" + ], + "nonce": "0x39", + "sender_address": "0x56e6fedc391f795fadeb64a21d9cf1b0a4e6f10f2586e6d84e463ac41a93f0b", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6a69676b7a383933343540676d61696c2e636f6d", + "0x6376636267" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x4831f1fd469f21dad2ff90ef3b5e10b18dfa827b669367859ae3a6f3ef39b7e", + "0x395ab5e9755d5d65b43f4bfcfd91ea833ec05739f4d909d46f803e9304c1ae5" + ], + "nonce": "0x4", + "sender_address": "0x5bf6eb94c8da5c92fb9d791faa0078b9dc753f4ad22b2f052d6e8ab07ee4224", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6a61686f6e64616440676d61696c2e636f6d", + "0x676864666a6b206268756469206767687670756920652047485650385545524" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x2f3d15aa43b92290a99aeb241f09b374e17c6e3ebdae9c99891d878df77407", + "0x7753e700ac671cc85dd588d4dda7fc9812d0945e915cbc252ac43f7cb2f8646" + ], + "nonce": "0xc", + "sender_address": "0x3aaff5decb44871272f03537576860189565bc2e8a6ce7c59dbefe682b108fb", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6a6f64796572696b40646d61696c2e6169", + "0x617364" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x37fb7a2ef9620", + "signature": [ + "0x7380f5ee88000d5e9c1df4960c82d5d3665aeabc1558d382251e54bf9dd029c", + "0x1b10d0ebe0c3fc1abb1b8095e94c68baa8aeb3381a438879ed9a718716fdcfe" + ], + "nonce": "0x4", + "sender_address": "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x8391c9a", + "0x0", + "0x8391c9a", + "0x0", + "0x761c081f105b8376c", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "0x64f32a36" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10ff05cc9b000", + "signature": [ + "0x6f9b8eb1e5953272e018dcf36ca52235e795069c1f6af61ccb08f31f111cf48", + "0x7b6ba95b8c0a5fa0d6de073f14d7b05d7ce88503277f44d6f0d1d395a0406fb" + ], + "nonce": "0x2", + "sender_address": "0x135d7f3bfc7e6912b960863efd478700dc566a57ad2a583c64c5c318d178f1c", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x1d8efef488000", + "0x0", + "0x1d8efef488000", + "0x0", + "0xc61d5094ab9ab8b", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x135d7f3bfc7e6912b960863efd478700dc566a57ad2a583c64c5c318d178f1c", + "0x64f32a37" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x686d0e50a157282b86902dd1fbd37aa29925517d20f915729c4ab4821755c1f", + "0x52cd43ab5c8b229eedbe6c93e415744af1fdbe7eec10d3c2462b0c7d6ebf75a" + ], + "nonce": "0x817ed", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x5e468c23200606b83382459808f4557b89b7ed029085fdd1b19f1de58465c62", + "0x169554ba6afe4000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21c15dafe44c2", + "signature": [ + "0x7678e91aa5b6c7e911394819e7043d85f2c8c857b24910103a339c92e55ad44", + "0x63d461f5f6da240beedf3a8c263239eaeb370cb823bba929fca7662db807c19" + ], + "nonce": "0x22", + "sender_address": "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xef67f119af90", + "signature": [ + "0xea09a1ce48495ba79091bb7562476a99e0edc2fd5d78e632245ac6bf2ea2d6", + "0x617c2848cebf943e9fe58c965f3aeffd9f4316351af8d95bacb4bfeebad1df8" + ], + "nonce": "0x1", + "sender_address": "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x62616e616e61325f6d6f6f6e407961686f6f2e636f6d", + "0x486f7720446d61696c206973204368616e67696e67207468652057617920576" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x259d14a3812b0", + "signature": [ + "0x5a44623c4bcb88905471f14025f7b749d34886d2c32a194ae23fbaa9d5846c9", + "0x4c05b5a2a5d260e77a1083c0cc50c4aaa66a807f6be0e1f612db357065eb34a" + ], + "nonce": "0x22", + "sender_address": "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xfa63e3", + "0x0", + "0xfa63e3", + "0x0", + "0x2141f5056ad92a", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "0x64f094c4" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x47043e9aaf5b537f7865bef09dac5766a89ced1359f080f6bd0b3a0ee39ad2e", + "0x28a76e6f959dd975cea8d1f90b7cb2e894b1796ae0aa150030bd85a1aaa500d" + ], + "nonce": "0x13", + "sender_address": "0x30db36e00854e1b78009a3af9a6a9a03b16974dc52cc8f3f5be7baa2ce02cb1", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6673646673647640676d61696c2e636f6d", + "0x66647364666574776567" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10ff05cc9b000", + "signature": [ + "0x64496e53e75e453b5e9cbf8427806664be85045e28e6697fa635069adfa1e56", + "0x3bb5341530a06f27338bf1829ad17f540ca67b8db91b3916068ad1baeeb1b02" + ], + "nonce": "0x4", + "sender_address": "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x71afd498d0000", + "0x0", + "0x2ebc5bf605f4cf1f", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "0x64f32a16" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1156558a81000", + "signature": [ + "0x25a61ab9a682ae49842ce9974fd4378bd9a8f3c9f96a8b2978dc09f8ed465af", + "0x638e713786a23802ed31c65ca767d36e1a019b988ed57b46cbe65b9affa5a4a" + ], + "nonce": "0xc", + "sender_address": "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x37a4818a78e000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x37a4818a78e000", + "0x0", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x197a9ab", + "0x0", + "0x193960d", + "0x0", + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xbb5b1cd2e000", + "signature": [ + "0x68fdcf9c9996836c1aaf594aa272cd2a4bd7be3d29058d5625f35d72296458c", + "0x3d181f7770749ecd06edd5e7b4b626e2a19040c60d9297333776f5090eea0" + ], + "nonce": "0x2a", + "sender_address": "0xa3abb7ad34f4de0c5c3b06397315d0f35de6489c5fd89a824529e4ba4faf18", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x3f01d80498096f7929858b5fc97cdfbd676b5d2ee673407df0c957d6a0fef5f", + "0x0", + "0x1", + "0x1", + "0x7300100008000000000000000000000000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2dc85e02ec242", + "signature": [ + "0x6f072000e3d7c428c17be4bd0fbbfddebb456489737691a74f52e5255a4110e", + "0x615844382f8632e33a2eb5e4870cc2f14087272029ac57504b91865c65de814" + ], + "nonce": "0x34", + "sender_address": "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd02ab486cedc0000", + "0x0", + "0x1", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xf4240", + "0x2", + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xd02ab486cedc0000", + "0x0", + "0x1e8e7b5ea66a08", + "0x0", + "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x4d20fede745223d1b852c0b69ce5ec195d1ec165d292500b42b9efdd5a30024", + "0x6459de56e67574796c33d99c50561f79bd5aaa20e23601af1b0ae229239c9fa" + ], + "nonce": "0x4", + "sender_address": "0x423dd2adb5100840b269d3dcd854faae35b6e822d0735f2fc9b86c57e9fd8f4", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1e39776", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1e39776", + "0x0", + "0x4041d6ed3c23f3", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x1646b706da12e20f54ae5dd7446a213661055ff06398ba16f898140bcfd413b", + "0x7956f18c92c7436917eb7036cf1ba1473dc57ca955b816b3fa397987b4e0f77" + ], + "nonce": "0x7", + "sender_address": "0x60655948c939796b9003faa1859fd03a1c2c55a1f96217c0c55d529e37f7a1b", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x73647364614073642e736572", + "0x63646364" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x258bc74c86276", + "signature": [ + "0x13d41eaaaf3e25ec2f3e0124ce28bc43f07e16a41836f349cae17932efd720a", + "0x5728bddb8dcb9c6c19caba9ed644868d5b7ed3fa879d4a4bbc0170e2ddba5c7" + ], + "nonce": "0x16", + "sender_address": "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x971fa7595f50", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x971fa7595f50", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2dc85e02ec242", + "signature": [ + "0x271a0c7119b6cf80ad0e6146d4ecdcc26b146acdd323a1a327e74d6d1d00bb0", + "0x4b877585377a44c46a17b61e8ad81468aa963e22146511a1a09982a914cb6a2" + ], + "nonce": "0x15", + "sender_address": "0x39ed6c275ed564f84e30ab6a02ef8350d3a998eec3648995ee7e6ba2dcc2e5f", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x5157373ce16e660", + "0x0", + "0x1", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xf4240", + "0x2", + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5157373ce16e660", + "0x0", + "0xbf0c6f5a350c", + "0x0", + "0x39ed6c275ed564f84e30ab6a02ef8350d3a998eec3648995ee7e6ba2dcc2e5f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xef7a100e35ec", + "signature": [ + "0xad8a282222378ec4e2a7784f1fd99d3bb03b6bd959ce1106f7b7c40401cf87", + "0x40414d26cbf705f2bcd3d35c843f30f21fc32e61f8c9dcc7fa7a7c0c3742561" + ], + "nonce": "0xdb", + "sender_address": "0x3604ed49665e514aa449dc0bcdad0e95aa95dd90947128ef64c146e98d1d51a", + "calldata": [ + "0x1", + "0x173f81c529191726c6e7287e24626fe24760ac44dae2a1f7e02080230f8458b", + "0x68bcbdba7cc8cac2832d23e2c32e9eec39a9f1d03521eff5dff800a62725fa", + "0x0", + "0x5", + "0x5", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7b393627bd514d2aa4c83e9f0c468939df15ea3c29980cd8e7be3ec847795f0", + "0x3045c25ee2ba329", + "0x0", + "0x4cb75146e98562c9d79b31649c6c739e4dcb7cd5" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x2267ca78df8ec280a170ee4d4d7d9527275fe6509a61ef94ee1bcb879bb1a1a", + "0x63e5b900d9faffd37ec07400367a99a48f0886db9c755692f7d6b721c45bf82" + ], + "nonce": "0x817ee", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0xaf32959a1273a9a3cb79a0604be1eaab8ce7107326e892657261b5bd4497a7", + "0x11c37937e08000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x59970ce7cb5e56f6f8e8d4b123662321bf4b6d3205ed70f2c9f7c957de30512", + "0x72fa2f5f4abeff208416c14eb4214ba6d775513f576392325cead1514c849c9" + ], + "nonce": "0x15", + "sender_address": "0x61176ce1442c6349d6b2e610aacc3c69f57f1cbd85868c45f6b760a1f066b9d", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x64616e746f6e6f76342e61663240676d61696c2e636f6d", + "0x466f72776172643a2057656c636f6d6520746f20446d61696c204e6574776f7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1a5189687f000", + "signature": [ + "0x16ec98ef436372299f4774c7f7f97ed8eed5b3a6634afcfd8f255e8fdc46145", + "0x39004bb948a848aa7819ed1b73029e36cc5ee0178f8dbfcfd2e2e3cbf48fc90" + ], + "nonce": "0x2", + "sender_address": "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3f35dbce7a07ce455b128890d383c554afbc1b07cf7390a13e2d602a38c1a0a", + "0x6", + "0xc", + "0x12", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x94e683935a", + "0x0", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x449", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x94e683935a", + "0x0", + "0x449", + "0x0", + "0x91ec24c8b9", + "0x0", + "0x433", + "0x0", + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x64f32a38" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x1141371f2544f52972297c8c667b276c4c66f06c4bf154c29186e9ae0047443", + "0x53a28bd74057e23d285d2763ae09bd03664b0890789b964eec16da6a075951" + ], + "nonce": "0x1", + "sender_address": "0x3fec9b4236c8a88c76b84550d5c79ed44734a3967f0553db6cdbaa95333e659", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x8b8d0aae12" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x512cebba51e5b0c6900757ffe0748ceae6ddab2f931c46c4fe0ee5a61358eb3", + "0x61113bd2dddafc9baf947c8d25c1b2a45ef1548b8f73169067f38771352ded5" + ], + "nonce": "0x15", + "sender_address": "0x2f00e58601a9967f8c1c0d349e97dc75a55d0d9bf2b8767398a689572be445", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x42656967686869657240676d61696c2e636f6d", + "0x69736f78617a696e652077726e7420" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2cd77edfb2b5a", + "signature": [ + "0x12f3d989b6eb8c27bf10eb2fec7791a7e9138794056a6af1d44a4d069d0b7cb", + "0x45f46d5eac6e81099b4f14858e8d161f37af2fcb813484ce36f9f5485d9a9fe" + ], + "nonce": "0x54", + "sender_address": "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "calldata": [ + "0x2", + "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xb69b4361a8bcfea4e074bd844f59471180e9e07bd42a66ff4906186a9f2628", + "0x3", + "0x7", + "0xa", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3e63aaa0cb", + "0x0", + "0x1", + "0x3e63aaa0cb", + "0x0", + "0x221d430c4254d4", + "0x0", + "0xfad91d", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2ccf07cc77706", + "signature": [ + "0x4cdd42e6c0f340f88f66fab53be187bd90df7ffeed748f54b49cc6a053e6cd9", + "0x18415df6233541779069f0637510742056d0b1573a0c4735c277d9dffe3b3af" + ], + "nonce": "0x1a", + "sender_address": "0xd595dea44e3759495547ac022981c330b82a3a8ca111eace41cec9a601bf43", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2f87bb821a1c1ad3c2c226efac39b9d415c9b34020d1a50d145bb3ef7248ce4", + "0x3", + "0x1", + "0x4", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x671f3e9", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f57607268a6", + "signature": [ + "0x5521704334b9ab4ddf7196028da5d974e1ee22f45a2f1cb4083642d3b6faf0", + "0x53a04595b0d9609f4968bad2962a487a3f5f14a95c8980e5377cbdae4f6a004" + ], + "nonce": "0xc", + "sender_address": "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x500d47", + "0x0", + "0x500d47", + "0x0", + "0xaadcac42b840a", + "0x0", + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x111c20613d000", + "signature": [ + "0x14345a31bd88fe8fc9e3fd54a15b472a8c3b27d3af6a4a45e78c372a3fbd47a", + "0x104ab106cdf28b709d3fe6a29309dd011da0c49dea55123c3bb4c362224e33e" + ], + "nonce": "0xd", + "sender_address": "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa87bee538000", + "0x0", + "0xaa87bee538000", + "0x0", + "0x4ca9c6", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x322cb0fd3802c", + "signature": [ + "0x36236d8a010f02fb1cbff11bb5b97cb8f65ad80e8e147a071f314be5bb89049", + "0x4362c3687dc4992408cedaaf42ad9c2ad884c864d1e162ff7a5a274c4e3e2f6" + ], + "nonce": "0xf", + "sender_address": "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x39d1cc435aba4b7727e32d1d8c6874f419df6432f3c1fd27d4e29d104abf", + "0x3", + "0xa", + "0xd", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x17d7840", + "0x0", + "0x17d7840", + "0x0", + "0x175a742", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x1", + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x64f0952b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x49baee5d174c8c60a1f1ec966f38a37dd32f28ae117014d959462787679187b", + "0x4b034bcf7809da122a1ac37f89269f87088e6fc05da8daff7dd8bd53fc48a88" + ], + "nonce": "0xd", + "sender_address": "0x71118565e4ee80c72bf28c3cef2783db2aefae4c4cf0abcc9f2cba378a23ae2", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6a6e626a6e6a6e6462666e7040676d61696c2e636f6d", + "0x66646166616466333234" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x14eb1ad470000", + "signature": [ + "0x37c8e9d778136f46b656a4b9374606264979cd09b204c96af467f3414967815", + "0x3e21d2d9711362026fab3967a2b12027cdd29f44efa54a645af40aa2d616e02" + ], + "nonce": "0x74", + "sender_address": "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x39d1cc435aba4b7727e32d1d8c6874f419df6432f3c1fd27d4e29d104abf", + "0x3", + "0xa", + "0xd", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x47358db", + "0x0", + "0x47358db", + "0x0", + "0x973b8de037b226", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x0", + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "0x64f09508" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x12d43e3b6d248c7fa9ddf5360eaf69f7f37e87a417dc9e371624fdefe4e1a7c", + "0x8460310f1fcf7949841e32c5835067613491d290ffd7a228314b8d77e36049" + ], + "nonce": "0x817ef", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x4157c5c2e7c24cec14ec95595be5e52538027158fa30f1910534bf95aabfb78", + "0x1e8da789118000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2988365acc108", + "signature": [ + "0x319fec127897249f39748e4f23cd3f334cb0d0047007b0e4f58575a038128a", + "0xf905df116a473eceb96f946e635fc80279d51c986093afeafe5561cefa7ae3" + ], + "nonce": "0x2", + "sender_address": "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x39d1cc435aba4b7727e32d1d8c6874f419df6432f3c1fd27d4e29d104abf", + "0x3", + "0xa", + "0xd", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2165668ec7c90d54d", + "0x0", + "0x2165668ec7c90d54d", + "0x0", + "0x4cc867366d76c3", + "0x0", + "0x1", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x0", + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "0x64f0932f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x5bb3cce151744070761ab74cb3f99b760e3f5d9ddcae7073adc81f92db5a237", + "0xd683f03305af9e71899da5f770626fb761bf9d8429b7634af083ff1d4ea77c" + ], + "nonce": "0x2", + "sender_address": "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2204f29", + "0x0", + "0x2204f29", + "0x0", + "0x4836cd545ecdaa", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "0x64f32a3f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21bcbfa566e08", + "signature": [ + "0x765b11845afbc80ab877d6106bbb6c726bec416d3ab2fa09f32f7a99193fbbc", + "0x586970b605e1794465435bc00d64f88033c2193de7d009f4ea3bea656715a5c" + ], + "nonce": "0x5", + "sender_address": "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x27f7f60f715b9", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x27f7f60f715b9", + "0x0", + "0x11f1c0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x5f326d4655c1cc8db5d4af5afaa1f87435ab4d8c969565008a6d02c3de33a46", + "0x130ca4a137fe3136eaeb6d34555bc0d24837917a94ed2093fd5dae96250da19" + ], + "nonce": "0x8", + "sender_address": "0x7f035c6f4143bc72418dd210f904d40d2e7d8671329662642102e0f5d29eff8", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x64786868766b7975696940676d61692e636f6d", + "0x727132656a75686b797569" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c910d9929bcc", + "signature": [ + "0x76003521c9ecbfddbe5abf3cb2e1dba6810f3fd38be69e6d5088edb1a37446c", + "0x4f42e9cc0182a00980dc5ed8b6bff90a6c0e81d3d9f6c496199c6dc544464a5" + ], + "nonce": "0x37", + "sender_address": "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x11d1057", + "0x0", + "0x1", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0xf4240", + "0x2", + "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x11d1057", + "0x0", + "0x1021097461817df1e", + "0x0", + "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xbed2c7882d000", + "signature": [ + "0x5c77ce5a4810fc373218c00062a9b4353107e950a67aeee8bd9ead4ba0143e3", + "0x32417bb85d7ef9bdebce034c7d5d96a83cac1be421a94ddb3ce50fa1ccb5e7" + ], + "nonce": "0xc", + "sender_address": "0x5ed652563eb172665eae6b9d4937d67503a69e02877fff69fb182bc3768b2ee", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x150f7528" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x11393af5df000", + "signature": [ + "0x37d6274b3cfc7a11ba740cba42ceb4ff0aea6d847f991ae16c08984e608b02c", + "0x426982a3ee942e3d3796344231354b840f5ebe6265d8f7e91a48ca49c79422d" + ], + "nonce": "0xf", + "sender_address": "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2b57d5da428000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2b57d5da428000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x13e508f", + "0x0", + "0x13b21ac", + "0x0", + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x5b34fead0a364266df3177a753215b0362da9ee08b291cca9ca6a7d18265865", + "0x4e6ebb57dced3278ddda39c784b52dc427e167023f8ed311ec8b13997a4f76c" + ], + "nonce": "0xf", + "sender_address": "0x18a9c632c0fcae0a64570f974f403977f0b4cb8d8f5023846370bbbd255d259", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x666a6667666840676d61696c2e636f6d", + "0x6a67206a6768" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x5af3107a4000", + "signature": [ + "0x2afa62a73b61ed87e161b3f8b05b4abe92165f97c8f8d26835e9e67adae7a89", + "0x12c7972a5556a8663314c456b887d5473bd7c8dd1e112b774a26f9bd43b474" + ], + "nonce": "0x8", + "sender_address": "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x16cc063b8338363cf388ce7fe1df408bf10f16cd51635d392e21d852fafb683", + "0x0", + "0x3", + "0x3", + "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "0x60cf6ccef800", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x165f0cd30072e", + "signature": [ + "0x7bdb5422ceaa05b4c87fbc44f06dd4e6e0e1c1e9bbed3638d86d327c4ef862b", + "0x62030d9fdd6e02624ae8dd4d9742620e132e04849d61626e3d423fd48f832cf" + ], + "nonce": "0x45", + "sender_address": "0x70e825ce22d70c965b9ca8a2a6aabcb5ee71fc08f2a6772341f634a1f5f7eba", + "calldata": [ + "0x1", + "0x2d5f0f2fcba62a54f0d8a73fb2e437d76c53f7297153b2afd1f198af6d12aa", + "0x329e5b0f1b7d514b82d367001be7a157b1faad40a1ad19c8f2cbb77502aa245", + "0x0", + "0x6", + "0x6", + "0xbd1579464e", + "0x64f09545", + "0x74776974746572", + "0x5240708b", + "0x72ca27346ed1ac35f8497968b8ad1ed4eb2f61262a8ecae980e6178215b8dcb", + "0x1795b21ee4d5387d06cdd2d12f8d6ca94ae12d14e4141f02b7239dd8091d596" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x600cf4e20f1d8917df2d2d7283121a5cb826776d02731966d87b360188eaf3f", + "0x74e672a46a83e76d7ef76c33d3c4befb1cabae5f2ef12ffa25bd46c0a615fa2" + ], + "nonce": "0x817f0", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x700c5957b4ec4a67202fa57e5bdbe8c13e740116c0e65129d2b736729661918", + "0x55d56459c6000", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x1af19b99fa000", + "signature": [ + "0x79063cad8b26d8bb18a4eabc7f4c8068769a80cc154b0aff15c37c5fb668a18", + "0x4f808d5cf317dc1392764ddd7ff646e6403bc13450d178fb0666294d8796504", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x160a87d8951d17b7beb4c8adfee0aa8f9d55b09f7b983999ff24a63e7ea9495", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x160a87d8951d17b7beb4c8adfee0aa8f9d55b09f7b983999ff24a63e7ea9495" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x53981dd121d8f62b666f4c68a306e14cd799542d978518866f79f9a464838c1", + "0x1b390aa152e81b654c5f32221ed969158b6b27d80a8af77acba31c314b85ae4" + ], + "nonce": "0xd", + "sender_address": "0x129c2e09eb0293df06d2a004bb11da6eafd7895089f0ab1e8c36f9d8eb75742", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x95c381eef83fcbecaec0c74641710f1b34b4e74e759810991766d41bf41dd1", + "0x425793ffb4d067247d327291d617c95506883c61d0cae23fe491a65adfddffc" + ], + "nonce": "0x12", + "sender_address": "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x135e", + "0x0", + "0x135e", + "0x0", + "0x295aaeee716", + "0x0", + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "0x64f32a21" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0xcd7e4e7b2e0f24b4c9d310e792f174b68f1c6f48787bdc76c1166cd276bcea", + "0x56ec8221ac1df111e930bd19879b3b481a57e672c9732659547ee363c42f161" + ], + "nonce": "0x2d", + "sender_address": "0x5e520aed1326da6b9a1c94bfb5c2b67342f45520ac5e42297a07862b6eb3a0", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6162646f756765757940646d61696c2e6169", + "0x5265706c793a205265706c793a205265706c793a205265706c793a205265706" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1a8bbe91c3000", + "signature": [ + "0x3185f301cf15af0a385fd01008ced3b83fa1c03479c6d3fe7950f6491b5d30", + "0x4e5caacb585c7ed5856f6d54de5d8832836fda09b4a840d98284520dc6e418a" + ], + "nonce": "0x1d", + "sender_address": "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0xacb887281b6b365ed8e05dc0305a07bdebb0e02ca85e59d11353c0194dd20", + "0x3", + "0x9", + "0xc", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x32364", + "0x0", + "0x1", + "0xed8000000000000000", + "0x64f1297f", + "0x0", + "0x38d7ea4c68000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x694d50ebaade657", + "0x64f09547" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x71a66283feecaa28754ce9d0bc60ed0d1b65d95f7e83a84a6ae75ae0c6188e6", + "0x528897a14db9409bd548208f22d132ddb41f5262302a3e9d81320f0f158a741" + ], + "nonce": "0x4", + "sender_address": "0x1ec0f411d35214bb02d1a83206448674f23e02058ccefe918fff45441cf3b9", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x646d61696c7465616d40646d61696c2e6169", + "0x5265706c793a2057656c636f6d6520746f20446d61696c204e6574776f726b2" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x13b84e105c8301b12428cdad5ff25f1cc94966f47373dd32c03ef42045f5446", + "0x3e120299e1f8e3380358e5dfb476dbf6a6831c18f1b246be89635ff0c1a53f2" + ], + "nonce": "0xd", + "sender_address": "0x41f3c9d06996c592f78fc707361fb1ad9bc7ec0d5329540c1e2fb83a221903b", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x5ea64b0de5104334936188c9a8f2baf4b4f07cd5da7a46595cc063001f010fc", + "0x9ae26b469cbf522c6da6e0be9f3b5d0e52401ea24159044cbee7b8a805a72b" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x5c221061e94feb8a05c1ea4a708ca484382573f12e211d468e5bdfa84663092", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x5c221061e94feb8a05c1ea4a708ca484382573f12e211d468e5bdfa84663092", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x25166a6a5845a", + "signature": [ + "0x205128a2306a9d49b7aa413b41807c5ad81173d3b9b9a5a9164c1ab5a001ca1", + "0x675493f4f8ca6e21acf3610de934fe7328d7e141291239e5ca752f10d2c4221" + ], + "nonce": "0xe", + "sender_address": "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1990caa5e12234", + "0x0", + "0x1990caa5e12234", + "0x0", + "0xb26010", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "0x64f0886b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x780da51c4000", + "signature": [ + "0x653baae268311e64c35918f29d21a89c0c9672114267247f787ea7cd6edca4e", + "0x535c27345f334bab92225f03b44add6f54f3dda9c05c21b2423febb5aac65ef" + ], + "nonce": "0xc", + "sender_address": "0x33cc887ed9534feae59f80492128f93eb05468f51001ab49fd1e681ecf654c9", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x1ab60da219d6c593f395286468892a6c035358c0183aba29f819d5ced1afceb", + "0x7772d5622f531b41dadde4787256c2845d6dba970ff0cbb4b153ed23bf579c3" + ], + "nonce": "0x1e", + "sender_address": "0x36b1ceb9ed6872aa8f4940ed386fd4ad25bd9a8639f55fff4a14f1f7415a59c", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x616c756d696e69756d333440646d61696c2e6169", + "0x33" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x9513eaaeb6d4", + "signature": [ + "0x58a3cf3cab8a5919fbf4f21a4c3bf79199a82eeffe9baed9c9d25e88cfbf4ae", + "0xcbbc71a4a5b68efdb53300402125fbcb2be5dc2b475a3d078571839f1d0350" + ], + "nonce": "0x4", + "sender_address": "0x1f83de91390aa9f5f4fbd7e3c04f1b34d288ccd95906bead7286c8d9604064", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x9b89412a96" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x4f94ae6af8000", + "signature": [ + "0x38ce1a1b39ae9b05d0e725c4335b15f6852b46b71f6f37d4eb4637122257bad", + "0x30f4cda01bc9dd787f7d35ca265f7f1ef7410a860a1e3661aad1ccf96d4351e" + ], + "nonce": "0x3", + "sender_address": "0x6fbe4811497fc4baafb5a223190cc4ea74ecf2cdeca53fdae2cd9c19964f113", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x42ae", + "0x0", + "0x42ae", + "0x0", + "0x8d8bccd2b34", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6fbe4811497fc4baafb5a223190cc4ea74ecf2cdeca53fdae2cd9c19964f113", + "0x64f32a31" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x25859f3e8997e", + "signature": [ + "0x173e1375bca0a58a254118ca2e04a7dea31f7c14d1f4f5420dc06b9c52ca70a", + "0x53bdfa68d97beafae52e406436a7f14f281edbbe6fd07365c4aa8515ed8fe8e" + ], + "nonce": "0xc", + "sender_address": "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc573de9921a8280", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xc573de9921a8280" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x2d85c15add32a477ac38aac287c3aff03e9e3e1c4ca3915d3a1587ba554c24", + "0x2d90a1bab3b08146107534dab445b7864e4f9e128139e26e24c5b023ed0ec31" + ], + "nonce": "0xf", + "sender_address": "0x137897a300b5601c8026621083418fd13af6ce1f386122e5296fe6bed28e8a3", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x3eb4edb3f38789b7d5fd3ee8a736e6f15ef19da2dccf7bc2081769ce8842b42", + "0x4d7e6fff83028ce6fe2861c83f29d5960289ce78f7d61588787c548a5cec5d4" + ], + "nonce": "0xe", + "sender_address": "0x59b6c99d7d0e4d52bbd4fcb14900b50832156cc10e3e5d65fb1e56f82941805", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x4b178e990c4ec", + "signature": [ + "0x5428aedf3c675dcc091cb9ffe8d950fdc7d957b38caeb2bb09534b3589734ba", + "0x6662a45fd0ed608d25efa8c5391abbafbdc82afb0b5ee4dbd01bbb254d69f5" + ], + "nonce": "0x1", + "sender_address": "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1c6bf526340000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1c6bf526340000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x6ac6d9fafe51df712d6000ce8fc77625818f7dadc3c5baa83e4b79e07f0a5e4", + "0x265ddc681aaaf098f4fc745de7482d5a09cf6198243e09911d7a808ea6f5d07" + ], + "nonce": "0xa", + "sender_address": "0x2877293255939e80a26cae426d9c078d3a16c3be71572bba912a41643dcbb39", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x7adc95f33bda4ded858021cdce4de2564426e71f7cc4702604c4886195b7f11", + "0x245146f7936dfa2a0153e12771c6e611afd778dfbcca9bbbc3cd7f628ad97b8" + ], + "nonce": "0xf", + "sender_address": "0x2e908292b66c0bbcb84a1599d50cbd5ab9effc572d29ac94eaa8d9d6000bb9f", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x12b4307e0cf72", + "signature": [ + "0x1e7d1a6aa43219a5e95c797b066b496ad3e128012139cce784d04d4dcf83d9c", + "0x33e74ce28d4d126548969d6fc44487822bf35f7727719f13eba023832fdc864" + ], + "nonce": "0x11", + "sender_address": "0x721ea975d5fb860dcafb33dcbfb84c324df6d04786ce2912e31a5726fe841e6", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x173f81c529191726c6e7287e24626fe24760ac44dae2a1f7e02080230f8458b", + "0x68bcbdba7cc8cac2832d23e2c32e9eec39a9f1d03521eff5dff800a62725fa", + "0x3", + "0x5", + "0x8", + "0x173f81c529191726c6e7287e24626fe24760ac44dae2a1f7e02080230f8458b", + "0xffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffff", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x1cd24698bd8a32a", + "0x0", + "0x25834ffbffc7d155ded11245265f83e3e4846394" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3be8851a47e46", + "signature": [ + "0x71254ff0bf3e0a419a3ac148e1619375c18d76abfe094070e3a8aeb736e4802", + "0x701c0f86c3f0d3f0fcd85bd5615a377a33c64857d374bf1a755959c1c64953f" + ], + "nonce": "0x6", + "sender_address": "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "calldata": [ + "0x3", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2cfb12ff9e08412ec5009c65ea06e727119ad948d25c8a8cc2c86fec4adee70", + "0x6", + "0xc", + "0x12", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2455a4bba923fda24", + "0x0", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x279bb33", + "0x0", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x2455a4bba923fda24", + "0x0", + "0x279bb33", + "0x0", + "0x239b9c5181eaf370e", + "0x0", + "0x26d0e7e", + "0x0", + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0xfa6a749d8261dd28d62a00e4ec2b7a57afeec77fdd1f07c0836014e7e3c33b", + "0x221cf0a12037f6b5435731e82673d84edaf2d9ad6e7bbd4c4e23587bbafcecd" + ], + "nonce": "0x1c", + "sender_address": "0x3c3f84c1b15d9a0c28ceac1e9c085f06f890fd6c05e778632512b67d81f66a7", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6b68626d78736168626e40676d61696c2e636f6d", + "0x476f6f676c65204461746120416e616c7974696373" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x4b637f063995cba1c8a0145d6a0814524ff6136953986bad9d0485bfb839d5b", + "0x6d95be2b282f04d47a10a3afd8be3ad0c8223e0897f23ea352de7f5a17ffe41" + ], + "nonce": "0x20", + "sender_address": "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x9184e72a000", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x9184e72a000", + "0x0", + "0x415b", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x353b569eca8b423d1c1929c860682f36a64d613f31fa2d7ad83555f087d5f21", + "0x69004a64f7e4137f32e50d0873f416d10bd09740ae114d5e4b109a2ff799366" + ], + "nonce": "0xe", + "sender_address": "0x272e5594a4e81bd28052575ba45424763061f0d05676595a31b46b84f729f9e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6e626d6e6262626240676d61696c2e636f6d", + "0x626a62626d626e626e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1703bc4924718", + "signature": [ + "0xe41db0fff6bea4421bdcebcbb64c2dd2946f32086aba49e1d4a5deef6be30a", + "0x2348bde5d54de0fb59db6749573a94d7c05d57c35ed99460a6ce8421092d35e" + ], + "nonce": "0x2", + "sender_address": "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x97ebbd5b83800", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0xf4240", + "0x2", + "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x97ebbd5b83800", + "0x0", + "0x40dd", + "0x0", + "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x2ad061b3c703f7956987290f3c12d2186cac495a8e99619b904423ab033417", + "0x454d388c83757e49df0177f0d6f828c79727b6a140ec76f1e3b61de6d4d1db4" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x4da4d37eb44659c92d9b051821b65fa699d7d1daba90e9c2af880ae3118aaf4", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4da4d37eb44659c92d9b051821b65fa699d7d1daba90e9c2af880ae3118aaf4", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x3644ee2d93171eac6561cda84a8e2822282eeb7146ac7e468b98e0f474a1ff1", + "0x7e44f11b894510ba1cc35573aa53cd9dcbe90088aef7207b9ef2e8f04fea501" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x1a57334b4fed1d0d3edb93981831363848499d2bd7a36734727d7664dd3731", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x1a57334b4fed1d0d3edb93981831363848499d2bd7a36734727d7664dd3731", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x3e980b87bec9a6955a163b318774802da02c0c0d6fd1d75602d149274a8c969", + "0x687cde4f63351b84ec3fb4ac16ebe309c1c51a19f7999f801524ab996b9bd36" + ], + "nonce": "0x10", + "sender_address": "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x71afd498d0000", + "0x0", + "0x3329e5", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x64f32a3f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf095429197b4", + "signature": [ + "0x2e44114b78292b0c1ba8045daaeee6d7777d6363da5a5430a422a623b78c7be", + "0x3ec3a04e6e61b2ee82b2bc14cd739493562a064970839b1e2c1fe1c505e529e" + ], + "nonce": "0x1", + "sender_address": "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x666a6a6640676d61696c2e636f6d", + "0x6667" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x7020a0fe421242fa20e8f4eabdf360fa3f3df8ddd7a43c7a33ca7a041eb60bb", + "0x1edea2317688e974bbc90b48d906b079ec4d27d8a60e4c0dedbf1ea4ad4cd1e" + ], + "nonce": "0x8", + "sender_address": "0x759b49c2d615899e859a56d96658c751c4c874956d34e64bed50959e46dbd8", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x346a6b6a676740676d61696c2e636f6d", + "0x38666d6b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x16550bbc4609a", + "signature": [ + "0x3c34c572b71184fdecdd3cead599c7b82e9a00a12b61f9d4c536c8fb57f6657", + "0x3ea8038bd11e4954b1f96588355abe3be1864bb25cd90493b79fd2dfa9a7d3c" + ], + "nonce": "0x16", + "sender_address": "0x45ddcd21a971f92a19ad69d0174380d77dac7d1875ecf9900a6a69d8ce54cd2", + "calldata": [ + "0x1", + "0x1b22f7a9d18754c994ae0ee9adb4628d414232e3ebd748c386ac286f86c3066", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x7", + "0x7", + "0x45ddcd21a971f92a19ad69d0174380d77dac7d1875ecf9900a6a69d8ce54cd2", + "0x28a1df", + "0x8", + "0x7a120", + "0x667f4e80", + "0x74cc919607321455ed8692e852480307eb7e7626080b694fee5180f4586285", + "0x43b5a22c35bacb15362c61b779f7ea70223e9027541022f54de6d5ac5405e95" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x3fc69d7abe0b5af6095403c5d8c36d83a5fe33d44119028ddb72113e5aa79b4", + "0x58548799eb932692c1e7a8520085fda59e44047871ff43c0eb2a331e2bc5167" + ], + "nonce": "0x817f1", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x4fa3f6d1a76e3d486bfed40225f9acb86e0aae855f15cfc004574b5ff8c9c2a", + "0x71afd498d0000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x66a21b0111d3d0c65eadedd15141019923d3241595d7ae08cff8303cda67d3c", + "0x4d5c2141b4271f0995da4db53e6d7c15ad8f046e745430b1f133a8a89535f43" + ], + "nonce": "0x4", + "sender_address": "0x602663e4ab3c5fe99772a3743c6e106e34fd8e3c7e035497dc813b1fa903c41", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x616e746f6e2e657468", + "0x61776572" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x43c35ff2a47b0", + "signature": [ + "0x1acebdbf3b8b7a65c58d36cdffae866bf3bfa61cb7fab68b7adb9440a8b033b", + "0x1aaf8f775e98f56b93f784335fdb8fbe398773edc2f51510f7aeb7a485f9610" + ], + "nonce": "0x1", + "sender_address": "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3e871b540c000", + "0x0", + "0x3e871b540c000", + "0x0", + "0x1bfa36", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x64f32a3d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2569eaff99122", + "signature": [ + "0x71403d96704c86a479af8eeb7ce73a35a5126b3abcd5925dc05c6dcbb1cb0eb", + "0x2bbe2d4e3a9d8c6795a452f83c6b54c8495a273525a3a91d97f006de4facb5f" + ], + "nonce": "0x6a", + "sender_address": "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "calldata": [ + "0x2", + "0x42b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1386fc391dc4142", + "0x0", + "0x7", + "0x42b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2", + "0x1386fc391dc4142", + "0x0", + "0x159136bc89bfd27", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x73dc2b2d107779c7a2b63997938a662addf09471a81a79e83b32909a34010e6", + "0x1663ec1fc43d7a0943b3834d66b7172cc5b0976fc55d183be794981f5520d05" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x1d908314dbee35855975b4a6a93f335431e332e2e5809ce2105fcba4cff0196", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x1d908314dbee35855975b4a6a93f335431e332e2e5809ce2105fcba4cff0196", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x22153f6e756f6", + "signature": [ + "0x1718006da8cfb0ffd0b3fe9ae6a4b5a61190951fc5253c732a9761fb684a142", + "0x4d22c803e1594b287be264b0b1df8a9957cfc44aad35158c549a4147fa8cf86" + ], + "nonce": "0x2", + "sender_address": "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x4209483", + "0x0", + "0x4209483", + "0x0", + "0x8c5623e86f92af", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "0x64f094d8" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x2efe6c4ad910720583f3aad11d819178a683b81f775330f650780afdf43578", + "0x6841357d00e3ac2c4ada3254cfdcb3d0ef59ad3f8554d704176b80beb9cc824", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x1e4bfc92f150ba176b6b7a0cd926eee6915c79f16fd63218a729ee9955fdf51", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x1e4bfc92f150ba176b6b7a0cd926eee6915c79f16fd63218a729ee9955fdf51" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21bcbfa566e08", + "signature": [ + "0x6a19a7d929d2e093ff92b724ef7091451dc43681eeaff4a00d56d0c927676ab", + "0x647e3b76f6e65f2ac6e4bb795facd3af4283b59cb683db84c977fd3d69789ff" + ], + "nonce": "0x2c", + "sender_address": "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xe90d5e35e407b", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xe90d5e35e407b", + "0x0", + "0x68ace0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb9f7d102869c", + "signature": [ + "0x7390b0aba282fb28573b93980107cb2937f0d846783ed03bfa08cf76180c332", + "0x42393df90af132b665e6df0a3f75ce129a9e081eea25453515531a5103948a0" + ], + "nonce": "0x14", + "sender_address": "0x5eb8d32af23e4d5011c46cf704e27e8762b5cfe62586e9fd565c7cbed9bcedf", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x3f01d80498096f7929858b5fc97cdfbd676b5d2ee673407df0c957d6a0fef5f", + "0x0", + "0x1", + "0x1", + "0x7300100008000000000000000000000000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x43c35ff2a47b0", + "signature": [ + "0x7c12efbae8ae277e352edaf5cb2ab5405665d3fdc01ceb00f15f568f9d1c58", + "0x40fda2bda9d371a66c4222ca36c1f0fcbf1f91d18c75f676a18aab472e492c6" + ], + "nonce": "0x1", + "sender_address": "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2f9b3a9ffd800", + "0x0", + "0x2f9b3a9ffd800", + "0x0", + "0x15be9c", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x64f32a3c" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1493cb168a000", + "signature": [ + "0x731c056ecc98960224d5fa4fee66d60e0c2e8a712e58ed966ef50e11837f3df", + "0x6f7c643096e0720e368128b4efe07996909252a93c88ec8d2753e04fe25a1c7" + ], + "nonce": "0xd", + "sender_address": "0x297123b98c2209d5b3143e3fe5b185564607ef4e81b0ef01e3d199283a6138c", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b68aa9", + "0x0", + "0x6", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1b68aa9", + "0x0", + "0x1875c04dfef547536", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x7a8ffafd004cb31fb06b62a439633c5cdea61b369442b8fffb70f8c99880c40", + "0x5429ce4dbc54bbac98f411f47a1004393a9982d9f89d2c42db4c151ac361f22" + ], + "nonce": "0xc", + "sender_address": "0x369323f83547d95dc2d8371186aaaab45ebc3e327da5c868f74046d61f3152e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6d6172696e6b6f6976616e63696340676d61696c2e636f6d", + "0x6976616e6b6f6f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf01b4a388000", + "signature": [ + "0x18feb555c7da00730c43d33cd195d665c304485b12dae499e2c1053e5b72574", + "0x34c0b28ce1dc99bd3953ebf43b8a092b0f4d4407f36bfe5aa9ed360b6debf1e" + ], + "nonce": "0x1", + "sender_address": "0x6828b4976826c0fac35101ffa6cb5a0de79034546e7fbc12194af6e1ba168de", + "calldata": [ + "0x2", + "0x3448896d4a0df143f98c9eeccc7e279bf3c2008bda2ad2759f5b20ed263585f", + "0x3f31d7da39f3378b3aa9884af9e68d40e61c4eba68dc754e4b09c683bb7256b", + "0x0", + "0x1", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x2d01c9f1ed8d814a32aac4171c6cc5a66828d7f97a5da83a6bb6b6f064a0ee2", + "0x1", + "0x3", + "0x4", + "0x2ea5a51e9e9", + "0x2", + "0x2ea5a51e9e9", + "0xce31cfe97" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x71f176e29f00aa055baff7648b2a9a8229240a942ec07de92e338d69d8ac7db", + "0x1e38bd761d04adde5d389a42d160650b7c7415d88c14aed29800ddc115e407f" + ], + "nonce": "0xa", + "sender_address": "0xd2010f814898522fd4e492a29353bcbdcb3d2002fca699d09e894216aa0233", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x536f6d6f47313140676f6f676c652e636f6d", + "0x426f626f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1f9135129e971", + "signature": [ + "0x30c6fae33a931a3d90682a0757a5d1ec870e0725c95a287f9964fd629209fee", + "0x441a49422840b7eaa8212c5f43041d280f8b58b111c6ac8bfbd2df094741993" + ], + "nonce": "0xe", + "sender_address": "0x1bb2312832bdb4152faa026f7e874c5b1fee859b8e257b51dde36f11c4dc54c", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x1a0e5717ed" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x524c988996344919d67f050a8d1359e81ab8667dc5da0a2a2a0b8928abfbd03", + "0x6f99f3db629a14867910aa3e00562982a538e436d2eba0d5c88abeac40beb3f" + ], + "nonce": "0x817f2", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x7ec5e5dc6bfdbcb210c844135c0b3714704cf753aa844d047b934ccc8dba32c", + "0x3e2d18145a7c00", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21c5fbba61b7c", + "signature": [ + "0x65b639a0ec2512a17790467fa459b3445f547b2c413c6206ab65b25711ba594", + "0x698bb8ea69e378a90c25172daa262b8afc764623282c3c6dfdebfc2cbf207df" + ], + "nonce": "0x2", + "sender_address": "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3ac6ae2b2a000", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x3ac6ae2b2a000", + "0x0", + "0x1a6638", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x220b3e57bb062", + "signature": [ + "0x30d74381db0241f2f53d465901012ce564da878110ec6c3c2e739fb7f3bc2f8", + "0x2d9f7b1274fdae11f115cbcf329bc78ccfd15d3205c3aedee59d3a7fe71d7ac" + ], + "nonce": "0x14", + "sender_address": "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "calldata": [ + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x98a7d9b8314c0000", + "0x0", + "0x98a7d9b8314c0000", + "0x0", + "0x259c46e1ad57a", + "0x0", + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1c1cf4294415d", + "signature": [ + "0x13af01627f7f8a7da12041b0173eab06e58f90098add24e198f5d97519a384d", + "0x3806dee212f8f35a648678254234dfca77a656d913f163601c02645b265bee6" + ], + "nonce": "0x12", + "sender_address": "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77", + "0x0", + "0x2", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2f40a406ff07c5" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x2b6f80305c538d6c4ea0565b295ebe5187319413ccddabaa5b1078ae66181d0", + "0x5a49411e90e7a357b77420b089ac170f6d0e24b1729e625f7d67ee8b1b888cc" + ], + "nonce": "0xc", + "sender_address": "0x68f8f56935665f27e0b4c2e0395c5ac8d23a2fa3d5f463e8c640b69dc057f2c", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1b195746ecc10", + "signature": [ + "0x58cc92d152e3cc302457cb6904c2aa743610d4848fac842970a76110ba866d5", + "0x69859e8deb0a9b5f6208bb94962b339104d0ac0a28546dac3ea5ca9c41040c" + ], + "nonce": "0x1", + "sender_address": "0x2165d10e2979ff2132020805fa6b280edc08445453df92d4087a22f1ae7c582", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0x299ef09ea5" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x3d922a917958a46b50f88c910688ccf869765e4edc8f9bccc0069c930611a49", + "0x2125ec28edef7c257c64d7f0a06851fada8a72250df32f75c82d6e686007f19" + ], + "nonce": "0x817f3", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x250ea9b47026822b806e241415f4857fa2f9b8d2380053d8b49ae13d2345555", + "0x9a9d359ca0000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x3127a2f0a11fcfd2a9f5523183d0364c0311a9bb37a5bef057a098bbbd87c88", + "0x1a310187ce2fe36036c88a0498d193877acd45dd17ccbe9d1e1493ff3624744" + ], + "nonce": "0x1c", + "sender_address": "0x258ecc7ad5d3829b68fc19d6d07be845ada70278ace7ea508a1f4d3da74a4cf", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x616c756d696e69756d333440646d61696c2e6169", + "0x33" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x10f6137a0b61df21175d7c026968bc5763ee17885f87e76af22fd8a26aa8a3", + "0x458d5f73fa5e3a0dc216db2782ce2d4ac5a203e21cfb2575edc5aabd2728027" + ], + "nonce": "0x19", + "sender_address": "0x6040f0aaf63b208c8d15a1b4e2b8dcfd352c0f428ff9df48e9b29ea972ed106", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6e7369736261726440646d61696c2e6169", + "0x7574612d686167656e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x129a06429b954", + "signature": [ + "0x6f5db9246f720d10e8a65d402cb413dca35698349b1f0d2dd5b908b5fbdd717", + "0x3455c6057c32cefd432b9cc4b951cc0373b6a28a39b3118e81988ae145e2a6c" + ], + "nonce": "0x13", + "sender_address": "0x26dbcfd8f0086fd4d380e4a9ecae4312194756b3c013067e2c0941ef293625", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xc67ef1383" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x111c20613d000", + "signature": [ + "0x4cec2a76fb4cd06a5b1aad6f8867036848ac69f1a6d05c95023035897a80637", + "0x4ba3f92eff7243e38b769b81c89e0cddc6f651898d4d506ab43737c4f5234b0" + ], + "nonce": "0x15", + "sender_address": "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "calldata": [ + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xf9ccd8a1c5080000", + "0x0", + "0xf9ccd8a1c5080000", + "0x0", + "0x3dd238d87a708", + "0x0", + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x7cc46c62cf4f7a3e7fdc39fb00c1cf864be724b47bfc86a31ad41d405ed12ed", + "0x8e6cd36a901d195d5d51ce6676dc717f4186f5b3a327b77984895098f2f23c" + ], + "nonce": "0x817f4", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0xf38be9d7cd33de7862c9b2c383758a10575cd7c40b299ea6b5fe750323e180", + "0x9f46776a92000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x21ba6bed7425ed7d04e8e334b1e17d47be486c01b494053acae9f96c545fd59", + "0x7054266fd8ec01bcd7ca480fa0853c8e850c5e4d9f0788b3b796fa90d4c8a5c" + ], + "nonce": "0xb", + "sender_address": "0x5c5496ebeade2e5738f5f697ead154be2ffd5c4d8cfad8573fb89a59e8b7dfa", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30786a65386c6f347135347779627a376775776d746f37326474667868616b6", + "0x6f6c3273716276333535" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2974f92f16d00", + "signature": [ + "0x214d4b1e2e38bc7f9e656f5905da01c63f97c44804d8ec55473f523d66a94d4", + "0x1d13e721d383bba519b9d1bb31aac7711bfe684e2c516ebae5f0f6f47bbc953" + ], + "nonce": "0x13", + "sender_address": "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "calldata": [ + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1314fb37062980000", + "0x0", + "0x1314fb37062980000", + "0x0", + "0x4b8eb8f63832b", + "0x0", + "0x2", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x225fe5180bbb4", + "signature": [ + "0xbcecea5e6786099866ddc724f27f2be4f57af43b4a9da16df8463966d21aac", + "0x3502fc652d9c24c88c8ada93c061b66f7341d3b12ecb12f3397d0856e89cad9" + ], + "nonce": "0x23", + "sender_address": "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x5e96630e8000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5e96630e8000", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2b6fb", + "0x0", + "0x2b007", + "0x0", + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x0", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x64" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10bb5c0327002", + "signature": [ + "0x5100907f7a58b3943c27acbf7545e7fb9ab787c0cf78148d16be28d11c75201", + "0x1eb7d89cd659c2c52cfc9e8b22fde63bb30eb2371ba784d65481b3d12900f2a" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x7c654577b5828a404afa6a6e32f86d241fa744e6844369b7a2ce7d651d88ee8", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x7c654577b5828a404afa6a6e32f86d241fa744e6844369b7a2ce7d651d88ee8", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb3faf8e37322", + "signature": [ + "0x63f250c78c38ece205eb75a4b736ff871d4a5e8b0f514f9f65adc9f53da9314", + "0x1a97f802458e34d7229544acceb819d090812a24f0a5da10285e581c194de3e" + ], + "nonce": "0x18", + "sender_address": "0x1811b16e99155dd9fc25fab52bed2f94b5332fdbd8c648d710aaf32f8d505f6", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x488333d12549b5accf4f71e6bba15b2d432edcd002252ddc4ef60393caa4f67", + "0x2386f26fc10000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x238ccac3a3a0e", + "signature": [ + "0x468f79c2017faa1083898449872b9b09de4c0bf338eddfcb60ff967b2b86a4b", + "0x43b12df900181a0516a147e637b65d0c3864c9b9290b2ecb9178b1edffaa7da" + ], + "nonce": "0xfc", + "sender_address": "0x115d39728cb7b9da37428334eacf88e8037f4fd1d76910ad75e906090a72be4", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x84faf3a5b3ed37" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb1e11cbf4734", + "signature": [ + "0x15482794c1339d8f991bdb0f05d1a9532c50f673724db899af34ab45c7ebbb0", + "0x5e8a9a01f558faae5ca2b7d83e178ef9858c1cdc7a2736285d0e65d3d7644d7" + ], + "nonce": "0x18", + "sender_address": "0x1357a25dd919bc0e6618f52b42c7270428780d298c91c1f9e0fa553d9d260e0", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x16fc87a2dd63d0158d7b708c7f6bc5e35779dcbf5861ecae06935a69fecc033", + "0x0", + "0x1", + "0x1", + "0xa8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2216047035014", + "signature": [ + "0x5d7c5245c8e05ff95fb720598afc10c6886b43aa8488f9b4b830cbff3f3be18", + "0x4bd7319b27ccb6d8965db117477c0442ce50ded646321ebc01f8f838876921" + ], + "nonce": "0xe", + "sender_address": "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x129a91aa5dc800", + "0x0", + "0x129a91aa5dc800", + "0x0", + "0x85d0c0", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x30da15fbf52e4", + "signature": [ + "0x7d0f80f7ce827e0b57924d70bd51fea4d9e0a8f3a21fe2dbb908890924615cc", + "0x7da9dbe55ee77709d3d158c788dfd765c85ae40bc591ced65a13c116c2c0cf3" + ], + "nonce": "0x26", + "sender_address": "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xe949c6", + "0x0", + "0xe949c6", + "0x0", + "0xe38e24", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "0x64f0952c" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x2725ebbbfd50108028a1f715d4b24fd6ab50ec94ac4f20848ddec33e2266215", + "0x1b3a102555d580006e3010ecd194ef56b53c325e67e6fbad6ef35ed4df0b0cb" + ], + "nonce": "0x817f5", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x3e52730153a4bb29440073b6d02e7e715ed9fc97708548a43fa27a1934649cc", + "0x46c7dce9dc3000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x312450e8f202b4815eabf3977e652de09ad04a550ff53d41d25000b4b1ab32e", + "0x4378edfe97fa2ea6d135981107c44702f0113d2da8d5699e4a109c89cb64cdf" + ], + "nonce": "0x1c", + "sender_address": "0x408dd2f24a40506e9495c5ac6ae459d1583371ef01735180bb2410596c0ef0b", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x221e7b837046a", + "signature": [ + "0x383d4d5e6618208ef34e65e65d4dbba8205538c4132b79ecf09d95cf151b390", + "0x4694ad9367414a39a74e5524644fee5d962fa0f4aa080f15086b47490f2e389" + ], + "nonce": "0x1", + "sender_address": "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x4953f87c2a000", + "0x0", + "0x4953f87c2a000", + "0x0", + "0x20f73e", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x23101fa869470", + "signature": [ + "0x698d70c12917253d04be4d46d8599e6ee1f8748145745b2c477b8af602d69d0", + "0x4a9a2a8544cc5432e70e7cf5759411db218dded7bed0cfab1bd4310389770b0" + ], + "nonce": "0x9", + "sender_address": "0x59bbf16c2cc69965ed4f9978525251162cbaf8456f5c8ca1893984b5a575060", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x0", + "0x2", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x570a9ee80d6a4b8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x5521d80690de5c3e8ba6b9707deab2e15b2b99c6d1a80adde61e57f0fe5f59a", + "0x3906ea6296ff59f6d9a3ab70fa1f98044847d9118f666fecbfe3369df7e2cff" + ], + "nonce": "0x1c", + "sender_address": "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x19aef827bdae4d7a", + "0x0", + "0x19aef827bdae4d7a", + "0x0", + "0x3bb0338e175ac", + "0x0", + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "0x64f32a38" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb4fd4c4f7000", + "signature": [ + "0x3e80a295fb4076a94be6136ac1b501ad739763bb8ca70656f7177d534f8158", + "0x6c2f057a302fbda520abc2cf4c8226c2056204ab635e8e38b40493e47f0f0a" + ], + "nonce": "0x3c", + "sender_address": "0x20f89774cfcdf23b903823b7bdefa06d57fd44c8e870c8510ee5757b2360a8a", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x20eadb8cc1e667dab2d95e011b2f2ae72a64de91e0b652eecb07930f6b2ffaa", + "0x3", + "0x3", + "0x6", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0", + "0x6eadeb", + "0x16d", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x489c700a6d763a79e0a1794b0fdfc2ba6d497e098813fc7effeba523b55924", + "0x59a26c6c4ad65ac97948f3c69715acff27141ad2d9772a76b6b7f9fcdfc93da" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x5c2bf52fefd9dc5d04bf631047b1e74502268193d7591c813f8725be8fbaf7e", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x5c2bf52fefd9dc5d04bf631047b1e74502268193d7591c813f8725be8fbaf7e", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x5d1384999b5f166b518b375b6589be6c0ac9c5d253e1c8da2688ca51cc51057", + "0x4c96faaf416ba548b8765c0e46e8e9b25b813c967ab81519ae527e506e80dac" + ], + "nonce": "0xa", + "sender_address": "0x5286f50d8b489884631332ffaec5d017506cf9ddcb656172ed7dc19390febe8", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x444647444647444640474d41494c2e434f4d", + "0x44464744464744" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x96110e635000", + "signature": [ + "0x47e5d2d60a257b1bd3f19634d1f420a62ed474dc0e9121b4e28c8ddc3427550", + "0x7a570b262cb4211c0c31ae89120a0be310ed036372b033225bbb01358b112f4" + ], + "nonce": "0x1", + "sender_address": "0x5883a787cf0634c9b79b2c2c3cf4d521b99f02870ccd9172741f48a5e48e6f3", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xb841d4ced2" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xf095429197b4", + "signature": [ + "0x70c676af92fdc1a67dc9d76d923a75e29dfb0fb9fa1ea1d583c0e1b8934fa79", + "0x2149d062b2b237a31ba38d1fe96b61cea915c33fb633ff0f22ae692be67da62" + ], + "nonce": "0x1", + "sender_address": "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x76696b61647340676d61696c2e636f6d", + "0x74657374" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x6557cb5d99f9bf5b6621772479438598c6a0cba675d4ab8833e17daaf33b281", + "0x475308553801996def2b9251d5206b0c7c51b3ff8969b230b472123a87be0cd" + ], + "nonce": "0x817f6", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x47c2b54e54ea63add8aea75cc7e92801b4cf61aef3db10b726a290df943dd9f", + "0xeb54edd5ec000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x9c6307b5f0ec05aebab8765b3ee421abc0e58a18356e5ffb2dd969c865d37d", + "0xdf7fcdda9cc47c61c64dc417546fb804aae06074a2f42e78f48faaa54747ab" + ], + "nonce": "0xc", + "sender_address": "0x68042faa192fc35262472748a10d37d2d6590e8ccb162d507580b958c094783", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x7279736572406d61696c2e7275", + "0x455241" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x30c862d3bf11c", + "signature": [ + "0x788a3d98032436ff4437bebaa078e2c1dc4ea0234831950460dee6d1411872e", + "0x7a85fc3c4cbddbe6ef5bd985644d67c9bdb2f4e580003abb135043147697131" + ], + "nonce": "0x19", + "sender_address": "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "calldata": [ + "0x2", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x147fd8f7d12de6da66feedc6d64a11bd371e5471ee1018f11f9072ede67a0fa", + "0x3", + "0xa", + "0xd", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xcc36564238", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xcc36564238", + "0x0", + "0x6a5cd34623392e", + "0x0", + "0x30da92c", + "0x0", + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x64f32a42" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3f8a255a4088e", + "signature": [ + "0x455162212a33d08c778e63fdf7192c1ff88aa1732b020d3fe8efbdec36591b", + "0x36b9bf1c9395e2d143adb0a303e235fa180af84773b275ae56fe8351cd5d302" + ], + "nonce": "0x54", + "sender_address": "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "calldata": [ + "0x2", + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x147fd8f7d12de6da66feedc6d64a11bd371e5471ee1018f11f9072ede67a0fa", + "0x3", + "0xb", + "0xe", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x4f1642c1964", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x0", + "0x4f1642c1964", + "0x0", + "0x1c82de054de0061", + "0x0", + "0xd2b121c", + "0x0", + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x64f09638" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x1d1be32198ed4ba81514845f2f5b8ef908aee2eb01205c36174b8cff1f264cd", + "0x1058d0559d1836c11c661fc99db69fc016cf6da75c6db1d38ea18ab0f9b704b" + ], + "nonce": "0xf", + "sender_address": "0x821f46ed5c3c9eef8261d0bbedd89242137dbaeab743b8c63849152cac768c", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x2e0de7c8e70e8cecd82e95460736c9641f3dd230226bbb002dd0bf949604844", + "0x4f683a39d05789430cfa718caab03d02785e74b3a8f3d91631ef79a7974bc8f" + ], + "nonce": "0x14", + "sender_address": "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2f4d60", + "0x0", + "0x2f4d60", + "0x0", + "0x646b6f748df86", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "0x64f32a3f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2c47f1247b000", + "signature": [ + "0x6d0795c5930863dd992aca5cec3369c5176c1089a37a03fbedea0a4d685896f", + "0x680d2aa18942c562446dad34213852e3692ba8e560333e13e02a2e79c820c0d" + ], + "nonce": "0xf", + "sender_address": "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4b77a83030930000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x4b77a83030930000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x7ba1ef03da3b7c7a0f181ef2316bf1a720ff23d54c63ae28e08b3d887311ce6", + "0xc4bbd2c3867272121db04dc1eef33d6c2f50fc31abd0c2e4fbc875d5d223b3" + ], + "nonce": "0x37", + "sender_address": "0x115673b5174e4686b83b2646372673ee319c2c65c40dc057f64aa860d259ee8", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x323735343538374071712e636f6d", + "0x3532353234" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x99f332e7bc277144fc0e4c4aecae4ebc10d7d0e986267827156c1afbbf6a4e", + "0x547031c7ca5e4781a7bd4a2993278fcea168f58f04b67ca1f9aada97d96c31" + ], + "nonce": "0x44", + "sender_address": "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x746a777064756432353640676d61696c2e636f6d", + "0x637a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0xa6e20f6a3b8856692c7fd171aee0b07919bf7fdedfa523c1f1cab9bd6f1096", + "0x368d5546989ca919c19372f0fb97ae9f8ddbe7db44fc1a89fb1246a3da9f68b" + ], + "nonce": "0x15", + "sender_address": "0x4882c6524fde55402e75eeef5453bf519ff7fd4a341a2a0faf9563969809624", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x73647678637a656b7a6f7440676d61696c2e636f6d", + "0x66776574777a6b7a75" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee777dc2c662", + "signature": [ + "0x28f98cded7075cabd0985afc702d206e10f6c44cd2a6fea3058edd0ea227e07", + "0x55284e9c22f70822749aa525ff2279b1b1673eae8f1217d7a13232a257d7e7" + ], + "nonce": "0x10", + "sender_address": "0xa1f5b7b3aa23a9736d6542fc45bae02dc799c52c6d23834479640abe4e371a", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x66fae54fa402c36d9404707bff4e778f797b8668c46fc97f540fa3e700394c", + "0x5b56e49dd49959896d1e5d07ba4fb5e963c60ff9daa6285b366f8cb0a3a29d4" + ], + "nonce": "0x817f7", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x86b26c77a1f781c4330c9b9e183ef9760569bcc47dbad0d1e3033d67991c1a", + "0x16bcc41e90000", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x85333a8cf5d8", + "signature": [ + "0x416e2ddb3147b17da41a166d5347e09c389c19fdde0ffcc9c8c2cd1b979bb52", + "0x3e990e0861631b0a8734a829464ca47435d65de238ab786677ebebab50884d" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x4d95ecb0dc7e7e8514bcdf88ca2875ae5c733ab7f77296af138a0977a493b77", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4d95ecb0dc7e7e8514bcdf88ca2875ae5c733ab7f77296af138a0977a493b77", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb3faf8e37322", + "signature": [ + "0x1e7f53bea2ecfff79bb336a9a00a950f27beebf0c67706df139d87a500181de", + "0x1e11a63a93fdb423d5c4586419087eb07c4943688bab50c8d9c31403f3d3450" + ], + "nonce": "0xf", + "sender_address": "0x7f3e5cd852e285fb809e7c5c578ae0c11a190e028dddec20ccd9b55b0cce2b4", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x3cfa875b8f0e7cfecc1f1365072715fc9906b99c3d5773e44aa1d7c2129960c", + "0x5bbf95ffa7de96", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x16ae36d43f000", + "signature": [ + "0x42bb4d4930c6d399daea7fe4eb5081e1f4fba2e574342aaff3a5fe4d959b43d", + "0x2e2829393e59de64ddec189be119e0a28ec3b6dcd43957500cf5a7470c07261" + ], + "nonce": "0x7", + "sender_address": "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2cfb12ff9e08412ec5009c65ea06e727119ad948d25c8a8cc2c86fec4adee70", + "0x6", + "0xc", + "0x12", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x22f2ba31d13f28", + "0x0", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x100d4a0", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x22f2ba31d13f28", + "0x0", + "0x100d4a0", + "0x0", + "0x22e9c7d5187622", + "0x0", + "0x10092e0", + "0x0", + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x64f0952c" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10bb5c0327002", + "signature": [ + "0x7bf5f105fee34f0d900bd744ab83fc9a93e8c49255ac9b8da561421f62d9d6e", + "0x7f8a20006dc5feeea0bf464cfdcb7579fa6debdbc52140bd17bb588476b9efc" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x32c5ff8509fe00915a9644a91d05163af52c50b7cd3e25afd12f3d09d2e1b84", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x32c5ff8509fe00915a9644a91d05163af52c50b7cd3e25afd12f3d09d2e1b84", + "0x0" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x85dae0193801", + "signature": [ + "0x3feea4653db8f7c40626f7e2661f859a7ab1dc2dcd27c5e6dc51cceb7a89a38", + "0x2597e1c17b881e9fc55ff8716778cb213a63067fd995ee24fcf2c7d8b4684f5" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x43aa3da22af08f85335b7f1319354179cdaf930867d8e8d038bcce705a5cfb7", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x43aa3da22af08f85335b7f1319354179cdaf930867d8e8d038bcce705a5cfb7", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x5f3dc94c2a8de143870943c28a31a503b6ba220b37d53765719d6f3017a3412", + "0x142f176b3846df3752236e73ffd3743dc77a1fe66bb64e2956ea65b2599ce92" + ], + "nonce": "0x16", + "sender_address": "0x77c76432a1480a2692926f8fb045fb3e7b50dcc0f5909e08f2c1151fad60338", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x6744a604671d44008b4764376b8e615e90f3f92a9bc24f6d998aadaba6a8f64", + "0x165c165f75b6d32efa91d2b63cae1dcfa4dbab99b8d7970c5d62676f9b2efe1" + ], + "nonce": "0xd", + "sender_address": "0x3317ff1621068fec9a668441e8a0500940d971889cb0a0aed6223112da856ad", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x632c2342be601bded0a7d00dcd9ed1067c1786bd790fbaa762422e3c7be0a90", + "0x73bffdc8ad64b8dfe057995ff7937283e05893f0bbeb9385c1cec607015c1ae" + ], + "nonce": "0x817f8", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x119f66edec9b3a3f6230655c562777b942476bb756e864ee31c6b7842218d5a", + "0x1ebb21114ea000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x258bc74c86276", + "signature": [ + "0x30b4f5716e8f90d2f6a831c919e23ed9d50f9afa68ea14251430c0d1f916b18", + "0x457bbdd2766d744f404f647dc79ebc041364923953f731b06a19d0552b42965" + ], + "nonce": "0x8", + "sender_address": "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4380663abb8000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x4380663abb8000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x156367974d095", + "signature": [ + "0x284b93e25f89dd243767c205d4d1b2866599e7c6981d548b1d2c485f4004155", + "0x4817d0bb414d5985d0e55eaa19c884f6e826d69898b42e1b8bb20609762a569" + ], + "nonce": "0x26", + "sender_address": "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7621226", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7621226", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x102104c3c9a4190", + "0x0", + "0xfb9cb0bb166652", + "0x0", + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0x0", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21eaec0e4d14c", + "signature": [ + "0x480a4b9751719d648d1c161c825322352bccd9f59a4b895ccd82a97a4f382d6", + "0x43feb87d2b7c540251097b0e5007cd7315b5dd10af75c3763336436ad223ece" + ], + "nonce": "0x1", + "sender_address": "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x71afd498d0000", + "0x0", + "0x3340d8", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x64f32a22" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x26286a1f9a03f", + "signature": [ + "0x426bb86214a43c3f4095c3e684ee1ce55eaaee21939f3e83127f5c050caf47", + "0x93930c4b2e342638005d3bbe35f7a8fa203c9e33f5a34ef583d6003a5063da" + ], + "nonce": "0x13", + "sender_address": "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x67a5da34b2825", + "0x0", + "0x67a5da34b2825", + "0x0", + "0x2d2a80", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "0x64f08874" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x6220c5cde404ff9299d47c413ff19f555b2dfc9bcedb6d431ca0c649e1eebe", + "0x7f7e301504493723ca5637a42c04c21e79142c1a9b57557d7ce42a5cc0821af" + ], + "nonce": "0x21", + "sender_address": "0x737d1bafd474f303837e1f03f06a867857402383f7baa5c7c2cc0e503e1d221", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x61706874686f6e677332303232403136332e636f6d", + "0x706874686f6e677332303232403136332e636f6d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x715d2eec08b540fce860b302f51bb95bc6cf14b226012814953c51302c08842", + "0x2526e2d23e68b34c099904f318a32f2c3fc47823abeb724698b292af47d94aa" + ], + "nonce": "0x2", + "sender_address": "0x197e968ee95240c770622b28f081949d0682012701b7a8ac2991b63691d21b8", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b48eb57e00000", + "0x0", + "0x4", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b48eb57e00000", + "0x0", + "0xc324fb", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1af19b99fa000", + "signature": [ + "0x631809824b541f2184a1524880aee18ce59ff5259412a350638395056c4a10d", + "0x74f692b92fb91bdb8f0e1479bc427c53657be0c716f61306c09e0e21fbbdd8b" + ], + "nonce": "0x1", + "sender_address": "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xe0c15664b7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f078824a000", + "signature": [ + "0x16adcfe8591d558e1b5c4fe01660bce2988aeff517714a74e0a9cc25286e85e", + "0x4c92a0b0bb010d02d4ffe03e5647eb7768c173e5b999accd27f5fd2726e0f1a" + ], + "nonce": "0x7", + "sender_address": "0x6b33feb724b953721e43c3bdc8add7c018ae1de52eb558ae328e6fff137769f", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1aa535d3d0c0000", + "0x0", + "0x4", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1aa535d3d0c0000", + "0x0", + "0xc1ccf0c", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0x45b517e80f4eb8d2fca0eb3171a191182c27f7b1c2310181a1e2c565c7ec345", + "0x49d850aeeb5cb98d027d11db170aade422303a5d64510718af45fb577573f4e" + ], + "nonce": "0x817f9", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x50270f69c87691e5d6274ca5dd626a5b8231a92b1a8beca200c4b08217ecbf0", + "0x1e8da789118000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x66ebb85038954735de8eb523c5bb05c981a48a185004ba4208d557489934a07", + "0x120465c4f372351d273ec058f9119728ae5dabc83d82c9f4b922d409b6b9b5b" + ], + "nonce": "0x14", + "sender_address": "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2dc6c0", + "0x0", + "0x2dc6c0", + "0x0", + "0x612e2a2223e20", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "0x64f32a40" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10efb07a09c3e", + "signature": [ + "0x26aa9fda70258f656c898e2284f57eda75eda52949fcd1d903523858be713a4", + "0x2692cd4df8fd6d1d6969de66890cf7672705934bf9fa1a2351dbf80a9ac682" + ], + "nonce": "0x2", + "sender_address": "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3d1b4f12230000", + "0x0", + "0x3d1b4f12230000", + "0x0", + "0x184b5c0c62189a312", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "0x64f09557" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10ff05cc9b000", + "signature": [ + "0x24ee8fd0d0420231289f7be44e1095fa06fbb080083d731465b0d11feb113a2", + "0x67da0133b28b346c5371c2b29aa546a4088f0c5ea02e7d95faa873469c827ff" + ], + "nonce": "0xa", + "sender_address": "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xe02745", + "0x0", + "0xe02745", + "0x0", + "0x1dbdc4b3cb85fd", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "0x64f32a42" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x18ab87fd52000", + "signature": [ + "0x6d5d6ec3f1b131dff3ac89f1a1b46457931ac53917743212afc9983556551a2", + "0x7aee98f783788794990a9a4116e6fe95705adacd5988ed5be707f273395d2a4" + ], + "nonce": "0x6", + "sender_address": "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1c80e", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1c80e", + "0x0", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0xf30a6d66c5e1900", + "0x0", + "0xf09c3e3a39a98c0", + "0x0", + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0x0", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21ce72cd9cfd2", + "signature": [ + "0x30c0fe4752fbf9c4359c4a1ee356ce9d902badd5ea82aecf57926c1eccf860", + "0x4ef34146950848b7db16cf385a403658d32ea3cdceace06c3f7d97b75e3292c" + ], + "nonce": "0x26", + "sender_address": "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1a5878bde99a0000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1a5878bde99a0000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x22045147fee4c", + "signature": [ + "0x40aeee5a5b53df223786d99535936199cb7e99970f1bfcc836754363f97f844", + "0x7afbd4a4e5165352cb8437d00361e8228d528f164a97d6819e7029aa55d712" + ], + "nonce": "0x11", + "sender_address": "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1c9dd18ed7f706e47", + "0x0", + "0x1c9dd18ed7f706e47", + "0x0", + "0x43b6576cfddef3", + "0x0", + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "0x64f0952c" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x780da51c4000", + "signature": [ + "0x67e660580c3e8d4c211879475409eee0d8db42de612474f6cf5ff36e7a5635d", + "0x1994743d619b4ea4f8cb43ddb4ecd7872587e493a7e4f63c1e2805f506b3756" + ], + "nonce": "0x9", + "sender_address": "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x0", + "0x1", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x78e2f1c759ca673da8fbb55305d952e8ebf16968b53d4fd4149bf7735448895", + "0x7cc2a9546cbe9538e0bfc656c549f0e555a3216adf8133a38fb11ce2449f4e8" + ], + "nonce": "0x1", + "sender_address": "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "0x70756d6963657273" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x4a0c82201aff626c112515122dd2a03da55d5f86af94fa05ccff4f21708eb1c", + "0x377b01495df946eca7b324b9793d54cb12a186e2875fc539225ac49cca2ec03" + ], + "nonce": "0x16", + "sender_address": "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x63616765696e6d796d696e6440676d61696c2e636f6d", + "0x63616765696e6d796d696e6440676d61696c2e636f6d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xd04637a75000", + "signature": [ + "0x2a8bd766082f3af199c58663e57a5a8921a93b9eb57997817888c9ca74fa523", + "0x5cefd5bc4577f58f3722ed0bfaf569f981090034135e3d2a21b09080ee9afec" + ], + "nonce": "0x2", + "sender_address": "0x6baa1b85be8c83d6c9ccfc8b3a6d811a4cdd7d09bb2d332a24a84cc9311e7f8", + "calldata": [ + "0x1", + "0x60582df2cd4ad2c988b11fdede5c43f56a432e895df255ccd1af129160044b8", + "0x19ea78dfeefee473cead0f17e6cea7018f57abbf524110c3d3a369b248c7ce0", + "0x0", + "0x1", + "0x1", + "0x6baa1b85be8c83d6c9ccfc8b3a6d811a4cdd7d09bb2d332a24a84cc9311e7f8" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xee901dfab8a0", + "signature": [ + "0x4d34b2233eba856eb5efbd1fafdc6977c80d0a174d432693132666aeae02eca", + "0x7f708462e8c2bc50dc74bb404d67aad83f0987bca64ef0cefdadccb1a6f1e7d" + ], + "nonce": "0xf", + "sender_address": "0x4bdeccd35800e17724a3d37ce2edec532089069c515ac8a04eb98a99792e14e", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x7a6b5cc294339242dab69c8527a73d6bed3ec925bf9b3a30c7692b1b430e3a0", + "0x43983bf901b84a644b423f38cc7bbedb48f0157b39d3c2431ca69f2ad5a7c5a" + ], + "nonce": "0x13", + "sender_address": "0x10e2bf36bc2c5554d9519e41ad40e5ee4acf44c5eca47c0b2ac25c2c928cb5", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x666467666740676d61696c2e636f6d", + "0x676e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x2917db5b8ad5a", + "signature": [ + "0x2863a1b29b0aa550d1680d9469fc12bf9b05eb12686e02096e9911315235bfb", + "0x4685043e9bb0201242cd7f0833908264b021d0da59280913578f90b40033fee" + ], + "nonce": "0x4", + "sender_address": "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2625a00", + "0x0", + "0x5", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2625a00", + "0x0", + "0x25658e8", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x5ff73da3bbccd615d8366f18aac56a6bccfcc2c15216dae811e5f0746eda98f", + "0x7ce526e6289eae2000cbb2d963599b48dec9906b541fed07a1d3db5a93b5383" + ], + "nonce": "0x2", + "sender_address": "0x1a02726d8b4f2a988e24ea7cf25418fb751d431850cedece765d66be9baeaea", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x22153f6e756f6", + "signature": [ + "0x5f652781613376d5e1575b556812030de0533d66aff673d8e4922e2e4e03956", + "0x4aa2641798c5e1bd4e29c5571b2ca7fafa1caabb7c513734bc387d1996dfd64" + ], + "nonce": "0x1c", + "sender_address": "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x5816e9", + "0x0", + "0x5816e9", + "0x0", + "0xbb35955e194b9", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21bcbfa566e08", + "signature": [ + "0x468f2b1eca6c0068d046a63892b952968e9c595a4aeaa4c5bcb951e5c74f9fe", + "0x6667127239df5240b5746a126f164a51ab00391f9fa0a055eccc329620559ea" + ], + "nonce": "0x26", + "sender_address": "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1211f218a6bfb31", + "0x0", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1211f218a6bfb31", + "0x0", + "0x81d0e90", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1e5ab904f6000", + "signature": [ + "0x7d090f5a06b06c38a5d5cf432df7e9c66eaeecfa23f0352fb2ef173305b3ed1", + "0x7a9446fa1e2afcc6a633808059ed303fcd8027410884b79353df9a754c911fb" + ], + "nonce": "0x12", + "sender_address": "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0xd", + "0x10", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xf4471", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0xf4240", + "0x2", + "0xcfd39f5244f7b617418c018204a8a9f9a7f72e71f0ef38f968eeb2a9ca302b", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0xf4471", + "0x0", + "0xda1b4e3627ae7b2", + "0x0", + "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xb2c0fe1a228b", + "signature": [ + "0x2c4fe2d15e886154af2fec5f7fd30d9e36838e15c992fb0fd467a2c7420e06a", + "0x602c7d5ef0d971d336bd2784d0354b5195cfce8eb8bd334a58fdba9e8a1cc14" + ], + "nonce": "0x1b", + "sender_address": "0x79b7b718eff45515b3726fc90e02322638005974325d2d675e33289eb6f8e7e", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x16fc87a2dd63d0158d7b708c7f6bc5e35779dcbf5861ecae06935a69fecc033", + "0x0", + "0x1", + "0x1", + "0x7f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x5e32e46ca6e1e93e0d1398f8ded42ae09d89e01d539676354d59d7b1ea159b6", + "0x4a118445c235c6b112c5c8392201dbc00894a8a04a20f5c81e02770f6582dbc" + ], + "nonce": "0x5e", + "sender_address": "0x7e3241296ee6c9266d868860bba2a7c3b05b07a544be935fadd69a294b4ea5f", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x64ccfc3187a05f733d4413535467ad06edd4dd348f4125b4074da04d89db593", + "0x4cb4df0fc824f0dba4fef41367fc12b34e9870d640f750543ce3ab9f3cd6ec4" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x73d7135623ba9101dd2c71a4b2d4d9c4d7997b12162b4c1b247351d2966653b", + "0x7da48501b217e333327a11e0811fa1f9375f4f9918c47689c8edc31b1919c67" + ], + "nonce": "0x5e", + "sender_address": "0x5a598378180ff46c0bff556a482a31616bf95500cf8d6eb4e9c42cdf2ffcee5", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x28b4098f8cc7b445b3c08a638cc41ec628b31abce5cb16a546b4a2e9405298a", + "0x50347253be99f24991783830d2195e5e83fd0f8a1be688cec42ef5193a86411" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x40d848d4778f240a87ccc8311996e5174383ce339cf6eb9ca701228164f722b", + "0x7a8629fb8d6e1a09257366ec8c6032d16ac6a7ff80c74aa39f350d5ea02966d" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x4e44f1572bfbbf10c97e8980e5675dab0f002f0f345c4048d010e43035b26c", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4e44f1572bfbbf10c97e8980e5675dab0f002f0f345c4048d010e43035b26c", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x2d96becbaf035aac896834fb7576d72718e7daf44ec8f4034314865e21d3efe", + "0x6c3bf497891528aab8463fe81b1f335a4da04a212484f17588fcbb1b144048a" + ], + "nonce": "0x59", + "sender_address": "0x7aeac00aa978fe97bb5cc51b407154affc34bfa1b196453cd61aa61ba0f405a", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0xdab21fc887e40691ed7d660f1e0c9de90ab5491a1106fe8d765a2ee2670821", + "0x5d137b45ed01c068a2b97b320fd052681591f55842c9ee99df89f414fa7e19b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x60ae8f759a65446cb6419a62397320097d74c38d6a86852363932567d99cf99", + "0x52432a21e330275cb82710d8b90fc878d2d9e9d03c645d5d69de54fe8d9cb10" + ], + "nonce": "0x62", + "sender_address": "0x52c616b110fff40a582ba6ef1a0be9a8543b8e27e5db4b4cbfb58a725c6069b", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x69c0f5e8ae4566b00248df3c145730c35c76d87dc8dc1932540351703f9f196", + "0x66de4b70e9cce438d248cb52d7ec8a7daaabfb515b62469dff73108c603a51b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x7ae901a344377248b36aa25b07768ef972e88b7f59f36207c0c2f9e869cf1a2", + "0x3d3ab84caf9df37ccdec587c87f6b31ee32c193732f267d2686bbdd42fcb96f" + ], + "nonce": "0xd", + "sender_address": "0xbf16f683c5efd280a0ccfff6a70d28bcd3afd47187bbc819ccc11554731778", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x3366676632646640676d61696c2e636f6d", + "0x663233" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21c15dafe44c2", + "signature": [ + "0x2c29684d47dc0754f8d839fc4e724b665fb570a292d8c453cb594435e3d41ff", + "0x21c111e6676ab9b411c020aefac222cda0fb6eb9b2eecea30fae12967e07c15" + ], + "nonce": "0x18", + "sender_address": "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x275dc81fcd5c700205ff6dc320e9d54ed3f0ace21177d591d6d5d259ee1d7c2", + "0x0", + "0x1", + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x4d442a7758430848a5c3737e7f322b44878267493851470f7f521b095e097a6", + "0xbe3a86ff0ed2afbcbe29e9a777e0f5402df8793ea3a9934dac5bf835849553" + ], + "nonce": "0x9", + "sender_address": "0x4176fe21fa98a0cae78f0778e44c412c02678bdb25858a51b4727788f624ef2", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30", + "0x30" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x5fb162cdbaa962d04af2890a744bb404c287c70c09b43868ddd6376450b96fd", + "0x7f4d8fde6dc3c6b92c8eadf5f383cfe916f77907b702ee8e651d68688a72dae" + ], + "nonce": "0x60", + "sender_address": "0x3c1528d4f6f2a6b5429f439cc9742bfd8f034e4cb839b028410dacbcfd83702", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x67c7b005b5374ff0b60fe271434ed2e0475dde60c3c7218b04a1d6297093f14", + "0x487539d7a22c49647eae6a3350d328653a966008759092957731fb6803066c9" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x78795d070c8037bff1cc7a2eba6c2a24437d9965671820b5a98e3c531da1c65", + "0x520f2b6e7dca3320afb4c596cf96295a24016671a9c0a80a4280451ec51e89b" + ], + "nonce": "0x5e", + "sender_address": "0x6b0d389a0770e4ee751ec03169a6c0e8b14ef2d791afd76017153fcf6db64bb", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x750596694cfd5bb3ef4f7a415b874cc33a3f2f2edae6ed6fb4aa5e636cb74cd", + "0x780ad9ddfe5d5036c2d85ed2af7273367d0790bae653d882faee17f4286129d" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0xd71e4d1acd008cab77548e02f1e7de1801aa4d80401bac64edf5bd57fc2907", + "0x5498dd89ce346e3d0ea8db4496ddfbdf098202c87b136ee36cc91a46d2183a1" + ], + "nonce": "0x63", + "sender_address": "0x582401e1d694d98bac21d93ec039e218d7b85c9e3f54ab178d67b1d8c140f96", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x56312ee69705e01494f6d6ee8ed107c91d8fc0a85203665cb60cbe693452012", + "0x70689911a2fc230b37bf0fd937c8204b92febb636e172f0555e634a28aaede5" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x5e670a3018fba7cc50c38c2ef58991093221140f9fd2ae922b556db0a612b4", + "0xf77e38f047e8a0dfb08a6bebe2efd446ce952f6f61ce2780e3c8fa8c289794" + ], + "nonce": "0x5f", + "sender_address": "0x7092baebed34a58347a58c26b5e6a9114daeb98ac274e347ff9786aa9df7eda", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x53115e800c796d7332c934a8d72d0e8aa5551d0b6192be4821e71b760c3e05f", + "0xc331e453de90f507cfca0040561ae5f8af8fc2309b99e90ab9d5501708d382" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x5603c21a767101f7d43a4cf56e8a2432641e1c6fd0775c1eb270c7626635e9f", + "0x61abd254f930ba1b731674712c7fffb437031e187403d0b2340b605224ed20a" + ], + "nonce": "0x17", + "sender_address": "0x71f1a45ae1b5d70536139c1f60de8ef0778b2c777fafc10ae79432f080a4310", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x33714d30637376406f75746c6f6f6b2e636f6d", + "0x6368696c64206172656120617274" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x10f36db05f5f9f48a1649065a6586630d75f17e5ff3bfd3fe3517caff4a8007", + "0x198b266dc57d637f635173e2b55afd78bb2f3c8a51c3a57c2b6a2917653382e" + ], + "nonce": "0x5d", + "sender_address": "0x6541717d6ef30f667561588c3f043cf0dbe5b7788673d7d8abb59f2092de76b", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x7c1f5e0aec95d3faf31eb29e6af9f651e1503cc314c9f5c2390be53dadf58c0", + "0x9c1831a336f3d371eca3bad75bbbc000f544627a0f86dee6d288d56b3d9389" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x6692d6e9a0a82a1c0d4771a7df8510d7ec2be7dff3dbfa165e0e15bd51d0920", + "0x642a1fdaa58912464fc8e906012709db5412e63e551e4da9f160ff694b6cf1f" + ], + "nonce": "0x5f", + "sender_address": "0x2ee5588d611de71d6fc402782886abe5e39e06d772500efa1128ecf13797b07", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x623927928ec342d081b931138951c6fdc4c163bb8ea69cd7862d69fbbc6dcc0", + "0x6669422e821d3aeb03b654beb3d4826c8b9cf155c2a647a01b12c8910852c7a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x507c116611bcbc42a868522510d9d356a30cdf2f5d45ffe59cfd4f977b5035a", + "0x2f012ebe911b96a7ed5bb2893b14b7081857957c4c3bddf234d755e170aa1e1" + ], + "nonce": "0x5e", + "sender_address": "0x714ab0f7f7ec80ef94ac09c9e52262b4800358b81f17e4f00e16cf2adfb4291", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x6e4879403adac7f97165965e440dac1a4162eb906f976d65ccfd2b221694c3e", + "0x4f0dbf448b9d80c44448817e1aad139b4ef1d8db597fcf52cdd3b3c0fd02716" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xde0b6b3a7640000", + "signature": [ + "0x324f86ed343e0052e2417864b005027a55f591ba6621518ff29a38acdd0fc2a", + "0x2cf96d5b81e69769bffd477b78123f6ee121409254b2165afb78768d8f40851" + ], + "nonce": "0x4885", + "sender_address": "0x6f40a7cba2e500321519acc0e8c6554fc19da93d7f46bc65637e9865752d4ae", + "calldata": [ + "0x1", + "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "0x8c3bba700788da00e373386640006338bc3ef7ec96291f998977238013f3a", + "0x0", + "0xa9", + "0xa9", + "0x1c", + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4554482f555344", + "0x27d955bf80", + "0x0", + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4254432f555344", + "0x27a52e4ec00", + "0x0", + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x555344432f555344", + "0x5f5f0a0", + "0x0", + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5f0a0", + "0x0", + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4441492f555344", + "0x5f2b480", + "0x0", + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4554482f555344", + "0x27cc945e00", + "0x0", + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4254432f555344", + "0x2799f7bf780", + "0x0", + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x555344432f555344", + "0x5f7dcd0", + "0x0", + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5b9f0", + "0x0", + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5e100", + "0x0", + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4554482f555344", + "0x27d92f99df", + "0x0", + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4254432f555344", + "0x27a41ab21bd", + "0x0", + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x555344432f555344", + "0x5f5e100", + "0x0", + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5cf6c", + "0x0", + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5a668", + "0x0", + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x4554482f555344", + "0x27e377bdff", + "0x66", + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x4254432f555344", + "0x27b59279800", + "0x6", + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x555344542f555344", + "0x5f7b5bf", + "0x303e5", + "0x64f0861c", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4554482f555344", + "0x27d4910b80", + "0x0", + "0x64f0861f", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4254432f555344", + "0x279e1a53900", + "0x0", + "0x64f0861e", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x555344432f555344", + "0x5f7679f", + "0x0", + "0x64f0861d", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5e100", + "0x0", + "0x64f08621", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5e100", + "0x0", + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4554482f555344", + "0x27d7db7777", + "0x0", + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4254432f555344", + "0x27a278034d4", + "0x0", + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x555344432f555344", + "0x5f60071", + "0x0", + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5ed87", + "0x0", + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5b526", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x842933f1a5000", + "signature": [ + "0xde13fd3e9eecfaa085223f84bbb33d313a0efcd70ff579efb92d18ff6c61b5", + "0x49113b5b08f7c378eb5e44eab12e1ed22c585b2e0f35997027e056bb61c3e40" + ], + "nonce": "0x817fa", + "sender_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x5cdadda64e7022faa661f4d34ed2d1883ef268a2748d6737d4195ad9c3c9c0a", + "0x2aa1efb94e0000", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x266c16a59760e23e24fdc755cb601479064d7e0dd7aeebb35e56b4d143e8c7a", + "0x33cfe52b0ecb65628efac0444e434e37ff3ca35f2e6a03a7725ae04fa1cd74a" + ], + "nonce": "0x5d", + "sender_address": "0x5555be7362c7bd36ad6395754827e973d955743d3a19f977e89ba41691b7391", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x15df64ceb4c99fb850c70af876f30a3a0297406ea069fa7946e79ad0278ab53", + "0x555d7e0ec9198c00ae81a44c907bac2bcd1003457ecbbe0a8c427ac89faf890" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x56fc69f60c519ae0ff29704ac22f052bef218b27548f7d1fab02b301a899a12", + "0x158e651ce22c347c0a972474c6366fe00ea609295ff2897de0d4a2bd282e964" + ], + "nonce": "0x64", + "sender_address": "0x3ca5df38a130dd86a16a0b7a4f2249a8a99dba57970b3acfaf123ab5fdac66a", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0xc956d7ff2f40f8c25014f193faa2c4913afea4aa5128a4d6a5e3426e6271d4", + "0x39a5194979234d789031e6bc10b1edd5d1dec3def1e400f43a8dfc09601406" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x1fb486d3c7240f880a2b572a1163b912b157efc97e54889481c3788eb8608c9", + "0x1ba5503e5de76d2f25ebac4878fd5c38c1ac5deaf9ab8374ad9c9c5d277c57e" + ], + "nonce": "0x5e", + "sender_address": "0x640bab67e33311c3200c1d98c8492e1d416b93166cda0d0a97d5b0b641bfdf4", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x680bff923ed643a2d2cd8ed115ed639b5d5e985ab35a22b21a8c50ba404d861", + "0x50cb76b3988d08fc4afbd88d52c187213c05dcd5cef2933e620bd34fd61c510" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x19e924b24e58cc4637cf5501f66d64d9a1df6cee55311799ed497c630e235b9", + "0x91542d646337e5f3fa44f5a3c80229c2b84e455324ad0cbd68ca89916c3f4b" + ], + "nonce": "0x10", + "sender_address": "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x647261676f6e40676d61696c2e636f6d", + "0x31" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21bcbfa566e08", + "signature": [ + "0x80f93f71fd17a818462aa3b3abc51877f9a816763091f13cc27c2d30bf89a4", + "0x7407e3d0a500d404e655418082dc2750f31f241c7d278a29e8bcef9baa218b4" + ], + "nonce": "0x1f", + "sender_address": "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x3", + "0x6", + "0x9", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x270753", + "0x0", + "0x4", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x270753", + "0x0", + "0x535937c9bb549", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x5821e44d08aa5e0fc25f7e210815da62ce896f47d35788993bf2490c493d7e2", + "0x44525acaf5fb550b7998ae7ccdc514312bd24967e694f7d8be0520751cfd034" + ], + "nonce": "0x5f", + "sender_address": "0x2c956c6254b4403e21105dc487433884b637685587b9adcf12ac6efe3e0d5cf", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x30807ccc87fedf7672446065440a02debc45cec28487f73904aace252b5ce25", + "0x4acb9988e5a6366c9f1c481ea4e14541b6731b4edb0b31f6575b75b189fb86e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x16150ec2fc7a4c1ed48b8e89dfa513df01f378e065dfc519c7268ce3e5dee39", + "0x50a2dc2c713dc20176df9a58ed8627dde09bb2ebcec24d0d82534309f089991" + ], + "nonce": "0x5f", + "sender_address": "0x6ab1243875b71c7417fbf68db53f7399fe884b3820d9fc365dbd9ae84d11a4", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x7781c4c9cfb04bc27f83cfbc84ebf004341ea988425eda424cbff72add4e3c1", + "0x13b8b895947652dab3bd3faf745c8db99389a40499fdce6531303eb11f724ba" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x10f57607268a6", + "signature": [ + "0x2bc0a6fe439900dba8961cd9d67ea9ebe08b9cdbb1065f389134a20c3b83671", + "0x460dd96faa546c736c7be61024af1bc1e0317e8b88c7dfb02e4caa5c9f2bac1" + ], + "nonce": "0x9", + "sender_address": "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x66602d3bf0af4", + "0x0", + "0x66602d3bf0af4", + "0x0", + "0x0", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "0x9f822f0b" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x37f3bb4091d7e3136a7a16f949a5380672408d9e5b5f5e221e46db7e06600da", + "0x336b1b8ebff79fe92f3e48689164f856b875e24a00372c3afca956b4b748943" + ], + "nonce": "0x12", + "sender_address": "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x819a5de168000", + "0x0", + "0x819a5de168000", + "0x0", + "0x3a5399", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "0x64f32a45" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x7b55d3e994d4ecad64c76d0d3a3b1629fd0aa4fc78612361a7f2e888589e9c1", + "0x5e2b60b6d9b645be0a157271def83ff674b5923ef64017c35a4bebc2f6193bf" + ], + "nonce": "0x65", + "sender_address": "0x1298195a9d32990d66ef9a9608b41ba796fd7a0ae0f8fbed4f8c3374d2da8db", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x3ca7fe43ef2165a86441b3b91d2451c7e91abcb39c674f6a0172774bca7897f", + "0x63b3d209e646ab6b8b887d42e2618143729e30d0a45bbf6e81d47a7369e6a03" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0xbb5b1cd2e000", + "signature": [ + "0x7767d94283450bb01f315ca7707f09b48e1a9a9ad472250e4d1c595f2743aa9", + "0x7bc1148afbc93684bd9519798c153125fd286f14a6a0ad710b59a344b8dd24b" + ], + "nonce": "0x21", + "sender_address": "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "calldata": [ + "0x1", + "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "0x3f01d80498096f7929858b5fc97cdfbd676b5d2ee673407df0c957d6a0fef5f", + "0x0", + "0x1", + "0x1", + "0x7300100008000000000000000000000000" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x4398c9ec6800d72311a27c5a178bfee24c924123d2754c4ed3d32b99c6f4a1f", + "0x60410b18800bbbb8a6b563983e3a01c446df5fcd0a5fec2b392b0c46ade60fb" + ], + "nonce": "0x5e", + "sender_address": "0x1c952311afd3ca9766d0f4bc2c41dd918016cf599e2662d15a8996e13510b4c", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x6c5b9262c5aebb3f72e613e34366a4f1c9b2b2dac1627751d600b4bc46100aa", + "0x351982c797cd783585d4bdce67f18ae9b9a172e47b9e2b3358b936364d5eb0f" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x14f9a81ec1000", + "signature": [ + "0x22c4ae863af4f7b846c8ff7456784309b3f1de6009197ea26103ed0d45f6a83", + "0x49073f490219e717847c0b1f29d33ca70081bd75204e0e14800e1e9a27a823f" + ], + "nonce": "0x12", + "sender_address": "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0xacb887281b6b365ed8e05dc0305a07bdebb0e02ca85e59d11353c0194dd20", + "0x3", + "0x9", + "0xc", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x5aa2b0035682", + "0x0", + "0x0", + "0xe10000000000000000", + "0x64fa63ff", + "0x1", + "0x5af3107a4000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xb95618c959", + "0x64f09555" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x349ad51cfb5d72b5a09359bd0db2c1ab11b18d264b44dc7ce96bf7ee25cd0ba", + "0x4cce4bb727eece2e266512a691df9135d14b8277ec373b6643f6eb72ae40549" + ], + "nonce": "0x70", + "sender_address": "0x5db491d68bdb6fd6101c8998ff9c1882b4f8bc9c54634839892abdc193c72ff", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x636f64653737372e626e62", + "0x617364617364" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x290d248126062d26163296d1db232c24f1a941d7c7962a0832702bf15662f01", + "0xf0493ef5a36c300be417519f7039554a4221c93d69600576098e9baa86fddf" + ], + "nonce": "0x3", + "sender_address": "0x4f49d8b4968e2a5f77e843ae6ede97495bd179170a7bca7abc23a785cd5984e", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x776965756668697766407266686f6c662e64736664", + "0x736466" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x32706997122d4", + "signature": [ + "0x62131bd520d7a34a28f45e9745ae1b91a7983b5129fb7dc56c100da3d7e8d8b", + "0x701eda0465d506bb3fa23f0f3760dc3a3cc26d356c90ce886fe767864b6e95c" + ], + "nonce": "0x1f", + "sender_address": "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1171593aa5bdadda4d6b0efde6cc94ee7649c3163d5efeb19da6c16d63a2a63", + "0x3", + "0x10", + "0x13", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1dcd6500", + "0x0", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1dcd6500", + "0x0", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x1dc99539", + "0x0", + "0x1dc1f512", + "0x0", + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x0", + "0x0", + "0x1", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x64" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x78d2127c8030", + "signature": [ + "0x43b798a040e1d382dea676a8f0d73a96e49a7424732e134bf86621606f99ee", + "0x75a7994d438c3040aa02862026410548d55326bd8ca896fa5023795d089cdf6" + ], + "nonce": "0x1d", + "sender_address": "0x7ce3bf01bdb37cc8065c41a1e1d9991755ea58f6336698983598f6516179947", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x307837636533626630316264623337636338303635633431613165316439393", + "0x6173646173646473" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3cefa7333000", + "signature": [ + "0x4a506fe192024e8531a6f214fd5cf84686c1761e7ac489b8776dee615986d73", + "0x3cde3ce4f18b311a790637971ce355eba8a76b45a55f98dffe2786cefa3ce79" + ], + "nonce": "0xd", + "sender_address": "0x40441b968c09e0441ee668d181ae1272196a229d01834ff05fc95ad2e4446a8", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x6164736667616f69696c706a6b6e40676d61696c2e636f6d", + "0x6661646661736466" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x156e127149000", + "signature": [ + "0x5eca548fbc2164a4d4da83badcb7f032cf53b478c1b514ec687cf4bbc9d9955", + "0x7524cd78c5c28bd9986673fb005a6f4dda423ebb0f5e7e4c03df10683e014ec", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x4d924c38c8920f546241b95ce07ae67b258b5e9b4945aff9cb7b4df6542f9b4", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x4d924c38c8920f546241b95ce07ae67b258b5e9b4945aff9cb7b4df6542f9b4" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x12d0af16bb000", + "signature": [ + "0x1160cad9c8e6c2f86bbf39883b15177ae9b31c6390809c1f2f1479d5df7ed0a", + "0x25946ea3f3800579229aab4770704ef3e0daf31e1d1ff7ab4de60394d862350" + ], + "nonce": "0x3", + "sender_address": "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "0x3", + "0x2", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda", + "0x5", + "0x1", + "0x6", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x155f2dd73a1a0000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x155f2dd73a1a0000", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x119f17fe16000", + "signature": [ + "0x2805960ef284d7faf8c2de91a26f758f0173a74b7c615b27c05030878996372", + "0x2bb8fe77e61983c9485113011b96c67d91c1e36bce940990e20d12e5c3b833d", + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ], + "nonce": "0x0", + "class_hash": "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e", + "contract_address_salt": "0x7080014d630a129a38a58938b8eeb5b1a4ece75de9243bab8f9f6890554c532", + "constructor_calldata": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570", + "0x2dd76e7ad84dbed81c314ffe5e7a7cacfb8f4836f01af4e913f275f89a3de1a", + "0x1", + "0x7080014d630a129a38a58938b8eeb5b1a4ece75de9243bab8f9f6890554c532" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x22153f6e756f6", + "signature": [ + "0x6d386927b94807d7de183da0eb0e5043485ab4d58b9951e1e701cc8a7ef9037", + "0x76d01587134c3e31c12f01897653f013c9fa884bff0602d6f10f50f8f9cd7e2" + ], + "nonce": "0x8", + "sender_address": "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "calldata": [ + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3276861cf5e05d6daf8f352cabb47df623eb10c383ab742fcc7abea94d5c5cc", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2dc6c0", + "0x0", + "0x2dc6c0", + "0x0", + "0x6148e86d9d1a7", + "0x0", + "0x2", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x3c69093e4018", + "signature": [ + "0x72f6c1337d8496526362eced50235993dee91b7c2f20bc8435a4a3d5931dc84", + "0x12b7d3443f3324e0073a9617972ec3070d72830418d795a11481218bb8a661" + ], + "nonce": "0x18", + "sender_address": "0x5aa500dc5b05fac944353b3c12d1add5534a2cd48a016e906f39022b9c62b08", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x33786e707333317240676d61696c2e636f6d", + "0x6c6576656c2077617465722e" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x5b05f8fdb6ae3865d67c7dc2f7f6aac0f7c789a4947dcae3351fc4bf92c3e17", + "0x2fc075411af8baee5b7e93aa566cc0f2eb51527bc8cd6e55f21f188935ff4cd" + ], + "nonce": "0x7", + "sender_address": "0x6a3f44a905ee102e20baf1976354095653eda068c506088db4b847da41fc938", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x73647364406173612e6c64", + "0x63786378" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x164859cc08000", + "signature": [ + "0x659d1a8a5046420a48c842cf9e3ad38cf3f5c3bdbf443f188bad8c9c5caf65e", + "0x3c2a205ab25632ba7619508be06692bb4d71b38aeb13f388ae6be4194e1d9f4" + ], + "nonce": "0x60", + "sender_address": "0x164cac9749e4abbca8295aaa50640cf428e06e6cb7d16d129a10e3df5aaf655", + "calldata": [ + "0x1", + "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "0x3bcbab0f12d1e1c14b87d50859af831fc38671a25bc658b0e1215ea469c282b", + "0x0", + "0x3", + "0x3", + "0xcb", + "0x235b9f31845ac4acb5aab668dcde6ad15b198c86d5535e8d0cf00b1bccf7908", + "0x11d4a2fc059d5f66fd853a0ea6de241df6c6e9332eb2058d2b6c6308121a6ca" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x1df4dbfcbf000", + "signature": [ + "0x7f78d70defe64153e2f0aedcbeacd42b711f14ae4ef49d8536db28eb053ea46", + "0x45af5158ca579e0ea60a95b8aa3f47fdf6258bf10c7a6a76ec43a81ccfbfb02" + ], + "nonce": "0x33", + "sender_address": "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "calldata": [ + "0x2", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xad257770e86a03742ebe0a615fb19503d9c891d118daa82163867444c08680", + "0x3", + "0x2", + "0x5", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2f27ef6e17db08000", + "0x0", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x2f27ef6e17db08000" + ] + } + } + }, + { + "DeployAccount": { + "V1": { + "max_fee": "0x10b3a9f1ab4cc", + "signature": [ + "0x4adf280883b3b1b0d45cc24ef91fc3169d182bec6f7dbf7afc660e1989e277a", + "0x39bbf16d0c6356bcb68025475069215ef69c5852984b0cb05033d4931c908b3" + ], + "nonce": "0x0", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "contract_address_salt": "0x4e71ffde595ab1018474a6318102346483e1b6b00d6def098440958f74b4af5", + "constructor_calldata": [ + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4e71ffde595ab1018474a6318102346483e1b6b00d6def098440958f74b4af5", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x780da51c4000", + "signature": [ + "0x33bc9eac5aacc728ddda1be24afc3dba06bbe89ab349a7875c590a55f18fe1c", + "0xa5a598f907783f0c38f47adc01e4bf8b3c391a55750a7a237b9c71dc6f24f5" + ], + "nonce": "0x19", + "sender_address": "0x2edcb8241b3161bc698c144b13421cab186eafa1a54ced5b8c5e8e1f39d6925", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2d4c8ea4c8fb9f571d1f6f9b7692fff8e5ceaf73b1df98e7da8c1109b39ae9a", + "0x0", + "0x2", + "0x2", + "0x3a2fc8b0db9a9ef748227ef61ed254897cb40ad39575a9bde734dc78073f779", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x21e1aff9523d8", + "signature": [ + "0x54e006a84ca28258ca4bf0a0c38155ce034a14227aa193d330731ac422291b1", + "0x16f721aea33cf12d304a39000819dff9a9a1faad329ffc586805352d798b3b5" + ], + "nonce": "0x10", + "sender_address": "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2c0f7bf2d6cf5304c29171bf493feb222fef84bdaf17805a6574b0c2e8bcc87", + "0x3", + "0x9", + "0xc", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xe35fa931a0000", + "0x0", + "0xe35fa931a0000", + "0x0", + "0x6653be", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "0x64f32a45" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x18552fc7c7eb1", + "signature": [ + "0x58c87ae6c3b2d8f983fabf484b1185d6f1973ec3ea5a5af073093c0f01e9603", + "0x5ec0d6afc351ff27e5084413d2fe116c4b8347e4c854749c4fabc3e270dccc0" + ], + "nonce": "0x10", + "sender_address": "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "calldata": [ + "0x3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x3", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2cfb12ff9e08412ec5009c65ea06e727119ad948d25c8a8cc2c86fec4adee70", + "0x6", + "0xa", + "0x10", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xa4d8eb863c2b", + "0x0", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4baf0", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xa4d8eb863c2b", + "0x0", + "0xa18ce6d059af", + "0x0", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x4baf0", + "0x0", + "0x4a2b8", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x25c4b9cde656c", + "signature": [ + "0x43ffbbcc5c888eeb17ff9f8649c2bdfaf0594161f19293cdb6a3b08c6934c69", + "0x55e87e6ba6c90c297e68601fd24547d035df800df17eed241079ec5e6344e85" + ], + "nonce": "0x2d", + "sender_address": "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "calldata": [ + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x0", + "0x3", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x3b1bf5248b545038b97fc53525d5be840cf237a3faddfcaa7b9e4c8439fdaad", + "0x3", + "0x9", + "0xc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x13e323a39c073d0", + "0x0", + "0x8f0d180", + "0x0", + "0x13e323a39c073d0", + "0x0", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "0x64f0950a" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x25340c85372a8", + "signature": [ + "0x74e921adc1768f4f30679e18bff88b7af0be1c6586f973405b21cbd40d6caa1", + "0x6026aa1becfd00c1472c48da3d48212e973f7d1a59f2bf2e06f6d539b272c52" + ], + "nonce": "0x1", + "sender_address": "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "calldata": [ + "0x1", + "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x1", + "0x1", + "0xbf2c9b2d87" + ] + } + } + }, + { + "Invoke": { + "V1": { + "max_fee": "0x784aa148cbda", + "signature": [ + "0x74ad75320cf59e3afe2ae981fbb5ba5e8396a861331572e98702e15a7e6a59d", + "0x5df2c798cb0a36559edca069be4aafd2127e4705e8b886d69ce165039313e87" + ], + "nonce": "0xb", + "sender_address": "0x5f08b14aa7133bbff9e5156ea7c4b479c41fd9eecf5e9578faf6d52918d863b", + "calldata": [ + "0x1", + "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "0x32a99297e1d12a9b91d4f90d5dd4b160d93c84a9e3b4daa916fec14ec852e05", + "0x0", + "0x2", + "0x2", + "0x30786b77656977697836357a61637a6c39767379366664316d6438767630616", + "0x74707776696e64716236" + ] + } + } + } + ], + "transaction_outputs": [ + { + "Invoke": { + "actual_fee": "0x104b845a657be", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x853a0d2313c000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x439d7ec4abbb69aaa8fa5acd9a682f118823f49f2542bc7673a9792ddff9fc2", + "0xc2b1b2a91d", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b4b223897258786f5062", + "0xd2da262bf3918718a7f45" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x853a0d2313c000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x853a0d2313c000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "0x853a0d2313c000", + "0x0" + ] + }, + { + "from_address": "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x85010702b16e9c5b8ebbf58704f3458534aaae7d3fc8b4f00c17c121c1892d", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7c2813a468be691c29195b8b71366b77746f3fe0b4f610f0fc4bdd6e27e3ea", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x104b845a657be", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34965, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 47, + "range_check_builtin_applications": 1917 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4fae6a5b7bf2", + "messages_sent": [], + "events": [ + { + "from_address": "0x1b22f7a9d18754c994ae0ee9adb4628d414232e3ebd748c386ac286f86c3066", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x26ca87088efb5de3fb30bc2985d16330eda9faaa84f7b9af8c2a043cbef83cf", + "0x3a2fc8b0db9a9ef748227ef61ed254897cb40ad39575a9bde734dc78073f779", + "0x1" + ] + }, + { + "from_address": "0x26ca87088efb5de3fb30bc2985d16330eda9faaa84f7b9af8c2a043cbef83cf", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x531af87d678ad23e6c563b012072ad3076e52ac5265b533458f32ff23a2e37e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26ca87088efb5de3fb30bc2985d16330eda9faaa84f7b9af8c2a043cbef83cf", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4fae6a5b7bf2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7301, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 165 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef27f9fe63c9", + "messages_sent": [], + "events": [ + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x309e2082", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0x0", + "0x309e2082", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0x1b1e6e55d806", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0xc785", + "0x0" + ] + }, + { + "from_address": "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1eb6bd1da0ef612df752831a8ae38922d0b6e963c316bbdeafb7ab849919101", + "0x9", + "0x1", + "0x1b1e6e55d806", + "0x0", + "0xc785", + "0x0", + "0x49ea9319ad53cb7925", + "0x0", + "0x21fd3ac3c51", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3fe9813f8955f070aba4e72b8cc36e4efb6caa2b9307b9d5414753849b224b7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef27f9fe63c9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22836, + "builtin_instance_counter": { + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 726 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4ff0159b5742", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4ff0159b5742", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8999, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 216 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x4af558b8506186e8202ec994d711d523cf379717284ff44ef8d4d9089f8782", + "0x626f6c6f6265696b696b40646d61696c2e6169", + "0x626f6c6f2067616d6573" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4af558b8506186e8202ec994d711d523cf379717284ff44ef8d4d9089f8782", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1197b5a26be59", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2d4a98c3e9e887a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x2d4a98c3e9e887a", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "0x14e20ee6", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0xc087ff1f956081ebeed0085a169b8b356cbb7990b64680a44f930ec401cbcd", + "0x1164533ce515b", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x1164533ce515b", + "0x0", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xc223864da7b6019bc", + "0x0", + "0x5991174ea9", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2d4a98c3e9e887a", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x14e20ee6", + "0x0", + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99" + ] + }, + { + "from_address": "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x62c1996e2917c549f6497044eb9651571120834be9e992ecb3e4d1dececefb7", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7dc54507a23982cab00983c69a91e47443c7bdd3d3c8622d06902b94b185a99", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1197b5a26be59", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42064, + "builtin_instance_counter": { + "pedersen_builtin_applications": 60, + "range_check_builtin_applications": 1280, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1038ca852ff21", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x54fd2a84932", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2710", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x54f3032690e", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2710", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x984b380", + "0x0" + ] + }, + { + "from_address": "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x329bf63ed895c3b7d28a025c64c774d7dc870d4a279962fce6cb87d38d14105", + "0x6", + "0x1", + "0x1", + "0x54f3032690e", + "0x0", + "0x2710", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2027076fef9174fba9febdb93e4e4237d2adc0d8fc903399ee7bdb63c9814f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1038ca852ff21", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 27664, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1062, + "pedersen_builtin_applications": 44 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x25d336ddc196a08e24d95d645cdc98738d57d8a78d502ba3bf60ef09fe302f1", + "0x4572657a757240676d61696c2e636f6d", + "0x65667320" + ] + }, + { + "from_address": "0x25d336ddc196a08e24d95d645cdc98738d57d8a78d502ba3bf60ef09fe302f1", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x239196f4d074fa12656bd5b865285ed5f6b198145f1f79de50cb5b95e34a4f2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x25d336ddc196a08e24d95d645cdc98738d57d8a78d502ba3bf60ef09fe302f1", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4bbdfef075d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1f1ed841f1d8360", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b4a71c9a670ab529b9cb", + "0xd2d77ca620bcd715bac79" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1f1ed841f1d8360" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1f1ed841f1d8360", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "0x1f1ed841f1d8360", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2fbdc67b2863ccb3e901d275da1fa15b0ae9a92d88a6d67f4819d4d739ac413", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4bbdfef075d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25683, + "builtin_instance_counter": { + "pedersen_builtin_applications": 45, + "range_check_builtin_applications": 971, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x36daa4935168fbfadf18f592e24de6b12a8862605a749fc43226f2a7efda030", + "0x20f81c5f840000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4932d5789900a4ba5dd170dfb635caa005beb71ced69c09a0cb472140c50859", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x11cd941ccdcd3", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1046491", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x163deb445ece26fed8", + "0x0", + "0xa3819adb1a", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2386f26fc10000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1046491", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x1046491", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "0x104573c", + "0x0" + ] + }, + { + "from_address": "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x37bed134982edfc4f0f6747759a490f66675decdbbe61303aa661e3c1109e4a", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x17f59fc43e9f3d60a981109ce3c6e9fcf4144deb55081ffae3aa1b8a5b79af8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x11cd941ccdcd3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 63071, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 2077, + "pedersen_builtin_applications": 80 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x56938b103be20e69464936717788d42cd68c313978b3c49eddae482fdfdd12b", + "0x9e4cfa86c0", + "0x0" + ] + }, + { + "from_address": "0x56938b103be20e69464936717788d42cd68c313978b3c49eddae482fdfdd12b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4f1ae8c8c58366839f84cb6fd0a31ee0b495ce312d9999cc1b7f33d377737b2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x56938b103be20e69464936717788d42cd68c313978b3c49eddae482fdfdd12b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 22 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x320de87ba71dd30890e2936910b6d5f583a09f46b9ae154dda6b6074d7675d9", + "0x7fb762ee4568f7b699adabf9f995462fea9e359cb679e8b32b9871468746bfc", + "0x60556bf9800", + "0x0" + ] + }, + { + "from_address": "0x320de87ba71dd30890e2936910b6d5f583a09f46b9ae154dda6b6074d7675d9", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2e5eceaab61078072e6b7c8ad8717da422b28ebe7d2fd60ffb5a7135f22f537", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x320de87ba71dd30890e2936910b6d5f583a09f46b9ae154dda6b6074d7675d9", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8069, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x2dbb492d8957b672dbff9840c4a2da5d1800d2f8df222fd51bcb40d8f493a8d", + "0x489156ba2ea001", + "0x0" + ] + }, + { + "from_address": "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x78c37baa8f4fa71d9f31bf9149fb1f1a1a7a78ebdca8e4146f55701e3382a0f", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc301e9394861", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b4a71848ea8afd77712f", + "0xd2d77b9b3b17f7c817206" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xc301e9394861" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc301e9394861", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0xc301e9394861", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7fdc10091e2c67b3722fe148d5dc9d655a00b55e2b3ed760e7b84cb2000565c", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2eedf1ee4156b0f8fe0c0841c614825565e7002a024b7b29f65aed2ba525338", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26090, + "builtin_instance_counter": { + "pedersen_builtin_applications": 47, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2, + "range_check_builtin_applications": 1028 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x944df26381000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x944df26381000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "0x43fd99", + "0x0" + ] + }, + { + "from_address": "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5790c57cd07dc25f2b757947445fffc8c547bfdbf41afe0c7c31da152ecd829", + "0x3", + "0x1", + "0x43fd99", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6a5e432ae9ecebb37a84914c0c43fa364ff52f1895fc9ec87796ca1b504ae86", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21791, + "builtin_instance_counter": { + "pedersen_builtin_applications": 37, + "range_check_builtin_applications": 555, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xddbeb2701df3", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x64acfe", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x64acfe", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "0xda3efb13d89e7", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e59c25960efb061f", + "0x0", + "0x372459b69f1", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x64acfe", + "0x0", + "0xda3efb13d89e7", + "0x0", + "0x0", + "0x0", + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x19c1227302982e0c7cf8d63494b1e52c74be9a6cce3fc422d5aec397619346a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xddbeb2701df3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 36638, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1290, + "pedersen_builtin_applications": 40 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x103c20376e152", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x652e68bb34000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x652e68bb34000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "0x2e63ca", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6cebc1f98522f182", + "0x1b53d417158" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x652e68bb34000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x2e63ca", + "0x0", + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409" + ] + }, + { + "from_address": "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x346c6d61faa344ea61d9fbf1420abdc81f597a643c9722ad986c696a0f3183b", + "0x6", + "0x1", + "0x2", + "0x652e68bb34000", + "0x0", + "0x2e63ca", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x623dfb532ec8a25e218d23e5b11eb23b4d0655164de311eb7797938bc5d5409", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x103c20376e152", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 28997, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 1223 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x7c1930a3fb0fdd9ea02fcadd27c45110e0063e29ebea9259714cf7e4c12ab25", + "0x54b3849164000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x15d63f3dc031dde726f9f5ebea183c3abc47f098a139b381a050f098e1411f8", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x7cbb7403055ae474991ee3c8e00ea4b14424a6a727405c1285e3341fd70e89b", + "0x7a73757370656837383640676d61696c2e636f6d", + "0x48656c6c6f" + ] + }, + { + "from_address": "0x7cbb7403055ae474991ee3c8e00ea4b14424a6a727405c1285e3341fd70e89b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x314efb03d2a37d0c36f28b60d7956620d565fd3ed49683d0efa99c9d832dc72", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7cbb7403055ae474991ee3c8e00ea4b14424a6a727405c1285e3341fd70e89b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x650ba08366996", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b4a6f47bcb1b1e5fceff", + "0xd2d772f67fad7304e6045" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x650ba08366996" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x650ba08366996", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x650ba08366996", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x439ac3642ccd1b11553c7e909836271ba4858fea604fda7ad7ad7417894084a", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x131379471425a351aa5c0d5929212592edc302933b2cef0fa6336460e4618de", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26094, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1028, + "pedersen_builtin_applications": 47 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf58d9886d0e4", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x17d3f1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x33a77e257ba4f", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e598eb1e2ca34bd0", + "0x0", + "0x37245b33de2", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x17d3f1", + "0x0", + "0x33a77e257ba4f", + "0x0", + "0x0", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x33a77e257ba4f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160", + "0x33a4d91a84c8d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x594b14128d929082023d3805d80ab602f8f177626c9f030d435dbcf6420b160", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf58d9886d0e4", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 62800, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 82, + "range_check_builtin_applications": 1932 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed1ebab386fe", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x384e48629dd2808efd905c59ea9b3503446fb98687f11947543ee27428325b0", + "0x108cb", + "0x0" + ] + }, + { + "from_address": "0x384e48629dd2808efd905c59ea9b3503446fb98687f11947543ee27428325b0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4ca8cea64d3c03b4fd1a387d565a72fbcff31e314f2baa7173135e72a149517", + "0x1", + "0x108cb" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x384e48629dd2808efd905c59ea9b3503446fb98687f11947543ee27428325b0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed1ebab386fe", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 10160, + "builtin_instance_counter": { + "pedersen_builtin_applications": 42, + "range_check_builtin_applications": 221, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xbb00a8d786d0", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b588cc76d06ee9be287a", + "0xd30df26a01f7dc353ab01" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x19336580bcb8886ce323d54d299c542e67b8567f70f43d93f643cf1133c657d", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x52260a31390a79c", + "0x5276e66c4675c8f" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x19336580bcb8886ce323d54d299c542e67b8567f70f43d93f643cf1133c657d", + "0x5276e66c4675c8f", + "0x0" + ] + }, + { + "from_address": "0x19336580bcb8886ce323d54d299c542e67b8567f70f43d93f643cf1133c657d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x76f203641cd38bba6bccc1676aaa964535a1261e1cde502cafadc58fd44a166", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x19336580bcb8886ce323d54d299c542e67b8567f70f43d93f643cf1133c657d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbb00a8d786d0", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 64754, + "builtin_instance_counter": { + "pedersen_builtin_applications": 157, + "bitwise_builtin_applications": 85, + "range_check_builtin_applications": 2679, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x173a1ebdd285d50ed9c2296cd2d71bbb978817cd59db9af17c51e96718fbf6", + "0x9016d1f519", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x173a1ebdd285d50ed9c2296cd2d71bbb978817cd59db9af17c51e96718fbf6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9340, + "builtin_instance_counter": { + "range_check_builtin_applications": 200, + "pedersen_builtin_applications": 24, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf1ac5a60fbca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x7ce9909b17f9", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x395f8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x7cdf36811b3f", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x395f8", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x109a1bcb6", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x163debc13e04a81a17", + "0x0", + "0xa3819e7112", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0x34e55c1cd55f1338241b50d352f0e91c7e4ffad0e4271d64eb347589ebdfd16" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x7cdf36811b3f", + "0x0", + "0x395f8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x12c86c169d02e1dbf04d86bed7e4d4879b1953555bdec2ba4474df8a3edb3ee", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf1ac5a60fbca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 38501, + "builtin_instance_counter": { + "pedersen_builtin_applications": 48, + "range_check_builtin_applications": 1132, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x3fe27c102924cb4578d1adb1048db2005337dbf92259b374866c0fd2a646c98", + "0x6f736e6f766e6f79373140646d61696c2e6169", + "0x422435441442" + ] + }, + { + "from_address": "0x3fe27c102924cb4578d1adb1048db2005337dbf92259b374866c0fd2a646c98", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6d119a6ec4ac591c9c931f63e6a6cbe92c9b6b1c128a949248eddf0b7124238", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3fe27c102924cb4578d1adb1048db2005337dbf92259b374866c0fd2a646c98", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x392dd78035901bf189312ae7135fd1a3b63b5622bedec774a9e58745081815c", + "0x1835d5603d6c00", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x38250f8078a04d19407b803e4f846e57720a91fc943dad37a309c853fcc7dab", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c5069064dda", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x528c925e7b695fd2f5167ececd8dcd5f458cf14c37eb909a98fc58142a4955c", + "0x364847c4f39b869760a8b213186b5b553127e9420e594075d13d1ce8a1d9157", + "0x7bb0f7b0800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x528c925e7b695fd2f5167ececd8dcd5f458cf14c37eb909a98fc58142a4955c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c5069064dda", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8926, + "builtin_instance_counter": { + "range_check_builtin_applications": 184, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xbde7b90", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0xbde7b90", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "0x19ba7ea74e990b4", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e3fd4333b7b9bb1c", + "0x0", + "0x3725191b972", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0xbde7b90", + "0x0", + "0x19ba7ea74e990b4", + "0x0", + "0x0", + "0x0", + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946" + ] + }, + { + "from_address": "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3c55afb78f7b46b59cb6a3d4bbfc50165f62ccce729065af6e32593ab6a8223", + "0x6", + "0x1", + "0x2", + "0xbde7b90", + "0x0", + "0x19ba7ea74e990b4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x8ff9fd439cd6d5e059d076b4a7c0f6aa6f22995cb90fe4de9b705b3f73c946", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33332, + "builtin_instance_counter": { + "range_check_builtin_applications": 1111, + "pedersen_builtin_applications": 38, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9764aa4a6f55", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b588c91ad7a52c6f6332", + "0xd30df19a982885a8a3ac5" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x9764aa4a6f55" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9764aa4a6f55", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x9764aa4a6f55", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5f923b35e38f889b0dfd4064d29378d92eb92b817eadf2a3713d3f2d4417811", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7dc082096fa4cdddff47f9b5f54f19ca100dd88da15fe1ae4adb0ccf7672cbc", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26087, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "range_check_builtin_applications": 1028, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 47 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb47619fb2e58", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2bdc13afc019b08ccbb816b2fd91b296dbc6a351bec4434013536be58d370de", + "0x0", + "0x82067838dfd457e", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b5b6f6417504903fd679", + "0xd31914688c7a84ee3ec71" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x2bdc13afc019b08ccbb816b2fd91b296dbc6a351bec4434013536be58d370de", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x82067838dfd457e" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2bdc13afc019b08ccbb816b2fd91b296dbc6a351bec4434013536be58d370de", + "0x82067838dfd457e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2bdc13afc019b08ccbb816b2fd91b296dbc6a351bec4434013536be58d370de", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb47619fb2e58", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23918, + "builtin_instance_counter": { + "range_check_builtin_applications": 965, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 42 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x6f410bc0b9048455ef06252168cdbfa30f2c66e9f16871848746edf421da90e", + "0xa590f8b670", + "0x0" + ] + }, + { + "from_address": "0x6f410bc0b9048455ef06252168cdbfa30f2c66e9f16871848746edf421da90e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7cbd8d419754e5914f87887a0eff35fdf0d3b7706aea9b5b67c849fd42a7fa", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6f410bc0b9048455ef06252168cdbfa30f2c66e9f16871848746edf421da90e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x6081507ddd07a260d08d938cb667aa0d22e6c5cdf23e719ec99c0622c5491ae", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x6081507ddd07a260d08d938cb667aa0d22e6c5cdf23e719ec99c0622c5491ae", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x73220097ea03286d1a91ee30b7340248858716cc1c6e39770f80f89c40f2343", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6081507ddd07a260d08d938cb667aa0d22e6c5cdf23e719ec99c0622c5491ae", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7299, + "builtin_instance_counter": { + "range_check_builtin_applications": 165, + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb781eb917aae", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x775f05a074000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x775f05a074000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x775f05a074000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x775f05a074000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x36bab7", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6cf337e9df2a3182", + "0x1b53d0ab6a1" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x775f05a074000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x36bab7", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x36bab7", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x775f05a074000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x36bab7", + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6" + ] + }, + { + "from_address": "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7abad30138d80438270ac135cfb1cf261848ebfc8f23c212dd6bf0cce468456", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xa7b028341fed232ed38383b9fd5f307a885c72f6b9ef198b2d285568fdb9d6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb781eb917aae", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 43000, + "builtin_instance_counter": { + "pedersen_builtin_applications": 73, + "bitwise_builtin_applications": 7, + "range_check_builtin_applications": 1428, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc99baf5b5deb", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "0x44364c5bb0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0xc377d07b442932b4c0b8cfa3f2579efe593a63b07fa3424dbf3d40b12576c5", + "0x105ef39b2000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0x6b03ff460e78a39768340bb909ff8e9e9c507994ecbf6dd0e30aeba34df0452", + "0x43305d21fe000", + "0x0" + ] + }, + { + "from_address": "0x76503062d78f4481be03c9145022d6a4a71ec0719aa07756f79a2384dc7ef16", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6b03ff460e78a39768340bb909ff8e9e9c507994ecbf6dd0e30aeba34df0452", + "0x0", + "0x2eabab", + "0x0" + ] + }, + { + "from_address": "0x76503062d78f4481be03c9145022d6a4a71ec0719aa07756f79a2384dc7ef16", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b03ff460e78a39768340bb909ff8e9e9c507994ecbf6dd0e30aeba34df0452", + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0x2eabab", + "0x0" + ] + }, + { + "from_address": "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "keys": [ + "0xf10f06595d3d707241f604672ec4b6ae50eb82728ec2f3c65f6789e897760", + "0x6e9b5d5873a3eabeea375f6c2ffbe1ea74531381e33fe05217aa97371399cfa", + "0x6b03ff460e78a39768340bb909ff8e9e9c507994ecbf6dd0e30aeba34df0452", + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0x12f3e256a78d411730c30d4ace443e31a59b1d48340d888d7aa198a2c4311f8", + "0x76503062d78f4481be03c9145022d6a4a71ec0719aa07756f79a2384dc7ef16", + "0x2eabab", + "0x0" + ], + "data": [ + "0x1", + "0x0", + "0x44364c5bb0000", + "0x0", + "0x105ef39b2000", + "0x0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x37598a35ca608561dfc309dabae9781cd1931d9dbf682b0550c4090f809a61f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc99baf5b5deb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33458, + "builtin_instance_counter": { + "range_check_builtin_applications": 886, + "pedersen_builtin_applications": 111, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef27f9fe63c9", + "messages_sent": [], + "events": [ + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xbea1317d47", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x0", + "0xbea1317d47", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x6a5548df1f6092", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x30e5346", + "0x0" + ] + }, + { + "from_address": "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x290575f96161edcc9580874e5df001bffe8da47f6f58f62f76fca8ca6ab8579", + "0x9", + "0x1", + "0x6a5548df1f6092", + "0x0", + "0x30e5346", + "0x0", + "0x49ea320e92cb1691a1", + "0x0", + "0x21fd05a1282", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x446c8e3c6a663018a1b64eed3fac03f20e3ebed27f3f8f343de41f2d293628f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef27f9fe63c9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22836, + "builtin_instance_counter": { + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 726 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "0x491fdf59535ebe73a642ac067a01cc65b5a8fe302006af023c58005f553e0b8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb6399352321e", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2e2f6e5e148000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x2e2f6e5e148000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "0x152df67", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e42b72a215ce3b1c", + "0x0", + "0x372503eda0b", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2e2f6e5e148000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x152df67", + "0x0", + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1f07fe2728d168b84fed7d1565c89ee4a133d1b6682ebb7fbc5402da32bf128", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb6399352321e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34911, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 40, + "range_check_builtin_applications": 1128 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e1ddb85493a97793de29d38006c598b948e1b03878bc8dc634500c00efe27d", + "0x6845b38126c7ce2118b0088b82c738c47a6da100d562097358dea2c25e0431f", + "0x3afc3904c5e0091", + "0x0" + ] + }, + { + "from_address": "0x2e1ddb85493a97793de29d38006c598b948e1b03878bc8dc634500c00efe27d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1f95e07ed835b2d5292cfd2919f1a0df751ef947b722e1c21c8e938472ac9c9", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e1ddb85493a97793de29d38006c598b948e1b03878bc8dc634500c00efe27d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "0x63616765696e6d796d696e6440676d61696c2e636f6d", + "0x63616765696e6d796d696e6440676d61696c2e636f6d" + ] + }, + { + "from_address": "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3c276d13ba16c9e3a8129fe4383cb821ab6fd3381abcba0a9914800697d953d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "0x676a686764406d61696c2e7275", + "0x6666647720667765776566" + ] + }, + { + "from_address": "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3443bca30399d83ca1e4a2305b2f1b22b93382287a51e9fc1e736be3172b59f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x748756581986d21174b902103e99dd610bec24af012665dee68ee22d96b1c19", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x6e28706aa59de87c577af87df1b6b253534a82d48e0b1e9f1038ea9ad9f832e", + "0x686868757967697540646d61696c2e6169", + "0x5265706c793a205265706c793a205265706c793a205265706c793a205265706" + ] + }, + { + "from_address": "0x6e28706aa59de87c577af87df1b6b253534a82d48e0b1e9f1038ea9ad9f832e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x51be4b826ef579fa0b7a9ce102660ad511025be4f80a33d77a64d3116293935", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e28706aa59de87c577af87df1b6b253534a82d48e0b1e9f1038ea9ad9f832e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x8a99c0369149", + "messages_sent": [], + "events": [ + { + "from_address": "0x60582df2cd4ad2c988b11fdede5c43f56a432e895df255ccd1af129160044b8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x465d17a4b9c37242556ea13db90332211a68ac5b4841806ef6c3b222bbaa5b1", + "0x318e8", + "0x0" + ] + }, + { + "from_address": "0x465d17a4b9c37242556ea13db90332211a68ac5b4841806ef6c3b222bbaa5b1", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x68a6e7cc5842ab2657d39b6719310eec57e585608ab4b9b285f0697c742dd84", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x465d17a4b9c37242556ea13db90332211a68ac5b4841806ef6c3b222bbaa5b1", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x8a99c0369149", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7648, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 26, + "range_check_builtin_applications": 177 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x76c9a967632f9fd33e271d61b93b0aa49f0106cde18d2dc5c3ece8b6a0b9b96", + "0x38d7ea4c68000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x578b6d1e0c9303b469b8796fafec9ca8c91a853d8b005eab3bcf57e045606f6", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc8ada293e2e9", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5af3107a4000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b5b6f43c8277c073955a", + "0xd31913ebe4d332998e200" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5af3107a4000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5af3107a4000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x5af3107a4000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4ad8392d9d3bd8d609e7a2b5e93c7b3ea478a479f680e9f9441dd3b373061b7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc8ada293e2e9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 27631, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1045, + "pedersen_builtin_applications": 49, + "bitwise_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x103c20376e152", + "messages_sent": [], + "events": [ + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x717e", + "0x0" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "0x2a6e0ecda844736c4803a385fb1372eff458c365d2325c7d4e08032c7a908f3", + "0x717e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2a6e0ecda844736c4803a385fb1372eff458c365d2325c7d4e08032c7a908f3", + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "0x108be45d57f673", + "0x0" + ] + }, + { + "from_address": "0x2a6e0ecda844736c4803a385fb1372eff458c365d2325c7d4e08032c7a908f3", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xae0bb7c", + "0x1972747ecd5da3e55" + ] + }, + { + "from_address": "0x2a6e0ecda844736c4803a385fb1372eff458c365d2325c7d4e08032c7a908f3", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x717e", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x108be45d57f673", + "0x0", + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d" + ] + }, + { + "from_address": "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7100dde30e49d0444ec66648fbabfe178172c4bf5d4edad16aea24665cc526f", + "0x6", + "0x1", + "0x2", + "0x717e", + "0x0", + "0x108be45d57f673", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7417254da804e072ce1401e16c031e1d7fe9242bbc080de73728226064e274d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x103c20376e152", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 28958, + "builtin_instance_counter": { + "range_check_builtin_applications": 1223, + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x226b0fdfbce6e933f1db111c6e6dad24bb05d15a0ef8565a97eeadd6b109439", + "0xdf6d70ccac", + "0x0" + ] + }, + { + "from_address": "0x226b0fdfbce6e933f1db111c6e6dad24bb05d15a0ef8565a97eeadd6b109439", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x527a655d172b635dda88f7a3e4ff0a881bfaa21992135f5e4ba2d3106ffd2d9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x226b0fdfbce6e933f1db111c6e6dad24bb05d15a0ef8565a97eeadd6b109439", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb7c396d155fe", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1049cf5", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d16bedc4eeb3182", + "0x1b53c0619ac" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2386f26fc10000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1049cf5", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x1049cf5", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2386f26fc10000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1049cf5", + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6a285a5bf09a4899d0b5ac695e08c31532feb38697d8ffe24ef50f71bfcb030", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb7c396d155fe", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 44542, + "builtin_instance_counter": { + "range_check_builtin_applications": 1445, + "pedersen_builtin_applications": 75, + "bitwise_builtin_applications": 7, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "0x53366a7258e5572f9ba5cd03e9378f10a41a2dea84c1797080ce1f14da5aea", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x7cd4264242f2", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x35bd041f99860ff57adfc16b848c6b8e27471acb669e969a60ae17c281df8a" + ], + "data": [ + "0x76a56a5fb9001d6af903dffab7b70b515522a970a74dfdaad09e2f5fa2353b", + "0x7300100008000000000000000000000000", + "0x377d6", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x76a56a5fb9001d6af903dffab7b70b515522a970a74dfdaad09e2f5fa2353b", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x76a56a5fb9001d6af903dffab7b70b515522a970a74dfdaad09e2f5fa2353b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x7cd4264242f2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 44124, + "builtin_instance_counter": { + "range_check_builtin_applications": 1344, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 27 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5f03d40dbf0cc25e17eae47060f09d277e07d1629e09fd8e63620e7e647367a", + "0xd9804cc437", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5f03d40dbf0cc25e17eae47060f09d277e07d1629e09fd8e63620e7e647367a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9340, + "builtin_instance_counter": { + "range_check_builtin_applications": 200, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 24 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x854d0cbf46d77a1bb0ec14ac70e943afab2cb628f4c74882d4221d47ce427a", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x854d0cbf46d77a1bb0ec14ac70e943afab2cb628f4c74882d4221d47ce427a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x206948d55851a0a600d41c5712f7eeb6e9639e8a980b53f2b407aedaa332613", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x854d0cbf46d77a1bb0ec14ac70e943afab2cb628f4c74882d4221d47ce427a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7299, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 165, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x464f5660a8164258c473d896ce18e66c50c7cc61e7c28a46a3003a24607ffe2", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x464f5660a8164258c473d896ce18e66c50c7cc61e7c28a46a3003a24607ffe2", + "0x3a5bf647cbad631ea5a24cd784b70d5620aaa0e4e7dcd77fc75c92943687ec5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x464f5660a8164258c473d896ce18e66c50c7cc61e7c28a46a3003a24607ffe2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x464f5660a8164258c473d896ce18e66c50c7cc61e7c28a46a3003a24607ffe2", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x69f39cf408157b2ff6b01935f1313d3f48c16b832ef96fee7da6e53b51110b0", + "0x98dea72e7e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x69f39cf408157b2ff6b01935f1313d3f48c16b832ef96fee7da6e53b51110b0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9342, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 24, + "range_check_builtin_applications": 200 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4223b2868034adfeb5ada2715b1752803dfd3ac0201efed3268415bb874c516", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4779fc726c848afb9e9f58cef18fc82f1aab02849be219ffe6de14227f3ab76", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x5cd61a11ab79dafad90e96a8c1a1b140d38e61ac0c7ea7ce04fe38a5c196e32", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x5cd61a11ab79dafad90e96a8c1a1b140d38e61ac0c7ea7ce04fe38a5c196e32", + "0x2a50b77a01d3c5f0f80f0517fc06767e8be82d146d8a6993371721c206f2c60", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5cd61a11ab79dafad90e96a8c1a1b140d38e61ac0c7ea7ce04fe38a5c196e32", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x5cd61a11ab79dafad90e96a8c1a1b140d38e61ac0c7ea7ce04fe38a5c196e32", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5b09cd3e5e90000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b5969ecabab580abcf84", + "0xd31147c893d54aee65f8c" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5b09cd3e5e90000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5b09cd3e5e90000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x5b09cd3e5e90000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6956e68b4dfadb6c3500e3c5721e961cb450550d96e6d9f62855d1042bea122", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2f9c40ad050aade40e3176c32724a79f86299edcc7c3bc9b2a6cb7411724209", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26087, + "builtin_instance_counter": { + "pedersen_builtin_applications": 47, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2, + "range_check_builtin_applications": 1028 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x124666420becbc84fe94e8fb41cda6da3cf994d6b7280f682e31e93b89ad58", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x124666420becbc84fe94e8fb41cda6da3cf994d6b7280f682e31e93b89ad58", + "0x407798b20e5cbdeb6aaade02defb04630af5b8da449444673452bd2ef722251", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x124666420becbc84fe94e8fb41cda6da3cf994d6b7280f682e31e93b89ad58", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x124666420becbc84fe94e8fb41cda6da3cf994d6b7280f682e31e93b89ad58", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x6020c742b42e0ef10bcf40910d16be0dddf9aedbab16db911ef9fb187ff96c1", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x6020c742b42e0ef10bcf40910d16be0dddf9aedbab16db911ef9fb187ff96c1", + "0x52d0cd65e537ffd80239806de2b489930aca7f927dded19f52a8e711808f2c7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6020c742b42e0ef10bcf40910d16be0dddf9aedbab16db911ef9fb187ff96c1", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x6020c742b42e0ef10bcf40910d16be0dddf9aedbab16db911ef9fb187ff96c1", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x103c61e2adf07", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "0x7a0922657e550ba1ef76531454cb6d203d4d168153a0f05671492982c2f7741", + "0xbd75889095000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "0x5a08fb18007357366a35739bd627fe00b00ff0881d58b076f34a69572f5fa8b", + "0xbd75889095000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5a08fb18007357366a35739bd627fe00b00ff0881d58b076f34a69572f5fa8b", + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "0x5512d9", + "0x0" + ] + }, + { + "from_address": "0x5a08fb18007357366a35739bd627fe00b00ff0881d58b076f34a69572f5fa8b", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xf959ce4617f7b09", + "0x6ff87c37" + ] + }, + { + "from_address": "0x5a08fb18007357366a35739bd627fe00b00ff0881d58b076f34a69572f5fa8b", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a0922657e550ba1ef76531454cb6d203d4d168153a0f05671492982c2f7741", + "0xbd75889095000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x5512d9", + "0x0", + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e" + ] + }, + { + "from_address": "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x19664972258a315d0862917c59d895f29ea057583037994118bbaf18f1ce987", + "0x6", + "0x1", + "0x2", + "0xbd75889095000", + "0x0", + "0x5512d9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x418ab7c0a8989c8a7b5b4d0ae05a69fb615198690c99190882786b23387b92e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x103c61e2adf07", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 29018, + "builtin_instance_counter": { + "range_check_builtin_applications": 1226, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x19961e608b5d0d51b9f8c76862f7231541e215ad9be1c1b3f67adaad7d23184", + "0x70a3a50e70e7a004b5e643ad03d01a270ea7d08839df454c03a56ffede2602a", + "0x27f7d0bdb920000", + "0x0" + ] + }, + { + "from_address": "0x19961e608b5d0d51b9f8c76862f7231541e215ad9be1c1b3f67adaad7d23184", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6fe934351cbeca7deeb2c3cbfc5a5eab03111b9122d9e3f350750cbac850c09", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x19961e608b5d0d51b9f8c76862f7231541e215ad9be1c1b3f67adaad7d23184", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb758e089919c", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1bda703f0a0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1bda703f0a0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1bda703f0a0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1bda703f0a0000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0xcc4f1f", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0xcc4f1f", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bda703f0a0000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0xcc4f1f", + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d" + ] + }, + { + "from_address": "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x43d7a163e1b0a5d00af46853554947ffd3e5aa6e5e4b678e6628b19afb13ce8", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x87f942ad4a90d8bcfbbc6d926ba72ddf03cd9238d6b27025fdaaa58252fa7d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb758e089919c", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 41920, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1087, + "bitwise_builtin_applications": 4, + "pedersen_builtin_applications": 55 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef658a8a4164", + "messages_sent": [], + "events": [ + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x385944bc69", + "0x0" + ] + }, + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0x0", + "0x385944bc69", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0x1e3ed96ae152db", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0xdd4704", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x15783c7ee5d5f185aef60203f9dd1907ac0c73c8a1b6cfe605c451995f8768", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef658a8a4164", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 24375, + "builtin_instance_counter": { + "pedersen_builtin_applications": 39, + "range_check_builtin_applications": 743, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0xf7069f39bc298e0e293d4e9ee511120964b623a90c6a2576d91e35b692d22c", + "0xe35fa931a0000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3f4cecb8cb1727fc6fd90f15e990eb8c6a01efd65f3e26b4e033573fb51ef9f", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1717b72f0a4000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x1717b72f0a4000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "0xa96f51", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e4428a5944d87b1c", + "0x0", + "0x3724f956aba", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1717b72f0a4000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0xa96f51", + "0x0", + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc" + ] + }, + { + "from_address": "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x245868a316c408a92de74be1ebdbaeea01c5ab397cdda1015543651097483d2", + "0x6", + "0x1", + "0x2", + "0x1717b72f0a4000", + "0x0", + "0xa96f51", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2abbb92f04af2487d6cb89e2a2cb84d508230c0bfe6d72e4c6a10240446a7fc", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33368, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1111, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x356b8eb227d4", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x32ff0324a913f56b666d6b1ec00c7ed5c1a277fab8fca29edf274838779337f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x356b8eb227d4", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x032ff0324a913f56b666d6b1ec00c7ed5c1a277fab8fca29edf274838779337f):\nError at pc=0:12:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:161)\nUnknown location (pc=0:147)\n\nError in the called contract (0x032ff0324a913f56b666d6b1ec00c7ed5c1a277fab8fca29edf274838779337f):\nError at pc=0:39:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1398)\nUnknown location (pc=0:1351)\nUnknown location (pc=0:569)\nUnknown location (pc=0:604)\nError message: argent: multicall 6:13 failed\nUnknown location (pc=0:586)\n\nError in the called contract (0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f):\nError at pc=0:10:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:430)\nUnknown location (pc=0:416)\n\nError in the called contract (0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f):\nError at pc=0:1218:\nError message: Insufficient tokens received\n\nCairo traceback (most recent call last):\nUnknown location (pc=0:1614)\nUnknown location (pc=0:1572)\n", + "execution_resources": { + "steps": 88333, + "builtin_instance_counter": { + "pedersen_builtin_applications": 109, + "range_check_builtin_applications": 2559, + "bitwise_builtin_applications": 6, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb781eb917aae", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x146d98337560000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x146d98337560000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x146d98337560000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x146d98337560000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x95d6b13", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6e5d985f86413182", + "0x1b532a8ae99" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x146d98337560000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x95d6b13", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x95d6b13", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x146d98337560000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x95d6b13", + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37" + ] + }, + { + "from_address": "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6b8fedce06f08a063bd2e23523f058099562b7b796d9e3fa2dfa34073bb6ef", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e48d6cfcf93bdc0245ecd3af531e5940543d79f6c474b428c0faa044994e37", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb781eb917aae", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42999, + "builtin_instance_counter": { + "bitwise_builtin_applications": 7, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1428, + "pedersen_builtin_applications": 73 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1596f70c703b2", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x340947d024ce7cd0a417122", + "0x343d5b733c51ee4c23f164e" + ] + }, + { + "from_address": "0x47ad51726d891f972e74e4ad858a261b43869f7126ce7436ee0b2529a98f486", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x439d7ec4abbb69aaa8fa5acd9a682f118823f49f2542bc7673a9792ddff9fc2", + "0xf77", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1864cc0a1976654ae1aa59", + "0x1df256f85577e7a54b5ecd" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x707766f45fb32682ac74df9145af9bf22dc9cb7e6e3e13cd5486b7d97cc34f5", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x23647ade", + "0x23c34600" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x707766f45fb32682ac74df9145af9bf22dc9cb7e6e3e13cd5486b7d97cc34f5", + "0x23c34600", + "0x0" + ] + }, + { + "from_address": "0x707766f45fb32682ac74df9145af9bf22dc9cb7e6e3e13cd5486b7d97cc34f5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3ef9a5fb19edd926a7202b07f4cd8b4478587b993e5301ab44802eac7055ced", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x707766f45fb32682ac74df9145af9bf22dc9cb7e6e3e13cd5486b7d97cc34f5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1596f70c703b2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 73719, + "builtin_instance_counter": { + "range_check_builtin_applications": 3614, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 79, + "pedersen_builtin_applications": 155 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x341d02", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6e64b35ccfce3182", + "0x1b532749197" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x341d02", + "0x0", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2" + ] + }, + { + "from_address": "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x69177f298b52aa07da72cb432fadda3481aa787b38b90c80625e77493172387", + "0x6", + "0x1", + "0x2", + "0x71afd498d0000", + "0x0", + "0x341d02", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26612, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 973, + "pedersen_builtin_applications": 56 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x60b7dc7225bda3b89210ce6264d22879ef639088445b0c08d7425fd6f151062", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x60b7dc7225bda3b89210ce6264d22879ef639088445b0c08d7425fd6f151062", + "0x4f87a1b68dc6d0e838eaf1a18b7d06848b37408508174ff807be333188f876b", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x60b7dc7225bda3b89210ce6264d22879ef639088445b0c08d7425fd6f151062", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x60b7dc7225bda3b89210ce6264d22879ef639088445b0c08d7425fd6f151062", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x386b102c7b0b", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7644743cf33d50422c7edb85177d23363e67e1295e7c157b8385ec6a083d8dd", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x386b102c7b0b", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x07644743cf33d50422c7edb85177d23363e67e1295e7c157b8385ec6a083d8dd):\nError at pc=0:10:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:228)\nUnknown location (pc=0:214)\n\nError in the called contract (0x07644743cf33d50422c7edb85177d23363e67e1295e7c157b8385ec6a083d8dd):\nError at pc=0:219:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:8090)\nUnknown location (pc=0:8038)\nUnknown location (pc=0:5734)\nUnknown location (pc=0:5771)\nUnknown location (pc=0:5755)\n\nError in the called contract (0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f):\nError at pc=0:10:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:430)\nUnknown location (pc=0:416)\n\nError in the called contract (0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f):\nError at pc=0:1218:\nError message: Insufficient tokens received\n\nCairo traceback (most recent call last):\nUnknown location (pc=0:1614)\nUnknown location (pc=0:1572)\n", + "execution_resources": { + "steps": 107045, + "builtin_instance_counter": { + "pedersen_builtin_applications": 91, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 3825 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb8990360dec2", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x243f3bbee6ca000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x243f3bbee6ca000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x243f3bbee6ca000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x243f3bbee6ca000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1098ea70", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x16402fb4f9f314ba17", + "0x0", + "0xa3710586a2", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x243f3bbee6ca000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1098ea70", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x1098ea70", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x243f3bbee6ca000", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x1098ea70", + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b" + ] + }, + { + "from_address": "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x67323eb65616dad5e7084cd34c9deb5276263e951bb3f99ba52c1ec450b1e03", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x42616b45d2af37c3959a55282227e9f9ad1770600c236d3b07dccb47c6fc74b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb8990360dec2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 49769, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1566, + "bitwise_builtin_applications": 4, + "pedersen_builtin_applications": 55 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1033eacf72ab2", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0" + ] + }, + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x307c3d542c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0" + ] + }, + { + "from_address": "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "keys": [ + "0x440fc089956d79d058ea92abe99c718a6b1441e3aaec132cc38a01e9b895cb" + ], + "data": [ + "0x1", + "0x27ce62e5e340", + "0x307c3d542c", + "0x66d1bad0" + ] + }, + { + "from_address": "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "keys": [ + "0x1b6d26c8b545f51ff2731ca42b81aa226221630abc95fd9d1bcacbe75bce7a1" + ], + "data": [ + "0x1", + "0x27ce62e5e340", + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518" + ] + }, + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x12b4597159a73c3f0f23a49a92e5a3d3e51f2d865a40669db649123433d1a5b" + ], + "data": [ + "0x307c3d542c", + "0x6e616d65", + "0x2e17d38e305166e3105ad33bbbe65ffc803d8cf08efb5cf19d84575546bbe76", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678" + ] + }, + { + "from_address": "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "keys": [ + "0x25d4f50ffa759476dcb003b1c94b6b1976321ccceae5f223696598ed626e9d3" + ], + "data": [ + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x1", + "0x27ce62e5e340" + ] + }, + { + "from_address": "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6c1df416dd2515a1d38a476de40cf80d201d2fc00e7aa2063155858b0baf", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x614281d8cc53096dc76b599ebcfd465c514919a73779e605e41e9cd17e17518", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1033eacf72ab2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25796, + "builtin_instance_counter": { + "range_check_builtin_applications": 862, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc1498c7403f8", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b95d9e0bcf2d2e4974de", + "0xd3f9fdc0bca8fd4132643" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x1d81237fd277baceaf255a1c663f754b8b5642612082f2ad6c65dba4f593df7", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x15ec2a5ff3c70ac1", + "0x1601be86ace47cec" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1d81237fd277baceaf255a1c663f754b8b5642612082f2ad6c65dba4f593df7", + "0x1601be86ace47cec", + "0x0" + ] + }, + { + "from_address": "0x1d81237fd277baceaf255a1c663f754b8b5642612082f2ad6c65dba4f593df7", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2e167bd20d5cc2d77c22f4505a7fcfdf3cd05bb9b21367c22a22c291586b520", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1d81237fd277baceaf255a1c663f754b8b5642612082f2ad6c65dba4f593df7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc1498c7403f8", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 103992, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 248, + "range_check_builtin_applications": 4086, + "bitwise_builtin_applications": 157 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x1be8bb665504cf62d6c2ad4c3074060dc8dff71e2c471c479736593d4af7929", + "0x58e8269ca1", + "0x0" + ] + }, + { + "from_address": "0x1be8bb665504cf62d6c2ad4c3074060dc8dff71e2c471c479736593d4af7929", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1934ca9e7eb721d87d546a976455f7aaafdd0b4ecb735f95ecf4ba23b4b09a9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1be8bb665504cf62d6c2ad4c3074060dc8dff71e2c471c479736593d4af7929", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7832, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1049b8aba67cb", + "messages_sent": [], + "events": [ + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x102038513c", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x102038513c", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x98707809b39a3b14d9f5004bc1fe77721baa2d8b67fd54ed5794f60671de0", + "0x13c05e0c6", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x0", + "0x102038513c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x88b00258ae2a0", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x3ed859", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6e5c285caa434ee2", + "0x1b53235b93e" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x243e1de00e8a6bc1dfa3e950e6ade24c52e4a25de4dee7fb5affe918ad1e744" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x88b00258ae2a0", + "0x0", + "0x3ed859", + "0x0", + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x274cfda88f97897d88d25214176fff6f7a75b25e9647f5e4e928bb14594949a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1049b8aba67cb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34226, + "builtin_instance_counter": { + "pedersen_builtin_applications": 53, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1190 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x5b9543e2656b0b7bee6bcd769d3590dccb859142266a501016ca94951538b0", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x5b9543e2656b0b7bee6bcd769d3590dccb859142266a501016ca94951538b0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x11645d82185173d8ef22f2fba28d2bf9339b91cc4f95e6fda610ab4e1e0a9f7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5b9543e2656b0b7bee6bcd769d3590dccb859142266a501016ca94951538b0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7299, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 165 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x12bf3841c6cd9", + "messages_sent": [], + "events": [ + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9851ff", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x33f92ceedc1b7d29aef0a87", + "0x346389409e3346e6013e9c8" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0xad9c32a7974a0a082b45e", + "0x1f17073728bc99bafb5be6" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "0x9851ff" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x9851ff", + "0x0" + ] + }, + { + "from_address": "0x2b9ea3acdb23da566cee8e8beae3125a1458e720dea68c4a9a7a2d8eb5bbb4a", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x9851ff", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2a87ebc5195b6e1ba7530fd89d1f1691082f72f829bc811bc9a6534f76257b7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x12bf3841c6cd9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34829, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1858 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b60d73a690ea6d956090372d5560cc3d36d211830acdf48ecefe9c1ac0ba6c", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x6b60d73a690ea6d956090372d5560cc3d36d211830acdf48ecefe9c1ac0ba6c", + "0x5e68470f58ffdf2395b3db8842788d89c316fa1f27c154d627d38dff902fca1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b60d73a690ea6d956090372d5560cc3d36d211830acdf48ecefe9c1ac0ba6c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x6b60d73a690ea6d956090372d5560cc3d36d211830acdf48ecefe9c1ac0ba6c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1029379fd69f67a123b5487a71c23e988239a8597aec643ca829a4f203f27d2", + "0x3e2d15c04e9800", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x425307f3d97419f578633721f37bfdc731eb6b2a85a44e1d60adef934a9259b", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x3502b7ab0b9bd201aaa37bac6b4329557bee7d57796eac7d056f58a3f5c333e", + "0x307831623532363934383736616361353935323435626136643933623734336", + "0x5265706c793a203531383620ff0c736b203036ff1b2054c854c8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3502b7ab0b9bd201aaa37bac6b4329557bee7d57796eac7d056f58a3f5c333e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 160 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x29d83f109f5a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1383eb2872e594ffda60114a8a6a151505a083629f9eead70bb082bcd3f213e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x29d83f109f5a", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x01383eb2872e594ffda60114a8a6a151505a083629f9eead70bb082bcd3f213e):\nError at pc=0:10:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:228)\nUnknown location (pc=0:214)\n\nError in the called contract (0x01383eb2872e594ffda60114a8a6a151505a083629f9eead70bb082bcd3f213e):\nError at pc=0:219:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:8090)\nUnknown location (pc=0:8038)\nUnknown location (pc=0:5734)\nUnknown location (pc=0:5771)\nUnknown location (pc=0:5755)\n\nError in the called contract (0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023):\nError at pc=0:15:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:305)\nUnknown location (pc=0:291)\n\nError in the called contract (0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023):\nError at pc=0:1625:\nError message: Router::swap_exact_tokens_for_tokens::insufficient output amount\n\nCairo traceback (most recent call last):\nUnknown location (pc=0:1710)\n", + "execution_resources": { + "steps": 16117, + "builtin_instance_counter": { + "range_check_builtin_applications": 298, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 22 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x7a70e197c312275cddc355c9996e75baf768fe94f35694d138b33713d5175c0", + "0x61706874686f6e677332303232403136332e636f6d", + "0x61706874686f6e677332303232403136332e636f6d" + ] + }, + { + "from_address": "0x7a70e197c312275cddc355c9996e75baf768fe94f35694d138b33713d5175c0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x67aa8d36e1302fa3c96cb303325437968f7126bb35361013755bac56cca5cfa", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7a70e197c312275cddc355c9996e75baf768fe94f35694d138b33713d5175c0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41fe9375e7f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4ed58b9570cf", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4ed58b9570cf", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "0x23f06", + "0x0" + ] + }, + { + "from_address": "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x364d240a543d11d473895783fcc45761f33f8084f6b8b280b505bc5402f1158", + "0x3", + "0x1", + "0x23f06", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1cf8c947598994947f08fa2afe8e2ee2eb77db18c6c5410984161cb2a1ecfb2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41fe9375e7f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21805, + "builtin_instance_counter": { + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb47e4f6329c2", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x8d6d7882642dce", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b95a739d6f410a923195", + "0xd3f93b230f66e9b2eb29f" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x8d6d7882642dce" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x8d6d7882642dce", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "0x8d6d7882642dce", + "0x0" + ] + }, + { + "from_address": "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x16a5ab64b265e945de345dc097854539a904ea140734c4011d5df58408ed8d9", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x600d59b0f4a4b62b4e3c7969f796fa2faec188dceac9f97925c5716faae65c0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb47e4f6329c2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 24144, + "builtin_instance_counter": { + "range_check_builtin_applications": 954, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 43 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef27f9fe63c9", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x970dca9f", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x340947d024ce7cd0a417122", + "0x343d5b733c51ee4c23f164e" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x183d9791a4a5cda8a1dfdf", + "0x1dda3cb3dd84c846ca5ac3" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x8fdc608b", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x7ae0ab7952bbfc33a72035e5eccec7c8816723421c0acb315bd4690a71d46e" + ], + "data": [ + "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x8e5f0e96", + "0x8fdc608b" + ] + }, + { + "from_address": "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5f92e620c9171f6baa3a64dfe1c89b206733f135e0970c203bcb3c573595484", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4f2783e315dadb0ecb18bf6509f31a3d7eec45ce13373327ecd90af8db96164", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef27f9fe63c9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22875, + "builtin_instance_counter": { + "pedersen_builtin_applications": 50, + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 964 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x489d8f2840456c0488589dcc9d1a3a08025740c29de78bbf5c51f2a3f262a61", + "0xaa87bee538000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x661888d9ff31079980032fc6096d4720969460e23d4d7a8cb15f6dbda3b287c", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc888b23ff78c", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x4bdb62a680400", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x49f0f9454dc63", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "0x21e4e5", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6e60c76c3e982b45", + "0x1b53213d459" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x49f0f9454dc63", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x21e4e5", + "0x0", + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2" + ] + }, + { + "from_address": "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x702c89ae32754be737c8e007dcd179be114330371e057d075feb5557529154b", + "0x6", + "0x1", + "0x2", + "0x49f0f9454dc63", + "0x0", + "0x21e4e5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x459b5aeec7765646e03e18250f36372681d3a7d166d9fa39c875154d0f1ce2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc888b23ff78c", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26742, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 982 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc99794a76036", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x8f6d6", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x8f6d6", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "0x1377a8bd1806a", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x16402e7d7f674339ad", + "0x0", + "0xa3710e7d78", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x8f6d6", + "0x0", + "0x1377a8bd1806a", + "0x0", + "0x0", + "0x0", + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6" + ] + }, + { + "from_address": "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1b9d0e05835d1d3fa718645db39bb98349b99e54a4e1feac0192324c62fb546", + "0x6", + "0x1", + "0x2", + "0x8f6d6", + "0x0", + "0x1377a8bd1806a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x516710f9cf82028c741a41a9e329154fb24b7f391c0e33c7e719060a694bcb6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc99794a76036", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33332, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1111 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5b4051fe17a5917afd5f2c60be97e35f0a9f2e6f5ffc350db48dbfc4e2c9da5", + "0x8383e7f2ec", + "0x0" + ] + }, + { + "from_address": "0x5b4051fe17a5917afd5f2c60be97e35f0a9f2e6f5ffc350db48dbfc4e2c9da5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x465910703f23c5812e1f1f1fb6d322f15407c1fb5ccc44ccc23ac706de42fcc", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5b4051fe17a5917afd5f2c60be97e35f0a9f2e6f5ffc350db48dbfc4e2c9da5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x23e0b0e0ef6aad67087a10f683437bc090007e0f20f036ab4d066674c042ca0", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x23e0b0e0ef6aad67087a10f683437bc090007e0f20f036ab4d066674c042ca0", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x2b39ba3678268a6bf04bbf750f4b32a87052cc4059a38859bf626a8bab1dfe6" + ] + }, + { + "from_address": "0x23e0b0e0ef6aad67087a10f683437bc090007e0f20f036ab4d066674c042ca0", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23e0b0e0ef6aad67087a10f683437bc090007e0f20f036ab4d066674c042ca0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x23e0b0e0ef6aad67087a10f683437bc090007e0f20f036ab4d066674c042ca0", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "pedersen_builtin_applications": 34, + "range_check_builtin_applications": 145, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xeb6a0c8e2b24", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b95a6e58746994e27402", + "0xd3f939df1d943949c196d" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xeb6a0c8e2b24" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xeb6a0c8e2b24", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0xeb6a0c8e2b24", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x486b420b9664cc090be1658c83906d7d807e99656dc4b6c62915677a6b11b81", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x31ebe9d4ac7478aa9225528afd55f32ddd2f9bdb9f13f168a298f669510b529", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26085, + "builtin_instance_counter": { + "pedersen_builtin_applications": 47, + "range_check_builtin_applications": 1028, + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf55007faf349", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0xd7ec0b", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1d4e799c6c5098", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1640112f05cad6e915", + "0x0", + "0xa371e66983", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0xd7ec0b", + "0x0", + "0x1d4e799c6c5098", + "0x0", + "0x0", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x1d4e799c6c5098", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "0x1d4cf97bfb72c8", + "0x0" + ] + }, + { + "from_address": "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x10499ad2395d0f2f99a839af6b58ff8bc839f0bbaeeee8c8e264ab427473564", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2da9256da595f0d92d2ae1306c2ecb863e172d90ae7c291627ae17aa15ea2a4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf55007faf349", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 61261, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 80, + "range_check_builtin_applications": 1915 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef27f9fe63c9", + "messages_sent": [], + "events": [ + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x172116a720", + "0x0" + ] + }, + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0x0", + "0x172116a720", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0xc6a2e3c8d2e95", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0x5ad3b1", + "0x0" + ] + }, + { + "from_address": "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1c187387ba69a4938c74985f14dd5c7175108cefbf9624178b9af456ad8efea", + "0x9", + "0x1", + "0xc6a2e3c8d2e95", + "0x0", + "0x5ad3b1", + "0x0", + "0x10b7ba7a4938aa15b7", + "0x0", + "0x7a4ea9027f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x72b64f7707d8afe5c2f15029ddbd573bd34319678481ff3e86e01b65f8deb32", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef27f9fe63c9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22833, + "builtin_instance_counter": { + "range_check_builtin_applications": 726, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x2646d0f4cf632c4477614da618a89496cc98f29127ebfac88e8908c38fb07fa", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x2646d0f4cf632c4477614da618a89496cc98f29127ebfac88e8908c38fb07fa", + "0x404c9752eccc53c8a4164358d82eef2fd8f9055eb76ee188d3f435bdb26f254", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2646d0f4cf632c4477614da618a89496cc98f29127ebfac88e8908c38fb07fa", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x2646d0f4cf632c4477614da618a89496cc98f29127ebfac88e8908c38fb07fa", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x2fa6b6eb177c848e45c0165ec06fcb68bebd49f5df7f44407dd0dc16bb84364", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x2fa6b6eb177c848e45c0165ec06fcb68bebd49f5df7f44407dd0dc16bb84364", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x1a735a288f631ed09a0b2bbcd5ab6d5b40df2d7c77e358d4fd752d60f0d30d7" + ] + }, + { + "from_address": "0x2fa6b6eb177c848e45c0165ec06fcb68bebd49f5df7f44407dd0dc16bb84364", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2fa6b6eb177c848e45c0165ec06fcb68bebd49f5df7f44407dd0dc16bb84364", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x2fa6b6eb177c848e45c0165ec06fcb68bebd49f5df7f44407dd0dc16bb84364", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 34, + "range_check_builtin_applications": 145 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xa0ce37fe2986", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xe9ccbccb8a46f", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1b957eae7397b32db7dab", + "0xd3f89f5aaa0e3309d28b8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xe9ccbccb8a46f", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x7ae0ab7952bbfc33a72035e5eccec7c8816723421c0acb315bd4690a71d46e" + ], + "data": [ + "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xe8e77c5ecad40", + "0xe9ccbccb8a46f" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23bb414a21ab2ed6b4c6d386cd2f11630fd641ac55a1da351283d0a7e4a38f3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xa0ce37fe2986", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23774, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 929, + "pedersen_builtin_applications": 48 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e0d042f2ba", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x8d18cad", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x8d18cad", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "0x131f0bb33c822d0", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d2ed6b10ad00875", + "0x1b53ae56106" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x8d18cad", + "0x0", + "0x131f0bb33c822d0", + "0x0", + "0x0", + "0x0", + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268" + ] + }, + { + "from_address": "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x470d25d4eacfcec39a19c443c3ea40e71d63f6519c727c6e27ddaaf3b8de872", + "0x6", + "0x1", + "0x2", + "0x8d18cad", + "0x0", + "0x131f0bb33c822d0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f087afa3378a973e3a6932167356c8eb1451be2accf440993e1f133fc65268", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e0d042f2ba", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26594, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973, + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x46bd12e2cc2593f8778d079ac0430d6c0c154776039bbc075d165f832a9b90c", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x46bd12e2cc2593f8778d079ac0430d6c0c154776039bbc075d165f832a9b90c", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x4880c6b60137ef3ccc9f159e1e2d46fc7dcae4650fec40903675ffb82af4846" + ] + }, + { + "from_address": "0x46bd12e2cc2593f8778d079ac0430d6c0c154776039bbc075d165f832a9b90c", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x46bd12e2cc2593f8778d079ac0430d6c0c154776039bbc075d165f832a9b90c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x46bd12e2cc2593f8778d079ac0430d6c0c154776039bbc075d165f832a9b90c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "range_check_builtin_applications": 145, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 34 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb438896f50bd", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "0x0", + "0x82c8d43fc66102b8", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bc49125ede08aa5799ac", + "0xd4ad2fd633bcd1ad33fe0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x82c8d43fc66102b8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "0x82c8d43fc66102b8", + "0x0" + ] + }, + { + "from_address": "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2f8aeb1edce334fc76c9af93aaeee1e1c12e6c611817f54abd35538b102a64", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x16f7471214a7e4e850b8f09e929c8f874ca1b13b5f4d22afc80ddb362ca471d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb438896f50bd", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22414, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 948, + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 40 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x40d8b68d4cb322fc69be5cd974df5d4a98744040735c6694ecc0b3da7c4a9f3", + "0x676466676466676466676440676d61696c2e636f6d", + "0x666573667365667365" + ] + }, + { + "from_address": "0x40d8b68d4cb322fc69be5cd974df5d4a98744040735c6694ecc0b3da7c4a9f3", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x26c42fffd319eeac6bac32c00ae65e4163c53872ca7c0a096867fd2be99935a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x40d8b68d4cb322fc69be5cd974df5d4a98744040735c6694ecc0b3da7c4a9f3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x5000806b4e16", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5845060531ca6bd2679c3c4c7dd6f2e8d7db4665e348adf96ed799e3e8cf30e", + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x18bea16edc7336", + "0x0" + ] + }, + { + "from_address": "0x5845060531ca6bd2679c3c4c7dd6f2e8d7db4665e348adf96ed799e3e8cf30e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1407a004f3f65a8a4db6bd613f41b5d65018d82885d856d741380496a99cfd2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5845060531ca6bd2679c3c4c7dd6f2e8d7db4665e348adf96ed799e3e8cf30e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x5000806b4e16", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9328, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 213, + "pedersen_builtin_applications": 24 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x32ec531e21017143b0992dfe578562a2edfe4a516eb4a9bd2bb733068fe8c83", + "0xc530ac5b04", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x32ec531e21017143b0992dfe578562a2edfe4a516eb4a9bd2bb733068fe8c83", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9340, + "builtin_instance_counter": { + "range_check_builtin_applications": 200, + "pedersen_builtin_applications": 24, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5dc9ac78471a66c0e8d71d72987878ff4f6024c478e10f4948a88f760a73e1b", + "0xdfc078fe2d", + "0x0" + ] + }, + { + "from_address": "0x5dc9ac78471a66c0e8d71d72987878ff4f6024c478e10f4948a88f760a73e1b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3126781be193eed7fac380878c65a0f1142f21d0d108b0490e69c87d8968c75", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5dc9ac78471a66c0e8d71d72987878ff4f6024c478e10f4948a88f760a73e1b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7836, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 22, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x7c9695b66557", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x35bd041f99860ff57adfc16b848c6b8e27471acb669e969a60ae17c281df8a" + ], + "data": [ + "0x49fccdd4f0d252b0431b20a618c3b7babfb2e206569d7fd9507cb9b88aa65cb", + "0x7300100008000000000000000000000000", + "0x377d7", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x49fccdd4f0d252b0431b20a618c3b7babfb2e206569d7fd9507cb9b88aa65cb", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x49fccdd4f0d252b0431b20a618c3b7babfb2e206569d7fd9507cb9b88aa65cb", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x88d9ce93071aa3106aab29458af83aa00bb12db902429be8f64519c6236f49", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x49fccdd4f0d252b0431b20a618c3b7babfb2e206569d7fd9507cb9b88aa65cb", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x7c9695b66557", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42615, + "builtin_instance_counter": { + "range_check_builtin_applications": 1327, + "pedersen_builtin_applications": 25, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x69606cd4198760cb95c44e481e6aa7ec5a860fef453e8c67fe32053d291352c", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x69606cd4198760cb95c44e481e6aa7ec5a860fef453e8c67fe32053d291352c", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x3458fdba97b689461cd2497df1178e8b5107f001078d3637cd4c74fe75d7473" + ] + }, + { + "from_address": "0x69606cd4198760cb95c44e481e6aa7ec5a860fef453e8c67fe32053d291352c", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x69606cd4198760cb95c44e481e6aa7ec5a860fef453e8c67fe32053d291352c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x69606cd4198760cb95c44e481e6aa7ec5a860fef453e8c67fe32053d291352c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "range_check_builtin_applications": 145, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 34 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "0x3ed14e213ebb97a5b132348ddd6b79a7a803ec0b93ece9da03857433cd5d4c0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x1655d596876c1c5c1492411cb8e4c308eaa7308a67a4bb8492091c1ec910ce7", + "0x646d61696c7465616d40646d61696c2e6169", + "0x5265706c793a2057656c636f6d6520746f20446d61696c204e6574776f726b2" + ] + }, + { + "from_address": "0x1655d596876c1c5c1492411cb8e4c308eaa7308a67a4bb8492091c1ec910ce7", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x57559631c86ae61c4bc364a346479fd644ef0450baa3b6dd87aa57dcaebe823", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1655d596876c1c5c1492411cb8e4c308eaa7308a67a4bb8492091c1ec910ce7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x18880c1a1aba000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x18880c1a1aba000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "0xb3ed5b4", + "0x0" + ] + }, + { + "from_address": "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5131b0bedd0695fe1017d96a2753bc91ec5a50ec9102bd15f08fe2cb55c8f2", + "0x3", + "0x1", + "0xb3ed5b4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7042dcc0eddd0625405231ec0b1a7f276d91fff12bad842cfc9ba112b3ae408", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21791, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x616e036a09afc3374e8dcfda106b4cd7ffca06e3bd0faf201f81b8b9d97c51e", + "0x6b617964656e696e64656e40646d61696c2e6169", + "0x7478" + ] + }, + { + "from_address": "0x616e036a09afc3374e8dcfda106b4cd7ffca06e3bd0faf201f81b8b9d97c51e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3b1f08fd16a9a48b3ffe7ea15ac85208800d30aa885c1337e28beacee86570a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x616e036a09afc3374e8dcfda106b4cd7ffca06e3bd0faf201f81b8b9d97c51e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "0x7768697465736f636b7340646d61696c2e6169", + "0x637a" + ] + }, + { + "from_address": "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6fdbee006a633304edcd40b726a0753c1e6d8b9f486e73cb7a4298edeb05dd1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdd8121e44058", + "messages_sent": [], + "events": [ + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa2", + "0x0" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "0xaa2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "0x18a2cb237247a", + "0x0" + ] + }, + { + "from_address": "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1a5cb523", + "0x0", + "0x3d43829a1a1eca730", + "0x0" + ] + }, + { + "from_address": "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa2", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x18a2cb237247a", + "0x0", + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0" + ] + }, + { + "from_address": "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6d6878f1128b533e6ddc2b64d510335bd80864f56f49575b0c6811e7ede4598", + "0x6", + "0x1", + "0x2", + "0xaa2", + "0x0", + "0x18a2cb237247a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x38d6d4fdb0dbcb2deb9bd00971af584862707ce3b235a4e361cfdbf412cd8d0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdd8121e44058", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 35108, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1273 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x299693d0c40a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1ae80d66cc58dc4250a95a019a8c6dcb11f2bd0053ae6e9136c03b01be59a88", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x299693d0c40a", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x01ae80d66cc58dc4250a95a019a8c6dcb11f2bd0053ae6e9136c03b01be59a88):\nError at pc=0:12:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:161)\nUnknown location (pc=0:147)\n\nError in the called contract (0x01ae80d66cc58dc4250a95a019a8c6dcb11f2bd0053ae6e9136c03b01be59a88):\nError at pc=0:39:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1398)\nUnknown location (pc=0:1351)\nUnknown location (pc=0:569)\nUnknown location (pc=0:604)\nError message: argent: multicall 6:13 failed\nUnknown location (pc=0:586)\n\nError in the called contract (0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023):\nError at pc=0:15:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:305)\nUnknown location (pc=0:291)\n\nError in the called contract (0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023):\nError at pc=0:1625:\nError message: Router::swap_exact_tokens_for_tokens::insufficient output amount\n\nCairo traceback (most recent call last):\nUnknown location (pc=0:1710)\n", + "execution_resources": { + "steps": 14542, + "builtin_instance_counter": { + "range_check_builtin_applications": 281, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x56e6fedc391f795fadeb64a21d9cf1b0a4e6f10f2586e6d84e463ac41a93f0b", + "0x6a69676b7a383933343540676d61696c2e636f6d", + "0x6376636267" + ] + }, + { + "from_address": "0x56e6fedc391f795fadeb64a21d9cf1b0a4e6f10f2586e6d84e463ac41a93f0b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3584478e8b309da6629b3942b7dc64d92484f0bd3ca4f1c6d2f561bbe4ffe9e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x56e6fedc391f795fadeb64a21d9cf1b0a4e6f10f2586e6d84e463ac41a93f0b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5bf6eb94c8da5c92fb9d791faa0078b9dc753f4ad22b2f052d6e8ab07ee4224", + "0x6a61686f6e64616440676d61696c2e636f6d", + "0x676864666a6b206268756469206767687670756920652047485650385545524" + ] + }, + { + "from_address": "0x5bf6eb94c8da5c92fb9d791faa0078b9dc753f4ad22b2f052d6e8ab07ee4224", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1c709a083f7df678e75a768bd1788b3e084850dd0aec971a8227deccf66f752", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5bf6eb94c8da5c92fb9d791faa0078b9dc753f4ad22b2f052d6e8ab07ee4224", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x3aaff5decb44871272f03537576860189565bc2e8a6ce7c59dbefe682b108fb", + "0x6a6f64796572696b40646d61696c2e6169", + "0x617364" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3aaff5decb44871272f03537576860189565bc2e8a6ce7c59dbefe682b108fb", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x12ac3cc151687", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x8391c9a", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "0x2e767b996c8d4594c73317bb102c2018b9036aee8eed08ace5f45b3568b94e5", + "0x8391c9a", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e767b996c8d4594c73317bb102c2018b9036aee8eed08ace5f45b3568b94e5", + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "0x774a645cd085637fa", + "0x0" + ] + }, + { + "from_address": "0x2e767b996c8d4594c73317bb102c2018b9036aee8eed08ace5f45b3568b94e5", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x12390b4f31dc7ca852b9", + "0x14120441a3" + ] + }, + { + "from_address": "0x2e767b996c8d4594c73317bb102c2018b9036aee8eed08ace5f45b3568b94e5", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x8391c9a", + "0x0", + "0x774a645cd085637fa", + "0x0", + "0x0", + "0x0", + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958" + ] + }, + { + "from_address": "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x236630f191d05f61e5e0c8df90d4c6088883c73ea8b786501283837796ffdb5", + "0x6", + "0x1", + "0x2", + "0x8391c9a", + "0x0", + "0x774a645cd085637fa", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5d5fd10a413abed3f8968c0a26d3cdf39564ec4a94dc5500996bad5162c958", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x12ac3cc151687", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 27412, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1185, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x29590344e66f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x135d7f3bfc7e6912b960863efd478700dc566a57ad2a583c64c5c318d178f1c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x29590344e66f", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x0135d7f3bfc7e6912b960863efd478700dc566a57ad2a583c64c5c318d178f1c):\nError at pc=0:10:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:228)\nUnknown location (pc=0:214)\n\nError in the called contract (0x0135d7f3bfc7e6912b960863efd478700dc566a57ad2a583c64c5c318d178f1c):\nError at pc=0:219:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:8090)\nUnknown location (pc=0:8038)\nUnknown location (pc=0:5734)\nUnknown location (pc=0:5771)\nUnknown location (pc=0:5755)\n\nError in the called contract (0x07a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1):\nError at pc=0:2104:\nError message: 10kSwapRouter: IOA\n\nCairo traceback (most recent call last):\nUnknown location (pc=0:2185)\n", + "execution_resources": { + "steps": 13038, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 219 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x5e468c23200606b83382459808f4557b89b7ed029085fdd1b19f1de58465c62", + "0x169554ba6afe4000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x160c79728647bf23440d3892c9bd615e7e2b25c163085beff85ee3be184c66", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb438896f50bd", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "0x0", + "0x1bc16d7f4ed84862", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bce9e0a4cb3a6287b00d", + "0xd4d3a95e4ff62bda5a095" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bc16d7f4ed84862" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "0x1bc16d7f4ed84862", + "0x0" + ] + }, + { + "from_address": "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x32b80244a5de8cae9a7854c9249d2deb9b19458cb82e21b8effc04318eaa5ef", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x52e9b3e2aaf90d0837c1bd0a7cf920a08db85f8a4688724ef49af467cb5dd7a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb438896f50bd", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22416, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 40, + "range_check_builtin_applications": 948, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "0x62616e616e61325f6d6f6f6e407961686f6f2e636f6d", + "0x486f7720446d61696c206973204368616e67696e67207468652057617920576" + ] + }, + { + "from_address": "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x57e9cd0d03b031e426bf1fe34cd3c0132266961d5451c24427cf67cefb04348", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7c0447f42f145e8e12ea98ef892cd5f3959eb0f26497cd1035115e9f02453fb", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc99794a76036", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xfa63e3", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0xfa63e3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "0x21ebf5c4ab0b22", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e4209e63802d6ffa", + "0x0", + "0x372508fce9d", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0xfa63e3", + "0x0", + "0x21ebf5c4ab0b22", + "0x0", + "0x0", + "0x0", + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064" + ] + }, + { + "from_address": "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4931c0411d431ce8920c948ce02a0a7cc31578be805e97788f7a4c9b3ca09ab", + "0x6", + "0x1", + "0x2", + "0xfa63e3", + "0x0", + "0x21ebf5c4ab0b22", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6fbd53e776e8cc992a8966823f67c3a537368befc1a830e65aa0ee214b7a064", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc99794a76036", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33336, + "builtin_instance_counter": { + "range_check_builtin_applications": 1111, + "pedersen_builtin_applications": 38, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x30db36e00854e1b78009a3af9a6a9a03b16974dc52cc8f3f5be7baa2ce02cb1", + "0x6673646673647640676d61696c2e636f6d", + "0x66647364666574776567" + ] + }, + { + "from_address": "0x30db36e00854e1b78009a3af9a6a9a03b16974dc52cc8f3f5be7baa2ce02cb1", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1c5cda08e76f6233f74f8415febbf691d8fd5e3ae04dd04786c92d10b44f92c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30db36e00854e1b78009a3af9a6a9a03b16974dc52cc8f3f5be7baa2ce02cb1", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf0267195d59f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "0x2f96049837b784a6", + "0x0" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1fadf9f78db4545da3d0", + "0x4b75b5dd4bd209dcf" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x71afd498d0000", + "0x0", + "0x2f96049837b784a6", + "0x0", + "0x0", + "0x0", + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x9d59f8ce7c9efc48d7d8c1ee60164d549f12615a54d6142986e7e35ac6d28d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf0267195d59f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 29047, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 58, + "range_check_builtin_applications": 1202, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb8daaea0ba12", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x37a4818a78e000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x37a4818a78e000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x37a4818a78e000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x37a4818a78e000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1977ebd", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x164048d387554fc915", + "0x0", + "0xa3704eeac6", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x37a4818a78e000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1977ebd", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x1977ebd", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x37a4818a78e000", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x1977ebd", + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x527d38b87ec28e8a8b8188e4f49e79b853fc705a3f64e88b1e8c79139d51dc3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb8daaea0ba12", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 51308, + "builtin_instance_counter": { + "range_check_builtin_applications": 1583, + "bitwise_builtin_applications": 4, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 57 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x7cd4264242f2", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x35bd041f99860ff57adfc16b848c6b8e27471acb669e969a60ae17c281df8a" + ], + "data": [ + "0xa3abb7ad34f4de0c5c3b06397315d0f35de6489c5fd89a824529e4ba4faf18", + "0x7300100008000000000000000000000000", + "0x377d8", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0xa3abb7ad34f4de0c5c3b06397315d0f35de6489c5fd89a824529e4ba4faf18", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xa3abb7ad34f4de0c5c3b06397315d0f35de6489c5fd89a824529e4ba4faf18", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x7cd4264242f2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 44123, + "builtin_instance_counter": { + "pedersen_builtin_applications": 27, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1344 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x11be2ff9d6667", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0xd02ab486cedc0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1ef7413c92d103", + "0x0" + ] + }, + { + "from_address": "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3a8b1a655485bbe5639d", + "0x0", + "0x8bbfe0e8ea62b2524", + "0x0" + ] + }, + { + "from_address": "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xd02ab486cedc0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1ef7413c92d103", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x1ef7413c92d103", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "0x1ef5ab5c75802e", + "0x0" + ] + }, + { + "from_address": "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1098f83cd2dbfbc372b13e9cb9bcb06afcdfbf9100c637b908d377ab97cab61", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x54b60df3769acb3c505d90ad619fdf76d5607ee38006aefc1b2475da65b62b8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x11be2ff9d6667", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 57043, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1925, + "pedersen_builtin_applications": 80 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4595f0f3e65", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x423dd2adb5100840b269d3dcd854faae35b6e822d0735f2fc9b86c57e9fd8f4", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1e39776", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x423dd2adb5100840b269d3dcd854faae35b6e822d0735f2fc9b86c57e9fd8f4", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1e39776", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x423dd2adb5100840b269d3dcd854faae35b6e822d0735f2fc9b86c57e9fd8f4", + "0x418af121ad1acb", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x423dd2adb5100840b269d3dcd854faae35b6e822d0735f2fc9b86c57e9fd8f4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4595f0f3e65", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23279, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 39, + "range_check_builtin_applications": 577 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x60655948c939796b9003faa1859fd03a1c2c55a1f96217c0c55d529e37f7a1b", + "0x73647364614073642e736572", + "0x63646364" + ] + }, + { + "from_address": "0x60655948c939796b9003faa1859fd03a1c2c55a1f96217c0c55d529e37f7a1b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x427b37d3379904eaa3d6fa0a8a0ccc4f1983e26874060ce4fdebec21c20225", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x60655948c939796b9003faa1859fd03a1c2c55a1f96217c0c55d529e37f7a1b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x971fa7595f50", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bce9dd384f622b3f1eb0", + "0xd4d3a88cad4ed86c4f1a4" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x971fa7595f50" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x971fa7595f50", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x971fa7595f50", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x561e526f24737eb9d101c8020f7a542f4fe537ba970ece6ba938f462d78d9b4", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3baf4a6347ca4995be41a9ba83cec07a7f481590f3db74cc961ff00477a9771", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26089, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 47, + "range_check_builtin_applications": 1028 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x28a46c554b53", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x39ed6c275ed564f84e30ab6a02ef8350d3a998eec3648995ee7e6ba2dcc2e5f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x28a46c554b53", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x039ed6c275ed564f84e30ab6a02ef8350d3a998eec3648995ee7e6ba2dcc2e5f):\nError at pc=0:12:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:161)\nUnknown location (pc=0:147)\n\nError in the called contract (0x039ed6c275ed564f84e30ab6a02ef8350d3a998eec3648995ee7e6ba2dcc2e5f):\nError at pc=0:39:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1398)\nUnknown location (pc=0:1351)\nUnknown location (pc=0:569)\nUnknown location (pc=0:604)\nError message: argent: multicall 6:13 failed\nUnknown location (pc=0:586)\n\nError in the called contract (0x01b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62):\nError at pc=0:134:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1436)\nUnknown location (pc=0:1294)\nUnknown location (pc=0:712)\n\nError in the called contract (0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3):\nError at pc=0:1718:\nAn ASSERT_EQ instruction failed: 0 != 1.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1369)\nUnknown location (pc=0:1277)\nError message: dai/insufficient-balance\nUnknown location (pc=0:1628)\n", + "execution_resources": { + "steps": 8630, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x5000806b4e16", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3604ed49665e514aa449dc0bcdad0e95aa95dd90947128ef64c146e98d1d51a", + "0x7b393627bd514d2aa4c83e9f0c468939df15ea3c29980cd8e7be3ec847795f0", + "0x3045c25ee2ba329", + "0x0" + ] + }, + { + "from_address": "0x3604ed49665e514aa449dc0bcdad0e95aa95dd90947128ef64c146e98d1d51a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x31bd092525444ef0981cb651228f19062683470b0dff76c3ee9c1f8005939f0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3604ed49665e514aa449dc0bcdad0e95aa95dd90947128ef64c146e98d1d51a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x5000806b4e16", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9328, + "builtin_instance_counter": { + "pedersen_builtin_applications": 24, + "range_check_builtin_applications": 213, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0xaf32959a1273a9a3cb79a0604be1eaab8ce7107326e892657261b5bd4497a7", + "0x11c37937e08000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x64d438a43295c8dd8de7e0df3ffbf750f304cc1c62c13f2bc7a57aca962f6a", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x61176ce1442c6349d6b2e610aacc3c69f57f1cbd85868c45f6b760a1f066b9d", + "0x64616e746f6e6f76342e61663240676d61696c2e636f6d", + "0x466f72776172643a2057656c636f6d6520746f20446d61696c204e6574776f7" + ] + }, + { + "from_address": "0x61176ce1442c6349d6b2e610aacc3c69f57f1cbd85868c45f6b760a1f066b9d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x77c8b556a878d440b85455a6f44807c00282ad826c29665497d3af8bc76227f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x61176ce1442c6349d6b2e610aacc3c69f57f1cbd85868c45f6b760a1f066b9d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1185c0cef5edb", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x94e683935a", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x449", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x94e683935a", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x447", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x98707809b39a3b14d9f5004bc1fe77721baa2d8b67fd54ed5794f60671de0", + "0x25a11cc0", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x118f3a7", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d2ed745f1539bcf", + "0x1b53ae5654d" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x34e55c1cd55f1338241b50d352f0e91c7e4ffad0e4271d64eb347589ebdfd16" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x94e683935a", + "0x0", + "0x447", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xc4aa263e699f245115353023452d5c0e42a1b28abb7b35981af0ab10414459", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1185c0cef5edb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 35054, + "builtin_instance_counter": { + "pedersen_builtin_applications": 62, + "range_check_builtin_applications": 1268, + "bitwise_builtin_applications": 4, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x3fec9b4236c8a88c76b84550d5c79ed44734a3967f0553db6cdbaa95333e659", + "0x8b8d0aae12", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3fec9b4236c8a88c76b84550d5c79ed44734a3967f0553db6cdbaa95333e659", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9342, + "builtin_instance_counter": { + "pedersen_builtin_applications": 24, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 200 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x2f00e58601a9967f8c1c0d349e97dc75a55d0d9bf2b8767398a689572be445", + "0x42656967686869657240676d61696c2e636f6d", + "0x69736f78617a696e652077726e7420" + ] + }, + { + "from_address": "0x2f00e58601a9967f8c1c0d349e97dc75a55d0d9bf2b8767398a689572be445", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4cfd5dc5f93146b5de820c9163379edab97489dfc1142eb6a984f048695aa2c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2f00e58601a9967f8c1c0d349e97dc75a55d0d9bf2b8767398a689572be445", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xef27f9fe63c9", + "messages_sent": [], + "events": [ + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3e63aaa0cb", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x0", + "0x3e63aaa0cb", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x22cda42a6339e7", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x100055c", + "0x0" + ] + }, + { + "from_address": "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2d3d8789f73032b36cc2e2eff1872fd6c6b6d07c506c67c84372919e45bcb80", + "0x9", + "0x1", + "0x22cda42a6339e7", + "0x0", + "0x100055c", + "0x0", + "0x49eb72112f5fbbdcef", + "0x0", + "0x21fc5327fc9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6108044310408fe63740020f457d780c3f9678c93dc474f6c5dc98dd07e12", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xef27f9fe63c9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22839, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 726, + "pedersen_builtin_applications": 37 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x28b4d7254227", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xd595dea44e3759495547ac022981c330b82a3a8ca111eace41cec9a601bf43", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x28b4d7254227", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x00d595dea44e3759495547ac022981c330b82a3a8ca111eace41cec9a601bf43):\nError at pc=0:12:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:161)\nUnknown location (pc=0:147)\n\nError in the called contract (0x00d595dea44e3759495547ac022981c330b82a3a8ca111eace41cec9a601bf43):\nError at pc=0:39:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1398)\nUnknown location (pc=0:1351)\nUnknown location (pc=0:569)\nUnknown location (pc=0:604)\nError message: argent: multicall 6:13 failed\nUnknown location (pc=0:586)\n\nError in the called contract (0x04c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05):\nError at pc=0:96:\nGot an exception while executing a hint: Assertion failed, 0 % 0x800000000000011000000000000000000000000000000000000000000000001 is equal to 0\nCairo traceback (most recent call last):\nUnknown location (pc=0:5682)\nUnknown location (pc=0:5671)\nUnknown location (pc=0:2655)\nUnknown location (pc=0:3550)\nError message: Market: no debt to repay\nUnknown location (pc=0:4539)\n", + "execution_resources": { + "steps": 9092, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x103c20376e152", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x500d47", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x500d47", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "0xae8de11f3826c", + "0x0" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xce0ccf8805211595f", + "0x5e36bcc8ab" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x500d47", + "0x0", + "0xae8de11f3826c", + "0x0", + "0x0", + "0x0", + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d" + ] + }, + { + "from_address": "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7bb2369c2803379f302fa539ef1ce94a0c31e616b3a7f062501cf711cc7834c", + "0x6", + "0x1", + "0x2", + "0x500d47", + "0x0", + "0xae8de11f3826c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6f47dab848a1c43fe7a5661bd957e723294eb573f4bc7556603d7b608ae089d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x103c20376e152", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 28976, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 1223 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb6399352321e", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa87bee538000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0xaa87bee538000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "0x4e3377", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e42b46df6e80effa", + "0x0", + "0x37250419b26", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xaa87bee538000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x4e3377", + "0x0", + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2517d570f32c6b6dd4cbeefc3c39dec79b9ebb30270970332827c882ea32051", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb6399352321e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34911, + "builtin_instance_counter": { + "pedersen_builtin_applications": 40, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1128 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x146c1ebad7301", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x17d7840", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x17d7840", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x17d4796", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x1122d536cde69f0bd3b95e73caa2bf8866f5f0ed3e5122f5ea74d0d3314807f", + "0x30d4", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x30d4", + "0x0", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x68355292f3", + "0x0", + "0x6a36dac4b3", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x17d7840", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x17d4796", + "0x0", + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b" + ] + }, + { + "from_address": "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3a4f19cc3bfb3f5cadfd4b4a2b09b85e55eaedb5cc01653295fde37b887c6c1", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x146c1ebad7301", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 73530, + "builtin_instance_counter": { + "range_check_builtin_applications": 4977, + "pedersen_builtin_applications": 60, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x71118565e4ee80c72bf28c3cef2783db2aefae4c4cf0abcc9f2cba378a23ae2", + "0x6a6e626a6e6a6e6462666e7040676d61696c2e636f6d", + "0x66646166616466333234" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x71118565e4ee80c72bf28c3cef2783db2aefae4c4cf0abcc9f2cba378a23ae2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 160, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdea8a4839b40", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x47358db", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x47358db", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "0x9a1636fde06063", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0xc087ff1f956081ebeed0085a169b8b356cbb7990b64680a44f930ec401cbcd", + "0x1b582", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x0", + "0x0", + "0x1b582", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xc219e4ea37d7fb959", + "0x0", + "0x599588f202", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x0", + "0x0", + "0x47358db", + "0x0", + "0x9a1636fde06063", + "0x0", + "0x0", + "0x0", + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3d76bb8419fe4197eb1a7ac01eee3f0b39cb7dc7efd1c3e7078d240d7dc3367", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdea8a4839b40", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42369, + "builtin_instance_counter": { + "pedersen_builtin_applications": 62, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1210 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x4157c5c2e7c24cec14ec95595be5e52538027158fa30f1910534bf95aabfb78", + "0x1e8da789118000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3121a1211117c1382bb2926aaf9b95f8d099c8e15214085cf17c92a37ae451e", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x118be8dcf27d3", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2165668ec7c90d54d", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "0x2165668ec7c90d54d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "0x4f4a7a726aed95", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "0xbe446ee3a7e32e33c938411708fb8763fceeb509f6315656d89a8022e9d4f5", + "0xcd2f8473630883", + "0x0" + ] + }, + { + "from_address": "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0xcd2f8473630883", + "0x0", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x619e252c8a342be81c5", + "0x0", + "0xe7cee1a0fd72fb44", + "0x0" + ] + }, + { + "from_address": "0x32ebb8e68553620b97b308684babf606d9556d5c0a652450c32e85f40d000d", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x2165668ec7c90d54d", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x4f4a7a726aed95", + "0x0", + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7" + ] + }, + { + "from_address": "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4572d060e3bfb9b0e8cbdc3bbecc2f6df1bf5114afb69d2795f982e4b4c25ab", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x65054c98682aa63b1fabe01668d81b861db3f510eb1e9a83a2be386954786a7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x118be8dcf27d3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 37491, + "builtin_instance_counter": { + "pedersen_builtin_applications": 60, + "range_check_builtin_applications": 1166, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e0d042f2ba", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2204f29", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2204f29", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "0x49c1c50d8cd670", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6ce51580e3c6c55f", + "0x1b53d05b476" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x2204f29", + "0x0", + "0x49c1c50d8cd670", + "0x0", + "0x0", + "0x0", + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844" + ] + }, + { + "from_address": "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x66379e40029c11f6053e555c030f67e8fe188315256897de8dd0a3d705a207d", + "0x6", + "0x1", + "0x2", + "0x2204f29", + "0x0", + "0x49c1c50d8cd670", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6981ab918578872264e13c61bf0e4ae9dc93372f97508027ced8fb77f68a844", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e0d042f2ba", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26594, + "builtin_instance_counter": { + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x27f7f60f715b9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x27f7f60f715b9", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "0x12522c", + "0x0" + ] + }, + { + "from_address": "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3d60c16de2c5fd074d7ebc34eb3da1340a4a4f721d6ca7c752a54d0b7f60260", + "0x3", + "0x1", + "0x12522c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e3b8dbf0daf585a9cad69722f38ff6bafb6379affc94196d95e2233c950b00", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21796, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x7f035c6f4143bc72418dd210f904d40d2e7d8671329662642102e0f5d29eff8", + "0x64786868766b7975696940676d61692e636f6d", + "0x727132656a75686b797569" + ] + }, + { + "from_address": "0x7f035c6f4143bc72418dd210f904d40d2e7d8671329662642102e0f5d29eff8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x733c74e0666c8572a88e1beeb472a91df7fa9407f927d55ee6c0530dc9d6727", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f035c6f4143bc72418dd210f904d40d2e7d8671329662642102e0f5d29eff8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x14336de4b6dc0", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "0x11d1057", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x104acb6ca230bc9da", + "0x0" + ] + }, + { + "from_address": "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1611b609f728e82981de", + "0x0", + "0x1810e2e0bf", + "0x0" + ] + }, + { + "from_address": "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x11d1057", + "0x0", + "0x104acb6ca230bc9da", + "0x0", + "0x0", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x104acb6ca230bc9da", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "0x1049f5e131b9057ca", + "0x0" + ] + }, + { + "from_address": "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5780251737e68a06de86b63d0ccfc37aee4efecb8ba123c94420559ad1e25d0", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xc589ba0cddf88460615e40e7a17fe47d60b46f6c9884ebfa57a20c48b6bf9b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x14336de4b6dc0", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 57525, + "builtin_instance_counter": { + "pedersen_builtin_applications": 80, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1944 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xe20aa6ddb76f", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x340947d024ce7cd0a417122", + "0x343d5b733c51ee4c23f164e" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x184352dfdda08a07d61206", + "0x1dddc3fe51db59fd96410e" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x5ed652563eb172665eae6b9d4937d67503a69e02877fff69fb182bc3768b2ee", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x14d7a276", + "0x150f7528" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x5ed652563eb172665eae6b9d4937d67503a69e02877fff69fb182bc3768b2ee", + "0x150f7528", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5ed652563eb172665eae6b9d4937d67503a69e02877fff69fb182bc3768b2ee", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xe20aa6ddb76f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 63490, + "builtin_instance_counter": { + "bitwise_builtin_applications": 79, + "pedersen_builtin_applications": 152, + "range_check_builtin_applications": 2656, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb7c396d155fe", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2b57d5da428000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2b57d5da428000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2b57d5da428000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2b57d5da428000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x13df2cf", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d106d56be09455f", + "0x1b53bc7c1a7" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2b57d5da428000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x13df2cf", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x13df2cf", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2b57d5da428000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x13df2cf", + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2c9cf60dc3733963084fa1e8eb2cec979496700727962ea6b233d870232580f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb7c396d155fe", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 44539, + "builtin_instance_counter": { + "range_check_builtin_applications": 1445, + "pedersen_builtin_applications": 75, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 7 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x18a9c632c0fcae0a64570f974f403977f0b4cb8d8f5023846370bbbd255d259", + "0x666a6667666840676d61696c2e636f6d", + "0x6a67206a6768" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x18a9c632c0fcae0a64570f974f403977f0b4cb8d8f5023846370bbbd255d259", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "range_check_builtin_applications": 160, + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c589e6e4944", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x51734077ba7baf5765896c56ce10b389d80cdcee8622e23c0556fb49e82df1b", + "0x60cf6ccef800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c589e6e4944", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9148, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 191 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x777d6a213e81", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x12b4597159a73c3f0f23a49a92e5a3d3e51f2d865a40669db649123433d1a5b" + ], + "data": [ + "0xbd1579464e", + "0x74776974746572", + "0x5240708b", + "0x2d5f0f2fcba62a54f0d8a73fb2e437d76c53f7297153b2afd1f198af6d12aa" + ] + }, + { + "from_address": "0x70e825ce22d70c965b9ca8a2a6aabcb5ee71fc08f2a6772341f634a1f5f7eba", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4b9664edb3e9fb1a93776afbe7ea25e1806d56106da59eee98b51249c34046c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x70e825ce22d70c965b9ca8a2a6aabcb5ee71fc08f2a6772341f634a1f5f7eba", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x777d6a213e81", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 10874, + "builtin_instance_counter": { + "ec_op_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 26, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x700c5957b4ec4a67202fa57e5bdbe8c13e740116c0e65129d2b736729661918", + "0x55d56459c6000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x34e59a631f795696ce30a6277da07ec4c099c5d4ef21537b234b7d9af07bacc", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x160a87d8951d17b7beb4c8adfee0aa8f9d55b09f7b983999ff24a63e7ea9495" + ] + }, + { + "from_address": "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 145, + "pedersen_builtin_applications": 34 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x129c2e09eb0293df06d2a004bb11da6eafd7895089f0ab1e8c36f9d8eb75742", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x129c2e09eb0293df06d2a004bb11da6eafd7895089f0ab1e8c36f9d8eb75742", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x777d6eb83a5d07d4b74fcc649ea5e7cfd662a67d7495a92aa316df211858f4a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x129c2e09eb0293df06d2a004bb11da6eafd7895089f0ab1e8c36f9d8eb75742", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7300, + "builtin_instance_counter": { + "range_check_builtin_applications": 165, + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e0d042f2ba", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x135e", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x135e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "0x2a3ad9317bc", + "0x0" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xce0ccf5dca47e41a3", + "0x5e36bcdc09" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x135e", + "0x0", + "0x2a3ad9317bc", + "0x0", + "0x0", + "0x0", + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3" + ] + }, + { + "from_address": "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x48bb8bbcc769fb196c56e882f093c89f09f1ef208b3db20d99f23a45c540275", + "0x6", + "0x1", + "0x2", + "0x135e", + "0x0", + "0x2a3ad9317bc", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7525880ad4a75f568b90ad281eac693bbf9bf95598e53a144088207025752d3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e0d042f2ba", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26587, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 973 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5e520aed1326da6b9a1c94bfb5c2b67342f45520ac5e42297a07862b6eb3a0", + "0x6162646f756765757940646d61696c2e6169", + "0x5265706c793a205265706c793a205265706c793a205265706c793a205265706" + ] + }, + { + "from_address": "0x5e520aed1326da6b9a1c94bfb5c2b67342f45520ac5e42297a07862b6eb3a0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3b773bdf22677476d99aa59adfbd2d2eb6be35b547e9b0b068425c4f41e6f28", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5e520aed1326da6b9a1c94bfb5c2b67342f45520ac5e42297a07862b6eb3a0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x11af0d821edb0", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x32364", + "0x0" + ] + }, + { + "from_address": "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "keys": [ + "0xfadd8dd819dba177689190ce1fe9bce0c841f1ba62789603eaae31ede81437" + ], + "data": [ + "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "0x1f01245344dcfbf5d076d9499c8fe00b2f425dcd17d4f7f5191b3d5940bd8ee", + "0x2fd23", + "0x0", + "0x38d7ea4c68000", + "0x0" + ] + }, + { + "from_address": "0x1f01245344dcfbf5d076d9499c8fe00b2f425dcd17d4f7f5191b3d5940bd8ee", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "0x38d7ea4c68000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x2fd23", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3bfa8d029132650e13036c21170784287295c562e31299add2001ee0eca2fc2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x11af0d821edb0", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 51135, + "builtin_instance_counter": { + "pedersen_builtin_applications": 112, + "bitwise_builtin_applications": 36, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1679 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x1ec0f411d35214bb02d1a83206448674f23e02058ccefe918fff45441cf3b9", + "0x646d61696c7465616d40646d61696c2e6169", + "0x5265706c793a2057656c636f6d6520746f20446d61696c204e6574776f726b2" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1ec0f411d35214bb02d1a83206448674f23e02058ccefe918fff45441cf3b9", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x41f3c9d06996c592f78fc707361fb1ad9bc7ec0d5329540c1e2fb83a221903b", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x41f3c9d06996c592f78fc707361fb1ad9bc7ec0d5329540c1e2fb83a221903b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xc61e8a74e5ef8f534da76913c956546ffd2b0544cbff4f306385946aafe3e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x41f3c9d06996c592f78fc707361fb1ad9bc7ec0d5329540c1e2fb83a221903b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7300, + "builtin_instance_counter": { + "range_check_builtin_applications": 165, + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x5c221061e94feb8a05c1ea4a708ca484382573f12e211d468e5bdfa84663092", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1990caa5e12234", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x1990caa5e12234", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "0xbb37b3", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1640626451fb30eb49", + "0x0", + "0xa36f93b313", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1990caa5e12234", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0xbb37b3", + "0x0", + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a" + ] + }, + { + "from_address": "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6756f9cad2febf873af5064e29214dfa7484818810d31eaabaf9f4513e4e9c8", + "0x6", + "0x1", + "0x2", + "0x1990caa5e12234", + "0x0", + "0xbb37b3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7938bfd9bfa1dd685aa39e398271c565f046e497d88883fc4ad8fe0bab2958a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33374, + "builtin_instance_counter": { + "range_check_builtin_applications": 1111, + "pedersen_builtin_applications": 38, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4febfae7598d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x33cc887ed9534feae59f80492128f93eb05468f51001ab49fd1e681ecf654c9", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x33cc887ed9534feae59f80492128f93eb05468f51001ab49fd1e681ecf654c9", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4febfae7598d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8806, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 182 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x36b1ceb9ed6872aa8f4940ed386fd4ad25bd9a8639f55fff4a14f1f7415a59c", + "0x616c756d696e69756d333440646d61696c2e6169", + "0x33" + ] + }, + { + "from_address": "0x36b1ceb9ed6872aa8f4940ed386fd4ad25bd9a8639f55fff4a14f1f7415a59c", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x12fddba4c5e3d1bce328ac691fa95c7c432cb4ce92775b9ee564a51051403e1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x36b1ceb9ed6872aa8f4940ed386fd4ad25bd9a8639f55fff4a14f1f7415a59c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x1f83de91390aa9f5f4fbd7e3c04f1b34d288ccd95906bead7286c8d9604064", + "0x9b89412a96", + "0x0" + ] + }, + { + "from_address": "0x1f83de91390aa9f5f4fbd7e3c04f1b34d288ccd95906bead7286c8d9604064", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x67840f591692a545ee35cf014cc89b27d8fbc4943c2def9449a063fdca5f6f5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1f83de91390aa9f5f4fbd7e3c04f1b34d288ccd95906bead7286c8d9604064", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x2927c2d501f3", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6fbe4811497fc4baafb5a223190cc4ea74ecf2cdeca53fdae2cd9c19964f113", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x2927c2d501f3", + "0x0" + ] + } + ], + "execution_status": "REVERTED", + "revert_reason": "Error in the called contract (0x06fbe4811497fc4baafb5a223190cc4ea74ecf2cdeca53fdae2cd9c19964f113):\nError at pc=0:81:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:731)\nUnknown location (pc=0:677)\nUnknown location (pc=0:291)\nUnknown location (pc=0:330)\nUnknown location (pc=0:314)\n\nError in the called contract (0x07a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1):\nError at pc=0:163:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:2185)\nUnknown location (pc=0:2122)\nUnknown location (pc=0:603)\n\nError in the called contract (0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8):\nError at pc=0:105:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1683)\nUnknown location (pc=0:1669)\n\nError in the called contract (0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8):\nError at pc=0:9:\nGot an exception while executing a hint: Assertion failed, 0 % 0x800000000000011000000000000000000000000000000000000000000000001 is equal to 0\nCairo traceback (most recent call last):\nUnknown location (pc=0:1434)\nUnknown location (pc=0:1395)\nUnknown location (pc=0:915)\n", + "execution_resources": { + "steps": 11855, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 201, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc81dfbf8332a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc573de9921a8280", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bca252f2e6c4bbd649cd", + "0xd4c28b7f084176c0402fb" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xc573de9921a8280" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0xc573de9921a8280", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "0xc573de9921a8280", + "0x0" + ] + }, + { + "from_address": "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5c33cd686177e11081276633bf6088b72eaa5ef1483bbeb40b86714f08b3ac3", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x13dcccd8d723fc7bc3d27bd70338169df509a025081ea53e904c62523e73529", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc81dfbf8332a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 24140, + "builtin_instance_counter": { + "pedersen_builtin_applications": 43, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 954 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x137897a300b5601c8026621083418fd13af6ce1f386122e5296fe6bed28e8a3", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x137897a300b5601c8026621083418fd13af6ce1f386122e5296fe6bed28e8a3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x59b6c99d7d0e4d52bbd4fcb14900b50832156cc10e3e5d65fb1e56f82941805", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x59b6c99d7d0e4d52bbd4fcb14900b50832156cc10e3e5d65fb1e56f82941805", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6d77087b59a1f6c1d78565b38fc9e122c8853e3d1696c4bbb10bf205aa3bc5e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x59b6c99d7d0e4d52bbd4fcb14900b50832156cc10e3e5d65fb1e56f82941805", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7299, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 165, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1c6bf526340000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bca1ae43e39aa909bb82", + "0xd4c264185aa811bb8084a" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1c6bf526340000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1c6bf526340000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x1c6bf526340000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3e2d5e58553ed489eef7e351a8119b7d0c6e4eeec639699df8f4e5074d5107", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x25fe27b50202675816eb34773b4a9862b990df7f20d7072faaf1637c6169837", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26090, + "builtin_instance_counter": { + "pedersen_builtin_applications": 47, + "range_check_builtin_applications": 1028, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x2877293255939e80a26cae426d9c078d3a16c3be71572bba912a41643dcbb39", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x2877293255939e80a26cae426d9c078d3a16c3be71572bba912a41643dcbb39", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x481dd6c4269e0755e68d1896e94d9c52132dfd997e097240ee591b8a4f6420e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2877293255939e80a26cae426d9c078d3a16c3be71572bba912a41643dcbb39", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x2e908292b66c0bbcb84a1599d50cbd5ab9effc572d29ac94eaa8d9d6000bb9f", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x2e908292b66c0bbcb84a1599d50cbd5ab9effc572d29ac94eaa8d9d6000bb9f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x9269e75e0736083647f03fe15af4598e6c72ab0c7a3486590969defec3cb8c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2e908292b66c0bbcb84a1599d50cbd5ab9effc572d29ac94eaa8d9d6000bb9f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7300, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 165, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63ee285c2bed", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x721ea975d5fb860dcafb33dcbfb84c324df6d04786ce2912e31a5726fe841e6", + "0x173f81c529191726c6e7287e24626fe24760ac44dae2a1f7e02080230f8458b", + "0xffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffff" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x721ea975d5fb860dcafb33dcbfb84c324df6d04786ce2912e31a5726fe841e6", + "0x64a24243f2aabae8d2148fa878276e6e6e452e3941b417f3c33b1649ea83e11", + "0x1cd24698bd8a32a", + "0x0" + ] + }, + { + "from_address": "0x721ea975d5fb860dcafb33dcbfb84c324df6d04786ce2912e31a5726fe841e6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x878e8a319aec680e959421d53e5c694cb50c7e45b714be0589dd3c9be96aa8", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x721ea975d5fb860dcafb33dcbfb84c324df6d04786ce2912e31a5726fe841e6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63ee285c2bed", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 11259, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 26, + "range_check_builtin_applications": 256 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1184ba21f6807", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2455a4bba923fda24", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x279bb33", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "0x24526602b3f12f255", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "0x279bb33", + "0x0" + ] + }, + { + "from_address": "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0x222752606cf3", + "0x0" + ] + }, + { + "from_address": "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1613fb305754273c7433", + "0x0", + "0x18135c9bf2", + "0x0" + ] + }, + { + "from_address": "0xf0f5b3eed258344152e1f17baf84a2e1b621cd754b625bec169e8595aea767", + "keys": [ + "0x34e55c1cd55f1338241b50d352f0e91c7e4ffad0e4271d64eb347589ebdfd16" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x24526602b3f12f255", + "0x0", + "0x279bb33", + "0x0" + ] + }, + { + "from_address": "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2d815b8b7258c8fd1d42f9e2994e6145a3848d056ece2705c491df8c68ac6bd", + "0x8", + "0x1", + "0x1", + "0x24526602b3f12f255", + "0x0", + "0x279bb33", + "0x0", + "0x222752606cf3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x34b23eb8376e33f70ffd4073d9673b05c923672d0be64057cd0321428792f8b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1184ba21f6807", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34607, + "builtin_instance_counter": { + "pedersen_builtin_applications": 46, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1058 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x3c3f84c1b15d9a0c28ceac1e9c085f06f890fd6c05e778632512b67d81f66a7", + "0x6b68626d78736168626e40676d61696c2e636f6d", + "0x476f6f676c65204461746120416e616c7974696373" + ] + }, + { + "from_address": "0x3c3f84c1b15d9a0c28ceac1e9c085f06f890fd6c05e778632512b67d81f66a7", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xf48c84b191a18376124e6460e0cb45e566cb26a5ad2430e6d6d46a7aedea21", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3c3f84c1b15d9a0c28ceac1e9c085f06f890fd6c05e778632512b67d81f66a7", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb45d79c33c1a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x9184e72a000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x9184e72a000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x42b4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb45d79c33c1a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23333, + "builtin_instance_counter": { + "range_check_builtin_applications": 572, + "pedersen_builtin_applications": 39, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x272e5594a4e81bd28052575ba45424763061f0d05676595a31b46b84f729f9e", + "0x6e626d6e6262626240676d61696c2e636f6d", + "0x626a62626d626e626e" + ] + }, + { + "from_address": "0x272e5594a4e81bd28052575ba45424763061f0d05676595a31b46b84f729f9e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x31e576ed38db972e22a1b94dd8fae29badfac10c379223485aac154f02aab19", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x272e5594a4e81bd28052575ba45424763061f0d05676595a31b46b84f729f9e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf591b33ace99", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "0x97ebbd5b83800", + "0x0" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x412c", + "0x0" + ] + }, + { + "from_address": "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1a5c73f7", + "0x0", + "0x3d441a85d77a4df30", + "0x0" + ] + }, + { + "from_address": "0x260e98362e0949fefff8b4de85367c035e44f734c9f8069b6ce2075ae86b45c", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x97ebbd5b83800", + "0x0", + "0x412c", + "0x0", + "0x0", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x412c", + "0x0" + ] + }, + { + "from_address": "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465", + "0x4129", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5966d3b7ea22f67259a753f00206969419fdd6c9687e7ad9a6b9377143d3465", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf591b33ace99", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 62837, + "builtin_instance_counter": { + "pedersen_builtin_applications": 82, + "range_check_builtin_applications": 1932, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "0x4da4d37eb44659c92d9b051821b65fa699d7d1daba90e9c2af880ae3118aaf4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x1a57334b4fed1d0d3edb93981831363848499d2bd7a36734727d7664dd3731", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x341f3d", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d1788540796455f", + "0x1b53b93a26a" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x341f3d", + "0x0", + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2" + ] + }, + { + "from_address": "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x77888451a1c6e90fc7f815f8196ca512206c066a7d0aafd73fc10db78ea8557", + "0x6", + "0x1", + "0x2", + "0x71afd498d0000", + "0x0", + "0x341f3d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x277fe921b0e71520788045cfe953fc9a10d7527ffa052a7c67a63184894f8c2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26612, + "builtin_instance_counter": { + "range_check_builtin_applications": 973, + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "0x666a6a6640676d61696c2e636f6d", + "0x6667" + ] + }, + { + "from_address": "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x38a22a36f0af13a0955e98b8880c4f808d5d6c92aaa26c5244a607a65883bbe", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x498982f8c91292db36f5d833b95dcd433fdc607c4be3e6bc540b575c30f9e50", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x759b49c2d615899e859a56d96658c751c4c874956d34e64bed50959e46dbd8", + "0x346a6b6a676740676d61696c2e636f6d", + "0x38666d6b" + ] + }, + { + "from_address": "0x759b49c2d615899e859a56d96658c751c4c874956d34e64bed50959e46dbd8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x72fc0406854fbd0afdd6eae70c4dba1fbbb233be0a53c309e91b47f819efbbf", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x759b49c2d615899e859a56d96658c751c4c874956d34e64bed50959e46dbd8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x771ae9417589", + "messages_sent": [], + "events": [ + { + "from_address": "0x1b22f7a9d18754c994ae0ee9adb4628d414232e3ebd748c386ac286f86c3066", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x45ddcd21a971f92a19ad69d0174380d77dac7d1875ecf9900a6a69d8ce54cd2", + "0x28a1df", + "0x0" + ] + }, + { + "from_address": "0x45ddcd21a971f92a19ad69d0174380d77dac7d1875ecf9900a6a69d8ce54cd2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2bad7ac836d42b825b965bc6de070818d3bfbcb418c765110814c9c87f877de", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x45ddcd21a971f92a19ad69d0174380d77dac7d1875ecf9900a6a69d8ce54cd2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x771ae9417589", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8414, + "builtin_instance_counter": { + "range_check_builtin_applications": 194, + "pedersen_builtin_applications": 31, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x4fa3f6d1a76e3d486bfed40225f9acb86e0aae855f15cfc004574b5ff8c9c2a", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7c5f6b2849238eb48a9e68b3f4f8f625e3150bc5b9028efd5b302cf11a576d0", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x602663e4ab3c5fe99772a3743c6e106e34fd8e3c7e035497dc813b1fa903c41", + "0x616e746f6e2e657468", + "0x61776572" + ] + }, + { + "from_address": "0x602663e4ab3c5fe99772a3743c6e106e34fd8e3c7e035497dc813b1fa903c41", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x77407bd5d5793822b8f7b65920a0025207ff96a2072f3adf73a7ceaf10646a4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x602663e4ab3c5fe99772a3743c6e106e34fd8e3c7e035497dc813b1fa903c41", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3e871b540c000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x3e871b540c000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x1c810f", + "0x0" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xce0d0de4e59bf01a3", + "0x5e36a05afa" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3e871b540c000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1c810f", + "0x0", + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e" + ] + }, + { + "from_address": "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1793ff61b6953314697d6b33a3aabfb4bbec17765f34c9d23fcf0d7e7150065", + "0x6", + "0x1", + "0x2", + "0x3e871b540c000", + "0x0", + "0x1c810f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x51cc29fea4456dd4dbf6ef3aa15f9da6ae5fc9212dd2d5a4fbd4b4322eff76e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26605, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc7bb7b186a32", + "messages_sent": [], + "events": [ + { + "from_address": "0x42b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1386fc391dc4142", + "0x0" + ] + }, + { + "from_address": "0x42b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1386fc391dc4142", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "0x1600f5d8cb2bfbd", + "0x0" + ] + }, + { + "from_address": "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7c0132dea5e0085732abc81652ddfd6c08c36a681ad5ffdbfad69b917042548", + "0x3", + "0x1", + "0x1600f5d8cb2bfbd", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x62205d5f0520f0de655d0f3027a56126485c31aac3cd7b3658d1399f7cd30f0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc7bb7b186a32", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21725, + "builtin_instance_counter": { + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x1d908314dbee35855975b4a6a93f335431e332e2e5809ce2105fcba4cff0196", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x4209483", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x4209483", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "0x8f2347a73618da", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e39c2397c74ad720", + "0x0", + "0x37254622fa9", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x4209483", + "0x0", + "0x8f2347a73618da", + "0x0", + "0x0", + "0x0", + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2" + ] + }, + { + "from_address": "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x20e1a45b53101ecdbfc3560b8ab734d38c5df517c0dba141f3d55e7108685c6", + "0x6", + "0x1", + "0x2", + "0x4209483", + "0x0", + "0x8f2347a73618da", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1115936b665fce94b2a2b0e1edab3f12eb5dd3ae6176807d27ce55bc10a7e2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33333, + "builtin_instance_counter": { + "range_check_builtin_applications": 1111, + "pedersen_builtin_applications": 38, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x24e0f9bffcc162a8efc4029a43dfa80a7790701e7deac6641382a7a863d364f", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x24e0f9bffcc162a8efc4029a43dfa80a7790701e7deac6641382a7a863d364f", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x1e4bfc92f150ba176b6b7a0cd926eee6915c79f16fd63218a729ee9955fdf51" + ] + }, + { + "from_address": "0x24e0f9bffcc162a8efc4029a43dfa80a7790701e7deac6641382a7a863d364f", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x24e0f9bffcc162a8efc4029a43dfa80a7790701e7deac6641382a7a863d364f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x24e0f9bffcc162a8efc4029a43dfa80a7790701e7deac6641382a7a863d364f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "range_check_builtin_applications": 145, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 34 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xe90d5e35e407b", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xe90d5e35e407b", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "0x6ad3c4", + "0x0" + ] + }, + { + "from_address": "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x44f406d9ada7d0b08f0c129a2626280ca3b0ab6f71dd32e1cb0b6af26f0f110", + "0x3", + "0x1", + "0x6ad3c4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x53e1c546f9c16028677ddcbe97e9db49ca79c5bd774c18db581181b44e29050", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21796, + "builtin_instance_counter": { + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x7c9695b66557", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x35bd041f99860ff57adfc16b848c6b8e27471acb669e969a60ae17c281df8a" + ], + "data": [ + "0x5eb8d32af23e4d5011c46cf704e27e8762b5cfe62586e9fd565c7cbed9bcedf", + "0x7300100008000000000000000000000000", + "0x377d9", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5eb8d32af23e4d5011c46cf704e27e8762b5cfe62586e9fd565c7cbed9bcedf", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x5eb8d32af23e4d5011c46cf704e27e8762b5cfe62586e9fd565c7cbed9bcedf", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x142daf638d33d649341f1d1685073fd59d1339879bb2a009de92e2e981b6ab6", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5eb8d32af23e4d5011c46cf704e27e8762b5cfe62586e9fd565c7cbed9bcedf", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x7c9695b66557", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42617, + "builtin_instance_counter": { + "pedersen_builtin_applications": 25, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1327 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2f9b3a9ffd800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2f9b3a9ffd800", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x15d377", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d1a8207b1961d5f", + "0x1b53b7dcef3" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2f9b3a9ffd800", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x15d377", + "0x0", + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f" + ] + }, + { + "from_address": "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x67289d9154acb02b7567961b9d732d85b36954578580dd4c8b1b3f5de6cfccf", + "0x6", + "0x1", + "0x2", + "0x2f9b3a9ffd800", + "0x0", + "0x15d377", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1fd3db9095af8cb30c0ec5d1371a758bef79630f063c4b53402d48d9bdce94f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26608, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdb7bfd4d6142", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x297123b98c2209d5b3143e3fe5b185564607ef4e81b0ef01e3d199283a6138c", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b68aa9", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x297123b98c2209d5b3143e3fe5b185564607ef4e81b0ef01e3d199283a6138c", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b68aa9", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x297123b98c2209d5b3143e3fe5b185564607ef4e81b0ef01e3d199283a6138c", + "0x18f58ac286c60a167", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x297123b98c2209d5b3143e3fe5b185564607ef4e81b0ef01e3d199283a6138c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdb7bfd4d6142", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22536, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 558, + "pedersen_builtin_applications": 39 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x369323f83547d95dc2d8371186aaaab45ebc3e327da5c868f74046d61f3152e", + "0x6d6172696e6b6f6976616e63696340676d61696c2e636f6d", + "0x6976616e6b6f6f" + ] + }, + { + "from_address": "0x369323f83547d95dc2d8371186aaaab45ebc3e327da5c868f74046d61f3152e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x48abbf51c740881c5e14f833956aee4ba440721dbf9f6ddf5263a292d0d4672", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x369323f83547d95dc2d8371186aaaab45ebc3e327da5c868f74046d61f3152e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x9fbf5596c0dc", + "messages_sent": [], + "events": [ + { + "from_address": "0x3448896d4a0df143f98c9eeccc7e279bf3c2008bda2ad2759f5b20ed263585f", + "keys": [ + "0x1b6d26c8b545f51ff2731ca42b81aa226221630abc95fd9d1bcacbe75bce7a1" + ], + "data": [ + "0x1", + "0x2ea5a51e9e9", + "0x6828b4976826c0fac35101ffa6cb5a0de79034546e7fbc12194af6e1ba168de" + ] + }, + { + "from_address": "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "keys": [ + "0x25d4f50ffa759476dcb003b1c94b6b1976321ccceae5f223696598ed626e9d3" + ], + "data": [ + "0x6828b4976826c0fac35101ffa6cb5a0de79034546e7fbc12194af6e1ba168de", + "0x2", + "0x2ea5a51e9e9", + "0xce31cfe97" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6828b4976826c0fac35101ffa6cb5a0de79034546e7fbc12194af6e1ba168de", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x9fbf5596c0dc", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 17144, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 32, + "range_check_builtin_applications": 636 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0xd2010f814898522fd4e492a29353bcbdcb3d2002fca699d09e894216aa0233", + "0x536f6d6f47313140676f6f676c652e636f6d", + "0x426f626f" + ] + }, + { + "from_address": "0xd2010f814898522fd4e492a29353bcbdcb3d2002fca699d09e894216aa0233", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7a5b3376cb397289168518264ff1cc80b78b58a856c3de5b7b1878078b603f3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xd2010f814898522fd4e492a29353bcbdcb3d2002fca699d09e894216aa0233", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x1bb2312832bdb4152faa026f7e874c5b1fee859b8e257b51dde36f11c4dc54c", + "0x1a0e5717ed", + "0x0" + ] + }, + { + "from_address": "0x1bb2312832bdb4152faa026f7e874c5b1fee859b8e257b51dde36f11c4dc54c", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1d74c4dcebccec472cfc88fb9dba8403864028df653d977603c119da3af554d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1bb2312832bdb4152faa026f7e874c5b1fee859b8e257b51dde36f11c4dc54c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7834, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 22 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x7ec5e5dc6bfdbcb210c844135c0b3714704cf753aa844d047b934ccc8dba32c", + "0x3e2d18145a7c00", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x50d645890807550d46aa7bf1383e2220c5b572a17bea7f718455e914337fdfa", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3ac6ae2b2a000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3ac6ae2b2a000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "0x1af11e", + "0x0" + ] + }, + { + "from_address": "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1c17b8bff58e3edc0515aeb0f69f89e12f4ed0daab1eea1de83688af4254fed", + "0x3", + "0x1", + "0x1af11e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5038c7b567129d28b8e9444673552e484f561a5d9fd1e6adf2caad81b35a195", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21791, + "builtin_instance_counter": { + "range_check_builtin_applications": 555, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 37 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdd47ac0c6072", + "messages_sent": [], + "events": [ + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x98a7d9b8314c0000", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0x98a7d9b8314c0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x265cd7a8c02b5", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x25655b53d70632be3a4b", + "0x0", + "0x96ce4596a0f989da", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x98a7d9b8314c0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x265cd7a8c02b5", + "0x0", + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02" + ] + }, + { + "from_address": "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x718afe487091f9be9ff706e2d7253c3119e9ae3bb1f72995b3e6a79c77ffcb", + "0x6", + "0x1", + "0x2", + "0x98a7d9b8314c0000", + "0x0", + "0x265cd7a8c02b5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f72104394190331e01372c84586be27436a017ae2eed4894fa50611bad6c02", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdd47ac0c6072", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33795, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1236, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb438896f50bd", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "0x0", + "0x2f40a406ff07c5", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bca2c00f896f6f528be4", + "0xd4c2a599fd16ed5e417d1" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x2f40a406ff07c5" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "0x2f40a406ff07c5", + "0x0" + ] + }, + { + "from_address": "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4c9ac9b9afb1e0503a905a9a65cba3d62213b41131ec47bf7f0649590accc0c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1da3cac88046ec470ed15bc044335edd45ecd42d3f34ad58fe174b36b849b08", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb438896f50bd", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22444, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 952, + "pedersen_builtin_applications": 40 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x68f8f56935665f27e0b4c2e0395c5ac8d23a2fa3d5f463e8c640b69dc057f2c", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x68f8f56935665f27e0b4c2e0395c5ac8d23a2fa3d5f463e8c640b69dc057f2c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 160 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2165d10e2979ff2132020805fa6b280edc08445453df92d4087a22f1ae7c582", + "0x299ef09ea5", + "0x0" + ] + }, + { + "from_address": "0x2165d10e2979ff2132020805fa6b280edc08445453df92d4087a22f1ae7c582", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3e6c28909b15eac6936103faec222cd56853665cf77ee04491b57690a4fcb41", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2165d10e2979ff2132020805fa6b280edc08445453df92d4087a22f1ae7c582", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7836, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x250ea9b47026822b806e241415f4857fa2f9b8d2380053d8b49ae13d2345555", + "0x9a9d359ca0000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4312ce58486aff4662c077162d9d2b49eef59ffeee9fcd4830eb13f72d5ce5d", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x258ecc7ad5d3829b68fc19d6d07be845ada70278ace7ea508a1f4d3da74a4cf", + "0x616c756d696e69756d333440646d61696c2e6169", + "0x33" + ] + }, + { + "from_address": "0x258ecc7ad5d3829b68fc19d6d07be845ada70278ace7ea508a1f4d3da74a4cf", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7af377f1cb3cc660c11de9492e53a98e5ab50332306401fb9f65f8d1d27b0c9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x258ecc7ad5d3829b68fc19d6d07be845ada70278ace7ea508a1f4d3da74a4cf", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x6040f0aaf63b208c8d15a1b4e2b8dcfd352c0f428ff9df48e9b29ea972ed106", + "0x6e7369736261726440646d61696c2e6169", + "0x7574612d686167656e" + ] + }, + { + "from_address": "0x6040f0aaf63b208c8d15a1b4e2b8dcfd352c0f428ff9df48e9b29ea972ed106", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x235111494afa08c67f96c361ed47d9ab6fa50c176647275d3ef99815a90d568", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6040f0aaf63b208c8d15a1b4e2b8dcfd352c0f428ff9df48e9b29ea972ed106", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x26dbcfd8f0086fd4d380e4a9ecae4312194756b3c013067e2c0941ef293625", + "0xc67ef1383", + "0x0" + ] + }, + { + "from_address": "0x26dbcfd8f0086fd4d380e4a9ecae4312194756b3c013067e2c0941ef293625", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7b8a0642ba120d69aacc0af08ccd1c496b84ddacf961a18db819a06eb81ea73", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26dbcfd8f0086fd4d380e4a9ecae4312194756b3c013067e2c0941ef293625", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7836, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb6001d7a5238", + "messages_sent": [], + "events": [ + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xf9ccd8a1c5080000", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0xf9ccd8a1c5080000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x3ec3d5e837999", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x25665520afa7f7c63a4b", + "0x0", + "0x96ca595942761041", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xf9ccd8a1c5080000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x3ec3d5e837999", + "0x0", + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2352f9b95ee016a52da5552db3b365b62306f43a3deccb477df79cbd014d11c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb6001d7a5238", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33564, + "builtin_instance_counter": { + "pedersen_builtin_applications": 40, + "range_check_builtin_applications": 1091, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0xf38be9d7cd33de7862c9b2c383758a10575cd7c40b299ea6b5fe750323e180", + "0x9f46776a92000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x44d8f03aff37860e028674d9a0a4d153f7bdc4ea6cf3dc6a72719b428765727", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5c5496ebeade2e5738f5f697ead154be2ffd5c4d8cfad8573fb89a59e8b7dfa", + "0x30786a65386c6f347135347779627a376775776d746f37326474667868616b6", + "0x6f6c3273716276333535" + ] + }, + { + "from_address": "0x5c5496ebeade2e5738f5f697ead154be2ffd5c4d8cfad8573fb89a59e8b7dfa", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6f5b1e9eebc09fbd2b4647d5fa57323092157b3deea42e85763d2ae395a8b95", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5c5496ebeade2e5738f5f697ead154be2ffd5c4d8cfad8573fb89a59e8b7dfa", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5c28cee749d", + "messages_sent": [], + "events": [ + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1314fb37062980000", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0x1314fb37062980000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x4cb2069e51238", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x2567867063185a5e3a4b", + "0x0", + "0x96c58e38d890fe09", + "0x0" + ] + }, + { + "from_address": "0x2b3030c04e9c920bd66c6a8dc209717bbefa1ea5f8bc8ebabd639e5a4766502", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1314fb37062980000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x4cb2069e51238", + "0x0", + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6" + ] + }, + { + "from_address": "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x72df12613184d9eee1ca24394a735d6adf0bf79ba8cb992cd0a01c578216f94", + "0x6", + "0x1", + "0x2", + "0x1314fb37062980000", + "0x0", + "0x4cb2069e51238", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x29e1ece04dd17382de468263d4aa140cbce0983386e1285bd502f51b6bd6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5c28cee749d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 32025, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1074, + "pedersen_builtin_applications": 38 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb781eb917aae", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x5e96630e8000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x5e96630e8000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x5e96630e8000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x5e96630e8000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x2b5d8", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6d1ae09e14a49d5f", + "0x1b53b7b191b" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x5e96630e8000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x2b5d8", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x2b5d8", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x5e96630e8000", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x2b5d8", + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311" + ] + }, + { + "from_address": "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6602344d8f1fd49dd7273b7981f6a8549afbf09b66bab410d61cef28356fddb", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4b0ae421e8e0a74b91a10fc351fa1b81cd4a84475fbc4e5b3e06a77ba2fc311", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb781eb917aae", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 42996, + "builtin_instance_counter": { + "pedersen_builtin_applications": 73, + "range_check_builtin_applications": 1428, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 7 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x7c654577b5828a404afa6a6e32f86d241fa744e6844369b7a2ce7d651d88ee8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1811b16e99155dd9fc25fab52bed2f94b5332fdbd8c648d710aaf32f8d505f6", + "0x488333d12549b5accf4f71e6bba15b2d432edcd002252ddc4ef60393caa4f67", + "0x2386f26fc10000", + "0x0" + ] + }, + { + "from_address": "0x1811b16e99155dd9fc25fab52bed2f94b5332fdbd8c648d710aaf32f8d505f6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x26f475d2f9cc4e9cf152aa2c5117f22d66325cbdba440b681bd9fbc1f9c5e6f", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1811b16e99155dd9fc25fab52bed2f94b5332fdbd8c648d710aaf32f8d505f6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xbe251aa5c564", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bcb9cba068dc27b4d697", + "0xd4c82903f13f1274dff53" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x115d39728cb7b9da37428334eacf88e8037f4fd1d76910ad75e906090a72be4", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x84788eee7c173b", + "0x84faf3a5b3ed37" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x115d39728cb7b9da37428334eacf88e8037f4fd1d76910ad75e906090a72be4", + "0x84faf3a5b3ed37", + "0x0" + ] + }, + { + "from_address": "0x115d39728cb7b9da37428334eacf88e8037f4fd1d76910ad75e906090a72be4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x55ce24427479da5491dd16471840670d4036f6b701e8554577d6ee920f2000a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x115d39728cb7b9da37428334eacf88e8037f4fd1d76910ad75e906090a72be4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbe251aa5c564", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 84345, + "builtin_instance_counter": { + "bitwise_builtin_applications": 115, + "pedersen_builtin_applications": 197, + "range_check_builtin_applications": 3468, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x772b54116c5d", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1357a25dd919bc0e6618f52b42c7270428780d298c91c1f9e0fa553d9d260e0", + "0x0", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0xd9af7cc4b444c201a3490be850f7e8cf76298eff75ae990d0fe66f5b1c1fb9" + ], + "data": [ + "0x1357a25dd919bc0e6618f52b42c7270428780d298c91c1f9e0fa553d9d260e0", + "0x377d9", + "0xa8", + "0x1000000000000000000000000000000000000000000" + ] + }, + { + "from_address": "0x1357a25dd919bc0e6618f52b42c7270428780d298c91c1f9e0fa553d9d260e0", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x66972c166f59deb2ed80a63c0f575f2ac3a8ce37e3ba6ea7830d85f87a7e5d4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1357a25dd919bc0e6618f52b42c7270428780d298c91c1f9e0fa553d9d260e0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x772b54116c5d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8866, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 1, + "range_check_builtin_applications": 212, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x129a91aa5dc800", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x129a91aa5dc800", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "0x88811f", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e3aebe2971a89f20", + "0x0", + "0x37253d9ae8a", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x129a91aa5dc800", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x88811f", + "0x0", + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324" + ] + }, + { + "from_address": "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4dc320e1c039986787ea90010babeab9fa7f76345154374e787b1fd076ac1cf", + "0x6", + "0x1", + "0x2", + "0x129a91aa5dc800", + "0x0", + "0x88811f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x9b62eb5ce7c13a44bffe61f2e5f7d021e15640ff4d25cc7691cf05b1c7d324", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33371, + "builtin_instance_counter": { + "range_check_builtin_applications": 1111, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 38 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x104bc605a5573", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xe949c6", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "0x5801bdad32f343035fb242e98d1e9371ae85bc1543962fedea16c59b35bd19b", + "0xe949c6", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5801bdad32f343035fb242e98d1e9371ae85bc1543962fedea16c59b35bd19b", + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "0xe81b3a", + "0x0" + ] + }, + { + "from_address": "0x5801bdad32f343035fb242e98d1e9371ae85bc1543962fedea16c59b35bd19b", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x97828772d0", + "0x0", + "0x97313fb327", + "0x0" + ] + }, + { + "from_address": "0x5801bdad32f343035fb242e98d1e9371ae85bc1543962fedea16c59b35bd19b", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xe949c6", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0xe81b3a", + "0x0", + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af" + ] + }, + { + "from_address": "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x196b8861fc7caaad050253c12e1360413dc792e69328bbd08622bf39ede8474", + "0x6", + "0x1", + "0x2", + "0xe949c6", + "0x0", + "0xe81b3a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7822bf219f0acd495f7cc35427fe022c6e264b41bf7bae553acf676f1696af", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x104bc605a5573", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 35046, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1273, + "pedersen_builtin_applications": 38 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x3e52730153a4bb29440073b6d02e7e715ed9fc97708548a43fa27a1934649cc", + "0x46c7dce9dc3000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x20df3d38f55e74a82e2a6eb86c6413fe8ae6c50c1a18f71ee0cb553fe4c0ae", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb47619fb2e58", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x408dd2f24a40506e9495c5ac6ae459d1583371ef01735180bb2410596c0ef0b", + "0x0", + "0x494654257ef7f69", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bcd457751f58fa976f79", + "0xd4ce82acc95ae5f32e02f" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x408dd2f24a40506e9495c5ac6ae459d1583371ef01735180bb2410596c0ef0b", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x494654257ef7f69" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x408dd2f24a40506e9495c5ac6ae459d1583371ef01735180bb2410596c0ef0b", + "0x494654257ef7f69", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x408dd2f24a40506e9495c5ac6ae459d1583371ef01735180bb2410596c0ef0b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb47619fb2e58", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23922, + "builtin_instance_counter": { + "range_check_builtin_applications": 965, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 42, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x4953f87c2a000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x4953f87c2a000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x21a0a0", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e3b35368f96b3f20", + "0x0", + "0x37253b80dea", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x4953f87c2a000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x21a0a0", + "0x0", + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855" + ] + }, + { + "from_address": "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x754c034fba112691f7f3bbc87b6ee7a5565419c32e5b8953af94323ccd6ff0c", + "0x6", + "0x1", + "0x2", + "0x4953f87c2a000", + "0x0", + "0x21a0a0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5d5921bb0148e1b4447cc7148730eb949543618fe0e34ad4af8322d431c9855", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33371, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1111, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xbb00a8d786d0", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bdc5e22f00e110f7c0ce", + "0xd50841b9a49cb6e0c1c15" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xfa3f9acdb7b24dcf6d40d77ff2f87a87bca64a830a2169aebc9173db23ff41" + ], + "data": [ + "0x59bbf16c2cc69965ed4f9978525251162cbaf8456f5c8ca1893984b5a575060", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x56b545bfa27831a", + "0x570a9ee80d6a4b8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x59bbf16c2cc69965ed4f9978525251162cbaf8456f5c8ca1893984b5a575060", + "0x570a9ee80d6a4b8", + "0x0" + ] + }, + { + "from_address": "0x59bbf16c2cc69965ed4f9978525251162cbaf8456f5c8ca1893984b5a575060", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x130b3a417200414e7a4618fd3e282796775cea0e2afa90e24ef969387979b5e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x59bbf16c2cc69965ed4f9978525251162cbaf8456f5c8ca1893984b5a575060", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbb00a8d786d0", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 64752, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 157, + "range_check_builtin_applications": 2679, + "bitwise_builtin_applications": 85 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4c4155702c7", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x19aef827bdae4d7a", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x19aef827bdae4d7a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "0x3cfe31e0540b8", + "0x0" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1fae13a685dc120bf14a", + "0x4b7578df19f1b5d17" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x19aef827bdae4d7a", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x3cfe31e0540b8", + "0x0", + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x713843335c582f27be61ccb9a002b9163ad5a68de91223344b42f4ac8f03a1b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4c4155702c7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25854, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 933, + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 58 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x788831d4a976", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x20f89774cfcdf23b903823b7bdefa06d57fd44c8e870c8510ee5757b2360a8a", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x20f89774cfcdf23b903823b7bdefa06d57fd44c8e870c8510ee5757b2360a8a", + "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "0x1ff973cafa7f83", + "0x0" + ] + }, + { + "from_address": "0x6ac597f8116f886fa1c97a23fa4e08299975ecaf6b598873ca6792b9bbfb678", + "keys": [ + "0x440fc089956d79d058ea92abe99c718a6b1441e3aaec132cc38a01e9b895cb" + ], + "data": [ + "0x1", + "0x6eadeb", + "0x2cf06fd163", + "0x66d1bad0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x20f89774cfcdf23b903823b7bdefa06d57fd44c8e870c8510ee5757b2360a8a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x788831d4a976", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 17373, + "builtin_instance_counter": { + "range_check_builtin_applications": 530, + "pedersen_builtin_applications": 32, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "0x5c2bf52fefd9dc5d04bf631047b1e74502268193d7591c813f8725be8fbaf7e", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5286f50d8b489884631332ffaec5d017506cf9ddcb656172ed7dc19390febe8", + "0x444647444647444640474d41494c2e434f4d", + "0x44464744464744" + ] + }, + { + "from_address": "0x5286f50d8b489884631332ffaec5d017506cf9ddcb656172ed7dc19390febe8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1a6182203b08d780f05ddb6d22d2512c01bbc889fa0c6d215748ba15d0a1e7c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5286f50d8b489884631332ffaec5d017506cf9ddcb656172ed7dc19390febe8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5883a787cf0634c9b79b2c2c3cf4d521b99f02870ccd9172741f48a5e48e6f3", + "0xb841d4ced2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5883a787cf0634c9b79b2c2c3cf4d521b99f02870ccd9172741f48a5e48e6f3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9340, + "builtin_instance_counter": { + "pedersen_builtin_applications": 24, + "range_check_builtin_applications": 200, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "0x76696b61647340676d61696c2e636f6d", + "0x74657374" + ] + }, + { + "from_address": "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xc1a13b029107c71f49e5927a21cefa15ad6d66d1fe4d41b88e9992193b673d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x771b0c230108a21949d04af888918069457e6340559d41a78c9e6dff13fa75f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x47c2b54e54ea63add8aea75cc7e92801b4cf61aef3db10b726a290df943dd9f", + "0xeb54edd5ec000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x265d45c104c3949b41f6575f05bf85829f8b3e5656ef1b99e6d6d181168de71", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x68042faa192fc35262472748a10d37d2d6590e8ccb162d507580b958c094783", + "0x7279736572406d61696c2e7275", + "0x455241" + ] + }, + { + "from_address": "0x68042faa192fc35262472748a10d37d2d6590e8ccb162d507580b958c094783", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4205958addf57e7a61cbc33c7012f7511e0dc9090ae148d2d133a0c5d5dae98", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x68042faa192fc35262472748a10d37d2d6590e8ccb162d507580b958c094783", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x10459df7a8c7b", + "messages_sent": [], + "events": [ + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xcc36564238", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0xcc36564238", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x98707809b39a3b14d9f5004bc1fe77721baa2d8b67fd54ed5794f60671de0", + "0xf6fec62", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x0", + "0xcc36564238", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x6c2d2063e95fec", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x31bea1c", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6caeb37db0bb3d73", + "0x1b5385f2eff" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0x243e1de00e8a6bc1dfa3e950e6ade24c52e4a25de4dee7fb5affe918ad1e744" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x6c2d2063e95fec", + "0x0", + "0x31bea1c", + "0x0", + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a" + ] + }, + { + "from_address": "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xb5a9a17193b18c09d3f23f175e87eff0ef5320ba0eef3f8ea1946d8e29e0e6", + "0x5", + "0x1", + "0x6c2d2063e95fec", + "0x0", + "0x31bea1c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2be41f001147ab2f2877a44c3603be399cbbf8cea9ddc6881836d55d0b004a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x10459df7a8c7b", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 32684, + "builtin_instance_counter": { + "pedersen_builtin_applications": 51, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1173 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1531207a69201", + "messages_sent": [], + "events": [ + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x4f1642c1964", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x4f1642c1964", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x0", + "0x4f1642c1964", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x1d1a7a52e8471ca", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0xd6ea48a", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xc1fcca6fe4efb478f", + "0x0", + "0x59881a4d78", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x243e1de00e8a6bc1dfa3e950e6ade24c52e4a25de4dee7fb5affe918ad1e744" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x1d1a7a52e8471ca", + "0x0", + "0xd6ea48a", + "0x0", + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491" + ] + }, + { + "from_address": "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x30c86a3042fafffdb8af395c66b1db6691a7e044138523678114273e4b6b3a9", + "0x5", + "0x1", + "0x1d1a7a52e8471ca", + "0x0", + "0xd6ea48a", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4ae541e9bd85bfe9ac37b486ae50e06e4268644231747fa4c1dba31a3e4a491", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1531207a69201", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 34030, + "builtin_instance_counter": { + "range_check_builtin_applications": 1027, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 68 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x821f46ed5c3c9eef8261d0bbedd89242137dbaeab743b8c63849152cac768c", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0x821f46ed5c3c9eef8261d0bbedd89242137dbaeab743b8c63849152cac768c", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x7cfbacb65c8e10e7d2b3c744c384ae75b9eae79e323aae8faa197ef78b801b3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x821f46ed5c3c9eef8261d0bbedd89242137dbaeab743b8c63849152cac768c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7300, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18, + "range_check_builtin_applications": 165 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e0d042f2ba", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2f4d60", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2f4d60", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "0x668e614aee1ed", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6ca84a979c0c5b86", + "0x1b5388e7c5f" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x2f4d60", + "0x0", + "0x668e614aee1ed", + "0x0", + "0x0", + "0x0", + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5" + ] + }, + { + "from_address": "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1659b34c61a3c08ffc9ff6c921bc7dea7917898bffbca876d0ca712896cda49", + "0x6", + "0x1", + "0x2", + "0x2f4d60", + "0x0", + "0x668e614aee1ed", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6ff77cc801aeafec08448d41e91eb7c702304c5c7a55fdfd05a5c1cf56a7cc5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e0d042f2ba", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26591, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973, + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4b77a83030930000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bc10b09605405c7937fb", + "0xd49fb0bacd723f22e6747" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x4b77a83030930000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4b77a83030930000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x4b77a83030930000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x47fa31bec4c9fc313ab0864c2d56d7dd229f10e3077f839ad4b305818080319", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7a352f16a51035f70012c558667087654abb22534a191c7ebd85fa4592c2a6b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26087, + "builtin_instance_counter": { + "range_check_builtin_applications": 1028, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 47, + "bitwise_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x115673b5174e4686b83b2646372673ee319c2c65c40dc057f64aa860d259ee8", + "0x323735343538374071712e636f6d", + "0x3532353234" + ] + }, + { + "from_address": "0x115673b5174e4686b83b2646372673ee319c2c65c40dc057f64aa860d259ee8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5ef39c192487a2bd9f0ff55439a64b705472552f72074a8ae38d66466238a3b", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x115673b5174e4686b83b2646372673ee319c2c65c40dc057f64aa860d259ee8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "0x746a777064756432353640676d61696c2e636f6d", + "0x637a" + ] + }, + { + "from_address": "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4bf71155873c7b5acdf0a6c33882ba1a1f04334c042dbdcce79554f56b10b06", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6ba4d9e4e35d9f5b846c1744f52d284aad76bc36c7a315492b89706ba72c7e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x4882c6524fde55402e75eeef5453bf519ff7fd4a341a2a0faf9563969809624", + "0x73647678637a656b7a6f7440676d61696c2e636f6d", + "0x66776574777a6b7a75" + ] + }, + { + "from_address": "0x4882c6524fde55402e75eeef5453bf519ff7fd4a341a2a0faf9563969809624", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4ba139181c4aed0bece1b9224299709d4ffb81fff8c2e0dae13e23b834d1754", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4882c6524fde55402e75eeef5453bf519ff7fd4a341a2a0faf9563969809624", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4faa4fa77e3d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0xa1f5b7b3aa23a9736d6542fc45bae02dc799c52c6d23834479640abe4e371a", + "0x44cf6f308cb181e0f0a6aeb3601802f45eda2714f3334aded57b3e9dbb1a20", + "0x1" + ] + }, + { + "from_address": "0xa1f5b7b3aa23a9736d6542fc45bae02dc799c52c6d23834479640abe4e371a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xa717e659581f6d62b308704871fdf6d190151a6aa6c7807832ede25e753bde", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xa1f5b7b3aa23a9736d6542fc45bae02dc799c52c6d23834479640abe4e371a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4faa4fa77e3d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7300, + "builtin_instance_counter": { + "range_check_builtin_applications": 165, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x86b26c77a1f781c4330c9b9e183ef9760569bcc47dbad0d1e3033d67991c1a", + "0x16bcc41e90000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x60a865ea177b8f1b97b9915c77bc9cc079ccdac8f2978c41adcd8ee654aaf52", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 183, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x22a8f1e01cedac06589ff1b28d5fa9318e27c096da38ef218300f29af7c26af", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x22a8f1e01cedac06589ff1b28d5fa9318e27c096da38ef218300f29af7c26af", + "0x4d95ecb0dc7e7e8514bcdf88ca2875ae5c733ab7f77296af138a0977a493b77", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x22a8f1e01cedac06589ff1b28d5fa9318e27c096da38ef218300f29af7c26af", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x22a8f1e01cedac06589ff1b28d5fa9318e27c096da38ef218300f29af7c26af", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f3e5cd852e285fb809e7c5c578ae0c11a190e028dddec20ccd9b55b0cce2b4", + "0x3cfa875b8f0e7cfecc1f1365072715fc9906b99c3d5773e44aa1d7c2129960c", + "0x5bbf95ffa7de96", + "0x0" + ] + }, + { + "from_address": "0x7f3e5cd852e285fb809e7c5c578ae0c11a190e028dddec20ccd9b55b0cce2b4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x474a7f49c98680a6fb1d9736301ba79a13ba8887e663c106d0337936048344c", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f3e5cd852e285fb809e7c5c578ae0c11a190e028dddec20ccd9b55b0cce2b4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xf18b84c10e22", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x22f2ba31d13f28", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x100d4a0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x22f2ba31d13f28", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "0x100b123", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x4a4f8cf4d8", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x164085570c2d022a71", + "0x0", + "0xa370946436", + "0x0" + ] + }, + { + "from_address": "0x45e7131d776dddc137e30bdd490b431c7144677e97bf9369f629ed8d3fb7dd6", + "keys": [ + "0x34e55c1cd55f1338241b50d352f0e91c7e4ffad0e4271d64eb347589ebdfd16" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x22f2ba31d13f28", + "0x0", + "0x100b123", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x709fc6bd524d2cb200344f2c3bdd60591aa0eaefdb5201646206f64cd8baecf", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xf18b84c10e22", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 37726, + "builtin_instance_counter": { + "pedersen_builtin_applications": 48, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1051 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x32c5ff8509fe00915a9644a91d05163af52c50b7cd3e25afd12f3d09d2e1b84", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x7f5391bd307c4321af2829873226612f7aeb0afaabb4256972743fc98d5b32d", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x7f5391bd307c4321af2829873226612f7aeb0afaabb4256972743fc98d5b32d", + "0x43aa3da22af08f85335b7f1319354179cdaf930867d8e8d038bcce705a5cfb7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f5391bd307c4321af2829873226612f7aeb0afaabb4256972743fc98d5b32d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x7f5391bd307c4321af2829873226612f7aeb0afaabb4256972743fc98d5b32d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 123, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb47619fb2e58", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x77c76432a1480a2692926f8fb045fb3e7b50dcc0f5909e08f2c1151fad60338", + "0x0", + "0x82f0300a91ca2db", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bc3ffa2d053d1558136e", + "0xd4ab02947131319c70b13" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x77c76432a1480a2692926f8fb045fb3e7b50dcc0f5909e08f2c1151fad60338", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x82f0300a91ca2db" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x77c76432a1480a2692926f8fb045fb3e7b50dcc0f5909e08f2c1151fad60338", + "0x82f0300a91ca2db", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x77c76432a1480a2692926f8fb045fb3e7b50dcc0f5909e08f2c1151fad60338", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb47619fb2e58", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23920, + "builtin_instance_counter": { + "range_check_builtin_applications": 965, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 42 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x3317ff1621068fec9a668441e8a0500940d971889cb0a0aed6223112da856ad", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x3317ff1621068fec9a668441e8a0500940d971889cb0a0aed6223112da856ad", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3be02e91932a2a1755f68ca57650468bc304226adad5b1386783217d93c1c77", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3317ff1621068fec9a668441e8a0500940d971889cb0a0aed6223112da856ad", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x119f66edec9b3a3f6230655c562777b942476bb756e864ee31c6b7842218d5a", + "0x1ebb21114ea000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2f4ba94af1e252f074e667fd796c9c96afc947c81dbaa082a59f4714e50e4b", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc86bf7540799", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4380663abb8000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bc3e7403adef01d70cc8", + "0xd4aaa53122e41867dc9c9" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x4380663abb8000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x4380663abb8000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x4380663abb8000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0xb047d825ccef5a103ac6bc226ff6369a0a28d24d0c5a59d613319d848f1bed", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7765f61e685cd0ce14477d4feeef00bcbb8147410308d240a876d4ba041a45", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc86bf7540799", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26085, + "builtin_instance_counter": { + "pedersen_builtin_applications": 47, + "range_check_builtin_applications": 1028, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xe438d67c7f97", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7621226", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7621226", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x7621226", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x7621226", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0xff7be2df374f46", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "0xc087ff1f956081ebeed0085a169b8b356cbb7990b64680a44f930ec401cbcd", + "0x2d5c9", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x0", + "0x0", + "0x2d5c9", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xc1ecd2b1b6fc3f849", + "0x0", + "0x598f7989d5", + "0x0" + ] + }, + { + "from_address": "0x30615bec9c1506bfac97d9dbd3c546307987d467a7f95d5533c2e861eb81f3f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x0", + "0x0", + "0x7621226", + "0x0", + "0xff7be2df374f46", + "0x0", + "0x0", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0xff7be2df374f46", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x7621226", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xff7be2df374f46", + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26d1ad56041051a9ff4b3f0a5d3859431e0ab0fc3fffab52beeab2bddb98dd8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xe438d67c7f97", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 77009, + "builtin_instance_counter": { + "pedersen_builtin_applications": 96, + "bitwise_builtin_applications": 4, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 3991 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x71afd498d0000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x341f36", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6caf6594e5995b86", + "0x1b5385a5d29" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x71afd498d0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x341f36", + "0x0", + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d" + ] + }, + { + "from_address": "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1766c93bff704d62161c1a15f5543da37edef9773c89efd45a23228cc342fb5", + "0x6", + "0x1", + "0x2", + "0x71afd498d0000", + "0x0", + "0x341f36", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6e5b64010b90c0d6bb9529a2308c57c763cbf0ed60b385ce4ab660f196bdc0d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26608, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x67a5da34b2825", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x67a5da34b2825", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "0x2f3fac", + "0x0" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0xce0d758abfd0a29c8", + "0x5e36711b4e" + ] + }, + { + "from_address": "0x5900cfa2b50d53b097cb305d54e249e31f24f881885aae5639b0cd6af4ed298", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x67a5da34b2825", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x2f3fac", + "0x0", + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5" + ] + }, + { + "from_address": "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x618878742e8199322ebc4aa4fbde053a87d7d30735db847c91e79689a4fe71e", + "0x6", + "0x1", + "0x2", + "0x67a5da34b2825", + "0x0", + "0x2f3fac", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x40ea09ec86f956de55267aa3a341981bbeba74323dce86f36c6f5265076cef5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26609, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x737d1bafd474f303837e1f03f06a867857402383f7baa5c7c2cc0e503e1d221", + "0x61706874686f6e677332303232403136332e636f6d", + "0x706874686f6e677332303232403136332e636f6d" + ] + }, + { + "from_address": "0x737d1bafd474f303837e1f03f06a867857402383f7baa5c7c2cc0e503e1d221", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x721d2a176b86f13e05836c1fabfeb6498a85401897e4bb8adf2c35cd88037ae", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x737d1bafd474f303837e1f03f06a867857402383f7baa5c7c2cc0e503e1d221", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb45d79c33c1a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x197e968ee95240c770622b28f081949d0682012701b7a8ac2991b63691d21b8", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b48eb57e00000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x197e968ee95240c770622b28f081949d0682012701b7a8ac2991b63691d21b8", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1b48eb57e00000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x197e968ee95240c770622b28f081949d0682012701b7a8ac2991b63691d21b8", + "0xc7035f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x197e968ee95240c770622b28f081949d0682012701b7a8ac2991b63691d21b8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb45d79c33c1a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23339, + "builtin_instance_counter": { + "pedersen_builtin_applications": 39, + "range_check_builtin_applications": 572, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63a02d00577e", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "0xe0c15664b7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x30200a69f24947901e3811327102808d83e412047be771b64d4cb52329939b8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63a02d00577e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9340, + "builtin_instance_counter": { + "range_check_builtin_applications": 200, + "pedersen_builtin_applications": 24, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb45d79c33c1a", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6b33feb724b953721e43c3bdc8add7c018ae1de52eb558ae328e6fff137769f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1aa535d3d0c0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b33feb724b953721e43c3bdc8add7c018ae1de52eb558ae328e6fff137769f", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1aa535d3d0c0000", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x6b33feb724b953721e43c3bdc8add7c018ae1de52eb558ae328e6fff137769f", + "0xc244c28", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b33feb724b953721e43c3bdc8add7c018ae1de52eb558ae328e6fff137769f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb45d79c33c1a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 23339, + "builtin_instance_counter": { + "range_check_builtin_applications": 572, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 39 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x50270f69c87691e5d6274ca5dd626a5b8231a92b1a8beca200c4b08217ecbf0", + "0x1e8da789118000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x32a7fda1d7e408749af42de287d4b2a1c841968912d25a15d477fc4b1b66b6d", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8067, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e0d042f2ba", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x2dc6c0", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x2dc6c0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "0x633f7987983a4", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6ca9319d4d1fd7e2", + "0x1b5388823e9" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x2dc6c0", + "0x0", + "0x633f7987983a4", + "0x0", + "0x0", + "0x0", + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f" + ] + }, + { + "from_address": "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2f38659a393c2bb22ed25f0c75639ae745cb1d52715772eda95992ec39e358a", + "0x6", + "0x1", + "0x2", + "0x2dc6c0", + "0x0", + "0x633f7987983a4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6090071a8c072b35b8b36b8b3e30ccd7388415f1633fec2841a04211684943f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e0d042f2ba", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26590, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4a75a6b12d4", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x3d1b4f12230000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x3d1b4f12230000", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "0x19928e335fd7f4ecb", + "0x0" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1fac7a7da2a6148ca27f", + "0x4b794a940b13e5d17" + ] + }, + { + "from_address": "0x17e9e62c04b50800d7c59454754fe31a2193c9c3c6c92c093f2ab0faadf8c87", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0x3d1b4f12230000", + "0x0", + "0x19928e335fd7f4ecb", + "0x0", + "0x0", + "0x0", + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03" + ] + }, + { + "from_address": "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6e3f831f55331e7b090a8d78f40fe0544b80ddcfc899660f9da9db0b62dcd7f", + "0x6", + "0x1", + "0x2", + "0x3d1b4f12230000", + "0x0", + "0x19928e335fd7f4ecb", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x770e8ac7ab87088fee6d8d116f4ee37f976287c62b2e95ed3a9da39a24c9b03", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4a75a6b12d4", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25123, + "builtin_instance_counter": { + "range_check_builtin_applications": 935, + "pedersen_builtin_applications": 56, + "bitwise_builtin_applications": 3, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5227b82ce0a", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xe02745", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0xe02745", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "0x1e5fbc1a17edcb", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6c8ad1e13307ea17", + "0x1b539684b2e" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x0", + "0x0", + "0xe02745", + "0x0", + "0x1e5fbc1a17edcb", + "0x0", + "0x0", + "0x0", + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7994040a8c37142a6d1ceab826d5f4b6778983d4393c62125511ee88aa850c0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5227b82ce0a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 28129, + "builtin_instance_counter": { + "pedersen_builtin_applications": 58, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 990, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x10717b5b50462", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1c80e", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1c80e", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1c80e", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7f409bd2e266e00486566dd3cb72bacc6996f49c0b19f04c0a8b5bd7bf991d1", + "0x1c80e", + "0x0" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7f409bd2e266e00486566dd3cb72bacc6996f49c0b19f04c0a8b5bd7bf991d1", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0xf30a6d66c5e18cb", + "0x0" + ] + }, + { + "from_address": "0x7f409bd2e266e00486566dd3cb72bacc6996f49c0b19f04c0a8b5bd7bf991d1", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x19daef1251434275863", + "0x0", + "0x3060a4ed", + "0x0" + ] + }, + { + "from_address": "0x7f409bd2e266e00486566dd3cb72bacc6996f49c0b19f04c0a8b5bd7bf991d1", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x1c80e", + "0x0", + "0xf30a6d66c5e18cb", + "0x0", + "0x0", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0xf30a6d66c5e18cb", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1c80e", + "0x124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", + "0xf30a6d66c5e18cb", + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7b83e7eaeed8c942e0282311f4b5417c66b29cc8ccd021c32d644f46e33aa66", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x10717b5b50462", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 49795, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 1681, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 4 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb47e4f6329c2", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1a5878bde99a0000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bba65439db1d3c6b5c98", + "0xd4863891f05f9b40a9b97" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1a5878bde99a0000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x1a5878bde99a0000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "0x1a5878bde99a0000", + "0x0" + ] + }, + { + "from_address": "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2deb5b70f9d822dd2718ea5c1ce49fd6ae1f9f71a90624bde798b3853f86daf", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2cdbc8d7af70fcea73a9e4fac2e28b1babbff8a55738eb8a156ab68a0d621de", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb47e4f6329c2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 24142, + "builtin_instance_counter": { + "range_check_builtin_applications": 954, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 43 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb59981e68b8b", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1c9dd18ed7f706e47", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0x1c9dd18ed7f706e47", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "0x44190158c304f1", + "0x0" + ] + }, + { + "from_address": "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3a8ce4426d733b55d1e4", + "0x0", + "0x8bbb9f58d4d682033", + "0x0" + ] + }, + { + "from_address": "0x7e2a13b40fc1119ec55e0bcf9428eedaa581ab3c924561ad4e955f95da63138", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x1c9dd18ed7f706e47", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x44190158c304f1", + "0x0", + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e" + ] + }, + { + "from_address": "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x370d5f60e8af6ecc5b4f9a96705fa9ae93948cc5d8a90aaec69a77af00dec61", + "0x6", + "0x1", + "0x2", + "0x1c9dd18ed7f706e47", + "0x0", + "0x44190158c304f1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6335299c589ddf6967faef5ae9046225d007af8732fe03916fb385c6a88515e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb59981e68b8b", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31081, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1054 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4ff0159b5742", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x26006d69194560cbba1d1b2fd755be1aca6cd832f2240ab852068cb2b4fab23", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4ff0159b5742", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8992, + "builtin_instance_counter": { + "range_check_builtin_applications": 216, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2, + "pedersen_builtin_applications": 22 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "0x70756d6963657273" + ] + }, + { + "from_address": "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x57857064e88c43cd1424c44ff818f7aa3e6411a05722c86f251a3cc624d5e08", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1fad8734c6644c5660d5c40ca8229d137170075fde0ca88d969d9733813aca2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "0x63616765696e6d796d696e6440676d61696c2e636f6d", + "0x63616765696e6d796d696e6440676d61696c2e636f6d" + ] + }, + { + "from_address": "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x46f8a21b7baf396f5d5a2d4f1d5e0bcd7876e8a83a0afe0ee0cd3086b3e2353", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x782b274402027459bd9c4892841a773e0605421972a2651305b89b1046d8ac5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x8ad750c26ee4", + "messages_sent": [], + "events": [ + { + "from_address": "0x60582df2cd4ad2c988b11fdede5c43f56a432e895df255ccd1af129160044b8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x6baa1b85be8c83d6c9ccfc8b3a6d811a4cdd7d09bb2d332a24a84cc9311e7f8", + "0x318e9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6baa1b85be8c83d6c9ccfc8b3a6d811a4cdd7d09bb2d332a24a84cc9311e7f8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x8ad750c26ee4", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 9153, + "builtin_instance_counter": { + "pedersen_builtin_applications": 28, + "range_check_builtin_applications": 194, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4fb2850f79a7", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x4bdeccd35800e17724a3d37ce2edec532089069c515ac8a04eb98a99792e14e", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x4bdeccd35800e17724a3d37ce2edec532089069c515ac8a04eb98a99792e14e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5824baf8b2c01d331fc1902924b42952ee2899a401979c0b614ea4374d708ba", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4bdeccd35800e17724a3d37ce2edec532089069c515ac8a04eb98a99792e14e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4fb2850f79a7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7452, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "range_check_builtin_applications": 198, + "pedersen_builtin_applications": 20, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x10e2bf36bc2c5554d9519e41ad40e5ee4acf44c5eca47c0b2ac25c2c928cb5", + "0x666467666740676d61696c2e636f6d", + "0x676e" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10e2bf36bc2c5554d9519e41ad40e5ee4acf44c5eca47c0b2ac25c2c928cb5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdb5b27ad739a", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2625a00", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x2625a00", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "0x2628dd6", + "0x0" + ] + }, + { + "from_address": "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x19c423d02c894419629e9d91c9f41befa42b3c0329f334a6b2ff4a8133f35d1", + "0x3", + "0x1", + "0x2628dd6", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3b7baf6955c2c9e881dcf29e95bf16c84b7a9e7180f9334bfb1fd42cfcad8db", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdb5b27ad739a", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21701, + "builtin_instance_counter": { + "range_check_builtin_applications": 555, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x1a02726d8b4f2a988e24ea7cf25418fb751d431850cedece765d66be9baeaea", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x1a02726d8b4f2a988e24ea7cf25418fb751d431850cedece765d66be9baeaea", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x891b49adb989a018592add8710102ff991d47fc67b949355a88609ed493a94", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1a02726d8b4f2a988e24ea7cf25418fb751d431850cedece765d66be9baeaea", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x5816e9", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x5816e9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "0xbeefdc56eb58d", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e3a7646b33fc8993", + "0x0", + "0x372541024d3", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x5816e9", + "0x0", + "0xbeefdc56eb58d", + "0x0", + "0x0", + "0x0", + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8" + ] + }, + { + "from_address": "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4b083acb1f18eedbc620692443aed0251022882ee5d2507f3155eb7bcc4c910", + "0x6", + "0x1", + "0x2", + "0x5816e9", + "0x0", + "0xbeefdc56eb58d", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x468334867510c46b0257f67570bcf4a6c5c188b53c5fcf78079d6aa1f926bf8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33336, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1111 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1211f218a6bfb31", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x1211f218a6bfb31", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "0x84851e2", + "0x0" + ] + }, + { + "from_address": "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x737ba8ff635a304604741a27c761762b5f55eb1cd893658bc77b3b68cbb6237", + "0x3", + "0x1", + "0x84851e2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7fc782e28e47516463127ee33eaad70a66b26d3a1465f91716dba2b239196e4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21799, + "builtin_instance_counter": { + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 555 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x143746ed74b5b", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xcfd39f5244f7b617418c018204a8a9f9a7f72e71f0ef38f968eeb2a9ca302b", + "0xf4471", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xcfd39f5244f7b617418c018204a8a9f9a7f72e71f0ef38f968eeb2a9ca302b", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0xdd2ffbe7c71aeda", + "0x0" + ] + }, + { + "from_address": "0xcfd39f5244f7b617418c018204a8a9f9a7f72e71f0ef38f968eeb2a9ca302b", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x1df1dc23b841dc9a238c", + "0x0", + "0x20f8c623d4", + "0x0" + ] + }, + { + "from_address": "0xcfd39f5244f7b617418c018204a8a9f9a7f72e71f0ef38f968eeb2a9ca302b", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0xf4471", + "0x0", + "0xdd2ffbe7c71aeda", + "0x0", + "0x0", + "0x0", + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x437bd0dab99c6a011ba3a9b17e103832c18af282a12c251555a1e05b8ea2f5b", + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0xdd2ffbe7c71aeda", + "0x0" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1b23ed400b210766111ba5b1e63e33922c6ba0c45e6ad56ce112e5f4c578e62", + "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9", + "0xdd24a8c1e504723", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x578a26ddc0a418f639ba557248f78455d8141aeb114db4bff9b40836f3349e9", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x143746ed74b5b", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 59069, + "builtin_instance_counter": { + "pedersen_builtin_applications": 82, + "range_check_builtin_applications": 1961, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x772b54116c5d", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x79b7b718eff45515b3726fc90e02322638005974325d2d675e33289eb6f8e7e", + "0x0", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0xd9af7cc4b444c201a3490be850f7e8cf76298eff75ae990d0fe66f5b1c1fb9" + ], + "data": [ + "0x79b7b718eff45515b3726fc90e02322638005974325d2d675e33289eb6f8e7e", + "0x377d9", + "0x7f", + "0x1000000000080000000000000000000000000000000" + ] + }, + { + "from_address": "0x79b7b718eff45515b3726fc90e02322638005974325d2d675e33289eb6f8e7e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5b5d0256b572cf7efd22881f524ed01c395dcef739296ed55184c5427311755", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x79b7b718eff45515b3726fc90e02322638005974325d2d675e33289eb6f8e7e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x772b54116c5d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8863, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 207, + "bitwise_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7e3241296ee6c9266d868860bba2a7c3b05b07a544be935fadd69a294b4ea5f", + "0x108cc", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7e3241296ee6c9266d868860bba2a7c3b05b07a544be935fadd69a294b4ea5f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12230, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5a598378180ff46c0bff556a482a31616bf95500cf8d6eb4e9c42cdf2ffcee5", + "0x108cd", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5a598378180ff46c0bff556a482a31616bf95500cf8d6eb4e9c42cdf2ffcee5", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12221, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "0x4e44f1572bfbbf10c97e8980e5675dab0f002f0f345c4048d010e43035b26c", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "pedersen_builtin_applications": 23, + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed5c4b3f6499", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7aeac00aa978fe97bb5cc51b407154affc34bfa1b196453cd61aa61ba0f405a", + "0x108ce", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7aeac00aa978fe97bb5cc51b407154affc34bfa1b196453cd61aa61ba0f405a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed5c4b3f6499", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 11667, + "builtin_instance_counter": { + "pedersen_builtin_applications": 44, + "range_check_builtin_applications": 238, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x52c616b110fff40a582ba6ef1a0be9a8543b8e27e5db4b4cbfb58a725c6069b", + "0x108cf", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x52c616b110fff40a582ba6ef1a0be9a8543b8e27e5db4b4cbfb58a725c6069b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12221, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0xbf16f683c5efd280a0ccfff6a70d28bcd3afd47187bbc819ccc11554731778", + "0x3366676632646640676d61696c2e636f6d", + "0x663233" + ] + }, + { + "from_address": "0xbf16f683c5efd280a0ccfff6a70d28bcd3afd47187bbc819ccc11554731778", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3886c0362140b83206c51cc77040b1529d359a42739a75fd1c0c7ccf419dc76", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xbf16f683c5efd280a0ccfff6a70d28bcd3afd47187bbc819ccc11554731778", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb438896f50bd", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "0x0", + "0xd3a5ba1d551035d", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bbf2abe3dc7c759a830a", + "0xd49880d87383ee1085408" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8" + ], + "data": [ + "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0xd3a5ba1d551035d" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "0xd3a5ba1d551035d", + "0x0" + ] + }, + { + "from_address": "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3327e4e2c5d8134dcb5eb260c48581a31c4cdc1f0f9ae791592ba0fd210a50f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6c312f5cda0842b012465871b6c04b5b253e89a0112ee7aa918ce02d5d5075f", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb438896f50bd", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 22412, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 40, + "range_check_builtin_applications": 948, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x4176fe21fa98a0cae78f0778e44c412c02678bdb25858a51b4727788f624ef2", + "0x30", + "0x30" + ] + }, + { + "from_address": "0x4176fe21fa98a0cae78f0778e44c412c02678bdb25858a51b4727788f624ef2", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5cf19b5140aff2c0a705a0436fd6060ca9862597ec51727f31f3f65cb5b24e4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4176fe21fa98a0cae78f0778e44c412c02678bdb25858a51b4727788f624ef2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x3c1528d4f6f2a6b5429f439cc9742bfd8f034e4cb839b028410dacbcfd83702", + "0x108d0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3c1528d4f6f2a6b5429f439cc9742bfd8f034e4cb839b028410dacbcfd83702", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12223, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x6b0d389a0770e4ee751ec03169a6c0e8b14ef2d791afd76017153fcf6db64bb", + "0x108d1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b0d389a0770e4ee751ec03169a6c0e8b14ef2d791afd76017153fcf6db64bb", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12227, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x582401e1d694d98bac21d93ec039e218d7b85c9e3f54ab178d67b1d8c140f96", + "0x108d2", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x582401e1d694d98bac21d93ec039e218d7b85c9e3f54ab178d67b1d8c140f96", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12219, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x7092baebed34a58347a58c26b5e6a9114daeb98ac274e347ff9786aa9df7eda", + "0x108d3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7092baebed34a58347a58c26b5e6a9114daeb98ac274e347ff9786aa9df7eda", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12224, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x71f1a45ae1b5d70536139c1f60de8ef0778b2c777fafc10ae79432f080a4310", + "0x33714d30637376406f75746c6f6f6b2e636f6d", + "0x6368696c64206172656120617274" + ] + }, + { + "from_address": "0x71f1a45ae1b5d70536139c1f60de8ef0778b2c777fafc10ae79432f080a4310", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x86e5177689081231857f3faa2cfb0ef65994097898b92143b09834aa527c72", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x71f1a45ae1b5d70536139c1f60de8ef0778b2c777fafc10ae79432f080a4310", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x6541717d6ef30f667561588c3f043cf0dbe5b7788673d7d8abb59f2092de76b", + "0x108d4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6541717d6ef30f667561588c3f043cf0dbe5b7788673d7d8abb59f2092de76b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12223, + "builtin_instance_counter": { + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 2, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2ee5588d611de71d6fc402782886abe5e39e06d772500efa1128ecf13797b07", + "0x108d5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2ee5588d611de71d6fc402782886abe5e39e06d772500efa1128ecf13797b07", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12218, + "builtin_instance_counter": { + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 2, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x714ab0f7f7ec80ef94ac09c9e52262b4800358b81f17e4f00e16cf2adfb4291", + "0x108d6", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x714ab0f7f7ec80ef94ac09c9e52262b4800358b81f17e4f00e16cf2adfb4291", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12228, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x27401e2bd261f", + "messages_sent": [], + "events": [ + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4554482f555344", + "0x27d955bf80", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4254432f555344", + "0x27a52e4ec00", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x555344432f555344", + "0x5f5f0a0", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5f0a0", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08745", + "0x4249545354414d50", + "0x454d5049524943", + "0x4441492f555344", + "0x5f2b480", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4554482f555344", + "0x27cc945e00", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4254432f555344", + "0x2799f7bf780", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x555344432f555344", + "0x5f7dcd0", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5b9f0", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434558", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5e100", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4554482f555344", + "0x27d92f99df", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4254432f555344", + "0x27a41ab21bd", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x555344432f555344", + "0x5f5e100", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5cf6c", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x434f494e42415345", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5a668", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x4554482f555344", + "0x27e377bdff", + "0x66" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x4254432f555344", + "0x27b59279800", + "0x6" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08748", + "0x415343454e444558", + "0x454d5049524943", + "0x555344542f555344", + "0x5f7b5bf", + "0x303e5" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f0861c", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4554482f555344", + "0x27d4910b80", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f0861f", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4254432f555344", + "0x279e1a53900", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f0861e", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x555344432f555344", + "0x5f7679f", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f0861d", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5e100", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f08621", + "0x444546494c4c414d41", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5e100", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4554482f555344", + "0x27d7db7777", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4254432f555344", + "0x27a278034d4", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x555344432f555344", + "0x5f60071", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x555344542f555344", + "0x5f5ed87", + "0x0" + ] + }, + { + "from_address": "0x346c57f094d641ad94e43468628d8e9c574dcb2803ec372576ccc60a40be2c4", + "keys": [ + "0x280bb2099800026f90c334a3a23888ffe718a2920ffbbf4f44c6d3d5efb613c" + ], + "data": [ + "0x64f086d8", + "0x4b41494b4f", + "0x454d5049524943", + "0x4441492f555344", + "0x5f5b526", + "0x0" + ] + }, + { + "from_address": "0x6f40a7cba2e500321519acc0e8c6554fc19da93d7f46bc65637e9865752d4ae", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3242df56cc04b37f01165e61e39416b53868c8111eea29617cf06fcb0ebe466", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6f40a7cba2e500321519acc0e8c6554fc19da93d7f46bc65637e9865752d4ae", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x27401e2bd261f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 122606, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 520, + "range_check_builtin_applications": 2431, + "bitwise_builtin_applications": 168 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x3c2b78b2627d", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x5cdadda64e7022faa661f4d34ed2d1883ef268a2748d6737d4195ad9c3c9c0a", + "0x2aa1efb94e0000", + "0x0" + ] + }, + { + "from_address": "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x65c75da4548260f85a7ada532f0d693aa548c2f2c933c4cb53deaeaa7b0ca0b", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3a20d4f7b4229e7c4863dab158b4d076d7f454b893d90a62011882dc4caca2a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x3c2b78b2627d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8065, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183, + "pedersen_builtin_applications": 20 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5555be7362c7bd36ad6395754827e973d955743d3a19f977e89ba41691b7391", + "0x108d7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5555be7362c7bd36ad6395754827e973d955743d3a19f977e89ba41691b7391", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12227, + "builtin_instance_counter": { + "pedersen_builtin_applications": 49, + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x3ca5df38a130dd86a16a0b7a4f2249a8a99dba57970b3acfaf123ab5fdac66a", + "0x108d8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3ca5df38a130dd86a16a0b7a4f2249a8a99dba57970b3acfaf123ab5fdac66a", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12222, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x640bab67e33311c3200c1d98c8492e1d416b93166cda0d0a97d5b0b641bfdf4", + "0x108d9", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x640bab67e33311c3200c1d98c8492e1d416b93166cda0d0a97d5b0b641bfdf4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12228, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 2, + "range_check_builtin_applications": 250, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x647261676f6e40676d61696c2e636f6d", + "0x31" + ] + }, + { + "from_address": "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2e2ba351e277f871b1781411fe6ac0e5fa3bf0e8f945e32f7565fe77b465ea8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x61896da708f6edbf72a18e33d094e55b2430049c825b641adf881c7e94d1c6b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb41bce8360ca", + "messages_sent": [], + "events": [ + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x270753", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x270753", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "0x552b243def7f7", + "0x0" + ] + }, + { + "from_address": "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x38926d19a4a9540438a881b25cd8b6b4b541273b47275f266ed929b155d73ca", + "0x3", + "0x1", + "0x552b243def7f7", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x77f0d5496a7d3df62586c3e5d57e976031d2cad663b1f750dd8180913a2c026", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb41bce8360ca", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 21749, + "builtin_instance_counter": { + "range_check_builtin_applications": 560, + "pedersen_builtin_applications": 37, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x2c956c6254b4403e21105dc487433884b637685587b9adcf12ac6efe3e0d5cf", + "0x108da", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2c956c6254b4403e21105dc487433884b637685587b9adcf12ac6efe3e0d5cf", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12227, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x6ab1243875b71c7417fbf68db53f7399fe884b3820d9fc365dbd9ae84d11a4", + "0x108db", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6ab1243875b71c7417fbf68db53f7399fe884b3820d9fc365dbd9ae84d11a4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12222, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x66602d3bf0af4", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x66602d3bf0af4", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "0x2eefd3", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6c9137e406c6f50b", + "0x1b539395b5b" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x66602d3bf0af4", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x2eefd3", + "0x0", + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18" + ] + }, + { + "from_address": "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x22b411e0dcbeac07d4471e4e80ee505733268205c81f026f6b90bf02c00b67", + "0x6", + "0x1", + "0x2", + "0x66602d3bf0af4", + "0x0", + "0x2eefd3", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5b387eae8fc162b404d6a594a3bddf6c377ab6cc15bf20623c76d04c8f0ce18", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26612, + "builtin_instance_counter": { + "bitwise_builtin_applications": 3, + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x819a5de168000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x819a5de168000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "0x3b6b70", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6c995189e4dd750b", + "0x1b538fdefeb" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0x819a5de168000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x3b6b70", + "0x0", + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e" + ] + }, + { + "from_address": "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1fe0b88f82c002ea3a42ba5af7a00ddb6b6541379e8c5008ec07d05f835c996", + "0x6", + "0x1", + "0x2", + "0x819a5de168000", + "0x0", + "0x3b6b70", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6cbf71b71c9bd3dc6d3e7817ac816bfc7bc64f86f1389f1507fc26a8b4c8c2e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26609, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3, + "range_check_builtin_applications": 973 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed8970fb4b60", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x1298195a9d32990d66ef9a9608b41ba796fd7a0ae0f8fbed4f8c3374d2da8db", + "0x108dc", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1298195a9d32990d66ef9a9608b41ba796fd7a0ae0f8fbed4f8c3374d2da8db", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed8970fb4b60", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12780, + "builtin_instance_counter": { + "range_check_builtin_applications": 262, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 54 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x7cd4264242f2", + "messages_sent": [], + "events": [ + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x35bd041f99860ff57adfc16b848c6b8e27471acb669e969a60ae17c281df8a" + ], + "data": [ + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x7300100008000000000000000000000000", + "0x377da", + "0x0" + ] + }, + { + "from_address": "0x6a05844a03bb9e744479e3298f54705a35966ab04140d3d8dd797c1f6dc49d0", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x1", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x144b7f55255582971d7d4c295c26a6c1c126714d87f0a9fed68f1b824dc6471", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x7cd4264242f2", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 44173, + "builtin_instance_counter": { + "pedersen_builtin_applications": 27, + "range_check_builtin_applications": 1344, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x1c952311afd3ca9766d0f4bc2c41dd918016cf599e2662d15a8996e13510b4c", + "0x108dd", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x1c952311afd3ca9766d0f4bc2c41dd918016cf599e2662d15a8996e13510b4c", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12226, + "builtin_instance_counter": { + "range_check_builtin_applications": 250, + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xdfab36cf0acb", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x5aa2b0035682", + "0x0" + ] + }, + { + "from_address": "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "keys": [ + "0xfadd8dd819dba177689190ce1fe9bce0c841f1ba62789603eaae31ede81437" + ], + "data": [ + "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "0x71f3a470ea52890d441c406fe025c9b5bac96a7e46de71095649fdb2a11b2ed", + "0x5a9b6dcf9df8", + "0x0", + "0x5af3107a4000", + "0x0" + ] + }, + { + "from_address": "0x71f3a470ea52890d441c406fe025c9b5bac96a7e46de71095649fdb2a11b2ed", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "0x5af3107a4000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "0x76dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa", + "0x5a9b6dcf9df8", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x560466254a9eaa87c58bc247659cd4d24ce2457296ff40b1ee9310d1424e374", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xdfab36cf0acb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 48630, + "builtin_instance_counter": { + "bitwise_builtin_applications": 36, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1408, + "pedersen_builtin_applications": 112 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5db491d68bdb6fd6101c8998ff9c1882b4f8bc9c54634839892abdc193c72ff", + "0x636f64653737372e626e62", + "0x617364617364" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5db491d68bdb6fd6101c8998ff9c1882b4f8bc9c54634839892abdc193c72ff", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "pedersen_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 160 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x4f49d8b4968e2a5f77e843ae6ede97495bd179170a7bca7abc23a785cd5984e", + "0x776965756668697766407266686f6c662e64736664", + "0x736466" + ] + }, + { + "from_address": "0x4f49d8b4968e2a5f77e843ae6ede97495bd179170a7bca7abc23a785cd5984e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4ca7a7cca722e958b19f297ab807a6c75d58cdc284cab78000f2279d0f62335", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4f49d8b4968e2a5f77e843ae6ede97495bd179170a7bca7abc23a785cd5984e", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x10d2f58e19d0e", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1dcd6500", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1dcd6500", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x1dcd6500", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x1dcd6500", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x1dc99745", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "0x1122d536cde69f0bd3b95e73caa2bf8866f5f0ed3e5122f5ea74d0d3314807f", + "0x3d090", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0x2733cef0ada90bcb6631ae9e3ae97bf6ba87bb9d6af562661297621afe8e6d7" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x3d090", + "0x0", + "0x0", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x68531c2763", + "0x0", + "0x6a19112d6e", + "0x0" + ] + }, + { + "from_address": "0x601f72228f73704e827de5bcd8dadaad52c652bb1e42bf492d90bbe22df2cec", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x28c858a586fa12123a1ccb337a0a3b369281f91ea00544d0c086524b759f627", + "0x1dcd6500", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x1dc99745", + "0x0", + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x1dc99745", + "0x0" + ] + }, + { + "from_address": "0x4270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "0x1dcd6500", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x1dc99745", + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6" + ] + }, + { + "from_address": "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x42908552e8421102c9fda44e514a938e7eea6b85c2d5ef52fb0d92963f74acf", + "0x2", + "0x1", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x218fbf5c8f0a6cf5fc9ca7c319de6ce135984d16571950a66ea5ba54bd16dc6", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x10d2f58e19d0e", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 87789, + "builtin_instance_counter": { + "bitwise_builtin_applications": 4, + "pedersen_builtin_applications": 94, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 5402 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x7ce3bf01bdb37cc8065c41a1e1d9991755ea58f6336698983598f6516179947", + "0x307837636533626630316264623337636338303635633431613165316439393", + "0x6173646173646473" + ] + }, + { + "from_address": "0x7ce3bf01bdb37cc8065c41a1e1d9991755ea58f6336698983598f6516179947", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1598f1bf98173fd9d46dfc288ee39ee22c1c1e65d38d47d0ad037dbcf20f03f", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x7ce3bf01bdb37cc8065c41a1e1d9991755ea58f6336698983598f6516179947", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x288396b55dab", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x40441b968c09e0441ee668d181ae1272196a229d01834ff05fc95ad2e4446a8", + "0x6164736667616f69696c706a6b6e40676d61696c2e636f6d", + "0x6661646661736466" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x40441b968c09e0441ee668d181ae1272196a229d01834ff05fc95ad2e4446a8", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x288396b55dab", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7871, + "builtin_instance_counter": { + "range_check_builtin_applications": 160, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x4b2327ce86ead69c46555bd8b78461fe599d1f46f06e44cabca200b5b6c238", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x4b2327ce86ead69c46555bd8b78461fe599d1f46f06e44cabca200b5b6c238", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x4d924c38c8920f546241b95ce07ae67b258b5e9b4945aff9cb7b4df6542f9b4" + ] + }, + { + "from_address": "0x4b2327ce86ead69c46555bd8b78461fe599d1f46f06e44cabca200b5b6c238", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4b2327ce86ead69c46555bd8b78461fe599d1f46f06e44cabca200b5b6c238", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x4b2327ce86ead69c46555bd8b78461fe599d1f46f06e44cabca200b5b6c238", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 34, + "range_check_builtin_applications": 145 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc8ada293e2e9", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x155f2dd73a1a0000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x33b75ba988dd9536e9e71c6", + "0x33e5c71e820b2d4b7be5acc" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x1bb775de7836ad131d1a0", + "0xd47af8b558cb1ecd69920" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2" + ], + "data": [ + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x155f2dd73a1a0000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x155f2dd73a1a0000", + "0x0" + ] + }, + { + "from_address": "0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x155f2dd73a1a0000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x2324062bde6ebb76ffd17d55fee62fee62a4877588eb02524b19c091983b365" + ], + "data": [ + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5e100cbd4d1028468abd0ec1b507cc6ab7419f72adfe8428bf401e62abd61ec", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc8ada293e2e9", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 27631, + "builtin_instance_counter": { + "range_check_builtin_applications": 1045, + "pedersen_builtin_applications": 49, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0xbba0ba432d63", + "messages_sent": [], + "events": [ + { + "from_address": "0x20babf2988c928980402c768c744e73b1fe14bdda260b068826f8fc921119e0", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x5aa23d5bb71ddaa783da7ea79d405315bafa7cf0387a74f4593578c3e9e6570" + ] + }, + { + "from_address": "0x20babf2988c928980402c768c744e73b1fe14bdda260b068826f8fc921119e0", + "keys": [ + "0xd876503fb434f7517a7b4ae8d0d5fba27e2fa7b1a9f200deb935316f46fcc3" + ], + "data": [ + "0x7080014d630a129a38a58938b8eeb5b1a4ece75de9243bab8f9f6890554c532" + ] + }, + { + "from_address": "0x20babf2988c928980402c768c744e73b1fe14bdda260b068826f8fc921119e0", + "keys": [ + "0x2db340e6c609371026731f47050d3976552c89b4fbb012941663841c59d1af3" + ], + "data": [ + "0x2c2b8f559e1221468140ad7b2352b1a5be32660d0bf1a3ae3a054a4ec5254e4" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x20babf2988c928980402c768c744e73b1fe14bdda260b068826f8fc921119e0", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xbba0ba432d63", + "0x0" + ] + } + ], + "contract_address": "0x20babf2988c928980402c768c744e73b1fe14bdda260b068826f8fc921119e0", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7438, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 145, + "pedersen_builtin_applications": 34 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb5f7e81256ce", + "messages_sent": [], + "events": [ + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x2dc6c0", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x2dc6c0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "0x6338ba74fdb84", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e3a130df8cacae0f", + "0x0", + "0x372543deb93", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x0", + "0x0", + "0x2dc6c0", + "0x0", + "0x6338ba74fdb84", + "0x0", + "0x0", + "0x0", + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd" + ] + }, + { + "from_address": "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x47e27990dcb1634927eb7e34602a97d43f9cdf193da920d223853b39115a065", + "0x6", + "0x1", + "0x2", + "0x2dc6c0", + "0x0", + "0x6338ba74fdb84", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0xda3450e00334a3a71bfa7d1da25539e3214a3bef4a258244af97751c6c10dd", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb5f7e81256ce", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33332, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1111, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5aa500dc5b05fac944353b3c12d1add5534a2cd48a016e906f39022b9c62b08", + "0x33786e707333317240676d61696c2e636f6d", + "0x6c6576656c2077617465722e" + ] + }, + { + "from_address": "0x5aa500dc5b05fac944353b3c12d1add5534a2cd48a016e906f39022b9c62b08", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4680b27b72239a5c59407481b3d1d2a3dad64e8a3f56897ffc2e96d458a5e24", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5aa500dc5b05fac944353b3c12d1add5534a2cd48a016e906f39022b9c62b08", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x6a3f44a905ee102e20baf1976354095653eda068c506088db4b847da41fc938", + "0x73647364406173612e6c64", + "0x63786378" + ] + }, + { + "from_address": "0x6a3f44a905ee102e20baf1976354095653eda068c506088db4b847da41fc938", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x63b40b6683a1a074f31bfabc0544c918a0f467921d376b3613251ebf346be61", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6a3f44a905ee102e20baf1976354095653eda068c506088db4b847da41fc938", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "range_check_builtin_applications": 143, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xed74eb7756d7", + "messages_sent": [], + "events": [ + { + "from_address": "0x6b1826599e9637eb16e11605ae5df008b7c043bfed0f1009ce99bd87b723fe7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x164cac9749e4abbca8295aaa50640cf428e06e6cb7d16d129a10e3df5aaf655", + "0x108de", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x164cac9749e4abbca8295aaa50640cf428e06e6cb7d16d129a10e3df5aaf655", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xed74eb7756d7", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 12223, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 2, + "pedersen_builtin_applications": 49, + "range_check_builtin_applications": 250 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x13f61f04191c5", + "messages_sent": [], + "events": [ + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2f27ef6e17db08000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x30c296ae369716818de77cb5b71ce9cda7cc2c0e8456f474e0abb1ae8d017da" + ], + "data": [ + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x3482a2663fc16cef53604bf", + "0x34e18f86d873a8e209cfd5b" + ] + }, + { + "from_address": "0x62fa7afe1ca2992f8d8015385a279f49fad36299754fb1e9866f4f052289376", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x439d7ec4abbb69aaa8fa5acd9a682f118823f49f2542bc7673a9792ddff9fc2", + "0x224b28721bb6f", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0xa2fb82b5656725dad81c7112b2c4ef0119096677c3c0fd82632d0a74f07666" + ], + "data": [ + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x1336d992d34eb8c2b2033e", + "0x1c30abee582b019e989dac" + ] + }, + { + "from_address": "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x2f27ef6e17db08000", + "0x0" + ] + }, + { + "from_address": "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "keys": [ + "0x7ae0ab7952bbfc33a72035e5eccec7c8816723421c0acb315bd4690a71d46e" + ], + "data": [ + "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", + "0x2e1a085cd24986028", + "0x2f27ef6e17db08000" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6b82ab6aad2d8863175e6264935c4d2f71ef242a0df8edf088472f79783cffc", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x13f61f04191c5", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33698, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 2014, + "pedersen_builtin_applications": 52 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "DeployAccount": { + "actual_fee": "0x593c95662556", + "messages_sent": [], + "events": [ + { + "from_address": "0x6d339f7302afe89a7b5b746429ff4b1787d2682a42349df8b95167f211321d2", + "keys": [ + "0x10c19bef19acd19b2c9f4caa40fd47c9fbe1d9f91324d44dcd36be2dae96784" + ], + "data": [ + "0x6d339f7302afe89a7b5b746429ff4b1787d2682a42349df8b95167f211321d2", + "0x4e71ffde595ab1018474a6318102346483e1b6b00d6def098440958f74b4af5", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6d339f7302afe89a7b5b746429ff4b1787d2682a42349df8b95167f211321d2", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x593c95662556", + "0x0" + ] + } + ], + "contract_address": "0x6d339f7302afe89a7b5b746429ff4b1787d2682a42349df8b95167f211321d2", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 5781, + "builtin_instance_counter": { + "range_check_builtin_applications": 123, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 23 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x4febfae7598d", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x6ad9ed7b6318f1bcffefe19df9aeb40d22c36bed567e1925a5ccde0536edd" + ], + "data": [ + "0x2edcb8241b3161bc698c144b13421cab186eafa1a54ced5b8c5e8e1f39d6925", + "0x3a2fc8b0db9a9ef748227ef61ed254897cb40ad39575a9bde734dc78073f779", + "0x1" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x2edcb8241b3161bc698c144b13421cab186eafa1a54ced5b8c5e8e1f39d6925", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x4febfae7598d", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 8806, + "builtin_instance_counter": { + "pedersen_builtin_applications": 20, + "range_check_builtin_applications": 182, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xb4e4eaf6f06f", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xe35fa931a0000", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0xe35fa931a0000", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "0x683e94", + "0x0" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x3b6ca7878477f7750b", + "0x1b53895b157" + ] + }, + { + "from_address": "0x23c72abdf49dffc85ae3ede714f2168ad384cc67d08524732acea90df325", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x7a6f98c03379b9513ca84cca1373ff452a7462a3b61598f0af5bb27ad7f76d1", + "0xe35fa931a0000", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x683e94", + "0x0", + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371" + ] + }, + { + "from_address": "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3ccae9d92df0bb57a386b2102ad987dd312b31aaa7f32e048f948d838949ed4", + "0x6", + "0x1", + "0x2", + "0xe35fa931a0000", + "0x0", + "0x683e94", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x6d9de9e35efa37fa9c38cd6a7a409182f68c838200cd7e81a0cbb4d8ddb3371", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xb4e4eaf6f06f", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 26605, + "builtin_instance_counter": { + "pedersen_builtin_applications": 56, + "range_check_builtin_applications": 973, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 3 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x1038ca852ff21", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xa4d8eb863c2b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4baf0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0xa4d8eb863c2b", + "0x0" + ] + }, + { + "from_address": "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "0x4b50b", + "0x0" + ] + }, + { + "from_address": "0x41f9a1e9a4d924273f5a5c0c138d52d66d2e6a8bee17412c6b0f48fe059ae04", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x132fddf24", + "0x0" + ] + }, + { + "from_address": "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x318c362dea082a0d44fd065914e9b90c760efb94526676139df1b7a09eb4e50", + "0x6", + "0x1", + "0x1", + "0xa4d8eb863c2b", + "0x0", + "0x4b50b", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x74cbefc23330bbab85d2b01ee96f34f6e5cbc6c4fa91728fe50a6d9d535d033", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x1038ca852ff21", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 27665, + "builtin_instance_counter": { + "pedersen_builtin_applications": 44, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 1062 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0xc99baf5b5deb", + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" + ], + "data": [ + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x13e323a39c073d0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x137f2ca103758a7", + "0x0" + ] + }, + { + "from_address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "0x8f0d180", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe14a408baf7f453312eec68e9b7d728ec5337fbdf671f917ee8c80f3255232" + ], + "data": [ + "0x77e4d923a99ce406b6", + "0x0", + "0x3724b4d1a13", + "0x0" + ] + }, + { + "from_address": "0x4d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a", + "keys": [ + "0xe316f0d9d2a3affa97de1d99bb2aac0538e2666d0d8545545ead241ef0ccab" + ], + "data": [ + "0x41fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023", + "0x137f2ca103758a7", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x8f0d180", + "0x0", + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b" + ] + }, + { + "from_address": "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2882c96f3a4ec3a45ab42a74a8b193d2096ad85e1931ca042075bc0a70a2668", + "0x6", + "0x1", + "0x2", + "0x137f2ca103758a7", + "0x0", + "0x8f0d180", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x53d69ee447561c2bc75dcf3bad0a04285ed50232dfdca84fc035d44e885415b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xc99baf5b5deb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 33494, + "builtin_instance_counter": { + "pedersen_builtin_applications": 38, + "range_check_builtin_applications": 1120, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x63629c7479e3", + "messages_sent": [], + "events": [ + { + "from_address": "0x5dbdedc203e92749e2e746e2d40a768d966bd243df04a6b712e222bc040a9af", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "0xbf2c9b2d87", + "0x0" + ] + }, + { + "from_address": "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x3d441f44150eb5cdc78f15403c9b9e30f967897112f896da00c84bffe3b26c0", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x346978697d214a1e16ba6288eaae1bc64547c437f8ff9ab4483a11f72b6dfc4", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x63629c7479e3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 7832, + "builtin_instance_counter": { + "pedersen_builtin_applications": 22, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 183 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x284606298010", + "messages_sent": [], + "events": [ + { + "from_address": "0x454f0bd015e730e5adbb4f080b075fdbf55654ff41ee336203aa2e1ac4d4309", + "keys": [ + "0x38fb7b2e3c9c2e712beb3f0810da51cfd22c24f931002cf7b8fe9ec042de50c" + ], + "data": [ + "0x5f08b14aa7133bbff9e5156ea7c4b479c41fd9eecf5e9578faf6d52918d863b", + "0x30786b77656977697836357a61637a6c39767379366664316d6438767630616", + "0x74707776696e64716236" + ] + }, + { + "from_address": "0x5f08b14aa7133bbff9e5156ea7c4b479c41fd9eecf5e9578faf6d52918d863b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x600f222f797801af5de701de7e240790c6b0bac312ec2d6c3f298381299fe38", + "0x0" + ] + }, + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x5f08b14aa7133bbff9e5156ea7c4b479c41fd9eecf5e9578faf6d52918d863b", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x284606298010", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 6365, + "builtin_instance_counter": { + "pedersen_builtin_applications": 16, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 143 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + } + ], + "transaction_hashes": [ + "0x85010702b16e9c5b8ebbf58704f3458534aaae7d3fc8b4f00c17c121c1892d", + "0x531af87d678ad23e6c563b012072ad3076e52ac5265b533458f32ff23a2e37e", + "0x1eb6bd1da0ef612df752831a8ae38922d0b6e963c316bbdeafb7ab849919101", + "0x620b3f13a6c8f208907b5a9fe89f4b308809f18db3514b74301e2f7d3eb6e55", + "0x3fdba15fa1f09d7aa3dfded8a4ec6b9c8443f9c0e6e33549648db7da02744d2", + "0x62c1996e2917c549f6497044eb9651571120834be9e992ecb3e4d1dececefb7", + "0x329bf63ed895c3b7d28a025c64c774d7dc870d4a279962fce6cb87d38d14105", + "0x239196f4d074fa12656bd5b865285ed5f6b198145f1f79de50cb5b95e34a4f2", + "0x4ad49ea5c3e9afad3fe623ff3c15b5a35318fc6dbfaa3cbc27cf340f6466cd6", + "0x4932d5789900a4ba5dd170dfb635caa005beb71ced69c09a0cb472140c50859", + "0x37bed134982edfc4f0f6747759a490f66675decdbbe61303aa661e3c1109e4a", + "0x4f1ae8c8c58366839f84cb6fd0a31ee0b495ce312d9999cc1b7f33d377737b2", + "0x2e5eceaab61078072e6b7c8ad8717da422b28ebe7d2fd60ffb5a7135f22f537", + "0x78c37baa8f4fa71d9f31bf9149fb1f1a1a7a78ebdca8e4146f55701e3382a0f", + "0x7fdc10091e2c67b3722fe148d5dc9d655a00b55e2b3ed760e7b84cb2000565c", + "0x5790c57cd07dc25f2b757947445fffc8c547bfdbf41afe0c7c31da152ecd829", + "0x563cf1dd1aa33082783a6fe7d53798ea6c81a03401fdde15b8323c5377880ac", + "0x346c6d61faa344ea61d9fbf1420abdc81f597a643c9722ad986c696a0f3183b", + "0x15d63f3dc031dde726f9f5ebea183c3abc47f098a139b381a050f098e1411f8", + "0x314efb03d2a37d0c36f28b60d7956620d565fd3ed49683d0efa99c9d832dc72", + "0x439ac3642ccd1b11553c7e909836271ba4858fea604fda7ad7ad7417894084a", + "0x200877db46730b868f9581064cc9361a2adf3ff29636880a2a632d09bba2505", + "0x4ca8cea64d3c03b4fd1a387d565a72fbcff31e314f2baa7173135e72a149517", + "0x76f203641cd38bba6bccc1676aaa964535a1261e1cde502cafadc58fd44a166", + "0x3f4d15befc5e3292f7d5fa363b7ff32a46fdcfcd9d16396b0b89ca394d47220", + "0x438ec780afd3561dfc7d6d8ab5e7db82f1d2e374854b15a450cbcd3de08ddd8", + "0x6d119a6ec4ac591c9c931f63e6a6cbe92c9b6b1c128a949248eddf0b7124238", + "0x38250f8078a04d19407b803e4f846e57720a91fc943dad37a309c853fcc7dab", + "0x4ae0c2f64cff2ebc1943c1901050f63fabf6f516b6ae410ecf3211aab500977", + "0x3c55afb78f7b46b59cb6a3d4bbfc50165f62ccce729065af6e32593ab6a8223", + "0x5f923b35e38f889b0dfd4064d29378d92eb92b817eadf2a3713d3f2d4417811", + "0x25863e1d032a0232c0bdc8fef8215e5592635a432dfd9ac5fffa338c07a3e13", + "0x7cbd8d419754e5914f87887a0eff35fdf0d3b7706aea9b5b67c849fd42a7fa", + "0x73220097ea03286d1a91ee30b7340248858716cc1c6e39770f80f89c40f2343", + "0x7abad30138d80438270ac135cfb1cf261848ebfc8f23c212dd6bf0cce468456", + "0x26a25b1bafd3967fe136f263905773d111d48b0e10e1a66c8186b977a958add", + "0x290575f96161edcc9580874e5df001bffe8da47f6f58f62f76fca8ca6ab8579", + "0x4ec9a53df70a40bdc730ddbdc77ee34d10cc0413dc64cee3ac988af044ea156", + "0x3a11f37d2ed99361c7b23d58255a64e35ac34b4d61d9de0f994a704d0d37f85", + "0x1f95e07ed835b2d5292cfd2919f1a0df751ef947b722e1c21c8e938472ac9c9", + "0x3c276d13ba16c9e3a8129fe4383cb821ab6fd3381abcba0a9914800697d953d", + "0x3443bca30399d83ca1e4a2305b2f1b22b93382287a51e9fc1e736be3172b59f", + "0x51be4b826ef579fa0b7a9ce102660ad511025be4f80a33d77a64d3116293935", + "0x68a6e7cc5842ab2657d39b6719310eec57e585608ab4b9b285f0697c742dd84", + "0x578b6d1e0c9303b469b8796fafec9ca8c91a853d8b005eab3bcf57e045606f6", + "0x24c5f3e4e77da419d171b770dd1c51fb4d1925d57024eef09f503c19c28f83a", + "0x7100dde30e49d0444ec66648fbabfe178172c4bf5d4edad16aea24665cc526f", + "0x527a655d172b635dda88f7a3e4ff0a881bfaa21992135f5e4ba2d3106ffd2d9", + "0x5b303de09ae870c43e2bc66668c6df053bfaf498bc992004373702a626fc354", + "0x653a831aab3a1dfb02e79bec462dca9ddc0ee912633518cb4627bff401075ca", + "0xf44166aafcdef4f824d4a2fd6694e879465dd85f6676831bc56f4315510994", + "0x6160ba389c4fb54296f18e6a779a8dab280908dd6115d7fc511d53b8dcddc70", + "0x206948d55851a0a600d41c5712f7eeb6e9639e8a980b53f2b407aedaa332613", + "0xc89043951c3328940cfbbbf49936767c48a424bbe7015da7149865b0439c33", + "0x5056034284927d6ed76a32fe239ae01bf5f107d11d0f25cc008b3b6990b2dc0", + "0x4223b2868034adfeb5ada2715b1752803dfd3ac0201efed3268415bb874c516", + "0x7641f17ee702549da64fb4f1ec114c760928f53ef8bdae4b2e5a32a1be16953", + "0x6956e68b4dfadb6c3500e3c5721e961cb450550d96e6d9f62855d1042bea122", + "0x421f2a28670b9332399fbe4e1c0bfdaa9d325bc6704c8898fddc2faac90e23f", + "0x185e56839fbc2c2c9796a5c7ab66406095a1fb6706660d2a45aee50cb416c88", + "0x19664972258a315d0862917c59d895f29ea057583037994118bbaf18f1ce987", + "0x6fe934351cbeca7deeb2c3cbfc5a5eab03111b9122d9e3f350750cbac850c09", + "0x43d7a163e1b0a5d00af46853554947ffd3e5aa6e5e4b678e6628b19afb13ce8", + "0x21f2c32332c26016de768c2e19ed7b20df265463c814ec578e4dec437812d48", + "0x3f4cecb8cb1727fc6fd90f15e990eb8c6a01efd65f3e26b4e033573fb51ef9f", + "0x245868a316c408a92de74be1ebdbaeea01c5ab397cdda1015543651097483d2", + "0x3400a9093fef4cfc41e5ae059572659f3a57c94f9dbe4ded279f3ab090be872", + "0x6b8fedce06f08a063bd2e23523f058099562b7b796d9e3fa2dfa34073bb6ef", + "0x3ef9a5fb19edd926a7202b07f4cd8b4478587b993e5301ab44802eac7055ced", + "0x69177f298b52aa07da72cb432fadda3481aa787b38b90c80625e77493172387", + "0x4d44c3a2b9f7584024094eb0f7cd870b3b683ff55c2e1423c56342fb4b4e7c3", + "0x527f1da80ccef53e0aae1c2893d2226f59651acaf5dd7334f73fa1e7b0c3f05", + "0x67323eb65616dad5e7084cd34c9deb5276263e951bb3f99ba52c1ec450b1e03", + "0x6c1df416dd2515a1d38a476de40cf80d201d2fc00e7aa2063155858b0baf", + "0x2e167bd20d5cc2d77c22f4505a7fcfdf3cd05bb9b21367c22a22c291586b520", + "0x1934ca9e7eb721d87d546a976455f7aaafdd0b4ecb735f95ecf4ba23b4b09a9", + "0x7d7efa5a2a7007b21e15104679b42dc5905dfc57317e856224a702c62790851", + "0x11645d82185173d8ef22f2fba28d2bf9339b91cc4f95e6fda610ab4e1e0a9f7", + "0x1a0447e327cd4770141e7d0dd0eb5e4d7abf8340e0a7a4952fa47cff049c3da", + "0x77b9af0069e8826b6c22c7011d3d5d8f754995a91ea4ad7bad7f72d14538ff3", + "0x425307f3d97419f578633721f37bfdc731eb6b2a85a44e1d60adef934a9259b", + "0x651cbf9e05f9bc0d6e4c6f69ac6a6ceb6ae7add5ea24065a8e65285c6232b68", + "0x14f87c2a87fb57835f3a3edbfca73a3840491881534dda5f1f0c69083107b8", + "0x67aa8d36e1302fa3c96cb303325437968f7126bb35361013755bac56cca5cfa", + "0x364d240a543d11d473895783fcc45761f33f8084f6b8b280b505bc5402f1158", + "0x16a5ab64b265e945de345dc097854539a904ea140734c4011d5df58408ed8d9", + "0x5f92e620c9171f6baa3a64dfe1c89b206733f135e0970c203bcb3c573595484", + "0x661888d9ff31079980032fc6096d4720969460e23d4d7a8cb15f6dbda3b287c", + "0x702c89ae32754be737c8e007dcd179be114330371e057d075feb5557529154b", + "0x1b9d0e05835d1d3fa718645db39bb98349b99e54a4e1feac0192324c62fb546", + "0x465910703f23c5812e1f1f1fb6d322f15407c1fb5ccc44ccc23ac706de42fcc", + "0xe30253e203d5afaa7abe6eca00a37e035977e9f2bc2aa103bbd6209611b18d", + "0x486b420b9664cc090be1658c83906d7d807e99656dc4b6c62915677a6b11b81", + "0x10499ad2395d0f2f99a839af6b58ff8bc839f0bbaeeee8c8e264ab427473564", + "0x1c187387ba69a4938c74985f14dd5c7175108cefbf9624178b9af456ad8efea", + "0x5fbed2119abd225964c4c5f58b6108965c2845fde962d2a2f4bc28c870b8556", + "0x1f9470296e004af3c5b239ec91c89c4a29208d48b41cc3c7ce5be27f6f1e521", + "0x78511d3a1873d5c3157ec1310cb6d8ce740f9bfea97a8abbbb979baac07a95a", + "0x470d25d4eacfcec39a19c443c3ea40e71d63f6519c727c6e27ddaaf3b8de872", + "0x1d586c6b004376236d4a990cce633bcc857b9e4c1409e6b9c3c37bc635c7cf9", + "0x2f8aeb1edce334fc76c9af93aaeee1e1c12e6c611817f54abd35538b102a64", + "0x26c42fffd319eeac6bac32c00ae65e4163c53872ca7c0a096867fd2be99935a", + "0x1407a004f3f65a8a4db6bd613f41b5d65018d82885d856d741380496a99cfd2", + "0x546c97baa4c60e3c1cf1ce27bb30a51f74f0684e3ab994f0598a2ca1547b33a", + "0x3126781be193eed7fac380878c65a0f1142f21d0d108b0490e69c87d8968c75", + "0x88d9ce93071aa3106aab29458af83aa00bb12db902429be8f64519c6236f49", + "0x51f6fcf4d157d262b5aa4613fd8f5692297e54794f40d82f536b4ca281861ad", + "0x3928ac3a7922068d3d58c872d475de4b6ee668ce92571180aa2e0f44b608685", + "0x57559631c86ae61c4bc364a346479fd644ef0450baa3b6dd87aa57dcaebe823", + "0x5131b0bedd0695fe1017d96a2753bc91ec5a50ec9102bd15f08fe2cb55c8f2", + "0x3b1f08fd16a9a48b3ffe7ea15ac85208800d30aa885c1337e28beacee86570a", + "0x6fdbee006a633304edcd40b726a0753c1e6d8b9f486e73cb7a4298edeb05dd1", + "0x6d6878f1128b533e6ddc2b64d510335bd80864f56f49575b0c6811e7ede4598", + "0x71bfebbb732cc71e76979b14e52fa8e69406bd2566626b58d8ff4d1f09489fa", + "0x3584478e8b309da6629b3942b7dc64d92484f0bd3ca4f1c6d2f561bbe4ffe9e", + "0x1c709a083f7df678e75a768bd1788b3e084850dd0aec971a8227deccf66f752", + "0x22b1c308489485ccf59755d82ffbd77c03250a9a62fd7ce9a5c12560aa5475c", + "0x236630f191d05f61e5e0c8df90d4c6088883c73ea8b786501283837796ffdb5", + "0xd6778571ddc9d83173b4e76f6050eb99e5677fdf01dc38761afbd25cb7f006", + "0x160c79728647bf23440d3892c9bd615e7e2b25c163085beff85ee3be184c66", + "0x32b80244a5de8cae9a7854c9249d2deb9b19458cb82e21b8effc04318eaa5ef", + "0x57e9cd0d03b031e426bf1fe34cd3c0132266961d5451c24427cf67cefb04348", + "0x4931c0411d431ce8920c948ce02a0a7cc31578be805e97788f7a4c9b3ca09ab", + "0x1c5cda08e76f6233f74f8415febbf691d8fd5e3ae04dd04786c92d10b44f92c", + "0x13881dbbb8fa92d709d68e360b7a013a418cd8e8607444f2400d26aeee2d891", + "0x44fcfbf1735690d807db146e2f70086fd82f5f2540665da5733cab4700e34fe", + "0x4b10f4ec277b4581a61b80e42c61491d7f5d8dbfa6935b31f83e2636e87231e", + "0x1098f83cd2dbfbc372b13e9cb9bcb06afcdfbf9100c637b908d377ab97cab61", + "0x782cabb4fec1edf8b17f4389ba59538a9f6d1e3996bd75d400d4ff3f72b8d96", + "0x427b37d3379904eaa3d6fa0a8a0ccc4f1983e26874060ce4fdebec21c20225", + "0x561e526f24737eb9d101c8020f7a542f4fe537ba970ece6ba938f462d78d9b4", + "0x3b77afd2d93fd5fbe173138beae794d78312af32dbee9b27e3777ab1a1d9221", + "0x31bd092525444ef0981cb651228f19062683470b0dff76c3ee9c1f8005939f0", + "0x64d438a43295c8dd8de7e0df3ffbf750f304cc1c62c13f2bc7a57aca962f6a", + "0x77c8b556a878d440b85455a6f44807c00282ad826c29665497d3af8bc76227f", + "0x11164de4ca9978c8560432c517a6bea9c105043aec236431a578cef73096f35", + "0x7cea3fde95e56e35fe6306fb3813aa2e95a9190856ae7185e9d5076ded0f7ba", + "0x4cfd5dc5f93146b5de820c9163379edab97489dfc1142eb6a984f048695aa2c", + "0x2d3d8789f73032b36cc2e2eff1872fd6c6b6d07c506c67c84372919e45bcb80", + "0x4b3e456a725e45134f80eec44d68ee4b12838dba5f1586a7d4dc969a190f877", + "0x7bb2369c2803379f302fa539ef1ce94a0c31e616b3a7f062501cf711cc7834c", + "0x2f3f040f7cb0f5a6ed851ebff612f3e2d6b296239c3678e944b510760b42e41", + "0x3a4f19cc3bfb3f5cadfd4b4a2b09b85e55eaedb5cc01653295fde37b887c6c1", + "0x7cd020d7ab1220fe831ce30a9b77a80af4e7c91b9cf236f05396f3097e4622b", + "0x498a9b2b397482983b978bb6b3f1793c427a398b52f186880300d39a88b0f61", + "0x3121a1211117c1382bb2926aaf9b95f8d099c8e15214085cf17c92a37ae451e", + "0x4572d060e3bfb9b0e8cbdc3bbecc2f6df1bf5114afb69d2795f982e4b4c25ab", + "0x66379e40029c11f6053e555c030f67e8fe188315256897de8dd0a3d705a207d", + "0x3d60c16de2c5fd074d7ebc34eb3da1340a4a4f721d6ca7c752a54d0b7f60260", + "0x733c74e0666c8572a88e1beeb472a91df7fa9407f927d55ee6c0530dc9d6727", + "0x5780251737e68a06de86b63d0ccfc37aee4efecb8ba123c94420559ad1e25d0", + "0x30cb8103a65ed5c8a54ce2c48d5a9151098928ca056b5a50366d0a65671ba76", + "0x18e699f5c1970b67a5c0fc5a779caa9fba0d88db93bcdc2805a61f55f653b35", + "0x71e34c066944020d71a400062a88199cf42e85ec6e33a6eabe671360f49d66", + "0x55f7f28df03ebdf5e800f15a760b9b7044106d469ad5d7cb0f5d3c903965396", + "0x4b9664edb3e9fb1a93776afbe7ea25e1806d56106da59eee98b51249c34046c", + "0x34e59a631f795696ce30a6277da07ec4c099c5d4ef21537b234b7d9af07bacc", + "0x190cc1e217cb3f4b45e0103f17a273db8fba555bc1d9838333c183a5dccfc40", + "0x777d6eb83a5d07d4b74fcc649ea5e7cfd662a67d7495a92aa316df211858f4a", + "0x48bb8bbcc769fb196c56e882f093c89f09f1ef208b3db20d99f23a45c540275", + "0x3b773bdf22677476d99aa59adfbd2d2eb6be35b547e9b0b068425c4f41e6f28", + "0x26a9e229dbca76a8ff782f7ba72f92fe8d21a62813b4f9b32d1684aa34dad32", + "0x6df14a5cfd348345d9b10324c6fa46b8c0ddc9d57b1596a97faedd818360f6b", + "0xc61e8a74e5ef8f534da76913c956546ffd2b0544cbff4f306385946aafe3e", + "0x1cb61f1ba52674a8c69f28d452046e766013952d95ef29a6b2e215ac1466759", + "0x6756f9cad2febf873af5064e29214dfa7484818810d31eaabaf9f4513e4e9c8", + "0x37c496f095ae4cd48f5bc98d3f53df035939989e69cb114405d6f2c5b5799ad", + "0x12fddba4c5e3d1bce328ac691fa95c7c432cb4ce92775b9ee564a51051403e1", + "0x67840f591692a545ee35cf014cc89b27d8fbc4943c2def9449a063fdca5f6f5", + "0x64c9911992fc24243d100c9874f1d45cba56c5722257f3378ad559cedaeddfd", + "0x5c33cd686177e11081276633bf6088b72eaa5ef1483bbeb40b86714f08b3ac3", + "0x26604322d8bcfc42bb6ff5e7778510afee4a58ccb926f9323fe329fca5a88cd", + "0x6d77087b59a1f6c1d78565b38fc9e122c8853e3d1696c4bbb10bf205aa3bc5e", + "0x3e2d5e58553ed489eef7e351a8119b7d0c6e4eeec639699df8f4e5074d5107", + "0x481dd6c4269e0755e68d1896e94d9c52132dfd997e097240ee591b8a4f6420e", + "0x9269e75e0736083647f03fe15af4598e6c72ab0c7a3486590969defec3cb8c", + "0x878e8a319aec680e959421d53e5c694cb50c7e45b714be0589dd3c9be96aa8", + "0x2d815b8b7258c8fd1d42f9e2994e6145a3848d056ece2705c491df8c68ac6bd", + "0xf48c84b191a18376124e6460e0cb45e566cb26a5ad2430e6d6d46a7aedea21", + "0x64e69082ad30369452ad004e43441d799e514500ac2db9e92d6b80e70f052f7", + "0x31e576ed38db972e22a1b94dd8fae29badfac10c379223485aac154f02aab19", + "0x17dfa318225b8008dec31ed02905c79fb2c724a014afc6f4d42d2d954909985", + "0x6e1ee5b62266ffb846caec716adf913d824d70efa595a494d8bb7b153ea611f", + "0x7919ab7b4e7c0dc9a521b45b3a6a9a6f83a098c42abe9fa05a78d6662980215", + "0x77888451a1c6e90fc7f815f8196ca512206c066a7d0aafd73fc10db78ea8557", + "0x38a22a36f0af13a0955e98b8880c4f808d5d6c92aaa26c5244a607a65883bbe", + "0x72fc0406854fbd0afdd6eae70c4dba1fbbb233be0a53c309e91b47f819efbbf", + "0x2bad7ac836d42b825b965bc6de070818d3bfbcb418c765110814c9c87f877de", + "0x7c5f6b2849238eb48a9e68b3f4f8f625e3150bc5b9028efd5b302cf11a576d0", + "0x77407bd5d5793822b8f7b65920a0025207ff96a2072f3adf73a7ceaf10646a4", + "0x1793ff61b6953314697d6b33a3aabfb4bbec17765f34c9d23fcf0d7e7150065", + "0x7c0132dea5e0085732abc81652ddfd6c08c36a681ad5ffdbfad69b917042548", + "0x5d1a9a67e47e100f52d2807b5e0d06bd94b70e3d2b2f99dded9b84eea406be9", + "0x20e1a45b53101ecdbfc3560b8ab734d38c5df517c0dba141f3d55e7108685c6", + "0x3189b271a6f95ddceab716181ed1707a7e02f0be274fb5c0507ba9802096f60", + "0x44f406d9ada7d0b08f0c129a2626280ca3b0ab6f71dd32e1cb0b6af26f0f110", + "0x142daf638d33d649341f1d1685073fd59d1339879bb2a009de92e2e981b6ab6", + "0x67289d9154acb02b7567961b9d732d85b36954578580dd4c8b1b3f5de6cfccf", + "0x7e2c91b5b1a5202a7fd7b0c292b4f8d6e488d4aed71dca85cbd469aabc9c96", + "0x48abbf51c740881c5e14f833956aee4ba440721dbf9f6ddf5263a292d0d4672", + "0x3b2ea643097273f9db55fcf5fcfc838b47c82ee63e84a80f1de8ac93e772777", + "0x7a5b3376cb397289168518264ff1cc80b78b58a856c3de5b7b1878078b603f3", + "0x1d74c4dcebccec472cfc88fb9dba8403864028df653d977603c119da3af554d", + "0x50d645890807550d46aa7bf1383e2220c5b572a17bea7f718455e914337fdfa", + "0x1c17b8bff58e3edc0515aeb0f69f89e12f4ed0daab1eea1de83688af4254fed", + "0x718afe487091f9be9ff706e2d7253c3119e9ae3bb1f72995b3e6a79c77ffcb", + "0x4c9ac9b9afb1e0503a905a9a65cba3d62213b41131ec47bf7f0649590accc0c", + "0x1e1d28aaad8895b0fe6675be25ffdcbe8986a8617c26c404248596f0bcc2185", + "0x3e6c28909b15eac6936103faec222cd56853665cf77ee04491b57690a4fcb41", + "0x4312ce58486aff4662c077162d9d2b49eef59ffeee9fcd4830eb13f72d5ce5d", + "0x7af377f1cb3cc660c11de9492e53a98e5ab50332306401fb9f65f8d1d27b0c9", + "0x235111494afa08c67f96c361ed47d9ab6fa50c176647275d3ef99815a90d568", + "0x7b8a0642ba120d69aacc0af08ccd1c496b84ddacf961a18db819a06eb81ea73", + "0x4e35e7809edefb7d1ca8191e8b41543cb42d72c4d784f1eaf567ce544ea69f3", + "0x44d8f03aff37860e028674d9a0a4d153f7bdc4ea6cf3dc6a72719b428765727", + "0x6f5b1e9eebc09fbd2b4647d5fa57323092157b3deea42e85763d2ae395a8b95", + "0x72df12613184d9eee1ca24394a735d6adf0bf79ba8cb992cd0a01c578216f94", + "0x6602344d8f1fd49dd7273b7981f6a8549afbf09b66bab410d61cef28356fddb", + "0x2266715c063cddeca95071bc0c5a86b5e3bf684291b3dbfe625040f09956cc0", + "0x26f475d2f9cc4e9cf152aa2c5117f22d66325cbdba440b681bd9fbc1f9c5e6f", + "0x55ce24427479da5491dd16471840670d4036f6b701e8554577d6ee920f2000a", + "0x66972c166f59deb2ed80a63c0f575f2ac3a8ce37e3ba6ea7830d85f87a7e5d4", + "0x4dc320e1c039986787ea90010babeab9fa7f76345154374e787b1fd076ac1cf", + "0x196b8861fc7caaad050253c12e1360413dc792e69328bbd08622bf39ede8474", + "0x20df3d38f55e74a82e2a6eb86c6413fe8ae6c50c1a18f71ee0cb553fe4c0ae", + "0x3fb3d9d18046e8e36a1a1d5b906e9605de57c3ab99a0c77739ab4c04672adfc", + "0x754c034fba112691f7f3bbc87b6ee7a5565419c32e5b8953af94323ccd6ff0c", + "0x130b3a417200414e7a4618fd3e282796775cea0e2afa90e24ef969387979b5e", + "0x55167fa61caf4b07ca86b7d1b9513c6caa351cbb82919605d7c148783230262", + "0x2e84353fad69c30f6a337ae55d720c36842a9464ca7278a95790071443fcb4c", + "0x4691bf76d0477e707569cc6ccbe69e65caeaeea36d5c7bdbf44d4cfff2bf698", + "0x1a6182203b08d780f05ddb6d22d2512c01bbc889fa0c6d215748ba15d0a1e7c", + "0x520b3ac7f1719e778e987cf8ed0baf8f866034c2f8935f951f6ee7c72ca7161", + "0xc1a13b029107c71f49e5927a21cefa15ad6d66d1fe4d41b88e9992193b673d", + "0x265d45c104c3949b41f6575f05bf85829f8b3e5656ef1b99e6d6d181168de71", + "0x4205958addf57e7a61cbc33c7012f7511e0dc9090ae148d2d133a0c5d5dae98", + "0xb5a9a17193b18c09d3f23f175e87eff0ef5320ba0eef3f8ea1946d8e29e0e6", + "0x30c86a3042fafffdb8af395c66b1db6691a7e044138523678114273e4b6b3a9", + "0x7cfbacb65c8e10e7d2b3c744c384ae75b9eae79e323aae8faa197ef78b801b3", + "0x1659b34c61a3c08ffc9ff6c921bc7dea7917898bffbca876d0ca712896cda49", + "0x47fa31bec4c9fc313ab0864c2d56d7dd229f10e3077f839ad4b305818080319", + "0x5ef39c192487a2bd9f0ff55439a64b705472552f72074a8ae38d66466238a3b", + "0x4bf71155873c7b5acdf0a6c33882ba1a1f04334c042dbdcce79554f56b10b06", + "0x4ba139181c4aed0bece1b9224299709d4ffb81fff8c2e0dae13e23b834d1754", + "0xa717e659581f6d62b308704871fdf6d190151a6aa6c7807832ede25e753bde", + "0x60a865ea177b8f1b97b9915c77bc9cc079ccdac8f2978c41adcd8ee654aaf52", + "0x773fc2cd26a54888baf4b2153aa36f8e707934da93d61facdaf5dfcb5b96679", + "0x474a7f49c98680a6fb1d9736301ba79a13ba8887e663c106d0337936048344c", + "0x31b2c6d12d94c10f2d0d972f953872236f12b0543d9f0ac158a3f1bfcbb030c", + "0x52f60fa506d5ce4f83424098a268a59dd5b1f0e22e4fe2f23385965c2a97ffb", + "0x773916b22992c4f5fa0ae67106cc44892bac15bdfd9eb0dcde7aa1688d05d30", + "0x6d2c6c79d72c593bf5b1f9016c320b2e78402d9ec6da13b4ad374c472096f4a", + "0x3be02e91932a2a1755f68ca57650468bc304226adad5b1386783217d93c1c77", + "0x2f4ba94af1e252f074e667fd796c9c96afc947c81dbaa082a59f4714e50e4b", + "0xb047d825ccef5a103ac6bc226ff6369a0a28d24d0c5a59d613319d848f1bed", + "0x3e87789bd383ec58981af41032da4355d635b2847098fcfa2af8236c0e197b3", + "0x1766c93bff704d62161c1a15f5543da37edef9773c89efd45a23228cc342fb5", + "0x618878742e8199322ebc4aa4fbde053a87d7d30735db847c91e79689a4fe71e", + "0x721d2a176b86f13e05836c1fabfeb6498a85401897e4bb8adf2c35cd88037ae", + "0x4df08c06ba3cd9315cc59195d89d5803d10cd3bc7fb8b30a0cefb2488ead935", + "0x4d14061763347ce0098f638614dff90d6e4413e8d2d593c82cccbc0c4d1b3ad", + "0x5a3119eb7dacf3aaa7b87072d526fa936702ce41debbc3d42c193eb24bee625", + "0x32a7fda1d7e408749af42de287d4b2a1c841968912d25a15d477fc4b1b66b6d", + "0x2f38659a393c2bb22ed25f0c75639ae745cb1d52715772eda95992ec39e358a", + "0x6e3f831f55331e7b090a8d78f40fe0544b80ddcfc899660f9da9db0b62dcd7f", + "0x24e64758196cca0aa203a7f5ae04d9dbea955c9f7c94e8705ad2f87ead00365", + "0x749eb73578ba7a273db8138624bfd856c75c14a10cf9dff9425bdf233e63db4", + "0x2deb5b70f9d822dd2718ea5c1ce49fd6ae1f9f71a90624bde798b3853f86daf", + "0x370d5f60e8af6ecc5b4f9a96705fa9ae93948cc5d8a90aaec69a77af00dec61", + "0x2291788e4339158ad2f6135a359713ff8477609064e204e7106e04afede1c6e", + "0x57857064e88c43cd1424c44ff818f7aa3e6411a05722c86f251a3cc624d5e08", + "0x46f8a21b7baf396f5d5a2d4f1d5e0bcd7876e8a83a0afe0ee0cd3086b3e2353", + "0x8005b81c33fa09c2e71593c069636325516c03d2dc85fa83f521f43f2241f7", + "0x5824baf8b2c01d331fc1902924b42952ee2899a401979c0b614ea4374d708ba", + "0xd25fd241fcd52a4b2a305b0577f7be8f25878c06d9fde8d6da25dda0d561da", + "0x19c423d02c894419629e9d91c9f41befa42b3c0329f334a6b2ff4a8133f35d1", + "0x891b49adb989a018592add8710102ff991d47fc67b949355a88609ed493a94", + "0x4b083acb1f18eedbc620692443aed0251022882ee5d2507f3155eb7bcc4c910", + "0x737ba8ff635a304604741a27c761762b5f55eb1cd893658bc77b3b68cbb6237", + "0x230bd9d7507d050573a4f84d8f15408a843266defcf4d4deaa3b767e2392231", + "0x5b5d0256b572cf7efd22881f524ed01c395dcef739296ed55184c5427311755", + "0x6242b30f96eabdb817fed9e48eb72ab9266ce0053b9bf872df61264d1598eea", + "0x24b05fa149d82e4f7d0537135e2b12530d0b7be1edd4b1f66e5704d2050a825", + "0x18bec5b5ff98f2820bf433f45f859d916223dbfa40726f4f1f19ec12612742c", + "0x31d81510b02a94f08444de459d9cacdbfa8e0afced536c77b09324527c936bd", + "0x6ba59c9d7d2624c4c7387e8934515fe726149bb5bfa47f409b040ccea726182", + "0x3886c0362140b83206c51cc77040b1529d359a42739a75fd1c0c7ccf419dc76", + "0x3327e4e2c5d8134dcb5eb260c48581a31c4cdc1f0f9ae791592ba0fd210a50f", + "0x5cf19b5140aff2c0a705a0436fd6060ca9862597ec51727f31f3f65cb5b24e4", + "0x5e894322faab80e5bc7ea3ab4bea86a994fa3533ef12515495d0a34a8e20f0", + "0x34551336c02689636849ebae18d8171ac114ce1a526e376d1a39910b590b1ac", + "0x4ab444ef5c07750919ce6e1df5d8ac8df745afcb99b3f24d851499b0d5b9c7d", + "0x1d3b8ed348b4e4a2976f014f4ec73494b39c71a52fb2880b3f1474cdd314e42", + "0x86e5177689081231857f3faa2cfb0ef65994097898b92143b09834aa527c72", + "0x3c80609dbd4bd82d76cd1ba8b5e3a89c3cef792515688cb98ded351594ac926", + "0x41b28e2d137b4bbf4df24fac8c3c59eb5f0f57f4a6ad302bb83065c4881e38", + "0x4643deb2888719bb9ab2e1b469d9890ed2c4482f69177e256605094ac623157", + "0x3242df56cc04b37f01165e61e39416b53868c8111eea29617cf06fcb0ebe466", + "0x65c75da4548260f85a7ada532f0d693aa548c2f2c933c4cb53deaeaa7b0ca0b", + "0x11e9c3624642de8ac93624c420eaf7f19e822b2c79c9f588b36ade12b849cda", + "0x6ebed5ef3479f2efe44c82c59068b3f2c440759fffe443ebc14221b1b0abb75", + "0x4d01a32131b1fbbe7d414132fda619d13d010bd2aa30b143d2ee79f4fe82749", + "0x2e2ba351e277f871b1781411fe6ac0e5fa3bf0e8f945e32f7565fe77b465ea8", + "0x38926d19a4a9540438a881b25cd8b6b4b541273b47275f266ed929b155d73ca", + "0x45fd42c8194615a4eaf162ffcab54bef12e78d32c1ac0b90a08a7a915a46c2", + "0x6327b500a293c4996b44f0d1d1caa8353bc6cc67f7d154fc73ece4b5f19fbfb", + "0x22b411e0dcbeac07d4471e4e80ee505733268205c81f026f6b90bf02c00b67", + "0x1fe0b88f82c002ea3a42ba5af7a00ddb6b6541379e8c5008ec07d05f835c996", + "0x73491c42aeaabb15b5d820d32bc54bb20fc53f56d0df504151e0c510c67c1ea", + "0x511c63ee1610609754383cd30c9264932b42d0d10caaf336076758654e6445", + "0x7eac9d6c57275f636ce6f35fef09bcd8b2afa184140e44c85e8d8fdee70ea5b", + "0x5e35ed457ed6c3b6d4acd125f7b1dd23620d205d4437073171ab1c9a6caf9d2", + "0x154e67f62d7854664dd1e1f27574bd4da9ede88634e9c4f1c59e1f5d29e8d09", + "0x4ca7a7cca722e958b19f297ab807a6c75d58cdc284cab78000f2279d0f62335", + "0x42908552e8421102c9fda44e514a938e7eea6b85c2d5ef52fb0d92963f74acf", + "0x1598f1bf98173fd9d46dfc288ee39ee22c1c1e65d38d47d0ad037dbcf20f03f", + "0x605261525e49d647e9d701bc15581be966ace9fa713f113074b204767c90f85", + "0x322aa3ea17385ba8d084785593ea7bdc48312aa63b71f92400be270516a6ca", + "0x1743abe73ad981481e66e97713873f83d8e311ad35d1563718af6099716406e", + "0x593ebcc37bc1e607f7a3dbaa131109c0061f7979a03f9be9e06bd7623746b0e", + "0x47e27990dcb1634927eb7e34602a97d43f9cdf193da920d223853b39115a065", + "0x4680b27b72239a5c59407481b3d1d2a3dad64e8a3f56897ffc2e96d458a5e24", + "0x63b40b6683a1a074f31bfabc0544c918a0f467921d376b3613251ebf346be61", + "0x729c57e82bc98ac9c7a5c5929d34e47283b66242da5d900fb59775f81c158e7", + "0x55c0f0060a4f203b42cf73e09ad24652f58e355b5b5a25b0db25bde3b02e530", + "0x2c6d987d401682d2cfd599f5555cd1fe2f95611c2b0fd3e400fe98b52e21c1f", + "0x1fb723538c5276b82c14743fedf840bdac75dabf6636a624dd81a08f8fde940", + "0x3ccae9d92df0bb57a386b2102ad987dd312b31aaa7f32e048f948d838949ed4", + "0x318c362dea082a0d44fd065914e9b90c760efb94526676139df1b7a09eb4e50", + "0x2882c96f3a4ec3a45ab42a74a8b193d2096ad85e1931ca042075bc0a70a2668", + "0x3d441f44150eb5cdc78f15403c9b9e30f967897112f896da00c84bffe3b26c0", + "0x600f222f797801af5de701de7e240790c6b0bac312ec2d6c3f298381299fe38" + ] + } +} diff --git a/crates/papyrus_common/resources/class.json b/crates/papyrus_common/resources/class.json new file mode 100644 index 00000000000..253f4eff78a --- /dev/null +++ b/crates/papyrus_common/resources/class.json @@ -0,0 +1,10573 @@ +{ + "contract_class_version": "0.1.0", + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x4", + "0x3", + "0x9fb", + "0x605", + "0xdd", + "0x52616e6765436865636b", + "0x800000000000000100000000000000000000000000000000", + "0x75313238", + "0x800000000000000700000000000000000000000000000000", + "0x537472756374", + "0x800000000000000700000000000000000000000000000003", + "0x0", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x1", + "0x553132384d756c47756172616e746565", + "0x800000000000000f00000000000000000000000000000001", + "0x456e756d", + "0x1909a2057b9c1373b889e003e050a09f431d8108e0659d03444ced99a6eea68", + "0x4", + "0x7538", + "0xc048ae671041dedb3ca1f250ad42a27aeddf8a7f491e553e7f2a70ff2e1800", + "0x6", + "0x45635374617465", + "0x4172726179", + "0x800000000000000300000000000000000000000000000001", + "0xc", + "0x536e617073686f74", + "0x800000000000000700000000000000000000000000000001", + "0x9", + "0x800000000000000700000000000000000000000000000002", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0xa", + "0x66656c74323532", + "0x1166fe35572d4e7764dac0caf1fd7fc591901fd01156db2561a07b68ab8dca2", + "0x800000000000000700000000000000000000000000000004", + "0xb", + "0xd", + "0x16a4c8d7c05909052238a862d8cc3e7975bf05a07b3a69c6b28951083a6d672", + "0x800000000000000300000000000000000000000000000003", + "0xf", + "0x24dcf3525a56e5b3859c521c7facf7812fc97631a3084d277859a564fb9fdbd", + "0xe", + "0x10", + "0x556e696e697469616c697a6564", + "0x800000000000000200000000000000000000000000000001", + "0x1ca27f4a416836d321a19551a437aeb9946fde25373762126dda39b53c0bd11", + "0x753634", + "0x3342418ef16b3e2799b906b1e4e89dbb9b111332dd44f72458ce44f9895b508", + "0x14", + "0x426f78", + "0x15", + "0x38b0179dda7eba3d95708820abf10d3d4f66e97d9a9013dc38d712dce2af15", + "0x16", + "0x18", + "0x2360086d8de14207bc705f7c51c3fc6bb6de6b826f1a4576e4db739d8b5edaf", + "0x1a", + "0x4563506f696e74", + "0x4e6f6e5a65726f", + "0x1c", + "0x65", + "0x1e", + "0x13d20f70b017632fd676250ec387876342924ff0d0d3c80e55961780f4e8f", + "0x1f", + "0x20", + "0x22", + "0x3ae40d407f8074730e48241717c3dd78b7128d346cf81094e31806a3a5bdf", + "0x23", + "0x753332", + "0x39a088813bcc109470bd475058810a7465bd632650a449e0ab3aee56f2e4e69", + "0x25", + "0x2f23416cc60464d4158423619ba713070eb82b686c9d621a22c67bd37f6e0a9", + "0x27", + "0x1597b831feeb60c71f259624b79cf66995ea4f7e383403583674ab9c33b9cec", + "0x19", + "0x800000000000000700000000000000000000000000000005", + "0x29", + "0xf98f4a6c1a3c4d9e27bc29334f4348768bffb65b1bb9b7ce0f91a525e1d84d", + "0x2a", + "0x6c", + "0xfeece2ea7edbbbebeeb5f270b77f64c680a68a089b794478dd9eca75e0196a", + "0x2c", + "0x1289347a53bd537cb2be622dc3ef1bae97ae391de352ed7871b08a409f130a8", + "0x19b9ae4ba181a54f9e7af894a81b44a60aea4c9803939708d6cc212759ee94c", + "0x2fffb69a24c0eccf3220a0a3685e1cefee1b1f63c6dcbe4030d1d50aa7a7b42", + "0x101dc0399934cc08fa0d6f6f2daead4e4a38cabeea1c743e1fc28d2d6e58e99", + "0x800000000000000300000000000000000000000000000002", + "0x31", + "0x5b9304f5e1c8e3109707ef96fc2ba4cf5360d21752ceb905d488f0aef67c7", + "0x32", + "0x17cc0d253de5ad59018ea04339445145fdcc7ecede2a33ec110184f1cefd2be", + "0x1bbd4b0c9742f41f0e556432056bba4255e26798f7858b7f11339dac76012b1", + "0x34", + "0x35", + "0x173c3aeee6bc7c98ea5205564f937f20718df97f0d752272ed3716e3e3d088b", + "0x36", + "0x66", + "0x1c85cfe38772db9df99e2b01984abc87d868a6ed1abf1013cf120a0f3457fe1", + "0x38", + "0x436c61737348617368", + "0x14a7ddbb1150a2edc3d078a24d9dd07049784d38d10f9253fc3ece33c2f46a3", + "0x3a", + "0x90d0203c41ad646d024845257a6eceb2f8b59b29ce7420dd518053d2edeedc", + "0x3288d594b9a45d15bb2fcb7903f06cdb06b27f0ba88186ec4cfaa98307cb972", + "0x2d7b9ba5597ffc180f5bbd030da76b84ecf1e4f1311043a0a15295f29ccc1b0", + "0x3d", + "0x161ee0e6962e56453b5d68e09d1cabe5633858c1ba3a7e73fee8c70867eced0", + "0x18672a8f646efb247fea41bb961b82efc61071ff1bf295f077ed3f7f5fbe1ec", + "0x40", + "0x248e8fae2f16a35027771ffd74d6a6f3c379424b55843563a18f566bba3d905", + "0x53746f7261676541646472657373", + "0x53746f726167654261736541646472657373", + "0x436f6e747261637441646472657373", + "0x3808c701a5d13e100ab11b6c02f91f752ecae7e420d21b56c90ec0a475cc7e5", + "0x45", + "0x46", + "0x47", + "0xe688ac0888a7171e23d265a0ea68699a0ab1f7192e9651213e940c13b80319", + "0x48", + "0x4a", + "0x1c61d0f622cd5a7f54eaac1e4af6d7e31f8c6d9acb92684f4e78963157c263b", + "0x4b", + "0x1f5d91ca543c7f9a0585a1c8beffc7a207d4af73ee640223a154b1da196a40d", + "0x4d", + "0x4f", + "0x50", + "0x800000000000000300000000000000000000000000000004", + "0x104eb68e98232f2362ae8fd62c9465a5910d805fa88b305d1f7721b8727f04", + "0x52", + "0x33db04f8bf393d7a10f45b3b9adce8d5f333d7a13db7a3ff2d5d3171e0b03a4", + "0x28f8d296e28032baef1f420f78ea9d933102ba47a50b1c5f80fc8a3a1041da", + "0x6d21884c4651d3ca8ce4f3cad5c986babe287f99c59302cfa7b0bbf79ae179", + "0x55", + "0x2ec7c338575592f1c8dfc7277475fb507fa6dbe32e91ed4877edd750118badf", + "0x5d18937d10b5347a398f158c0087055a32385cb792a13447ae8cf78756ac03", + "0x26ee0aadcf9d5ca1f9dc79dd0c46ccb60ebe57085963750610cd67a59d50975", + "0x13152081fc9f5c0c9940e9b41ae0cdb53f68d70078cf676f50239842e0b52d0", + "0x3ae507569ecac2989ca90094d2595cd0ef5cbfc283eced198c7ab0e2e1397f8", + "0x3eba5f295a6f9a28c0e58874daaae7a01414aee71fed3a4f321c9ee5d8a357f", + "0x3b49669d6f61e22f521612046d7c2d3fcbd59faee13c997508cc6dd42c50d4d", + "0x33a44665fba067e31d08b2c13820c7aab471d4b6b0c5578a7ce7f0fb50260ec", + "0x281341dd9f4ac08d5a12a917325719d2acb34fda2c86607606e585c3832b026", + "0x711cec3aa770776575f4905535364c29e2abc42bb005a5a0f1729791f8da8a", + "0x1deefea9d0c16c2eb738021b7529472d18d2684fe3fc6f066df8bd982fc0d75", + "0x80000000000000070000000000000000000000000000000e", + "0x156c60808ca6240a5f664e67b7c5c245c75d99dc1786f4326631a816f77178", + "0x54", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x61", + "0x800000000000000300000000000000000000000000000005", + "0x24d1fd89b67292dedf95c26145ffde2e9f0bfe5cf06b20b04b05b51fbb0033b", + "0x63", + "0x3693aea200ee3080885d21614d01b9532a8670f69e658a94addaadd72e9aca", + "0x3c7ee94100b5c63828928ad04b4ee403391886571321a2f8f2e58d1b6141cde", + "0x67", + "0xa7", + "0x800000000000000700000000000000000000000000000006", + "0x7d4d99e9ed8d285b5c61b493cedb63976bc3d9da867933d829f49ce838b5e7", + "0x6b", + "0x2ca39cde64b91db1514d78c135ee79d71b3b57fffee52f1a3ef96618a34d8c8", + "0x6d", + "0x18508a22cd4cf1437b721f596cd2277fc0a5e4dcd247b107ef2ef5fd2752cf7", + "0x6f", + "0x8416421239ce8805ed9d27e6ddae62a97ab5d01883bb8f5246b4742a44b429", + "0x70", + "0x13a34c3a07fb12ab04f8961d12c1cac659a74ffde34a7bada0708a1103ce365", + "0x800000000000000f00000000000000000000000000000003", + "0x72", + "0x2c9020782f9525cb15d3f132b6086816a5dabefb1a0437054202fb171c75145", + "0x73", + "0x27b05fbc8418f9db2745f2ae71e4af5fac6811448414afa4f894aa3b8c68ce2", + "0x75", + "0x1c8505637721e9ff545656181cd5571862c272c7063ad675b57401799d34587", + "0x76", + "0x135087deb84076d911a865705036d6031bdc60a0efa11ee97ca7e0fbfee376c", + "0x78", + "0x29dcb52dff8b4a828c533d9fa3b99ec6edf0b67728df2a286ab21ac76176500", + "0x79", + "0x15cb9d83db8ab255128a341c754cfa20b8c39f9b71e1035c358b97e36aa69c4", + "0x7b", + "0x29ad92e55ab8088ed8e3d2827639508b79913a70e9dc213ebffd77f5bc69c3d", + "0x7c", + "0x3096c001e81cc138a13933bbc6e499779a1fe08346f38449c473a7956dbdcec", + "0x7e", + "0x3c0dae5c4b3564a789109132738a600f194ecd06a3252657c655a1b742e71a3", + "0x7f", + "0x1db896f0b05cfa6707983a0f413233717fbee8a5dc1f78a4250d2d6267c5930", + "0x81", + "0x9ecd72f6c3f1e25b229d98babf09e1c73a432451cce99b16397a57a0ad5209", + "0x82", + "0xd27204ee93f77fb1714731cc4bb4ea705fe77800afad081d36a66e2c8fbbff", + "0x84", + "0x153eba592a63c38cda70751d13e87acb197c7345bfebbc315b0a51e3c8135ea", + "0x85", + "0x87", + "0x212c0191d31f49f0f3dfb855d91d40f886e0cb5f1dac8834b67820dc5346a20", + "0x89", + "0x1814137beace2d8dcf2ed91c08ef2f9c05067d77bc0ca16bbbbb3f4e25e27b2", + "0x8b", + "0x23b3001b4b3b7f9e1b6498723467af80e066e8cf805c10c103bd93ad4f02bc0", + "0x8c", + "0x224a57ba2504f0018c4fd92c0f0e6ef13a37bf8d3d6479b8faa16fc36f624d2", + "0x8e", + "0x2bcddf47e99bd2b365b672ce4ab3c5daf69bca568e14d0c1ccc9cee29ffaf43", + "0x91", + "0x3bf35e9f5398ac00dd0d96dba9e1f1fd0d8c12f1e9cce4e7abdd660163733b2", + "0x800000000000000f00000000000000000000000000000002", + "0xcc5e86243f861d2d64b08c35db21013e773ac5cf10097946fe0011304886d5", + "0x94", + "0x23204b4adf3854c5fba975a31d32de6ddf23cbf2f59f33b548a4903d33f6eef", + "0x28af69a60ef73f46d9a506e15d44c1a38e349b1b80cf4a6b70d56c9fe7a9203", + "0x97", + "0x107532bc0d80b6ebbe945434585c46cebc10c524181721cf8e2201f0910307", + "0x98", + "0x1735eb34ffeaf8accaa4abeaef6521748bab5d1302d7967492fda631b0d8660", + "0x1ee471fea880cdb75aff7b143b1653e4803b9dca47f4fcdd349d11fec9d7a16", + "0x9b", + "0x341d38eba34b7f63af136a2fa0264203bb537421424d8af22f13c0486c6bd62", + "0x9d", + "0x103a42e181f130718945bf95d02f3ba8a4b02e42a52022215a4b71dc9d7dc64", + "0x9e", + "0x156b6b29ca961a0da2cfe5b86b7d70df78ddc905131c6ded2cd9024ceb26b4e", + "0x3d37ad6eafb32512d2dd95a2917f6bf14858de22c27a1114392429f2e5c15d7", + "0x25abf8fd76a01c7e2544d26b0a2e29212b05a36781e0330b46d878e43b307d1", + "0xa4", + "0x348a62b7a38c0673e61e888d83a3ac1bf334ee7361a8514593d3d9532ed8b39", + "0xa36a0a15af8cf1727a3a4fd9137671f23256b1f42299af56605a6910c522ce", + "0xa8", + "0x3e1934b18d91949ab9afdbdd1866a30ccca06c2b1e6581582c6b27f8b4f6555", + "0xab", + "0x29d7d57c04a880978e7b3689f6218e507f3be17588744b58dc17762447ad0e7", + "0xae", + "0x28d3252c9df96ada7602e4debae27c6fdfcd09d9f2ea8a09e99e56efab1307f", + "0xaf", + "0x3ab802bcce3a9ca953b0e1f31a5b29eb27a9b727c891e24300e1b5cc57387ba", + "0xb1", + "0x2857c8eed09aa950d2bc411e245e9f97cbb8625661593905246875ea75c45cb", + "0x306ee1b3df3368a2d9762b655e64321cb3d06bfe8688fa5ec7fc954c936371a", + "0xb4", + "0x800000000000000f00000000000000000000000000000009", + "0x1552851bac512fea401910db633a4f5871c9a0e9765a5b07cb2142c85b684c1", + "0xb6", + "0x580bfb4857efc49e54c7e93e36506161857cae277315f915e9a36cf0d7cc21", + "0xb7", + "0x1c25c9665833e285eaa79ed5e2438c2487467dbe5b2f1e0ac47b57996671144", + "0xb9", + "0x11771f2d3e7dc3ed5afe7eae405dfd127619490dec57ceaa021ac8bc2b9b315", + "0xa853c166304d20fb0711becf2cbdf482dee3cac4e9717d040b7a7ab1df7eec", + "0xbd", + "0x506564657273656e", + "0x1b8ede3ee9a223bf2a237d374233c99c13677364744717814226e9174a88067", + "0x3d092b7967b0fdc524ce95075d03229cfc59ee514c4a7ded5c90b2b37408b0c", + "0xc0", + "0xc1", + "0x10cfbfe828407532cf9f305abb44380ee6893535051d5b10b0f73ebdae0aa08", + "0xc2", + "0x45634f70", + "0xc5", + "0xbf", + "0x10203be321c62a7bd4c060d69539c1fbe065baa9e253c74d2cc48be163e259", + "0x17b6ecc31946835b0d9d92c2dd7a9c14f29af0371571ae74a1b228828b2242", + "0xc9", + "0x34f9bd7c6cb2dd4263175964ad75f1ff1461ddc332fbfb274e0fb2a5d7ab968", + "0xca", + "0x11c6d8087e00642489f92d2821ad6ebd6532ad1a3b6d12833da6d6810391511", + "0x74584e9f10ffb1a40aa5a3582e203f6758defc4a497d1a2d5a89f274a320e9", + "0xce", + "0x1d0c38954feffa7920ed6c6d5e3231a98e72f2f9f770df7e1f662b96a81b646", + "0xd0", + "0x53797374656d", + "0xd2", + "0x179de9c76344467236b20ddfcbd854b82e7eb901c82c7d76f8293262f0aa4f8", + "0xd5", + "0x4275696c74696e436f737473", + "0x9931c641b913035ae674b400b61a51476d506bbe8bba2ff8a6272790aba9e6", + "0xd4", + "0x28f184fd9e4406cc4475e4faaa80e83b54a57026386ee7d5fc4fa8f347e327d", + "0xd9", + "0xc1f0cb41289e2f6a79051e9af1ead07112b46ff17a492a90b3944dc53a51c8", + "0xda", + "0x4761734275696c74696e", + "0x441", + "0x7265766f6b655f61705f747261636b696e67", + "0x77697468647261775f676173", + "0x6272616e63685f616c69676e", + "0x73746f72655f74656d70", + "0xdc", + "0x66756e6374696f6e5f63616c6c", + "0x3", + "0x21", + "0x656e756d5f6d61746368", + "0xdb", + "0x7374727563745f6465636f6e737472756374", + "0x61727261795f6c656e", + "0x736e617073686f745f74616b65", + "0x64726f70", + "0x7533325f636f6e7374", + "0x2", + "0x72656e616d65", + "0x7533325f6571", + "0x61727261795f6e6577", + "0x66656c743235325f636f6e7374", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x61727261795f617070656e64", + "0x7374727563745f636f6e737472756374", + "0x656e756d5f696e6974", + "0xd8", + "0x6765745f6275696c74696e5f636f737473", + "0xd7", + "0x77697468647261775f6761735f616c6c", + "0xd6", + "0x4f7574206f6620676173", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x616c6c6f635f6c6f63616c", + "0x66696e616c697a655f6c6f63616c73", + "0xd3", + "0x24", + "0x73746f72655f6c6f63616c", + "0xd1", + "0xcf", + "0x26", + "0xcc", + "0xcb", + "0x28", + "0xc8", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0xcd", + "0xc3", + "0xc6", + "0xc7", + "0xc4", + "0x2b", + "0xbe", + "0x2d", + "0x2e", + "0xbb", + "0x2f", + "0xba", + "0x30", + "0xbc", + "0x33", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0xb8", + "0x37", + "0x39", + "0x3b", + "0x3c", + "0x3e", + "0x3f", + "0xb5", + "0x41", + "0xb3", + "0x42", + "0x417267656e744163636f756e74", + "0x43", + "0xb2", + "0x7533325f746f5f66656c74323532", + "0x44", + "0xb0", + "0x302e332e31", + "0x49", + "0x64697361626c655f61705f747261636b696e67", + "0x61727261795f736e617073686f745f706f705f66726f6e74", + "0xad", + "0x6a756d70", + "0x756e626f78", + "0x4c", + "0xac", + "0x636f6e74726163745f616464726573735f746f5f66656c74323532", + "0x66656c743235325f737562", + "0x66656c743235325f69735f7a65726f", + "0xa9", + "0x656e61626c655f61705f747261636b696e67", + "0xaa", + "0x100000000000000000000000000000003", + "0x100000000000000000000000000000001", + "0x617267656e742f696e76616c69642d74782d76657273696f6e", + "0x617267656e742f756e737570706f727465642d7061796d6173746572", + "0x4e", + "0x56414c4944", + "0x617267656e742f6e6f6e2d6e756c6c2d63616c6c6572", + "0xa6", + "0xa5", + "0x647570", + "0x51", + "0x53", + "0xa1", + "0xa0", + "0x9f", + "0xa3", + "0xa2", + "0x414e595f43414c4c4552", + "0x9c", + "0x7536345f6f766572666c6f77696e675f737562", + "0x617267656e742f696e76616c69642d74696d657374616d70", + "0x626f6f6c5f6e6f745f696d706c", + "0x617267656e742f6475706c6963617465642d6f7574736964652d6e6f6e6365", + "0x537461726b4e6574204d657373616765", + "0x706564657273656e", + "0x1bfc207425a47a5dfa1a50a4f5241203f50624ca5fdf5e18755765416b8e288", + "0x4163636f756e742e657865637574655f66726f6d5f6f757473696465", + "0x9a", + "0x99", + "0x617267656e742f696e76616c69642d63616c6c6572", + "0x636c6173735f686173685f7472795f66726f6d5f66656c74323532", + "0x96", + "0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd", + "0x617267656e742f696e76616c69642d696d706c656d656e746174696f6e", + "0x7265706c6163655f636c6173735f73797363616c6c", + "0x95", + "0x93", + "0x92", + "0x617267656e742f6f6e6c792d73656c66", + "0x90", + "0x617267656e742f6e756c6c2d6f776e6572", + "0x62", + "0x617267656e742f6261636b75702d73686f756c642d62652d6e756c6c", + "0x64", + "0x8f", + "0x636c6173735f686173685f636f6e7374", + "0x8d", + "0x617267656e742f696e76616c69642d63616c6c73", + "0x68", + "0x8a", + "0x100000000000000000000000000000002", + "0x617267656e742f696e76616c69642d6465636c6172652d76657273696f6e", + "0x69", + "0x617267656e742f696e76616c69642d6465706c6f792d6163636f756e742d76", + "0x6a", + "0x86", + "0x7536345f636f6e7374", + "0x6e", + "0x83", + "0x88", + "0x71", + "0x80", + "0x7d", + "0x7a", + "0x74", + "0x77", + "0x617267656e742f677561726469616e2d7265717569726564", + "0x617267656e742f63616e6e6f742d6f766572726964652d657363617065", + "0x93a80", + "0x617267656e742f696e76616c69642d657363617065", + "0x7536345f746f5f66656c74323532", + "0x75385f636f6e7374", + "0x75385f746f5f66656c74323532", + "0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055", + "0x68cfd18b92d1907b8ba3cc324900277f5a3622099431ea85dd8089255e4181", + "0x1ffc9a7", + "0xa66bd575", + "0x3943f10f", + "0x617267656e742f696e76616c69642d7369676e6174757265", + "0x7374727563745f736e617073686f745f6465636f6e737472756374", + "0x26e71b81ea2af0a2b5c6bfceb639b4fc6faae9d8de072a61fc913d3301ff56b", + "0x617267656e742f696e76616c69642d63616c6c64617461", + "0x617267656e742f696e76616c69642d677561726469616e2d736967", + "0x395b662db8770f18d407bbbfeebf45fffec4a7fa4f6c7cee13d084055a9387d", + "0x29ce6d1019e7bef00e94df2973d8d36e9e9b6c5f8783275441c9e466cb8b43", + "0x617267656e742f696e76616c69642d6f776e65722d736967", + "0x3ad2979f59dc1535593f6af33e41945239f4811966bcd49314582a892ebcee8", + "0x1a1e41f464a235695e5050a846a26ca22ecc27acac54be5f6666848031efb8f", + "0x617267656e742f666f7262696464656e2d63616c6c", + "0x656d69745f6576656e745f73797363616c6c", + "0x21adb5788e32c84f69a1863d85ef9394b7bf761a0ce1190f826984e5075c371", + "0x7536345f7472795f66726f6d5f66656c74323532", + "0x73746f726167655f616464726573735f66726f6d5f62617365", + "0x73746f726167655f726561645f73797363616c6c", + "0x11ff76fe3f640fa6f3d60bbd94a3b9d47141a2c96f87fdcfbeb2af1d03f7050", + "0x7", + "0x626f6f6c5f746f5f66656c74323532", + "0x73746f726167655f77726974655f73797363616c6c", + "0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283", + "0x6c6962726172795f63616c6c5f73797363616c6c", + "0x52657475726e6564206461746120746f6f2073686f7274", + "0x526573756c743a3a756e77726170206661696c65642e", + "0x73746f726167655f626173655f616464726573735f636f6e7374", + "0x1ccc09c8a19948e048de7add6929589945e25f22059c7345aaf7837188d8d05", + "0x31e7534f8ddb1628d6e07db5c743e33403b9a0b57508a93f4c49582040a2f71", + "0x1c0f41bf28d630c8a0bd10f3a5d5c0d1619cf96cfdb7da51b112c420ced36c9", + "0xf920571b9f85bdd92a867cfdc73319d0f8836f0e69e06e4c5566b6203f75cc", + "0x4e6f6e20436c61737348617368", + "0x636c6173735f686173685f746f5f66656c74323532", + "0x617267656e742f6e6f2d6d756c746963616c6c2d746f2d73656c66", + "0x1746f7542cac71b5c88f0b2301e87cd9b0896dab1c83b8b515762697e521040", + "0x13f17de67551ae34866d4aa875cbace82f3a041eaa58b1d9e34568b0d0561b", + "0x7536345f6571", + "0x109831a1d023b114d1da4655340bd1bb108c4ddf1bba00f9330573c23f34989", + "0x3a3f1aae7e2c4017af981d69ebf959c39e6f1c53b8ffa09a3ed92f40f524ec7", + "0x7536345f6f766572666c6f77696e675f616464", + "0x7536345f616464204f766572666c6f77", + "0x53746f7265553332202d206e6f6e20753332", + "0x6765745f657865637574696f6e5f696e666f5f76325f73797363616c6c", + "0x61727261795f676574", + "0x496e646578206f7574206f6620626f756e6473", + "0x753132385f636f6e7374", + "0xb1a2bc2ec50000", + "0x753132385f6f766572666c6f77696e675f737562", + "0x617267656e742f6d61782d6665652d746f6f2d68696768", + "0x617267656e742f696e76616c69642d64612d6d6f6465", + "0x617267656e742f696e76616c69642d6465706c6f796d656e742d64617461", + "0xde0b6b3a7640000", + "0x2b5e3af16b1880000", + "0x5", + "0x7533325f6f766572666c6f77696e675f737562", + "0x617267656e742f6d61782d6573636170652d617474656d707473", + "0x617267656e742f7469702d746f6f2d68696768", + "0x7533325f6f766572666c6f77696e675f616464", + "0x7533325f616464204f766572666c6f77", + "0x63616c6c5f636f6e74726163745f73797363616c6c", + "0x66656c743235325f616464", + "0x617267656e742f6d756c746963616c6c2d6661696c6564", + "0x1d9ca8a89626bead91b5cb4275a622219e9443975b34f3fdbc683e8621231a9", + "0x1dcde06aabdbca2f80aa51392b345d7549d7757aa855f7e37f5d335ac8243b1", + "0x1eb8543121901145815b1fa94ab7062e6ecb788bee88efa299b9866bab0bd64", + "0x3c93161122e8fd7a48238feee22dd3d7d49a69099523547d4a7cc7c460fc9c4", + "0x250670a8d933a7d458c994fc396264aba18fc1f1b9136990bb0923a27eaa060", + "0x2811029a978f84c1f4c4fc70c0891f83642ded105942eda119ddc941376122e", + "0x11a96d42fc514f9d4f6f7083acbde6629ff1d2753bf6d25156be7b03e5e1207", + "0x67753421a99564465b580dcc61f1e7befc7fd138c447dae233bba1d477458c", + "0xd885f12a9241174cd02e71d9c751eec91ebc58dffa0addd86642969cbe006f", + "0x2e200b0f001d9c2e6cb94ab8cc4907810f7fe134eca20d8d02224ac5e94e01f", + "0x2b2db2ed38136ca6c54b95187166f98ea84503db8768617a558705b508fec82", + "0x38f6a5b87c23cee6e7294bcc3302e95019f70f81586ff3cac38581f5ca96381", + "0xca58956845fecb30a8cb3efe23582630dbe8b80cc1fb8fd5d5e866b1356ad", + "0x617267656e742f696e76616c69642d7369676e61747572652d6c656e677468", + "0x61727261795f736c696365", + "0x32b90df821786fc0a5a5492c92e3241a5e680e5d53cd88c2bfdd094a70c90f5", + "0xad292db4ff05a993c318438c1b6c8a8303266af2da151aa28ccece6726f1f1", + "0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f", + "0x65635f706f696e745f66726f6d5f785f6e7a", + "0x1d", + "0x756e777261705f6e6f6e5f7a65726f", + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + "0x65635f706f696e745f7472795f6e65775f6e7a", + "0x65635f706f696e745f69735f7a65726f", + "0x65635f706f696e745f756e77726170", + "0x2679d68052ccd03a53755ca9169677965fbd93e489df62f5f40d4f03c24f7a4", + "0x1b", + "0x53746f7265553634202d206e6f6e20753634", + "0x8", + "0x7533325f7472795f66726f6d5f66656c74323532", + "0x17", + "0x757063617374", + "0x4c325f474153", + "0x753132385f6f766572666c6f77696e675f616464", + "0x13", + "0x753132385f616464204f766572666c6f77", + "0x61727261795f706f705f66726f6e74", + "0x11", + "0xf00de1fccbb286f9a020ba8821ee936b1deea42a5c485c11ccdc82c8bebb3a", + "0x65635f73746174655f696e6974", + "0x65635f73746174655f6164645f6d756c", + "0x65635f73746174655f7472795f66696e616c697a655f6e7a", + "0x65635f706f696e745f7a65726f", + "0x65635f73746174655f616464", + "0x65635f6e6567", + "0x75385f6f766572666c6f77696e675f616464", + "0x75385f616464204f766572666c6f77", + "0x753132385f6d756c204f766572666c6f77", + "0x753132385f67756172616e7465655f6d756c", + "0x753132385f746f5f66656c74323532", + "0x753132385f6d756c5f67756172616e7465655f766572696679", + "0x49e3", + "0xffffffffffffffff", + "0x12", + "0x119", + "0x111", + "0x101", + "0xf2", + "0xeb", + "0xe4", + "0x1c6", + "0x1b5", + "0x1ac", + "0x19b", + "0x157", + "0x18b", + "0x183", + "0x2af", + "0x2a2", + "0x28d", + "0x280", + "0x26b", + "0x210", + "0x257", + "0x24e", + "0x245", + "0x343", + "0x33b", + "0x32b", + "0x2e9", + "0x31c", + "0x314", + "0x3c6", + "0x3b6", + "0x374", + "0x3a7", + "0x39f", + "0x47d", + "0x46c", + "0x463", + "0x452", + "0x405", + "0x442", + "0x43b", + "0x434", + "0x518", + "0x510", + "0x500", + "0x4b5", + "0x4f1", + "0x4ea", + "0x4e3", + "0x59b", + "0x58b", + "0x549", + "0x57c", + "0x574", + "0x669", + "0x659", + "0x648", + "0x636", + "0x623", + "0x5db", + "0x611", + "0x609", + "0x71d", + "0x70c", + "0x6fa", + "0x6e7", + "0x6a5", + "0x6d5", + "0x6cc", + "0x793", + "0x784", + "0x74e", + "0x776", + "0x76f", + "0x807", + "0x7f8", + "0x7c2", + "0x7ea", + "0x7e3", + "0x87b", + "0x86c", + "0x836", + "0x85e", + "0x857", + "0x8ef", + "0x8e0", + "0x8aa", + "0x8d2", + "0x8cb", + "0x94d", + "0x919", + "0x940", + "0x939", + "0x9ab", + "0x977", + "0x99e", + "0x997", + "0xa09", + "0x9d5", + "0x9fc", + "0x9f5", + "0xa6f", + "0xa33", + "0xa62", + "0xa5b", + "0xad5", + "0xa99", + "0xac8", + "0xac1", + "0xb3b", + "0xaff", + "0xb2e", + "0xb27", + "0xba1", + "0xb65", + "0xb94", + "0xb8d", + "0xbfa", + "0xbcb", + "0xbed", + "0xc48", + "0xc24", + "0xc3b", + "0xcad", + "0xc72", + "0xca0", + "0xc99", + "0xd12", + "0xcd7", + "0xd05", + "0xcfe", + "0xd78", + "0xd3c", + "0xd6b", + "0xd64", + "0xde7", + "0xdd8", + "0xda7", + "0xdca", + "0xe35", + "0xe11", + "0xe28", + "0xe83", + "0xe5f", + "0xe76", + "0xef2", + "0xee3", + "0xeb2", + "0xed5", + "0xf9e", + "0xf8d", + "0xf84", + "0xf73", + "0xf2f", + "0xf63", + "0xf5b", + "0x102b", + "0x101c", + "0x100c", + "0xfd4", + "0xffd", + "0xff6", + "0x1041", + "0x1046", + "0x1062", + "0x105c", + "0x1187", + "0x1176", + "0x116c", + "0x10ab", + "0x10c2", + "0x10bb", + "0x10c0", + "0x10db", + "0x10d3", + "0x10d8", + "0x10e1", + "0x1104", + "0x10f0", + "0x1107", + "0x115f", + "0x113a", + "0x1157", + "0xde", + "0xdf", + "0xe0", + "0xe1", + "0xe2", + "0xe3", + "0x1282", + "0x1270", + "0x1265", + "0x11d8", + "0x11ef", + "0x11e8", + "0x11ed", + "0x1208", + "0x1200", + "0x1205", + "0x120e", + "0x1230", + "0x121d", + "0x1233", + "0xe5", + "0xe6", + "0xe7", + "0xe8", + "0x125b", + "0xe9", + "0xea", + "0xec", + "0xed", + "0xee", + "0x1253", + "0xef", + "0xf0", + "0xf1", + "0xf3", + "0xf4", + "0x12a7", + "0xf5", + "0xf6", + "0xf7", + "0xf8", + "0x12b4", + "0x12b9", + "0x12c3", + "0xf9", + "0xfa", + "0xfb", + "0x12d2", + "0x12d7", + "0x12f3", + "0xfc", + "0x12ed", + "0xfd", + "0xfe", + "0xff", + "0x100", + "0x102", + "0x131c", + "0x1310", + "0x1314", + "0x103", + "0x104", + "0x105", + "0x106", + "0x107", + "0x108", + "0x109", + "0x10a", + "0x13ca", + "0x10b", + "0x13be", + "0x133d", + "0x1342", + "0x13ae", + "0x10c", + "0x10d", + "0x13a6", + "0x10e", + "0x1355", + "0x135a", + "0x1396", + "0x138e", + "0x10f", + "0x110", + "0x1384", + "0x112", + "0x1378", + "0x113", + "0x114", + "0x115", + "0x116", + "0x117", + "0x118", + "0x11a", + "0x11b", + "0x11c", + "0x139f", + "0x13b7", + "0x11d", + "0x11e", + "0x11f", + "0x120", + "0x13f8", + "0x121", + "0x1414", + "0x162e", + "0x160f", + "0x122", + "0x123", + "0x15f7", + "0x124", + "0x125", + "0x126", + "0x1432", + "0x127", + "0x1448", + "0x1457", + "0x128", + "0x129", + "0x12a", + "0x12b", + "0x12c", + "0x15d8", + "0x12d", + "0x148f", + "0x12e", + "0x12f", + "0x130", + "0x131", + "0x132", + "0x133", + "0x134", + "0x135", + "0x136", + "0x137", + "0x15bc", + "0x138", + "0x139", + "0x13a", + "0x13b", + "0x13c", + "0x13d", + "0x13e", + "0x13f", + "0x140", + "0x141", + "0x142", + "0x143", + "0x144", + "0x15a0", + "0x145", + "0x1586", + "0x146", + "0x1578", + "0x147", + "0x148", + "0x1565", + "0x1552", + "0x149", + "0x1548", + "0x14a", + "0x14b", + "0x16d1", + "0x16c6", + "0x16bd", + "0x16f6", + "0x14c", + "0x14d", + "0x14e", + "0x14f", + "0x150", + "0x1705", + "0x1709", + "0x1722", + "0x151", + "0x171b", + "0x152", + "0x153", + "0x154", + "0x17d5", + "0x17ca", + "0x17b9", + "0x155", + "0x156", + "0x158", + "0x159", + "0x17af", + "0x1764", + "0x15a", + "0x15b", + "0x15c", + "0x15d", + "0x176f", + "0x15e", + "0x15f", + "0x1774", + "0x160", + "0x161", + "0x162", + "0x17a5", + "0x163", + "0x164", + "0x165", + "0x166", + "0x179c", + "0x167", + "0x168", + "0x169", + "0x16a", + "0x1794", + "0x16b", + "0x16c", + "0x16d", + "0x16e", + "0x16f", + "0x170", + "0x171", + "0x17f9", + "0x172", + "0x1a6b", + "0x1a5d", + "0x1a49", + "0x173", + "0x174", + "0x1a35", + "0x1841", + "0x1846", + "0x1865", + "0x175", + "0x176", + "0x177", + "0x178", + "0x1a21", + "0x18b6", + "0x179", + "0x17a", + "0x18a2", + "0x1887", + "0x17b", + "0x18bb", + "0x17c", + "0x17d", + "0x17e", + "0x17f", + "0x1a0d", + "0x180", + "0x181", + "0x182", + "0x194e", + "0x18da", + "0x18df", + "0x1939", + "0x184", + "0x185", + "0x1925", + "0x1910", + "0x186", + "0x187", + "0x188", + "0x189", + "0x1904", + "0x18a", + "0x1956", + "0x1a00", + "0x19f5", + "0x19e2", + "0x18c", + "0x198c", + "0x18d", + "0x19d7", + "0x18e", + "0x18f", + "0x19cd", + "0x190", + "0x19c5", + "0x19bd", + "0x191", + "0x1b50", + "0x1a9e", + "0x1ab5", + "0x192", + "0x1aae", + "0x1ab3", + "0x1ace", + "0x1ac6", + "0x1acb", + "0x1ad4", + "0x1af5", + "0x193", + "0x1ae3", + "0x1af8", + "0x194", + "0x1b45", + "0x1b29", + "0x195", + "0x1b3d", + "0x1c34", + "0x1b82", + "0x1b99", + "0x1b92", + "0x1b97", + "0x1bb2", + "0x1baa", + "0x1baf", + "0x1bb8", + "0x1bd9", + "0x1bc7", + "0x1bdc", + "0x196", + "0x1c29", + "0x1c0d", + "0x1c21", + "0x197", + "0x1dfc", + "0x1deb", + "0x1dd4", + "0x198", + "0x1dc8", + "0x199", + "0x19a", + "0x1db5", + "0x19c", + "0x19d", + "0x19e", + "0x1da2", + "0x19f", + "0x1a0", + "0x1a1", + "0x1a2", + "0x1a3", + "0x1a4", + "0x1ce5", + "0x1a5", + "0x1a6", + "0x1a7", + "0x1a8", + "0x1cd2", + "0x1a9", + "0x1aa", + "0x1ab", + "0x1cc6", + "0x1ad", + "0x1cbb", + "0x1ccd", + "0x1ae", + "0x1af", + "0x1b0", + "0x1b1", + "0x1b2", + "0x1b3", + "0x1ced", + "0x1b4", + "0x1d90", + "0x1b6", + "0x1b7", + "0x1d7e", + "0x1b8", + "0x1b9", + "0x1d6b", + "0x1ba", + "0x1bb", + "0x1bc", + "0x1d59", + "0x1bd", + "0x1be", + "0x1bf", + "0x1c0", + "0x1d4e", + "0x1c1", + "0x1c2", + "0x1c3", + "0x1d44", + "0x1d3b", + "0x1c4", + "0x1c5", + "0x1c7", + "0x1f86", + "0x1f7c", + "0x1f6c", + "0x1e6d", + "0x1e5d", + "0x1e46", + "0x1e72", + "0x1f5c", + "0x1f4c", + "0x1ee1", + "0x1ed1", + "0x1ec5", + "0x1ebd", + "0x1ecc", + "0x1ee9", + "0x1f3d", + "0x1f2e", + "0x1c8", + "0x1c9", + "0x1f1f", + "0x1ca", + "0x1cb", + "0x1cc", + "0x1cd", + "0x1f18", + "0x210c", + "0x2102", + "0x20f2", + "0x20e9", + "0x1fd3", + "0x1fd8", + "0x1fec", + "0x1ce", + "0x20d9", + "0x20c9", + "0x205e", + "0x204e", + "0x2042", + "0x203a", + "0x2049", + "0x2066", + "0x20ba", + "0x20ab", + "0x1cf", + "0x1d0", + "0x209c", + "0x1d1", + "0x1d2", + "0x1d3", + "0x1d4", + "0x2095", + "0x229e", + "0x2294", + "0x2284", + "0x2274", + "0x2183", + "0x2173", + "0x216d", + "0x1d5", + "0x2189", + "0x2264", + "0x2254", + "0x21f6", + "0x21e6", + "0x21da", + "0x21d2", + "0x21e1", + "0x21fe", + "0x224b", + "0x1d6", + "0x1d7", + "0x2242", + "0x2232", + "0x1d8", + "0x1d9", + "0x1da", + "0x222b", + "0x23cd", + "0x23c3", + "0x23b3", + "0x23a3", + "0x2393", + "0x2335", + "0x2325", + "0x2319", + "0x2311", + "0x2320", + "0x233d", + "0x238a", + "0x2381", + "0x2371", + "0x1db", + "0x1dc", + "0x1dd", + "0x236a", + "0x2533", + "0x2528", + "0x2517", + "0x2506", + "0x24f5", + "0x1de", + "0x242e", + "0x1df", + "0x24e5", + "0x24d5", + "0x24c4", + "0x24b4", + "0x1e0", + "0x1e1", + "0x1e2", + "0x24ab", + "0x24a3", + "0x249c", + "0x248e", + "0x264c", + "0x2643", + "0x2634", + "0x2625", + "0x2615", + "0x2590", + "0x2606", + "0x25f7", + "0x25e8", + "0x1e3", + "0x1e4", + "0x1e5", + "0x25e1", + "0x25d3", + "0x27af", + "0x27a6", + "0x2797", + "0x2788", + "0x2779", + "0x26ad", + "0x276a", + "0x275b", + "0x271d", + "0x270e", + "0x2702", + "0x26fb", + "0x2709", + "0x2725", + "0x274d", + "0x273f", + "0x27cb", + "0x27e5", + "0x27ff", + "0x281b", + "0x1e6", + "0x1e7", + "0x1e8", + "0x1e9", + "0x1ea", + "0x1eb", + "0x1ec", + "0x1ed", + "0x1ee", + "0x1ef", + "0x1f0", + "0x1f1", + "0x1f2", + "0x1f3", + "0x1f4", + "0x1f5", + "0x1f6", + "0x286c", + "0x1f7", + "0x1f8", + "0x1f9", + "0x1fa", + "0x1fb", + "0x2889", + "0x28bc", + "0x28b2", + "0x1fc", + "0x1fd", + "0x1fe", + "0x1ff", + "0x200", + "0x201", + "0x202", + "0x203", + "0x28d8", + "0x2921", + "0x28e5", + "0x2920", + "0x204", + "0x28f2", + "0x291f", + "0x205", + "0x28ff", + "0x291e", + "0x206", + "0x290c", + "0x291d", + "0x207", + "0x2917", + "0x291c", + "0x292a", + "0x292e", + "0x295c", + "0x294d", + "0x208", + "0x2979", + "0x297e", + "0x2992", + "0x29fd", + "0x29ed", + "0x29dd", + "0x209", + "0x20a", + "0x20b", + "0x29d5", + "0x29ce", + "0x20c", + "0x20d", + "0x2a53", + "0x2a1e", + "0x20e", + "0x20f", + "0x2a4b", + "0x211", + "0x212", + "0x2a41", + "0x213", + "0x2a3b", + "0x214", + "0x215", + "0x2a74", + "0x216", + "0x217", + "0x218", + "0x219", + "0x21a", + "0x21b", + "0x21c", + "0x21d", + "0x21e", + "0x2a8c", + "0x21f", + "0x220", + "0x221", + "0x222", + "0x223", + "0x224", + "0x31d2", + "0x225", + "0x226", + "0x227", + "0x2ad1", + "0x228", + "0x229", + "0x2ac6", + "0x31a3", + "0x22a", + "0x22b", + "0x22c", + "0x31c0", + "0x22d", + "0x22e", + "0x22f", + "0x230", + "0x231", + "0x232", + "0x3198", + "0x233", + "0x2c70", + "0x2b7e", + "0x234", + "0x2b6a", + "0x235", + "0x236", + "0x237", + "0x2b56", + "0x238", + "0x2b43", + "0x2b31", + "0x2b86", + "0x239", + "0x2c5d", + "0x2bab", + "0x23a", + "0x2bc2", + "0x2bc7", + "0x2bdd", + "0x2c51", + "0x2c03", + "0x2c08", + "0x2c1e", + "0x23b", + "0x2c48", + "0x2c3d", + "0x23c", + "0x23d", + "0x2e19", + "0x2cf6", + "0x2ce2", + "0x2cce", + "0x2cbb", + "0x2ca9", + "0x2cfe", + "0x2d1c", + "0x2e0e", + "0x2d42", + "0x2d47", + "0x2d5d", + "0x2dfb", + "0x2de0", + "0x2d8a", + "0x2d8f", + "0x2dac", + "0x2dd7", + "0x2dcc", + "0x23e", + "0x2fa8", + "0x2e9e", + "0x23f", + "0x2e8a", + "0x2e76", + "0x2e63", + "0x2e51", + "0x2ea6", + "0x2f95", + "0x2ecb", + "0x2f14", + "0x2f01", + "0x2ee7", + "0x2f19", + "0x240", + "0x241", + "0x242", + "0x243", + "0x244", + "0x246", + "0x247", + "0x248", + "0x249", + "0x24a", + "0x2f89", + "0x24b", + "0x24c", + "0x24d", + "0x24f", + "0x250", + "0x251", + "0x252", + "0x253", + "0x254", + "0x255", + "0x256", + "0x258", + "0x259", + "0x25a", + "0x2f3b", + "0x25b", + "0x25c", + "0x25d", + "0x25e", + "0x2f40", + "0x25f", + "0x260", + "0x261", + "0x262", + "0x2f56", + "0x263", + "0x264", + "0x265", + "0x266", + "0x267", + "0x268", + "0x269", + "0x26a", + "0x26c", + "0x26d", + "0x26e", + "0x26f", + "0x270", + "0x271", + "0x2f80", + "0x272", + "0x273", + "0x274", + "0x2f75", + "0x275", + "0x276", + "0x277", + "0x278", + "0x279", + "0x27a", + "0x27b", + "0x27c", + "0x27d", + "0x27e", + "0x27f", + "0x281", + "0x282", + "0x283", + "0x284", + "0x285", + "0x286", + "0x287", + "0x288", + "0x289", + "0x3160", + "0x28a", + "0x28b", + "0x302c", + "0x28c", + "0x28e", + "0x28f", + "0x290", + "0x291", + "0x292", + "0x293", + "0x294", + "0x295", + "0x296", + "0x297", + "0x298", + "0x299", + "0x29a", + "0x29b", + "0x3018", + "0x29c", + "0x29d", + "0x29e", + "0x29f", + "0x2a0", + "0x2a1", + "0x3004", + "0x2a3", + "0x2a4", + "0x2a5", + "0x2a6", + "0x2a7", + "0x2ff1", + "0x2a8", + "0x2a9", + "0x2aa", + "0x2ab", + "0x2ac", + "0x2ad", + "0x2fdf", + "0x2ae", + "0x2b0", + "0x2b1", + "0x2b2", + "0x2b3", + "0x2b4", + "0x2b5", + "0x3034", + "0x2b6", + "0x2b7", + "0x2b8", + "0x2b9", + "0x2ba", + "0x2bb", + "0x2bc", + "0x2bd", + "0x2be", + "0x2bf", + "0x2c0", + "0x2c1", + "0x2c2", + "0x2c3", + "0x2c4", + "0x3052", + "0x2c5", + "0x2c6", + "0x2c7", + "0x2c8", + "0x2c9", + "0x2ca", + "0x2cb", + "0x2cc", + "0x2cd", + "0x2ce", + "0x2cf", + "0x2d0", + "0x2d1", + "0x2d2", + "0x2d3", + "0x2d4", + "0x2d5", + "0x2d6", + "0x2d7", + "0x2d8", + "0x3155", + "0x2d9", + "0x2da", + "0x2db", + "0x2dc", + "0x2dd", + "0x2de", + "0x2df", + "0x2e0", + "0x2e1", + "0x2e2", + "0x2e3", + "0x2e4", + "0x2e5", + "0x2e6", + "0x2e7", + "0x2e8", + "0x3078", + "0x2ea", + "0x2eb", + "0x2ec", + "0x307d", + "0x2ed", + "0x2ee", + "0x2ef", + "0x2f0", + "0x3093", + "0x2f1", + "0x2f2", + "0x2f3", + "0x2f4", + "0x2f5", + "0x2f6", + "0x2f7", + "0x2f8", + "0x2f9", + "0x2fa", + "0x2fb", + "0x2fc", + "0x2fd", + "0x2fe", + "0x2ff", + "0x300", + "0x301", + "0x302", + "0x303", + "0x304", + "0x305", + "0x306", + "0x3142", + "0x307", + "0x308", + "0x309", + "0x30a", + "0x30b", + "0x30c", + "0x30d", + "0x30e", + "0x30f", + "0x310", + "0x311", + "0x312", + "0x313", + "0x3127", + "0x30f0", + "0x315", + "0x316", + "0x317", + "0x318", + "0x319", + "0x31a", + "0x31b", + "0x30dd", + "0x31d", + "0x31e", + "0x31f", + "0x320", + "0x321", + "0x322", + "0x323", + "0x324", + "0x325", + "0x30c3", + "0x326", + "0x327", + "0x328", + "0x329", + "0x30f5", + "0x32a", + "0x32c", + "0x32d", + "0x32e", + "0x32f", + "0x330", + "0x331", + "0x332", + "0x333", + "0x334", + "0x335", + "0x336", + "0x337", + "0x338", + "0x339", + "0x311e", + "0x33a", + "0x33c", + "0x3113", + "0x33d", + "0x33e", + "0x33f", + "0x340", + "0x341", + "0x342", + "0x344", + "0x345", + "0x346", + "0x347", + "0x348", + "0x349", + "0x34a", + "0x34b", + "0x34c", + "0x34d", + "0x34e", + "0x34f", + "0x350", + "0x351", + "0x352", + "0x353", + "0x354", + "0x355", + "0x356", + "0x357", + "0x358", + "0x359", + "0x35a", + "0x35b", + "0x35c", + "0x35d", + "0x317a", + "0x35e", + "0x35f", + "0x360", + "0x361", + "0x317f", + "0x362", + "0x363", + "0x364", + "0x365", + "0x3195", + "0x366", + "0x367", + "0x368", + "0x369", + "0x36a", + "0x36b", + "0x36c", + "0x31a0", + "0x36d", + "0x36e", + "0x36f", + "0x370", + "0x371", + "0x372", + "0x373", + "0x31b7", + "0x375", + "0x376", + "0x377", + "0x378", + "0x379", + "0x37a", + "0x37b", + "0x31fb", + "0x323e", + "0x3224", + "0x3229", + "0x3235", + "0x3292", + "0x3256", + "0x325b", + "0x3284", + "0x327d", + "0x3277", + "0x328b", + "0x32da", + "0x32b2", + "0x32d0", + "0x32ca", + "0x3372", + "0x3367", + "0x330c", + "0x335c", + "0x333b", + "0x3331", + "0x3335", + "0x334c", + "0x3354", + "0x338e", + "0x3387", + "0x339a", + "0x339f", + "0x33a8", + "0x33ad", + "0x33d7", + "0x33d1", + "0x33c9", + "0x33f1", + "0x3423", + "0x3418", + "0x341d", + "0x3428", + "0x3434", + "0x344e", + "0x34c4", + "0x34de", + "0x34e3", + "0x34ef", + "0x350d", + "0x3512", + "0x352e", + "0x3521", + "0x353f", + "0x357f", + "0x3565", + "0x356a", + "0x3576", + "0x35de", + "0x35a5", + "0x35aa", + "0x35d6", + "0x35cf", + "0x35c1", + "0x3624", + "0x35f5", + "0x35fa", + "0x3616", + "0x3610", + "0x361d", + "0x363f", + "0x3644", + "0x364e", + "0x3661", + "0x3666", + "0x3670", + "0x3683", + "0x3688", + "0x3692", + "0x36bb", + "0x36ad", + "0x36c1", + "0x36cc", + "0x36e7", + "0x36ec", + "0x36fd", + "0x3702", + "0x370c", + "0x374f", + "0x3735", + "0x373a", + "0x3746", + "0x37b3", + "0x3765", + "0x376a", + "0x37a8", + "0x3791", + "0x37a2", + "0x3860", + "0x3855", + "0x37e7", + "0x384a", + "0x381b", + "0x3815", + "0x383d", + "0x3842", + "0x3837", + "0x387e", + "0x3883", + "0x389a", + "0x3925", + "0x3917", + "0x390a", + "0x38fe", + "0x3951", + "0x394a", + "0x39a7", + "0x399f", + "0x3992", + "0x398a", + "0x397f", + "0x39d3", + "0x39f3", + "0x3a13", + "0x39bd", + "0x39c4", + "0x39cb", + "0x39d1", + "0x3a32", + "0x39dc", + "0x39e4", + "0x39eb", + "0x39f1", + "0x39fc", + "0x3a03", + "0x3a0b", + "0x3a11", + "0x3a1c", + "0x3a23", + "0x3a2a", + "0x3a31", + "0x3a55", + "0x3a4d", + "0x3a9e", + "0x3a84", + "0x3a89", + "0x3a95", + "0x3ab6", + "0x3abb", + "0x3ac5", + "0x3adc", + "0x3ae1", + "0x3aeb", + "0x3b01", + "0x3b06", + "0x3b10", + "0x3b53", + "0x3b39", + "0x3b3e", + "0x3b4a", + "0x3b97", + "0x3b7d", + "0x3b82", + "0x3b8e", + "0x3bae", + "0x3bb3", + "0x3bbd", + "0x3c00", + "0x3be6", + "0x3beb", + "0x3bf7", + "0x3c17", + "0x3c1c", + "0x3c26", + "0x3c69", + "0x3c4f", + "0x3c54", + "0x3c60", + "0x3c77", + "0x3c7b", + "0x3c86", + "0x3cc7", + "0x3cad", + "0x3cb2", + "0x3cbe", + "0x3d0b", + "0x3cf1", + "0x3cf6", + "0x3d02", + "0x3d4f", + "0x3d35", + "0x3d3a", + "0x3d46", + "0x3d93", + "0x3d79", + "0x3d7e", + "0x3d8a", + "0x3dbe", + "0x3db0", + "0x3dc4", + "0x3dcf", + "0x3df9", + "0x3deb", + "0x3dff", + "0x3e0a", + "0x3e1f", + "0x3e2c", + "0x3e39", + "0x3e45", + "0x3e83", + "0x3e69", + "0x3e6e", + "0x3e7a", + "0x3ec7", + "0x3ebd", + "0x3eb5", + "0x3eab", + "0x3ed8", + "0x3edd", + "0x3ee7", + "0x3ef4", + "0x4045", + "0x3f29", + "0x3f40", + "0x3f39", + "0x3f3e", + "0x3f8b", + "0x3f54", + "0x3f61", + "0x3f7a", + "0x3f6a", + "0x3ffa", + "0x3f9e", + "0x3fac", + "0x3fb9", + "0x3fd6", + "0x403d", + "0x4034", + "0x4024", + "0x4015", + "0x400b", + "0x4053", + "0x4057", + "0x4062", + "0x4087", + "0x4113", + "0x4108", + "0x40fc", + "0x40e7", + "0x40dc", + "0x40f4", + "0x413e", + "0x418f", + "0x4184", + "0x4179", + "0x4213", + "0x41aa", + "0x41af", + "0x4207", + "0x41e4", + "0x41dd", + "0x4200", + "0x4237", + "0x4250", + "0x425e", + "0x426c", + "0x427a", + "0x4288", + "0x4295", + "0x42a3", + "0x42b1", + "0x42bf", + "0x42cd", + "0x42db", + "0x42e8", + "0x424a", + "0x37c", + "0x37d", + "0x37e", + "0x37f", + "0x380", + "0x381", + "0x382", + "0x383", + "0x384", + "0x42f5", + "0x385", + "0x4315", + "0x4371", + "0x386", + "0x4340", + "0x387", + "0x388", + "0x389", + "0x38a", + "0x4365", + "0x4359", + "0x38b", + "0x38c", + "0x38d", + "0x438e", + "0x38e", + "0x38f", + "0x390", + "0x391", + "0x392", + "0x393", + "0x394", + "0x43a8", + "0x395", + "0x4405", + "0x43be", + "0x43c3", + "0x396", + "0x43f6", + "0x397", + "0x43ec", + "0x43e5", + "0x398", + "0x399", + "0x39a", + "0x39b", + "0x39c", + "0x39d", + "0x39e", + "0x441c", + "0x4429", + "0x442e", + "0x4454", + "0x444a", + "0x444f", + "0x3a0", + "0x3a1", + "0x4462", + "0x3a2", + "0x3a3", + "0x4474", + "0x4480", + "0x4485", + "0x3a4", + "0x448c", + "0x3a5", + "0x44a9", + "0x44ae", + "0x44bc", + "0x3a6", + "0x44ce", + "0x44e0", + "0x455d", + "0x3a8", + "0x3a9", + "0x4552", + "0x3aa", + "0x3ab", + "0x3ac", + "0x4546", + "0x3ad", + "0x3ae", + "0x3af", + "0x4504", + "0x3b0", + "0x3b1", + "0x3b2", + "0x3b3", + "0x4517", + "0x452a", + "0x4528", + "0x3b4", + "0x4531", + "0x4540", + "0x453e", + "0x3b5", + "0x45c6", + "0x45b6", + "0x3b7", + "0x45a9", + "0x3b8", + "0x3b9", + "0x3ba", + "0x459e", + "0x3bb", + "0x4593", + "0x3bc", + "0x3bd", + "0x3be", + "0x3bf", + "0x3c0", + "0x3c1", + "0x3c2", + "0x3c3", + "0x3c4", + "0x45d7", + "0x462a", + "0x461d", + "0x4613", + "0x460a", + "0x3c5", + "0x3c7", + "0x3c8", + "0x3c9", + "0x3ca", + "0x3cb", + "0x3cc", + "0x3cd", + "0x3ce", + "0x464d", + "0x3cf", + "0x3d0", + "0x3d1", + "0x3d2", + "0x3d3", + "0x4668", + "0x3d4", + "0x3d5", + "0x466d", + "0x3d6", + "0x3d7", + "0x4674", + "0x3d8", + "0x3d9", + "0x4687", + "0x4730", + "0x3da", + "0x3db", + "0x469b", + "0x3dc", + "0x3dd", + "0x3de", + "0x46a0", + "0x3df", + "0x3e0", + "0x3e1", + "0x4725", + "0x3e2", + "0x3e3", + "0x3e4", + "0x3e5", + "0x3e6", + "0x3e7", + "0x3e8", + "0x4718", + "0x470c", + "0x3e9", + "0x46f0", + "0x46e5", + "0x46db", + "0x46f5", + "0x3ea", + "0x3eb", + "0x4706", + "0x3ec", + "0x3ed", + "0x3ee", + "0x3ef", + "0x4746", + "0x3f0", + "0x3f1", + "0x474a", + "0x3f2", + "0x3f3", + "0x3f4", + "0x4755", + "0x3f5", + "0x3f6", + "0x3f7", + "0x3f8", + "0x3f9", + "0x4761", + "0x3fa", + "0x4771", + "0x3fb", + "0x3fc", + "0x3fd", + "0x3fe", + "0x47b1", + "0x3ff", + "0x478a", + "0x478f", + "0x47a7", + "0x47a1", + "0x400", + "0x401", + "0x402", + "0x403", + "0x404", + "0x406", + "0x47ed", + "0x407", + "0x408", + "0x409", + "0x40a", + "0x40b", + "0x40c", + "0x40d", + "0x40e", + "0x40f", + "0x410", + "0x411", + "0x412", + "0x413", + "0x414", + "0x415", + "0x416", + "0x48ad", + "0x417", + "0x418", + "0x419", + "0x48bd", + "0x48cd", + "0x41a", + "0x41b", + "0x41c", + "0x41d", + "0x48c8", + "0x48cb", + "0x41e", + "0x48d4", + "0x48da", + "0x41f", + "0x420", + "0x48e6", + "0x48e9", + "0x48f0", + "0x421", + "0x422", + "0x48fd", + "0x423", + "0x424", + "0x4901", + "0x425", + "0x426", + "0x427", + "0x490c", + "0x428", + "0x429", + "0x42a", + "0x42b", + "0x42c", + "0x42d", + "0x491c", + "0x42e", + "0x42f", + "0x492f", + "0x430", + "0x431", + "0x4952", + "0x49a7", + "0x4970", + "0x4975", + "0x4998", + "0x4991", + "0x432", + "0x433", + "0x435", + "0x436", + "0x49be", + "0x437", + "0x438", + "0x439", + "0x43a", + "0x43c", + "0x49d6", + "0x43d", + "0x43e", + "0x49dc", + "0x43f", + "0x440", + "0x48d", + "0x527", + "0x5aa", + "0x678", + "0x72d", + "0x7a1", + "0x815", + "0x889", + "0x8fd", + "0x95b", + "0x9b9", + "0xa17", + "0xa7d", + "0xae3", + "0xb49", + "0xbaf", + "0xc08", + "0xc56", + "0xcbb", + "0xd20", + "0xd86", + "0xdf5", + "0xe43", + "0xe91", + "0xf00", + "0xfae", + "0x1039", + "0x106c", + "0x1191", + "0x1196", + "0x128d", + "0x12ad", + "0x12ca", + "0x12fd", + "0x1324", + "0x13d6", + "0x1646", + "0x16dc", + "0x16fe", + "0x1710", + "0x1728", + "0x17df", + "0x17ff", + "0x1a78", + "0x1b59", + "0x1c3d", + "0x1e0c", + "0x1f8f", + "0x2115", + "0x22a7", + "0x23d6", + "0x253d", + "0x2654", + "0x27b7", + "0x27d1", + "0x27eb", + "0x2805", + "0x2822", + "0x2838", + "0x283f", + "0x2856", + "0x2873", + "0x2890", + "0x28c3", + "0x28cc", + "0x2922", + "0x292f", + "0x2964", + "0x2a0d", + "0x2a62", + "0x2a7a", + "0x2a92", + "0x31e4", + "0x3202", + "0x3246", + "0x32a1", + "0x32e9", + "0x337c", + "0x3394", + "0x33a0", + "0x33e1", + "0x33f7", + "0x343c", + "0x3454", + "0x34cd", + "0x34f8", + "0x3534", + "0x3543", + "0x3587", + "0x35e7", + "0x3632", + "0x3654", + "0x3676", + "0x3698", + "0x36d3", + "0x36ed", + "0x3713", + "0x3757", + "0x37c1", + "0x386a", + "0x3932", + "0x3958", + "0x39b2", + "0x3a33", + "0x3a5d", + "0x3a63", + "0x3aa6", + "0x3acc", + "0x3af2", + "0x3b17", + "0x3b5b", + "0x3b9f", + "0x3bc4", + "0x3c08", + "0x3c2d", + "0x3c71", + "0x3c8b", + "0x3ccf", + "0x3d13", + "0x3d57", + "0x3d9b", + "0x3dd6", + "0x3e11", + "0x3e47", + "0x3e8b", + "0x3ed1", + "0x3eed", + "0x3eff", + "0x404d", + "0x4067", + "0x411e", + "0x419a", + "0x4224", + "0x4227", + "0x42ef", + "0x42fb", + "0x431b", + "0x437c", + "0x4394", + "0x43a2", + "0x43ae", + "0x4416", + "0x4422", + "0x445b", + "0x446b", + "0x446e", + "0x447a", + "0x4486", + "0x4492", + "0x4495", + "0x44af", + "0x4567", + "0x45d1", + "0x45dd", + "0x45e3", + "0x4637", + "0x463a", + "0x463d", + "0x4640", + "0x4643", + "0x4646", + "0x4656", + "0x4659", + "0x465c", + "0x465f", + "0x4662", + "0x466e", + "0x467a", + "0x467e", + "0x4681", + "0x468d", + "0x4740", + "0x475a", + "0x476a", + "0x477c", + "0x47bf", + "0x47d0", + "0x47f4", + "0x4804", + "0x4814", + "0x481d", + "0x4826", + "0x482b", + "0x4834", + "0x483d", + "0x4846", + "0x484f", + "0x4857", + "0x485f", + "0x48b6", + "0x48ce", + "0x48ea", + "0x48f7", + "0x4911", + "0x4928", + "0x4938", + "0x4958", + "0x4962", + "0x49b7", + "0x49c7", + "0x49df", + "0x26655", + "0xc00800700b00500200a009009009009008007006005004003002001000", + "0x1300401201100901100901000700600c00400f00e00900900900d007006", + "0x901d00701900500401c01b00901a007019005018009017016015009014", + "0x900800702200502100700b00501500902000901f00900800701e005015", + "0x902900700600c01800902802702600902500902400702200c018009023", + "0xc02e00901702d00900902c00901500902b00701e00500402a009009009", + "0x900800701900503100901701602e00901401300e00903000902f007006", + "0x1603700901401303600901703500403402600903300903200702200c011", + "0x701900501500901702d03b00902802703a009039007019005038009017", + "0x904100904000700600c00403f02600903e00903d00702200c03c009008", + "0x904400701900502600904300904200702200c009009008007019005041", + "0x904900904800702200c00e009009009009009047009008007046005045", + "0x904100904d00702200c01800904c00904b00702200c04a00901702d026", + "0x702200c02c00902c00904f00700600c00e00904100904e00700600c018", + "0x502600905400905300702200c05200900800705100501800900e009050", + "0x705100501800905700905600702200c01500901500902c00905500701e", + "0x905c00700600c05b00901702d02600905a00905900702200c058009008", + "0x901500906100702200c01800906000905f00702200c00405e00e00905d", + "0x702200c00e00906400906300700600c00e00900e00906200700600c018", + "0x906600702200c01500902000903b00900800701e00501800901f009065", + "0x701e00500406b00406a00406901800906400906800702200c026009067", + "0x702200c06f00900800701900506e00901702d06d00902c00902c00906c", + "0xc07200900800701900501f00901f009008007006005026009071009070", + "0x1300e00907600907500700600c01f00901702d026009074009073007022", + "0x901800901800900800707900507800902802707700901701601f009014", + "0x701900501500901500907c00700600502600907b00907a00702200c00e", + "0x501500902c00908000700600507f00901500907e00700600507800907d", + "0x501500908300701900501500908200701900501500902c009081007006", + "0x908700701900501500908600701900501500908500701900508400700b", + "0xc01500908a007019005015009089007019005060009088007019005015", + "0x909400909300909200909100909000908f00908e00908d00908c00708b", + "0x901500907700903b00900800709a005099009098009097009096009095", + "0x1601800901500906d00909d00707900502600909c00909b00702200c00e", + "0x902802702600909f00909e00702200c05d009008007019005037009017", + "0x906d0090a300906f0090a20070a10050a000901702d05b009028027041", + "0x702200c0260090a50090a400702200c04c00900800701900501500906d", + "0x90a90090a800702200c0a700901f00900800702200500e0090370090a6", + "0x90ae0090ad00702200c00e0090ac0090080070ab0050aa00700b005026", + "0x90b20090b100702200c00e0090b00090080070ab0050af00700b005026", + "0x90b60090b500702200c00e0090b40090080070ab0050b300700b005026", + "0x90ba0090b900702200c00e0090b80090080070ab0050b700700b005026", + "0x90be0090bd00702200c00e0090bc0090080070ab0050bb00700b005026", + "0x90c20090c100702200c00e0090c00090080070ab0050bf00700b005026", + "0xc0c400900800701900500e00900e00900e00900e0090c300704600c026", + "0x70060050c70090280270150090080070190050260090c60090c5007022", + "0x70ab0050ca00700b0050260090c90090c800702200c00e00903b009008", + "0xc0600090080070190050260090cd0090cc00702200c00e0090cb009008", + "0x702200c0180090080070510050380090280270260090cf0090ce007022", + "0x702200c00e0090080070d30050600090d20070190050260090d10090d0", + "0x90080070ab0050d700700b0050600090d60070190050260090d50090d4", + "0x90150090150090db00701e0050260090da0090d900702200c00e0090d8", + "0x90de00700600c0260090dd0090dc00702200c02c009008007019005015", + "0xc0260090e10090e000702200c0df00901f00900800700600500e00903b", + "0x2706d00902802700e00906d0090e300700600c00e00902c0090e2007006", + "0x90280270260090e50090e400702200c07700900800705100502c009028", + "0x901500901500901500901f00900900906d0090150090e600708b005077", + "0x702200c0a300900800701900501f00904100904100901f009009009047", + "0x90e900702200c06d0090080070190050150090170350260090e80090e7", + "0x50c400905700900800700600500e00903c0090eb00700600c0260090ea", + "0xc0410090080070190050260090ee0090ed00702200c0ec009008007019", + "0x70190050110090110090110090f100701e0050260090f00090ef007022", + "0x90b40090cb0090f50070f40050260090f30090f200702200c057009008", + "0xc00e0090f60090080070ab0050bc0090b80090d80090c00090ac0090b0", + "0x90f900702200c0180090f60090080070220050260090f80090f7007022", + "0x900800701900506000902802700e0090600090fb00700600c0260090fa", + "0x901500906d0090ff0070a10050020fe0260090fd0090fc00702200c064", + "0x901f00900800700600500e00910100910000700600c03b00902c00902c", + "0x2710600902802700210510100902802702600910400910300702200c102", + "0x500e00901800910900702200c0260090c700910800702200c107009028", + "0x910d00700600c02600910c00910b00702200c10a00901f009008007022", + "0x910e00702200c00e00901800900800702200501500902802700e009015", + "0x11202600911100911000702200c0770090f600900800702200502600910f", + "0xc0150090f600900800700600501f009008007019005113009028027002", + "0x702200c02600911800911700702200c004116026009115009114007022", + "0x911c00911b00702200c11a00901f00900800702200500e009038009119", + "0x912212300900912200700900912200712100712000711f11e00211d026", + "0x912911a00900912711c00900912912800900912712612500912401f009", + "0x912f00712e00912d04100900912c04100900912b01500900912a01f009", + "0x13312e00913201500900913103800900912c007130041009009122041009", + "0x13700912e136026009009135023009009135015009009134015009009122", + "0x13900900912200713813700900912211300900912210600900912200912e", + "0x91350ac0090091350b00090091350b40090091350cb00900913500713a", + "0x91220f60090091350bc0090091350b80090091350d80090091350c0009", + "0x912b0f600900912c11500900912913b00900912703c125009124038009", + "0x912b00e00900912c03e12500912401800900912201500900912c015009", + "0x712e13700912e13611800900913501f00900913501800900912c018009", + "0x912c00713f11300900913e13d12e00913201f00900912c13c12e009132", + "0x912b111009009129143009009127113009009142141125009124140009", + "0x912914400900912704112500912407800900912207700900912c077009", + "0x912401500900914214600900912714512500912401500900913e10f009", + "0x91240f600900912b10a00900912710c009009129147009009127043125", + "0x913e14b00900912c14a12e0091320c7009009129149009009127148125", + "0x912914c00900912704712500912410100900913e10600900913e107009", + "0x912c14e00900912c14d00900912c101009009142102009009127104009", + "0x9142106009009142049125009124101009009122107009009122101009", + "0x912915100900912704c12500912415012500912414f00900912c107009", + "0x913e15212500912406400900912206400900912c06400900912b0fd009", + "0x912206000900912c060009009142154009009127153125009124060009", + "0x912401b0090091220fa009009129156009009127155125009124060009", + "0x913215912500912405412500912405212500912415800900912c157125", + "0x91240f800900912c15c00900912705712500912415b12e00913215a12e", + "0x912415e12500912405d12500912415d12500912405a125009124058125", + "0x912416112500912406412500912416012500912415f125009124060125", + "0x912205700900912c05700900912b0f3009009129163009009127162125", + "0x912216500900912c16500900912b164125009124067125009124057009", + "0x912916900900912716812500912416712e009132166125009124165009", + "0xee00900912916c00900912706d12500912416b12500912400716a0f0009", + "0x6f12500912406e1250091240ec0090091220ec00900912c0ec00900912b", + "0x917000716f07212500912416e12500912407112500912416d12e009132", + "0x12e13600e00900913500717217100900912200712e17100912e136015009", + "0x1500900912f03700900913101500900917317100900912700912e171009", + "0x12e13612800900912200712e12800912e13611c009009135074125009124", + "0x912917500900912717412500912400912e11a00912e13600912e128009", + "0x712e00913200717606d00900912f06d00900912c06d00900912b0ea009", + "0xa00090091730e8009009129179009009127076125009124007178007177", + "0x12e13600717a12512e00913204700900912c00900900912c0a0009009129", + "0x912700712e06400912e13600912e00913217b00900912c00912e064009", + "0x912e13b00912e13617e12e00913217d12e00913217c12e009132064009", + "0x3b00900912203b00900913503800900912b17f12e00913213b009009122", + "0x13b00912e13611500900913518112e0091320f8009009129180125009124", + "0x912e14300912e13618300900912c07700900913e18212e00913200712e", + "0x770090091420e5009009129184009009127077125009124143009009122", + "0x11100900913507812500912408e00900912208e00900913507f009009135", + "0x912407f00900912201f00900912a07800900918500712e14300912e136", + "0x14400912e13614400900912200712e14400912e13610f009009135186125", + "0x912400912e14600912e13614600900912200712e14600912e13600912e", + "0x14700912e13614700900912200712e14700912e13610c00900913507b125", + "0x14900912e1360c700900913518712500912400912e10a00912e13600912e", + "0x6d00900913e02c00900913e00912e14900912e13614900900912200712e", + "0x18900900912707f12500912406d00900914218800900912708d125009124", + "0xdf0090091270e100900912918a00900912708e12500912402c009009142", + "0x712e14c00912e13610400900913500712e10200912e136101009009135", + "0x912e14c00912e13600912e10200912e13602c00900912c14c009009122", + "0x6d00900918510100900912918c00900912c00e00900912f18b00900912c", + "0xdd00900912918e00900912708f12500912406d00900912218d12e009132", + "0x912b0f600900912919012e00913203b00900912c00718f02c009009185", + "0xb400900912c0cb00900912c0071910901250091240150090091850d8009", + "0xac00900912c0c000900912c0d800900912c0b800900912c0bc00900912c", + "0x19312e00913202000900913510100900912b19212e0091320b000900912c", + "0x912b19700900913519612e00913219512e009132007194020009009129", + "0x912400e12e00913219700900912919700900912f19700900912c197009", + "0x912919800900912709312500912403b009009185092125009124091125", + "0x712e15100912e1360fd00900913519912e0091320da00900912c0da009", + "0x15400912e13600719a06400900912f00912e15100912e136151009009122", + "0x19b00900913506000900918500912e15400912e13615400900912200712e", + "0x15600912e13619d12e00913209412500912419b00900912219c12e009132", + "0x12e13605200900912200712e05200912e13600719e15600900912200912e", + "0x970090091350d500900912c19f00900912709512500912400912e052009", + "0x971250091241a00090091221a0009009135096125009124097009009122", + "0x913200712e15600912e1360fa0090091350d10090091291a1009009127", + "0x912b03800900913e09812500912401b0090091850ea00900912c1a212e", + "0x91240b000900912b1a412e0091321a300900912c0991250091240b4009", + "0x912b1a612e0091320ac00900912f09c1250091240ac00900912b1a5125", + "0x91a906000900912b0cf0090091291a80090091271a71250091240cb009", + "0x91350cd0090091291aa00900912705b12500912403712500912400712e", + "0x91420cd00900912c0f600900912f09f125009124098009009122098009", + "0x912c0c900900912c1ad0090091271ac1250091241ab12e009132038009", + "0x91321b01250091241af12e0091321ae12e00913212e12e00913203a009", + "0x91290a31250091240c000900912b1b21250091240c700900913e1b112e", + "0x912b0c60090091291b300900912704a12500912402c009009122057009", + "0xa51250091240c40090091220c400900912c00712e0c400912e1360c4009", + "0xc400912e1361b60090091271b512500912405700900913500712e0091b4", + "0x912c0a91250091240930090091350c20090091290a712500912412512e", + "0x12300900912f00700900912f15c00900912200912e15c00912e1361b7009", + "0x1ba0090091270ac1250091241b90090091271b812500912411300900912f", + "0x1bb0090091270c70090091420ae1250091240ba0090091290be009009129", + "0x990090091351bc1250091240940090091220940090091350b6009009129", + "0x912c00712e15c00912e1360f80090091350b0125009124099009009122", + "0x91350b20090091291bd0090091270b21250091240be00900912c0c7009", + "0x91270b41250091241be12e0091321bd125009124095009009122095009", + "0x91320b61250091240960090091220960090091350ae0090091291bc009", + "0x912408f00900912208f0090091351bb1250091241c012e0091b41bf12e", + "0x12e12e0c400912e1360ba1250091240900090091220900090091350b8125", + "0x920090091351ba1250091240910090091220910090091351c112e009132", + "0x912200712e16300912e1360f30090091350bc125009124092009009122", + "0x91c30071c202c00900912f05700900918500912e16300912e136163009", + "0x912916500900918516500900913500912e0091c312512e0091c300712e", + "0xf00090091350be1250091240071c401100900912f01100900912c165009", + "0x1b912500912400912e16900912e13616900900912200712e16900912e136", + "0x12e13616c00900912200712e16c00912e1360ee0090091350ec009009135", + "0x1c612e0091321c512e0091320c01250091240ec00900912900912e16c009", + "0x8d0090091351ca12e0091321c912e0091321c812e0091321c712e009132", + "0x11a00912e1360b200900912c0b600900912c0c212500912408d009009122", + "0x91340a70090091270a90090091291b80090091271b612500912400712e", + "0x912904a0090091730a50090091291b50090091270c4125009124037009", + "0x712e17500912e1360ea0090091350a300900912c06f00900912c04a009", + "0x712e17900912e1360e800900913500912e17500912e136175009009122", + "0x912904100900913e05b00900913e00912e17900912e136179009009122", + "0x91221b000900912c1b200900912c00912e00912d03700900912a03b009", + "0x914205b00900917309f0090091291ac0090091270c612500912403a009", + "0x912b1cc12e00913201b00900912c0370090091cb05b00900918505b009", + "0x912c0c71250091241b31250091240410090091420410090091850b8009", + "0x91321cf12e0091321ce12e0091321b71250091241cd12e00913205b009", + "0x91321d212e0091321d112e0091320c91250091240bc00900912b1d012e", + "0x91271ad12500912407700900912201f0090091311d412e0091321d312e", + "0x18400900912200712e18400912e1360e500900913509c0090091291a7009", + "0x91221a500900912c1a500900912b0cb12500912400912e18400912e136", + "0x1aa1250091240071d507b0090091291870090091270cd1250091241a5009", + "0x18000912e13601f00900917007f00900912907800900913e0d5009009129", + "0x18000900912707800900914200912e18000912e13618000900912200712e", + "0x7f00900912c18600900912c07800900912c0cf12500912401f009009173", + "0x91290740090091291740090091271a812500912400712e10a00912e136", + "0x12e13618800900912200712e18800912e1360071d60f6009009185072009", + "0x18900912e13618900900912200712e18900912e1360071d700912e188009", + "0x912200712e18a00912e1360e100900913500712e0df00912e13600912e", + "0x91271a312500912400912e18a00912e13600912e0df00912e13618a009", + "0x12e1360dd00900913506e00900912906e00900917307100900912916e009", + "0x71d80d112500912400912e18e00912e13618e00900912200712e18e009", + "0x912400912e16600912e13616600900912200712e16600912e1360071d9", + "0x91271a012500912402000900912203b00900912f1010090091851a1125", + "0x71dc1db12e00913202000900912c0670090091291da12e009132164009", + "0x19800912e13619800900912200712e19800912e1360da0090091350071dd", + "0x912200712e16200912e1360071df1de12e00913219b00900912900912e", + "0x1180090091291370090091270d512500912400912e16200912e136162009", + "0x19b1250091241e112e0091321e012e00913216100900912719f125009124", + "0x912e19f00912e13619f00900912200712e19f00912e1360d5009009135", + "0x912200712e1a100912e1360d10090091351a00090091290d8125009124", + "0x1680090091221e312e0091e21a000900912c00912e1a100912e1361a1009", + "0xda12500912400912e16000912e13616000900912200712e16000912e136", + "0x15f00912e1361981250091241e612e0091e21e512e0091e21e412e0091e2", + "0x1a800900912200912e1a800912e1361e712e00913215f00900912200712e", + "0x712e1a800912e1360cf00900913519712500912400912e15f00912e136", + "0x1aa00900912200712e1aa00912e1360cd0090091350071e806000900912f", + "0x712e15e00912e1360370090091700dd12500912400912e1aa00912e136", + "0x912405b00900912215e00900912700912e15e00912e13615e009009122", + "0xc90090091291ad00900912200912e1ad00912e1361e912e00913218e125", + "0x91e20df1250091241ea12e00913200712e1ad00912e1360c9009009135", + "0x912205a00900912915d0090091270e112500912416b0090091221eb12e", + "0x1b300912e1360c60090091350071ec02c00900912b18a125009124058009", + "0x912700912e0c400912e13600912e1b300912e1361b300900912200712e", + "0x912915900900912718812500912418912500912400e00900912b0c4009", + "0x1b600912e1361b600900912200712e1b600912e1360c2009009135054009", + "0x12e1360be0090091351ed12e0091e218c1250091240c400900912f00912e", + "0x91351ee12e0091e200912e1b900912e1361b900900912200712e1b9009", + "0x913500912e1ba00912e1361ba00900912200712e1ba00912e1360ba009", + "0x912400912e1bb00912e1361bb00900912200712e1bb00912e1360b6009", + "0x1bd00900912200712e1bd00912e1360b20090091350e512500912418b125", + "0x712e1bc00912e1360ae00900913518412500912400912e1bd00912e136", + "0x15700912e1360071ef18312500912400912e1bc00912e1361bc009009122", + "0xa01250091241f012e00913200912e15700912e13615700900912200712e", + "0x1751250091240ea12500912417b1250091241791250091240e8125009124", + "0x12e1361f112e00913215300900912200712e15300912e136155009009127", + "0xee12500912401800900912f0ec12500912417112500912400912e153009", + "0x712e1b800912e1360a900900913500712e0a700912e136037009009135", + "0x12e1360071f200912e1b800912e13600912e0a700912e1361b8009009122", + "0x913516c12500912400912e15200912e13615200900912200712e152009", + "0x91f300912e1b500912e1361b500900912200712e1b500912e1360a5009", + "0x1f412e0091321ac00900912200712e1ac00912e13609f009009135037009", + "0x71f71f612e0091f504700900912200900900912200912e1ac00912e136", + "0xf012500912400712e0091f51fa12e0091321f912e0091321f812e009132", + "0x148009009127169125009124009009009185049009009129150009009127", + "0x91320071fe1fd12e00912d1fc12e0091f50430090091291fb12e0091f5", + "0x912200712e14500912e13600720120012e00913204300900912c1ff12e", + "0x1f00900918516512500912420212e00913200912e14500912e136145009", + "0x1410090091270f312500912401b00900912f01f00900912b12e12e00912d", + "0x1a700912e13609c00900913500720401f00900913400720303e009009129", + "0x16312500912420512e00913200912e1a700912e1361a700900912200712e", + "0x91320f612500912420612e0091321a500900912700912e1a500912e136", + "0x20812e00913218700900912200912e18700912e1360f812500912420712e", + "0x15612500912420a12e0091320fa12500912420912e00913215c125009124", + "0x20d12e00913215812500912420c12e00913215412500912420b12e009132", + "0x10712500912420f12e00913215112500912420e12e0091320fd125009124", + "0x21212e00913210212500912421112e00913210112500912421012e009132", + "0x912f05200900912700712e18700912e13607b009009135104125009124", + "0x17400900912200912e17400912e13621312e00913200e12e00912d01f009", + "0x913500712e17400912e136074009009135072009009135015009009214", + "0x913200912e16e00912e13616e00900912200712e16e00912e136071009", + "0x14c12500912403b00900914203b00900913e16600900912700721621512e", + "0x912e16400912e13616400900912200712e16400912e136067009009135", + "0x912200712e16100912e13616200900912712600900912c020009009185", + "0x912716000900912701b12e1a500912e13600912e16100912e136161009", + "0x921a21900900912200721821712e00913201f12e1a500912e13615f009", + "0x14f12500912403600900912200721d21c12e00913221b12e009132036009", + "0x14d12500912410612500912403600900918500721f03600900912c00721e", + "0x912714e12500912401100900912200722001100900918516b009009185", + "0x15d00912e13605a00900913500712e05800912e136033009009129221009", + "0x15d00912e13616b00900912c00912e05800912e13615d00900912200712e", + "0x712e15900912e13605400900913505800900912722212e00913200912e", + "0x1a500912e13601112e1a500912e13600912e15900912e136159009009122", + "0x1812e1a500912e13622312e1a500912e13601512e1a500912e1361db12e", + "0x1a500912e13612512e1a500912e13612e12e1a500912e136157009009127", + "0x15500900912200712e15500912e1360072241fd12e1a500912e13600e12e", + "0x15200900912700712e1a500912e13615300900912700912e15500912e136", + "0x912204500900912200712e22500912e13602e009009170047009009129", + "0x2e00900917322500900912704700900913500912e22500912e136225009", + "0x912f00900902c00912e22602e00900912902e00900918502e009009122", + "0x15000900912200912e15000912e13622712e009132149125009124009009", + "0x22900912e13600722802e00900912c00712e15000912e136049009009135", + "0x10a12500912422a12e00913200912e22900912e13622900900912200712e", + "0x912e14800912e13614800900912200712e14800912e136043009009135", + "0x912200712e14100912e13603e0090091350150090091f3145009009127", + "0x8d00900912908d00900918501500900922b00912e14100912e136141009", + "0x10c12500912401800900914208e00900912908e00900918501800900913e", + "0x9100900912909000900912909000900918508f00900912908f009009185", + "0x9600900912909500900912909400900912909300900912c092009009129", + "0x146125009124099009009129098009009129147125009124097009009129", + "0x722f00722e1fd12e00913202500900912922d12e00913222c009009127", + "0x12e13600723400723300723221900900912c007231007230223009009122", + "0x912423512e00913200912e1db00912e1361db00900912200712e1db009", + "0x22100912e13622100900912200712e22100912e13603300900913514b125", + "0x918522900900912723612e0091321fd00900912710f12500912400912e", + "0x22c00900912200712e22c00912e13602500900913507f00900912f07f009", + "0x1441250091241250090091220072371db00900912700912e22c00912e136", + "0x1fd00900912200712e1fd00912e13600723812e00900912912e009009135", + "0x12e00712e00900700723b00900700700723a00723900912e1fd00912e136", + "0x91fd00912500700723b00900712e0072231db12e0be0111fd12e23b12e", + "0x700e00923b00900e0091fd00701100923b00901100900e0071fd00923b", + "0x1bd01500923b12e01f0091db00701f01b01812523b00900e0111fd125011", + "0x901800702302512e23b00901500922300700723b00900712e007020009", + "0x23b00902500901b00700723b00900712e00722c00909f02600923b12e023", + "0x702e02c12e23b00922900901500722900923b00923c00901f00723c009", + "0x12e23b00903000901500703000923b00900702500700723b00902c009020", + "0x902300704500923b00902e00902300700723b009225009020007031225", + "0x23b12e03304512e22c00704500923b00904500902600703300923b009031", + "0x900722900700723b00902600923c00700723b00900712e007007145007", + "0x3000703600923b00903600902e00703600923b00900702c00722100923b", + "0x921903812e03100703800923b00900722500721900923b00903622112e", + "0x701800923b00901800912500703b00923b00903a00904500703a00923b", + "0x912500922100701b00923b00901b00900e00700900923b009009009033", + "0x12e00703b12501b0090181fd00903b00923b00903b00903600712500923b", + "0x712600923b00912600903800712600923b00900721900700723b009007", + "0x723b00900712e00704114112e09003e03c12e23b12e12601b01812503a", + "0x923b00900703c00704300923b00900712600714500923b00900703b007", + "0x23b00900704100704900923b00900714100704700923b00900703e007148", + "0x14522314800715200923b00900704300704c00923b009007145007150009", + "0x703c00923b00903c00912500715300923b00915204c150049047148043", + "0x912500922100703e00923b00903e00900e00700900923b009009009033", + "0x2615312503e00903c01104900702600923b00902600904700712500923b", + "0x705800907805700923b12e1590091500071590540521571551fd23b009", + "0x15d12e23b00905700904c00705a00923b00900722900700723b00900712e", + "0x915500706015e12e23b00905d00915300700723b00915d00915200705d", + "0x5a00923b00905a00915700706000923b00906000902e00700723b00915e", + "0x915900700723b00916000905400716015f12e23b00905a06012e052007", + "0x923b00916100905800700723b00906400905700716106412e23b00915f", + "0x912500716400923b00906700915d00706700923b00916200905a007162", + "0x923b00905200900e00715700923b00915700903300715500923b009155", + "0x1551fd00916400923b00916400903600705400923b009054009221007052", + "0x12500716600923b00905800904500700723b00900712e007164054052157", + "0x23b00905200900e00715700923b00915700903300715500923b009155009", + "0x1fd00916600923b00916600903600705400923b009054009221007052009", + "0x22900700723b00902600923c00700723b00900712e007166054052157155", + "0x16b00923b00916b00902e00716b00923b00900705d00716800923b009007", + "0x6e12e03100706e00923b00900722500706d00923b00916b16812e030007", + "0x923b00914100912500707100923b00906f00904500706f00923b00906d", + "0x922100704100923b00904100900e00700900923b009009009033007141", + "0x711250410091411fd00907100923b00907100903600712500923b009125", + "0x723b00902500915e00700723b00922c00905400700723b00900712e007", + "0x23b00907200902e00707200923b00900706000716e00923b009007229007", + "0x3100717400923b00900722500707400923b00907216e12e030007072009", + "0x901800912500718000923b00907600904500707600923b00907417412e", + "0x701b00923b00901b00900e00700900923b00900900903300701800923b", + "0x1b0090181fd00918000923b00918000903600712500923b009125009221", + "0x1800912500707700923b00902000904500700723b00900712e007180125", + "0x1b00923b00901b00900e00700900923b00900900903300701800923b009", + "0x90181fd00907700923b00907700903600712500923b009125009221007", + "0x900722900700723b00900e00915e00700723b00900712e00707712501b", + "0x3000718600923b00918600902e00718600923b00900705d00707800923b", + "0x907b18712e03100718700923b00900722500707b00923b00918607812e", + "0x71db00923b0091db00912500707f00923b00908d00904500708d00923b", + "0x912500922100722300923b00922300900e00700900923b009009009033", + "0x15f00707f1252230091db1fd00907f00923b00907f00903600712500923b", + "0x12e00900700723b00900700700700723b0090071600071fd00923b009007", + "0x912500700723b00900712e00701822312e23d1db01112e23b12e009007", + "0x923b0091250091fd0071db00923b0091db00900e00701100923b009011", + "0x923b12e0150091db00701501f01b12523b0091251db011125011007125", + "0x702602312e23b00902000922300700723b00900712e00702500923e020", + "0x2300901b00700723b00900712e00723c00923f22c00923b12e026009018", + "0x2e12e23b00902c00901500702c00923b00922900901f00722900923b009", + "0x922500901500722500923b00900702500700723b00902e009020007030", + "0x703300923b00903000902300700723b00903100902000704503112e23b", + "0x22103312e22c00703300923b00903300902600722100923b009045009023", + "0x23c00700723b0091fd00906400700723b00900712e0070070f600723b12e", + "0x721900923b00900702c00703600923b00900722900700723b00922c009", + "0x900722500703800923b00921903612e03000721900923b00921900902e", + "0x12600923b00903b00904500703b00923b00903803a12e03100703a00923b", + "0x12e00922100701f00923b00901f00900e00701b00923b00901b009125007", + "0x12e00712612e01f01b00e00912600923b00912600903600712e00923b009", + "0x703c00923b00903c00903800703c00923b00900721900700723b009007", + "0x723b00900712e00714504112e24014103e12e23b12e03c01f01b12503a", + "0x923b00900703c00714800923b00900712600704300923b00900703b007", + "0x23b00900704100715000923b00900714100704900923b00900703e007047", + "0x4322314800715300923b00900704300715200923b00900714500704c009", + "0x703e00923b00903e00912500715500923b00915315204c150049047148", + "0x922c00904700712e00923b00912e00922100714100923b00914100900e", + "0x16200705400e05215700e23b00922c15512e14103e1fd16100722c00923b", + "0x12e00705700924115900923b12e05400906700700e00923b00900e1fd12e", + "0x15d05a12e23b00915900916400705800923b00900722900700723b009007", + "0x5d00916800715e05d12e23b00915d00916600700723b00905a009152007", + "0x705200923b00905200900e00715700923b00915700912500700723b009", + "0x5215700e06d00705800923b00905800915700715e00923b00915e00916b", + "0x716100924206400923b12e16000906e00716015f06012523b00905815e", + "0x23b00906700905400706716212e23b00906400906f00700723b00900712e", + "0x905800700723b00916400905700716616412e23b009162009159007007", + "0x923b00916b00915d00716b00923b00916800905a00716800923b009166", + "0x922100715f00923b00915f00900e00706000923b00906000912500706d", + "0x706d00e15f06000e00906d00923b00906d00903600700e00923b00900e", + "0x923b00906000912500706e00923b00916100904500700723b00900712e", + "0x903600700e00923b00900e00922100715f00923b00915f00900e007060", + "0x904500700723b00900712e00706e00e15f06000e00906e00923b00906e", + "0x923b00905200900e00715700923b00915700912500706f00923b009057", + "0x15700e00906f00923b00906f00903600700e00923b00900e009221007052", + "0x22c00923c00700723b0091fd00906400700723b00900712e00706f00e052", + "0x902e00716e00923b00900705d00707100923b00900722900700723b009", + "0x923b00900722500707200923b00916e07112e03000716e00923b00916e", + "0x12500707600923b00917400904500717400923b00907207412e031007074", + "0x23b00912e00922100714500923b00914500900e00704100923b009041009", + "0x900712e00707612e14504100e00907600923b00907600903600712e009", + "0x2300915e00700723b0091fd00906400700723b00923c00905400700723b", + "0x902e00707700923b00900706000718000923b00900722900700723b009", + "0x923b00900722500707800923b00907718012e03000707700923b009077", + "0x12500718700923b00907b00904500707b00923b00907818612e031007186", + "0x23b00912e00922100701f00923b00901f00900e00701b00923b00901b009", + "0x900712e00718712e01f01b00e00918700923b00918700903600712e009", + "0x912500708d00923b00902500904500700723b0091fd00906400700723b", + "0x923b00912e00922100701f00923b00901f00900e00701b00923b00901b", + "0x23b00900712e00708d12e01f01b00e00908d00923b00908d00903600712e", + "0x23b00900722900700723b00912500915e00700723b0091fd009064007007", + "0x12e03000708e00923b00908e00902e00708e00923b00900705d00707f009", + "0x23b00908f09012e03100709000923b00900722500708f00923b00908e07f", + "0xe00722300923b00922300912500709200923b009091009045007091009", + "0x23b00909200903600712e00923b00912e00922100701800923b009018009", + "0x23b00900716000701100923b00900707100709212e01822300e009092009", + "0x1812e2432231db12e23b12e12e00712e00900700723b009007007007007", + "0x900e00916e00700e00923b00900e0091fd00700723b00900712e00701b", + "0x1fd00923b12e0150090720071db00923b0091db00912500701501f12e23b", + "0x900e0071db00923b0091db00912500700723b00900712e007020009244", + "0x23b0091fd01112e07400701f00923b00901f0091fd00722300923b009223", + "0x23b12e02600907600702602302512523b00901f2231db1251740071fd009", + "0x2c22912e23b00922c00918000700723b00900712e00723c00924522c009", + "0x901b00700723b00900712e00703000924602e00923b12e02c009077007", + "0x12e23b00903100901500703100923b00922500901f00722500923b009229", + "0x22100901500722100923b00900702500700723b009045009020007033045", + "0x3800923b00903300902300700723b00903600902000721903612e23b009", + "0x3812e22c00703800923b00903800902600703a00923b009219009023007", + "0x700723b00902e00905700700723b00900712e00700724700723b12e03a", + "0x12600923b00900702c00703b00923b00900722900700723b0091fd009155", + "0x722500703c00923b00912603b12e03000712600923b00912600902e007", + "0x923b00914100904500714100923b00903c03e12e03100703e00923b009", + "0x900e00700900923b00900900903300702500923b009025009125007041", + "0x923b00904100903600712500923b00912500922100702300923b009023", + "0x923b00900721900700723b00900712e0070411250230090251fd009041", + "0x14804312e23b12e14502302512503a00714500923b009145009038007145", + "0x712600715000923b00900703b00700723b00900712e00704904712e248", + "0x14100715300923b00900703e00715200923b00900703c00704c00923b009", + "0x705200923b00900714500715700923b00900704100715500923b009007", + "0x923b00905405215715515315204c15022314800705400923b009007043", + "0x912500700723b00905700915200705805712e23b009159009078007159", + "0x923b00914800900e00700900923b00900900903300704300923b009043", + "0x91570071fd00923b0091fd00902e00712500923b009125009221007148", + "0x15d05a1fd23b00902e1fd0581251480090431db18600702e00923b00902e", + "0x723b00900712e00716000924915f00923b12e06000907b00706015e05d", + "0x916100915300716100923b00915f00918700706400923b009007229007", + "0x706700923b00906700902e00700723b00916200915500706716212e23b", + "0x905400716616412e23b00906406712e05200706400923b009064009157", + "0x723b00916800905700716b16812e23b00916400915900700723b009166", + "0x6e00915d00706e00923b00906d00905a00706d00923b00916b009058007", + "0x15d00923b00915d00903300705a00923b00905a00912500706f00923b009", + "0x6f00903600715e00923b00915e00922100705d00923b00905d00900e007", + "0x904500700723b00900712e00706f15e05d15d05a1fd00906f00923b009", + "0x923b00915d00903300705a00923b00905a00912500707100923b009160", + "0x903600715e00923b00915e00922100705d00923b00905d00900e00715d", + "0x5700700723b00900712e00707115e05d15d05a1fd00907100923b009071", + "0x716e00923b00900722900700723b0091fd00915500700723b00902e009", + "0x907216e12e03000707200923b00907200902e00707200923b00900705d", + "0x707600923b00907417412e03100717400923b00900722500707400923b", + "0x900900903300704700923b00904700912500718000923b009076009045", + "0x712500923b00912500922100704900923b00904900900e00700900923b", + "0x723b00900712e0071801250490090471fd00918000923b009180009036", + "0x23b0091fd00915500700723b00922900915e00700723b009030009054007", + "0x907800902e00707800923b00900708d00707700923b009007229007007", + "0x707b00923b00900722500718600923b00907807712e03000707800923b", + "0x2500912500708d00923b00918700904500718700923b00918607b12e031", + "0x2300923b00902300900e00700900923b00900900903300702500923b009", + "0x90251fd00908d00923b00908d00903600712500923b009125009221007", + "0x23c00904500700723b0091fd00915500700723b00900712e00708d125023", + "0x900923b00900900903300702500923b00902500912500707f00923b009", + "0x7f00903600712500923b00912500922100702300923b00902300900e007", + "0x905400700723b00900712e00707f1250230090251fd00907f00923b009", + "0x22900700723b00901100907f00700723b00901f00915e00700723b009020", + "0x8f00923b00908f00902e00708f00923b00900706000708e00923b009007", + "0x9112e03100709100923b00900722500709000923b00908f08e12e030007", + "0x923b0091db00912500709300923b00909200904500709200923b009090", + "0x922100722300923b00922300900e00700900923b0090090090330071db", + "0x931252230091db1fd00909300923b00909300903600712500923b009125", + "0x723b00901100907f00700723b00900e00915e00700723b00900712e007", + "0x23b00909500902e00709500923b00900705d00709400923b009007229007", + "0x3100709700923b00900722500709600923b00909509412e030007095009", + "0x901800912500709900923b00909800904500709800923b00909609712e", + "0x701b00923b00901b00900e00700900923b00900900903300701800923b", + "0x1b0090181fd00909900923b00909900903600712500923b009125009221", + "0x900708f00701800923b00900715f0071db00923b00900708e007099125", + "0x900700700700723b00900716000702000923b00900709000701f00923b", + "0x900712e00722c02612e24a02302512e23b12e12500912e00900700723b", + "0x1fd00702300923b00902300900e00702500923b00902500912500700723b", + "0x9200702c22923c12523b0091fd0230251250910071fd00923b0091fd009", + "0x902e00909300700723b00900712e00703000924b02e00923b12e02c009", + "0x23b00900712e00704500924c01500923b12e03100909400703122512e23b", + "0x91fd00722900923b00922900900e00723c00923b00923c009125007007", + "0x22522923c12517400701500923b00901502012e09500722500923b009225", + "0x712e00703800924d21900923b12e03600907600703622103312523b009", + "0x12600923b12e03b00907700703b03a12e23b00921900918000700723b009", + "0x901f00703e00923b00903a00901b00700723b00900712e00703c00924e", + "0x23b00904100902000714504112e23b00914100901500714100923b00903e", + "0x902000704714812e23b00904300901500704300923b009007025007007", + "0x15000923b00904700902300704900923b00914500902300700723b009148", + "0x12e00700724f00723b12e15004912e22c00704900923b009049009026007", + "0x6400700723b0091db00909700700723b00901f00909600700723b009007", + "0x700723b00901500909800700723b00912600905700700723b009018009", + "0x923b00915200902e00715200923b00900702c00704c00923b009007229", + "0x12e03100715500923b00900722500715300923b00915204c12e030007152", + "0x23b00900700909900705200923b00915700904500715700923b009153155", + "0xe00712e00923b00912e00903300703300923b009033009125007007009", + "0x23b00905200903600700e00923b00900e00922100722100923b009221009", + "0x900721900700723b00900712e00705200e22112e033007011009052009", + "0x12e23b12e05422103312503a00705400923b00905400903800705400923b", + "0x715d00923b00900703b00700723b00900712e00705a05812e250057159", + "0x6000923b00900703e00715e00923b00900703c00705d00923b009007126", + "0x923b00900714500716000923b00900704100715f00923b009007141007", + "0x916106416015f06015e05d15d22314800716100923b009007043007064", + "0x712e00923b00912e00903300715900923b00915900912500716200923b", + "0x900e00922100700700923b00900700909900705700923b00905700900e", + "0x712600923b00912600915700701500923b0090150091a500700e00923b", + "0x716622301116401b06701123b00912601516200e00705712e15922309c", + "0x12e16200701100923b0090111db12e03700701b00923b00901b01f12e1a7", + "0x712e00716b00925116800923b12e16600906700722300923b009223018", + "0x706f06e12e23b00916800916400706d00923b00900722900700723b009", + "0x907100916800716e07112e23b00906f00916600700723b00906e009152", + "0x16b00716400923b00916400900e00706700923b00906700912500700723b", + "0x16e16406700e06d00706d00923b00906d00915700716e00923b00916e009", + "0x12e00718000925207600923b12e17400906e00717407407212523b00906d", + "0x723b00907800905400707807712e23b00907600906f00700723b009007", + "0x7b00905800700723b00918600905700707b18612e23b009077009159007", + "0x7f00923b00908d00915d00708d00923b00918700905a00718700923b009", + "0x1b00903300707200923b00907200912500701100923b009011009099007", + "0x22300923b00922300922100707400923b00907400900e00701b00923b009", + "0x900712e00707f22307401b07201101100907f00923b00907f009036007", + "0x12500701100923b00901100909900708e00923b00918000904500700723b", + "0x23b00907400900e00701b00923b00901b00903300707200923b009072009", + "0x1100908e00923b00908e00903600722300923b009223009221007074009", + "0x8f00923b00916b00904500700723b00900712e00708e22307401b072011", + "0x1b00903300706700923b00906700912500701100923b009011009099007", + "0x22300923b00922300922100716400923b00916400900e00701b00923b009", + "0x900712e00708f22316401b06701101100908f00923b00908f009036007", + "0x1800906400700723b0091db00909700700723b00901f00909600700723b", + "0x722900700723b00901500909800700723b00912600905700700723b009", + "0x709100923b00909100902e00709100923b00900705d00709000923b009", + "0x9209312e03100709300923b00900722500709200923b00909109012e030", + "0x700923b00900700909900709500923b00909400904500709400923b009", + "0x5a00900e00712e00923b00912e00903300705800923b009058009125007", + "0x9500923b00909500903600700e00923b00900e00922100705a00923b009", + "0x23b00903c00905400700723b00900712e00709500e05a12e058007011009", + "0x901800906400700723b0091db00909700700723b00901f009096007007", + "0x900722900700723b00901500909800700723b00903a00915e00700723b", + "0x3000709700923b00909700902e00709700923b00900708d00709600923b", + "0x909809912e03100709900923b00900722500709800923b00909709612e", + "0x700700923b00900700909900709c00923b0091a50090450071a500923b", + "0x922100900e00712e00923b00912e00903300703300923b009033009125", + "0x909c00923b00909c00903600700e00923b00900e00922100722100923b", + "0x723b00901f00909600700723b00900712e00709c00e22112e033007011", + "0x23b00901500909800700723b00901800906400700723b0091db009097007", + "0x912500700700923b0090070090990071a700923b009038009045007007", + "0x923b00922100900e00712e00923b00912e00903300703300923b009033", + "0x70110091a700923b0091a700903600700e00923b00900e009221007221", + "0x6400700723b00904500905400700723b00900712e0071a700e22112e033", + "0x700723b0091db00909700700723b00901f00909600700723b009018009", + "0x3700923b00900722900700723b00902000905b00700723b00922500915e", + "0x5b03712e03000705b00923b00905b00902e00705b00923b009007060007", + "0x1b000923b00909f1ac12e0310071ac00923b00900722500709f00923b009", + "0x23c00912500700700923b0090070090990071b200923b0091b0009045007", + "0x22900923b00922900900e00712e00923b00912e00903300723c00923b009", + "0x23c0070110091b200923b0091b200903600700e00923b00900e009221007", + "0x909600700723b00901800906400700723b00900712e0071b200e22912e", + "0x4500700723b00902000905b00700723b0091db00909700700723b00901f", + "0x23b00923c00912500700700923b0090070090990070a300923b009030009", + "0x22100722900923b00922900900e00712e00923b00912e00903300723c009", + "0x22912e23c0070110090a300923b0090a300903600700e00923b00900e009", + "0x901800906400700723b00902000905b00700723b00900712e0070a300e", + "0x1fd00915e00700723b0091db00909700700723b00901f00909600700723b", + "0x902e0070a500923b00900705d00704a00923b00900722900700723b009", + "0x923b0090072250071b500923b0090a504a12e0300070a500923b0090a5", + "0x990071b800923b0090a90090450070a900923b0091b50a712e0310070a7", + "0x23b00912e00903300702600923b00902600912500700700923b009007009", + "0x3600700e00923b00900e00922100722c00923b00922c00900e00712e009", + "0x723b0090070070071b800e22c12e0260070110091b800923b0091b8009", + "0x723b00900712e0072231db12e2530111fd12e23b12e12e00912e009007", + "0xe0091fd00701100923b00901100900e0071fd00923b0091fd009125007", + "0x1f00909200701f01b01812523b00900e0111fd12509100700e00923b009", + "0x12e23b00901500909300700723b00900712e00702000925401500923b12e", + "0x700723b00900712e00722c00925502600923b12e023009094007023025", + "0x922900901500722900923b00923c00901f00723c00923b00902500901b", + "0x1500703000923b00900702500700723b00902c00902000702e02c12e23b", + "0x23b00902e00902300700723b00922500902000703122512e23b009030009", + "0x22c00704500923b00904500902600703300923b009031009023007045009", + "0x23b00902600909800700723b00900712e00700725600723b12e03304512e", + "0x903600902e00703600923b00900702c00722100923b009007229007007", + "0x703800923b00900722500721900923b00903622112e03000703600923b", + "0x700909900703b00923b00903a00904500703a00923b00921903812e031", + "0x1b00923b00901b00900e00701800923b00901800912500700700923b009", + "0x180071fd00903b00923b00903b00903600712500923b009125009221007", + "0x12600903800712600923b00900721900700723b00900712e00703b12501b", + "0x704114112e25703e03c12e23b12e12601b01812503a00712600923b009", + "0x704300923b00900712600714500923b00900703b00700723b00900712e", + "0x4900923b00900714100704700923b00900703e00714800923b00900703c", + "0x923b00900704300704c00923b00900714500715000923b009007041007", + "0x15300907800715300923b00915204c150049047148043145223148007152", + "0x3c00923b00903c00912500700723b00915500915200715715512e23b009", + "0x12500922100700700923b00900700909900703e00923b00903e00900e007", + "0x15712500703e03c01109f00702600923b0090260091a500712500923b009", + "0x15d00925805a00923b12e05800907b0070580571590540521fd23b009026", + "0x923b00905a00918700705d00923b00900722900700723b00900712e007", + "0x902e00700723b00906000915500715f06012e23b00915e00915300715e", + "0x23b00905d15f12e05200705d00923b00905d00915700715f00923b00915f", + "0x716216112e23b00916000915900700723b00906400905400706416012e", + "0x23b00906700905a00706700923b00916200905800700723b009161009057", + "0x12500715900923b00915900909900716600923b00916400915d007164009", + "0x23b00905700922100705400923b00905400900e00705200923b009052009", + "0x712e0071660570540521591fd00916600923b009166009036007057009", + "0x715900923b00915900909900716800923b00915d00904500700723b009", + "0x905700922100705400923b00905400900e00705200923b009052009125", + "0x12e0071680570540521591fd00916800923b00916800903600705700923b", + "0x5d00716b00923b00900722900700723b00902600909800700723b009007", + "0x23b00906d16b12e03000706d00923b00906d00902e00706d00923b009007", + "0x4500707100923b00906e06f12e03100706f00923b00900722500706e009", + "0x23b00914100912500700700923b00900700909900716e00923b009071009", + "0x3600712500923b00912500922100704100923b00904100900e007141009", + "0x700723b00900712e00716e1250411410071fd00916e00923b00916e009", + "0x7200923b00900722900700723b00902500915e00700723b00922c009054", + "0x7407212e03000707400923b00907400902e00707400923b009007060007", + "0x18000923b00917407612e03100707600923b00900722500717400923b009", + "0x1800912500700700923b00900700909900707700923b009180009045007", + "0x12500923b00912500922100701b00923b00901b00900e00701800923b009", + "0x23b00900712e00707712501b0180071fd00907700923b009077009036007", + "0x912500700700923b00900700909900707800923b009020009045007007", + "0x923b00912500922100701b00923b00901b00900e00701800923b009018", + "0x900712e00707812501b0180071fd00907800923b009078009036007125", + "0x900705d00718600923b00900722900700723b00900e00915e00700723b", + "0x18700923b00907b18612e03000707b00923b00907b00902e00707b00923b", + "0x7f00904500707f00923b00918708d12e03100708d00923b009007225007", + "0x1db00923b0091db00912500700700923b00900700909900708e00923b009", + "0x8e00903600712500923b00912500922100722300923b00922300900e007", + "0x12e00900700723b00900700700708e1252231db0071fd00908e00923b009", + "0x91fd00700723b00900712e0072231db12e2590111fd12e23b12e12e009", + "0x23b0091fd00912500701b01812e23b00900e00916e00700e00923b00900e", + "0x700723b00900712e00701500925a01f00923b12e01b0090720071fd009", + "0x902500901500702500923b00902000901f00702000923b00901800901b", + "0x1500722c00923b00900702500700723b00902300902000702602312e23b", + "0x23b00902600902300700723b00923c00902000722923c12e23b00922c009", + "0x22c00702c00923b00902c00902600702e00923b00922900902300702c009", + "0x23b00901f00915500700723b00900712e00700725b00723b12e02e02c12e", + "0x922500902e00722500923b00900702c00703000923b009007229007007", + "0x704500923b00900722500703100923b00922503012e03000722500923b", + "0x700909900722100923b00903300904500703300923b00903104512e031", + "0x1100923b00901100900e0071fd00923b0091fd00912500700700923b009", + "0x1fd0071fd00922100923b00922100903600712500923b009125009221007", + "0x3600903800703600923b00900721900700723b00900712e007221125011", + "0x703b03a12e25c03821912e23b12e0360111fd12503a00703600923b009", + "0x703c00923b00900712600712600923b00900703b00700723b00900712e", + "0x4100923b00900714100714100923b00900703e00703e00923b00900703c", + "0x923b00900704300704300923b00900714500714500923b009007041007", + "0x4700907800704700923b00914804314504114103e03c126223148007148", + "0x21900923b00921900912500700723b00904900915200715004912e23b009", + "0x12500922100700700923b00900700909900703800923b00903800900e007", + "0x1501250070382190111ac00701f00923b00901f00902e00712500923b009", + "0x5400925d05200923b12e1570091b000715715515315204c1fd23b00901f", + "0x923b0090520091b200715900923b00900722900700723b00900712e007", + "0x90a500700723b00905800904a00705a05812e23b0090570090a3007057", + "0x23b00915905a12e1b500715900923b00915900915700705a00923b00905a", + "0x706015e12e23b00915d00915900700723b00905d00905400705d15d12e", + "0x23b00915f00905a00715f00923b00906000905800700723b00915e009057", + "0x12500715300923b00915300909900706400923b00916000915d007160009", + "0x23b00915500922100715200923b00915200900e00704c00923b00904c009", + "0x712e00706415515204c1531fd00906400923b009064009036007155009", + "0x715300923b00915300909900716100923b00905400904500700723b009", + "0x915500922100715200923b00915200900e00704c00923b00904c009125", + "0x12e00716115515204c1531fd00916100923b00916100903600715500923b", + "0x5d00716200923b00900722900700723b00901f00915500700723b009007", + "0x23b00906716212e03000706700923b00906700902e00706700923b009007", + "0x4500716800923b00916416612e03100716600923b009007225007164009", + "0x23b00903a00912500700700923b00900700909900716b00923b009168009", + "0x3600712500923b00912500922100703b00923b00903b00900e00703a009", + "0x700723b00900712e00716b12503b03a0071fd00916b00923b00916b009", + "0x6d00923b00900722900700723b00901800915e00700723b009015009054", + "0x6e06d12e03000706e00923b00906e00902e00706e00923b009007060007", + "0x16e00923b00906f07112e03100707100923b00900722500706f00923b009", + "0x1fd00912500700700923b00900700909900707200923b00916e009045007", + "0x12500923b00912500922100701100923b00901100900e0071fd00923b009", + "0x23b00900712e0070721250111fd0071fd00907200923b009072009036007", + "0x23b00900705d00707400923b00900722900700723b00900e00915e007007", + "0x707600923b00917407412e03000717400923b00917400902e007174009", + "0x907700904500707700923b00907618012e03100718000923b009007225", + "0x71db00923b0091db00912500700700923b00900700909900707800923b", + "0x907800903600712500923b00912500922100722300923b00922300900e", + "0x70a70071fd00923b00900715f0070781252231db0071fd00907800923b", + "0x712e00900700723b00900700700700723b0090071600071db00923b009", + "0x22300912500700723b00900712e00701f01b12e25e01822312e23b12e009", + "0x12523b00912522312e0a900712500923b0091250091fd00722300923b009", + "0x723b00900712e00702300925f01100923b12e0250091b8007025020015", + "0x200091fd00701800923b00901800900e00701500923b009015009125007", + "0x902001801512517400701100923b0090111db12e0ac00702000923b009", + "0x900712e00702c00926022900923b12e23c00907600723c22c02612523b", + "0x26122500923b12e03000907700703002e12e23b00922900918000700723b", + "0x4500901f00704500923b00902e00901b00700723b00900712e007031009", + "0x723b00922100902000703622112e23b00903300901500703300923b009", + "0x3800902000703a03812e23b00921900901500721900923b009007025007", + "0x712600923b00903a00902300703b00923b00903600902300700723b009", + "0x712e00700726200723b12e12603b12e22c00703b00923b00903b009026", + "0x90ae00700723b00922500905700700723b0091fd00906400700723b009", + "0x2e00703e00923b00900702c00703c00923b00900722900700723b009011", + "0x23b00900722500714100923b00903e03c12e03000703e00923b00903e009", + "0x704300923b00914500904500714500923b00914104112e031007041009", + "0x912e00922100722c00923b00922c00900e00702600923b009026009125", + "0x712e00704312e22c02600e00904300923b00904300903600712e00923b", + "0x3a00714800923b00914800903800714800923b00900721900700723b009", + "0x700723b00900712e00704c15012e26304904712e23b12e14822c026125", + "0x15500923b00900703c00715300923b00900712600715200923b00900703b", + "0x923b00900704100705200923b00900714100715700923b00900703e007", + "0x15315222314800705700923b00900704300715900923b009007145007054", + "0xe00704700923b00904700912500705800923b009057159054052157155", + "0x23b0090110091bc00712e00923b00912e00922100704900923b009049009", + "0x922501105812e0490470110b000722500923b009225009157007011009", + "0x12e05d0090b200700e00923b00900e1fd12e16200705d00e15d05a00e23b", + "0x715f00923b00900722900700723b00900712e00706000926415e00923b", + "0x906400915900700723b00916000915200706416012e23b00915e0091bd", + "0x705a00923b00905a00912500700723b00916100905700716216112e23b", + "0x915f00915700716200923b0091620090b400715d00923b00915d00900e", + "0x16600906e00716616406712523b00915f16215d05a00e0b600715f00923b", + "0x12e23b00916800906f00700723b00900712e00716b00926516800923b12e", + "0x5700707106f12e23b00906d00915900700723b00906e00905400706e06d", + "0x923b00916e00905a00716e00923b00907100905800700723b00906f009", + "0x900e00706700923b00906700912500707400923b00907200915d007072", + "0x923b00907400903600700e00923b00900e00922100716400923b009164", + "0x923b00916b00904500700723b00900712e00707400e16406700e009074", + "0x922100716400923b00916400900e00706700923b009067009125007174", + "0x717400e16406700e00917400923b00917400903600700e00923b00900e", + "0x923b00905a00912500707600923b00906000904500700723b00900712e", + "0x903600700e00923b00900e00922100715d00923b00915d00900e00705a", + "0x906400700723b00900712e00707600e15d05a00e00907600923b009076", + "0x22900700723b0090110090ae00700723b00922500905700700723b0091fd", + "0x7700923b00907700902e00707700923b00900705d00718000923b009007", + "0x18612e03100718600923b00900722500707800923b00907718012e030007", + "0x923b00915000912500718700923b00907b00904500707b00923b009078", + "0x903600712e00923b00912e00922100704c00923b00904c00900e007150", + "0x905400700723b00900712e00718712e04c15000e00918700923b009187", + "0xae00700723b00902e00915e00700723b0091fd00906400700723b009031", + "0x707f00923b00900708d00708d00923b00900722900700723b009011009", + "0x900722500708e00923b00907f08d12e03000707f00923b00907f00902e", + "0x9100923b00909000904500709000923b00908e08f12e03100708f00923b", + "0x12e00922100722c00923b00922c00900e00702600923b009026009125007", + "0x12e00709112e22c02600e00909100923b00909100903600712e00923b009", + "0x4500700723b0090110090ae00700723b0091fd00906400700723b009007", + "0x23b00922c00900e00702600923b00902600912500709200923b00902c009", + "0xe00909200923b00909200903600712e00923b00912e00922100722c009", + "0x906400700723b00902300905400700723b00900712e00709212e22c026", + "0x22900700723b0091db0091bb00700723b00902000915e00700723b0091fd", + "0x9400923b00909400902e00709400923b00900706000709300923b009007", + "0x9612e03100709600923b00900722500709500923b00909409312e030007", + "0x923b00901500912500709800923b00909700904500709700923b009095", + "0x903600712e00923b00912e00922100701800923b00901800900e007015", + "0x906400700723b00900712e00709812e01801500e00909800923b009098", + "0x22900700723b0091db0091bb00700723b00912500915e00700723b0091fd", + "0x1a500923b0091a500902e0071a500923b00900705d00709900923b009007", + "0x1a712e0310071a700923b00900722500709c00923b0091a509912e030007", + "0x923b00901b00912500705b00923b00903700904500703700923b00909c", + "0x903600712e00923b00912e00922100701f00923b00901f00900e00701b", + "0x1600071fd00923b00900715f00705b12e01f01b00e00905b00923b00905b", + "0x1db01112e23b12e00900712e00900700723b00900700700700723b009007", + "0xe00701100923b00901100912500700723b00900712e00701822312e266", + "0x1251db01112517400712500923b0091250091fd0071db00923b0091db009", + "0x712e00702500926702000923b12e01500907600701501f01b12523b009", + "0x22c00923b12e02600907700702602312e23b00902000918000700723b009", + "0x901f00722900923b00902300901b00700723b00900712e00723c009268", + "0x23b00902e00902000703002e12e23b00902c00901500702c00923b009229", + "0x902000704503112e23b00922500901500722500923b009007025007007", + "0x22100923b00904500902300703300923b00903000902300700723b009031", + "0x12e00700726900723b12e22103312e22c00703300923b009033009026007", + "0x22900700723b00922c00905700700723b0091fd00906400700723b009007", + "0x21900923b00921900902e00721900923b00900702c00703600923b009007", + "0x3a12e03100703a00923b00900722500703800923b00921903612e030007", + "0x923b00901b00912500712600923b00903b00904500703b00923b009038", + "0x903600712e00923b00912e00922100701f00923b00901f00900e00701b", + "0x721900700723b00900712e00712612e01f01b00e00912600923b009126", + "0x23b12e03c01f01b12503a00703c00923b00903c00903800703c00923b009", + "0x4300923b00900703b00700723b00900712e00714504112e26a14103e12e", + "0x923b00900703e00704700923b00900703c00714800923b009007126007", + "0x23b00900714500704c00923b00900704100715000923b009007141007049", + "0x15315204c15004904714804322314800715300923b009007043007152009", + "0x14100923b00914100900e00703e00923b00903e00912500715500923b009", + "0x3e1fd0b800722c00923b00922c00915700712e00923b00912e009221007", + "0xe00923b00900e1fd12e16200705400e05215700e23b00922c15512e141", + "0x722900700723b00900712e00705700926b15900923b12e0540090b2007", + "0x723b00905a00915200715d05a12e23b0091590091bd00705800923b009", + "0x15700912500700723b00905d00905700715e05d12e23b00915d009159007", + "0x15e00923b00915e0090b400705200923b00905200900e00715700923b009", + "0x15f06012523b00905815e05215700e0b600705800923b009058009157007", + "0x6f00700723b00900712e00716100926c06400923b12e16000906e007160", + "0x23b00916200915900700723b00906700905400706716212e23b009064009", + "0x5a00716800923b00916600905800700723b00916400905700716616412e", + "0x23b00906000912500706d00923b00916b00915d00716b00923b009168009", + "0x3600700e00923b00900e00922100715f00923b00915f00900e007060009", + "0x4500700723b00900712e00706d00e15f06000e00906d00923b00906d009", + "0x23b00915f00900e00706000923b00906000912500706e00923b009161009", + "0xe00906e00923b00906e00903600700e00923b00900e00922100715f009", + "0x12500706f00923b00905700904500700723b00900712e00706e00e15f060", + "0x23b00900e00922100705200923b00905200900e00715700923b009157009", + "0x900712e00706f00e05215700e00906f00923b00906f00903600700e009", + "0x900722900700723b00922c00905700700723b0091fd00906400700723b", + "0x3000716e00923b00916e00902e00716e00923b00900705d00707100923b", + "0x907207412e03100707400923b00900722500707200923b00916e07112e", + "0x704100923b00904100912500707600923b00917400904500717400923b", + "0x907600903600712e00923b00912e00922100714500923b00914500900e", + "0x923c00905400700723b00900712e00707612e14504100e00907600923b", + "0x900722900700723b00902300915e00700723b0091fd00906400700723b", + "0x3000707700923b00907700902e00707700923b00900706000718000923b", + "0x907818612e03100718600923b00900722500707800923b00907718012e", + "0x701b00923b00901b00912500718700923b00907b00904500707b00923b", + "0x918700903600712e00923b00912e00922100701f00923b00901f00900e", + "0x91fd00906400700723b00900712e00718712e01f01b00e00918700923b", + "0xe00701b00923b00901b00912500708d00923b00902500904500700723b", + "0x23b00908d00903600712e00923b00912e00922100701f00923b00901f009", + "0x23b0091fd00906400700723b00900712e00708d12e01f01b00e00908d009", + "0x23b00900705d00707f00923b00900722900700723b00912500915e007007", + "0x708f00923b00908e07f12e03000708e00923b00908e00902e00708e009", + "0x909100904500709100923b00908f09012e03100709000923b009007225", + "0x701800923b00901800900e00722300923b00922300912500709200923b", + "0x12e01822300e00909200923b00909200903600712e00923b00912e009221", + "0x1db12e26d0111fd12e23b12e12e00712e00900700723b009007007007092", + "0x900e00916e00700e00923b00900e0091fd00700723b00900712e007223", + "0x1f00923b12e01b0090720071fd00923b0091fd00912500701b01812e23b", + "0x901f00702000923b00901800901b00700723b00900712e00701500926e", + "0x23b00902300902000702602312e23b00902500901500702500923b009020", + "0x902000722923c12e23b00922c00901500722c00923b009007025007007", + "0x2e00923b00922900902300702c00923b00902600902300700723b00923c", + "0x12e00700726f00723b12e02e02c12e22c00702c00923b00902c009026007", + "0x2c00703000923b00900722900700723b00901f00915500700723b009007", + "0x23b00922503012e03000722500923b00922500902e00722500923b009007", + "0x4500703300923b00903104512e03100704500923b009007225007031009", + "0x23b0090090090330071fd00923b0091fd00912500722100923b009033009", + "0x3600712500923b00912500922100701100923b00901100900e007009009", + "0x700723b00900712e0072211250110091fd1fd00922100923b009221009", + "0x360111fd12503a00703600923b00903600903800703600923b009007219", + "0x23b00900703b00700723b00900712e00703b03a12e27003821912e23b12e", + "0x900703e00703e00923b00900703c00703c00923b009007126007126009", + "0x714500714500923b00900704100704100923b00900714100714100923b", + "0x14504114103e03c12622314800714800923b00900704300704300923b009", + "0x904900915200715004912e23b00904700907800704700923b009148043", + "0xe00700900923b00900900903300721900923b00921900912500700723b", + "0x23b00901f00902e00712500923b00912500922100703800923b009038009", + "0x715715515315204c1fd23b00901f1501250380092190110ba00701f009", + "0x900722900700723b00900712e00705400927105200923b12e15700907b", + "0x5a05812e23b00905700915300705700923b00905200918700715900923b", + "0x915900915700705a00923b00905a00902e00700723b009058009155007", + "0x723b00905d00905400705d15d12e23b00915905a12e05200715900923b", + "0x6000905800700723b00915e00905700706015e12e23b00915d009159007", + "0x6400923b00916000915d00716000923b00915f00905a00715f00923b009", + "0x15300900e00715200923b00915200903300704c00923b00904c009125007", + "0x6400923b00906400903600715500923b00915500922100715300923b009", + "0x923b00905400904500700723b00900712e00706415515315204c1fd009", + "0x900e00715200923b00915200903300704c00923b00904c009125007161", + "0x923b00916100903600715500923b00915500922100715300923b009153", + "0x23b00901f00915500700723b00900712e00716115515315204c1fd009161", + "0x906700902e00706700923b00900705d00716200923b009007229007007", + "0x716600923b00900722500716400923b00906716212e03000706700923b", + "0x3a00912500716b00923b00916800904500716800923b00916416612e031", + "0x3b00923b00903b00900e00700900923b00900900903300703a00923b009", + "0x903a1fd00916b00923b00916b00903600712500923b009125009221007", + "0x1800915e00700723b00901500905400700723b00900712e00716b12503b", + "0x902e00706e00923b00900706000706d00923b00900722900700723b009", + "0x923b00900722500706f00923b00906e06d12e03000706e00923b00906e", + "0x12500707200923b00916e00904500716e00923b00906f07112e031007071", + "0x23b00901100900e00700900923b0090090090330071fd00923b0091fd009", + "0x1fd00907200923b00907200903600712500923b009125009221007011009", + "0x22900700723b00900e00915e00700723b00900712e0070721250110091fd", + "0x17400923b00917400902e00717400923b00900705d00707400923b009007", + "0x18012e03100718000923b00900722500707600923b00917407412e030007", + "0x923b0091db00912500707800923b00907700904500707700923b009076", + "0x922100722300923b00922300900e00700900923b0090090090330071db", + "0x781252230091db1fd00907800923b00907800903600712500923b009125", + "0x2231db12e2720111fd12e23b12e12e00712e00900700723b009007007007", + "0x23b00900e00916e00700e00923b00900e0091fd00700723b00900712e007", + "0x27301f00923b12e01b0090720071fd00923b0091fd00912500701b01812e", + "0x1800916e00701800923b0090180091fd00700723b00900712e007015009", + "0x900712e00702600927402300923b12e02500907200702502012e23b009", + "0x723c22c12e23b00902000916e00702000923b0090200091fd00700723b", + "0x22c0091fd00700723b00900712e00702c00927522900923b12e23c009072", + "0x923b12e03000907200703002e12e23b00922c00916e00722c00923b009", + "0x1f00704500923b00902e00901b00700723b00900712e007031009276225", + "0x922100902000703622112e23b00903300901500703300923b009045009", + "0x2000703a03812e23b00921900901500721900923b00900702500700723b", + "0x923b00903a00902300703b00923b00903600902300700723b009038009", + "0x700727700723b12e12603b12e22c00703b00923b00903b009026007126", + "0x700723b00922900915500700723b00922500915500700723b00900712e", + "0x3c00923b00900722900700723b00901f00915500700723b009023009155", + "0x3e03c12e03000703e00923b00903e00902e00703e00923b00900702c007", + "0x14500923b00914104112e03100704100923b00900722500714100923b009", + "0x90090330071fd00923b0091fd00912500704300923b009145009045007", + "0x12500923b00912500922100701100923b00901100900e00700900923b009", + "0x23b00900712e0070431250110091fd1fd00904300923b009043009036007", + "0x1fd12503a00714800923b00914800903800714800923b009007219007007", + "0x703b00700723b00900712e00704c15012e27804904712e23b12e148011", + "0x3e00715500923b00900703c00715300923b00900712600715200923b009", + "0x705400923b00900704100705200923b00900714100715700923b009007", + "0x15715515315222314800705700923b00900704300715900923b009007145", + "0x915200715d05a12e23b00905800907800705800923b009057159054052", + "0x900923b00900900903300704700923b00904700912500700723b00905a", + "0x1f00902e00712500923b00912500922100704900923b00904900900e007", + "0x22900923b00922900902e00702300923b00902300902e00701f00923b009", + "0x22522902301f15d1250490090470181ba00722500923b00922500902e007", + "0x716100927906400923b12e16000907b00716015f06015e05d1fd23b009", + "0x6700923b00906400918700716200923b00900722900700723b00900712e", + "0x16600902e00700723b00916400915500716616412e23b009067009153007", + "0x12e23b00916216612e05200716200923b00916200915700716600923b009", + "0x5700706e06d12e23b00916800915900700723b00916b00905400716b168", + "0x923b00906f00905a00706f00923b00906e00905800700723b00906d009", + "0x903300705d00923b00905d00912500716e00923b00907100915d007071", + "0x923b00915f00922100706000923b00906000900e00715e00923b00915e", + "0x900712e00716e15f06015e05d1fd00916e00923b00916e00903600715f", + "0x3300705d00923b00905d00912500707200923b00916100904500700723b", + "0x23b00915f00922100706000923b00906000900e00715e00923b00915e009", + "0x712e00707215f06015e05d1fd00907200923b00907200903600715f009", + "0x915500700723b00922900915500700723b00922500915500700723b009", + "0x5d00707400923b00900722900700723b00901f00915500700723b009023", + "0x23b00917407412e03000717400923b00917400902e00717400923b009007", + "0x4500707700923b00907618012e03100718000923b009007225007076009", + "0x23b00900900903300715000923b00915000912500707800923b009077009", + "0x3600712500923b00912500922100704c00923b00904c00900e007009009", + "0x700723b00900712e00707812504c0091501fd00907800923b009078009", + "0x723b00922900915500700723b00902e00915e00700723b009031009054", + "0x923b00900722900700723b00901f00915500700723b009023009155007", + "0x18612e03000707b00923b00907b00902e00707b00923b0090070bc007186", + "0x923b00918708d12e03100708d00923b00900722500718700923b00907b", + "0x90330071fd00923b0091fd00912500708e00923b00907f00904500707f", + "0x923b00912500922100701100923b00901100900e00700900923b009009", + "0x900712e00708e1250110091fd1fd00908e00923b00908e009036007125", + "0x22c00915e00700723b00901f00915500700723b00902c00905400700723b", + "0x70be00708f00923b00900722900700723b00902300915500700723b009", + "0x923b00909008f12e03000709000923b00909000902e00709000923b009", + "0x904500709300923b00909109212e03100709200923b009007225007091", + "0x923b0090090090330071fd00923b0091fd00912500709400923b009093", + "0x903600712500923b00912500922100701100923b00901100900e007009", + "0x5400700723b00900712e0070941250110091fd1fd00909400923b009094", + "0x700723b00902000915e00700723b00901f00915500700723b009026009", + "0x923b00909600902e00709600923b00900708d00709500923b009007229", + "0x12e03100709800923b00900722500709700923b00909609512e030007096", + "0x23b0091fd0091250071a500923b00909900904500709900923b009097098", + "0x22100701100923b00901100900e00700900923b0090090090330071fd009", + "0x1250110091fd1fd0091a500923b0091a500903600712500923b009125009", + "0x23b00901800915e00700723b00901500905400700723b00900712e0071a5", + "0x91a700902e0071a700923b00900706000709c00923b009007229007007", + "0x705b00923b00900722500703700923b0091a709c12e0300071a700923b", + "0x1fd0091250071ac00923b00909f00904500709f00923b00903705b12e031", + "0x1100923b00901100900e00700900923b0090090090330071fd00923b009", + "0x91fd1fd0091ac00923b0091ac00903600712500923b009125009221007", + "0x900722900700723b00900e00915e00700723b00900712e0071ac125011", + "0x300071b200923b0091b200902e0071b200923b00900705d0071b000923b", + "0x90a304a12e03100704a00923b0090072250070a300923b0091b21b012e", + "0x71db00923b0091db0091250071b500923b0090a50090450070a500923b", + "0x912500922100722300923b00922300900e00700900923b009009009033", + "0x70071b51252230091db1fd0091b500923b0091b500903600712500923b", + "0x12e00701822312e27a1db01112e23b12e12500912e00900700723b009007", + "0x1b12e23b0091fd00916e0071fd00923b0091fd0091fd00700723b009007", + "0x2000927b01500923b12e01f00907200701100923b00901100912500701f", + "0x23b00901b00916e00701b00923b00901b0091fd00700723b00900712e007", + "0x723b00900712e00722c00927c02600923b12e02300907200702302512e", + "0x907200722923c12e23b00902500916e00702500923b0090250091fd007", + "0x23b00923c00901b00700723b00900712e00702e00927d02c00923b12e229", + "0x704503112e23b00922500901500722500923b00903000901f007030009", + "0x12e23b00903300901500703300923b00900702500700723b009031009020", + "0x902300721900923b00904500902300700723b009221009020007036221", + "0x23b12e03821912e22c00721900923b00921900902600703800923b009036", + "0x2600915500700723b00902c00915500700723b00900712e00700727e007", + "0x702c00703a00923b00900722900700723b00901500915500700723b009", + "0x923b00903b03a12e03000703b00923b00903b00902e00703b00923b009", + "0x904500703e00923b00912603c12e03100703c00923b009007225007126", + "0x923b00901100912500700700923b00900700909900714100923b00903e", + "0x92210071db00923b0091db00900e00712e00923b00912e009033007011", + "0xe1db12e01100701100914100923b00914100903600700e00923b00900e", + "0x23b00904100903800704100923b00900721900700723b00900712e007141", + "0x712e00704714812e27f04314512e23b12e0411db01112503a007041009", + "0x703c00715000923b00900712600704900923b00900703b00700723b009", + "0x4100715300923b00900714100715200923b00900703e00704c00923b009", + "0x705200923b00900704300715700923b00900714500715500923b009007", + "0x23b00914500912500705400923b00905215715515315204c150049223148", + "0x9900704300923b00904300900e00712e00923b00912e009033007145009", + "0x23b00901500902e00700e00923b00900e00922100700700923b009007009", + "0x1b900702c00923b00902c00902e00702600923b00902600902e007015009", + "0x705d15d05a05805715901123b00902c02601505400e00704312e145018", + "0x15e0090c200700723b00900712e00706000928015e00923b12e05d0090c0", + "0x706416012e23b00915f00915900715f00923b00900722900700723b009", + "0x23b00916100905a00716100923b00906400905800700723b009160009057", + "0x12500705a00923b00905a00909900706700923b00916200915d007162009", + "0x23b00905800900e00705700923b00905700903300715900923b009159009", + "0x1100906700923b00906700903600715d00923b00915d009221007058009", + "0x16400923b00906000904500700723b00900712e00706715d05805715905a", + "0x5700903300715900923b00915900912500705a00923b00905a009099007", + "0x15d00923b00915d00922100705800923b00905800900e00705700923b009", + "0x900712e00716415d05805715905a01100916400923b009164009036007", + "0x1500915500700723b00902600915500700723b00902c00915500700723b", + "0x902e00716800923b00900705d00716600923b00900722900700723b009", + "0x923b00900722500716b00923b00916816612e03000716800923b009168", + "0x9900706f00923b00906e00904500706e00923b00916b06d12e03100706d", + "0x23b00912e00903300714800923b00914800912500700700923b009007009", + "0x3600700e00923b00900e00922100704700923b00904700900e00712e009", + "0x723b00900712e00706f00e04712e14800701100906f00923b00906f009", + "0x23b00902600915500700723b00923c00915e00700723b00902e009054007", + "0x23b0090070be00707100923b00900722900700723b009015009155007007", + "0x707200923b00916e07112e03000716e00923b00916e00902e00716e009", + "0x917400904500717400923b00907207412e03100707400923b009007225", + "0x701100923b00901100912500700700923b00900700909900707600923b", + "0x900e0092210071db00923b0091db00900e00712e00923b00912e009033", + "0x707600e1db12e01100701100907600923b00907600903600700e00923b", + "0x700723b00901500915500700723b00922c00905400700723b00900712e", + "0x7700923b00900708d00718000923b00900722900700723b00902500915e", + "0x722500707800923b00907718012e03000707700923b00907700902e007", + "0x923b00907b00904500707b00923b00907818612e03100718600923b009", + "0x903300701100923b00901100912500700700923b009007009099007187", + "0x923b00900e0092210071db00923b0091db00900e00712e00923b00912e", + "0x712e00718700e1db12e01100701100918700923b00918700903600700e", + "0x722900700723b00901b00915e00700723b00902000905400700723b009", + "0x707f00923b00907f00902e00707f00923b00900706000708d00923b009", + "0x8e08f12e03100708f00923b00900722500708e00923b00907f08d12e030", + "0x700923b00900700909900709100923b00909000904500709000923b009", + "0x1db00900e00712e00923b00912e00903300701100923b009011009125007", + "0x9100923b00909100903600700e00923b00900e0092210071db00923b009", + "0x23b0091fd00915e00700723b00900712e00709100e1db12e011007011009", + "0x909300902e00709300923b00900705d00709200923b009007229007007", + "0x709500923b00900722500709400923b00909309212e03000709300923b", + "0x700909900709700923b00909600904500709600923b00909409512e031", + "0x12e00923b00912e00903300722300923b00922300912500700700923b009", + "0x9700903600700e00923b00900e00922100701800923b00901800900e007", + "0x900700723b00900700700709700e01812e22300701100909700923b009", + "0x1fd00700723b00900712e0071db01112e2811fd00e12e23b12e00900712e", + "0x900e00912500701822312e23b00912500916e00712500923b009125009", + "0x723b00900712e00701f00928201b00923b12e01800907200700e00923b", + "0x2000901500702000923b00901500901f00701500923b00922300901b007", + "0x702600923b00900702500700723b00902500902000702302512e23b009", + "0x902300902300700723b00922c00902000723c22c12e23b009026009015", + "0x722900923b00922900902600702c00923b00923c00902300722900923b", + "0x901b00915500700723b00900712e00700728300723b12e02c22912e22c", + "0x3000902e00703000923b00900702c00702e00923b00900722900700723b", + "0x3100923b00900722500722500923b00903002e12e03000703000923b009", + "0x912500703300923b00904500904500704500923b00922503112e031007", + "0x923b00912e0092210071fd00923b0091fd00900e00700e00923b00900e", + "0x23b00900712e00703312e1fd00e00e00903300923b00903300903600712e", + "0xe12503a00722100923b00922100903800722100923b009007219007007", + "0x703b00700723b00900712e00703a03812e28421903612e23b12e2211fd", + "0x3e00703c00923b00900703c00712600923b00900712600703b00923b009", + "0x704100923b00900704100714100923b00900714100703e00923b009007", + "0x3e03c12603b22314800704300923b00900704300714500923b009007145", + "0x21900900e00703600923b00903600912500714800923b009043145041141", + "0x1b00923b00901b00902e00712e00923b00912e00922100721900923b009", + "0x12e04c0090c000704c15004904700e23b00901b14812e2190361fd1b6007", + "0x700723b0091520090c200700723b00900712e00715300928515200923b", + "0x915700905700705215712e23b00915500915900715500923b009007229", + "0x15d00715900923b00905400905a00705400923b00905200905800700723b", + "0x23b00904900900e00704700923b00904700912500705700923b009159009", + "0xe00905700923b00905700903600715000923b009150009221007049009", + "0x12500705800923b00915300904500700723b00900712e007057150049047", + "0x23b00915000922100704900923b00904900900e00704700923b009047009", + "0x900712e00705815004904700e00905800923b009058009036007150009", + "0x900705d00705a00923b00900722900700723b00901b00915500700723b", + "0x5d00923b00915d05a12e03000715d00923b00915d00902e00715d00923b", + "0x6000904500706000923b00905d15e12e03100715e00923b009007225007", + "0x3a00923b00903a00900e00703800923b00903800912500715f00923b009", + "0x3a03800e00915f00923b00915f00903600712e00923b00912e009221007", + "0x922300915e00700723b00901f00905400700723b00900712e00715f12e", + "0x6400902e00706400923b00900706000716000923b00900722900700723b", + "0x16200923b00900722500716100923b00906416012e03000706400923b009", + "0x912500716400923b00906700904500706700923b00916116212e031007", + "0x923b00912e0092210071fd00923b0091fd00900e00700e00923b00900e", + "0x23b00900712e00716412e1fd00e00e00916400923b00916400903600712e", + "0x23b00900705d00716600923b00900722900700723b00912500915e007007", + "0x716b00923b00916816612e03000716800923b00916800902e007168009", + "0x906e00904500706e00923b00916b06d12e03100706d00923b009007225", + "0x71db00923b0091db00900e00701100923b00901100912500706f00923b", + "0x12e1db01100e00906f00923b00906f00903600712e00923b00912e009221", + "0x1112e2861fd00e12e23b12e00900712e00900700723b00900700700706f", + "0x912500916e00712500923b0091250091fd00700723b00900712e0071db", + "0x1b00923b12e01800907200700e00923b00900e00912500701822312e23b", + "0x901f00701500923b00922300901b00700723b00900712e00701f009287", + "0x23b00902500902000702302512e23b00902000901500702000923b009015", + "0x902000723c22c12e23b00902600901500702600923b009007025007007", + "0x2c00923b00923c00902300722900923b00902300902300700723b00922c", + "0x12e00700728800723b12e02c22912e22c00722900923b009229009026007", + "0x2c00702e00923b00900722900700723b00901b00915500700723b009007", + "0x23b00903002e12e03000703000923b00903000902e00703000923b009007", + "0x4500704500923b00922503112e03100703100923b009007225007225009", + "0x23b0091fd00900e00700e00923b00900e00912500703300923b009045009", + "0xe00903300923b00903300903600712e00923b00912e0092210071fd009", + "0x903800722100923b00900721900700723b00900712e00703312e1fd00e", + "0x3a03812e28921903612e23b12e2211fd00e12503a00722100923b009221", + "0x12600923b00900712600703b00923b00900703b00700723b00900712e007", + "0x923b00900714100703e00923b00900703e00703c00923b00900703c007", + "0x23b00900704300714500923b00900714500704100923b009007041007141", + "0x912500714800923b00904314504114103e03c12603b223148007043009", + "0x923b00912e00922100721900923b00921900900e00703600923b009036", + "0xe23b00901b14812e2190361fd0c400701b00923b00901b00902e00712e", + "0x23b00900712e00715300928a15200923b12e04c0090c000704c150049047", + "0x915500915900715500923b00900722900700723b0091520090c2007007", + "0x705400923b00905200905800700723b00915700905700705215712e23b", + "0x904700912500705700923b00915900915d00715900923b00905400905a", + "0x715000923b00915000922100704900923b00904900900e00704700923b", + "0x700723b00900712e00705715004904700e00905700923b009057009036", + "0x904900900e00704700923b00904700912500705800923b009153009045", + "0x905800923b00905800903600715000923b00915000922100704900923b", + "0x22900700723b00901b00915500700723b00900712e00705815004904700e", + "0x15d00923b00915d00902e00715d00923b00900705d00705a00923b009007", + "0x15e12e03100715e00923b00900722500705d00923b00915d05a12e030007", + "0x923b00903800912500715f00923b00906000904500706000923b00905d", + "0x903600712e00923b00912e00922100703a00923b00903a00900e007038", + "0x905400700723b00900712e00715f12e03a03800e00915f00923b00915f", + "0x6000716000923b00900722900700723b00922300915e00700723b00901f", + "0x23b00906416012e03000706400923b00906400902e00706400923b009007", + "0x4500706700923b00916116212e03100716200923b009007225007161009", + "0x23b0091fd00900e00700e00923b00900e00912500716400923b009067009", + "0xe00916400923b00916400903600712e00923b00912e0092210071fd009", + "0x722900700723b00912500915e00700723b00900712e00716412e1fd00e", + "0x716800923b00916800902e00716800923b00900705d00716600923b009", + "0x16b06d12e03100706d00923b00900722500716b00923b00916816612e030", + "0x1100923b00901100912500706f00923b00906e00904500706e00923b009", + "0x6f00903600712e00923b00912e0092210071db00923b0091db00900e007", + "0x712e00900700723b00900700700706f12e1db01100e00906f00923b009", + "0x1250091fd00700723b00900712e0071db01112e28b1fd00e12e23b12e009", + "0x923b00900e00912500701822312e23b00912500916e00712500923b009", + "0x1b00700723b00900712e00701f00928c01b00923b12e01800907200700e", + "0x23b00902000901500702000923b00901500901f00701500923b009223009", + "0x901500702600923b00900702500700723b00902500902000702302512e", + "0x923b00902300902300700723b00922c00902000723c22c12e23b009026", + "0x12e22c00722900923b00922900902600702c00923b00923c009023007229", + "0x723b00901b00915500700723b00900712e00700728d00723b12e02c229", + "0x23b00903000902e00703000923b00900702c00702e00923b009007229007", + "0x3100703100923b00900722500722500923b00903002e12e030007030009", + "0x900e00912500703300923b00904500904500704500923b00922503112e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00703312e1fd00e00e00903300923b009033009036", + "0x2211fd00e12503a00722100923b00922100903800722100923b009007219", + "0x23b00900703b00700723b00900712e00703a03812e28e21903612e23b12e", + "0x900703e00703c00923b00900703c00712600923b00900712600703b009", + "0x714500704100923b00900704100714100923b00900714100703e00923b", + "0x4114103e03c12603b22314800704300923b00900704300714500923b009", + "0x23b00921900900e00703600923b00903600912500714800923b009043145", + "0xc600701b00923b00901b00902e00712e00923b00912e009221007219009", + "0x923b12e04c0090c000704c15004904700e23b00901b14812e2190361fd", + "0x722900700723b0091520090c200700723b00900712e00715300928f152", + "0x723b00915700905700705215712e23b00915500915900715500923b009", + "0x15900915d00715900923b00905400905a00705400923b009052009058007", + "0x4900923b00904900900e00704700923b00904700912500705700923b009", + "0x4904700e00905700923b00905700903600715000923b009150009221007", + "0x4700912500705800923b00915300904500700723b00900712e007057150", + "0x15000923b00915000922100704900923b00904900900e00704700923b009", + "0x723b00900712e00705815004904700e00905800923b009058009036007", + "0x923b00900705d00705a00923b00900722900700723b00901b009155007", + "0x22500705d00923b00915d05a12e03000715d00923b00915d00902e00715d", + "0x23b00906000904500706000923b00905d15e12e03100715e00923b009007", + "0x22100703a00923b00903a00900e00703800923b00903800912500715f009", + "0x15f12e03a03800e00915f00923b00915f00903600712e00923b00912e009", + "0x723b00922300915e00700723b00901f00905400700723b00900712e007", + "0x23b00906400902e00706400923b00900706000716000923b009007229007", + "0x3100716200923b00900722500716100923b00906416012e030007064009", + "0x900e00912500716400923b00906700904500706700923b00916116212e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00716412e1fd00e00e00916400923b009164009036", + "0x16800923b00900705d00716600923b00900722900700723b00912500915e", + "0x722500716b00923b00916816612e03000716800923b00916800902e007", + "0x923b00906e00904500706e00923b00916b06d12e03100706d00923b009", + "0x92210071db00923b0091db00900e00701100923b00901100912500706f", + "0x706f12e1db01100e00906f00923b00906f00903600712e00923b00912e", + "0x71db01112e2901fd00e12e23b12e00900712e00900700723b009007007", + "0x12e23b00912500916e00712500923b0091250091fd00700723b00900712e", + "0x929101b00923b12e01800907200700e00923b00900e009125007018223", + "0x901500901f00701500923b00922300901b00700723b00900712e00701f", + "0x700723b00902500902000702302512e23b00902000901500702000923b", + "0x922c00902000723c22c12e23b00902600901500702600923b009007025", + "0x2600702c00923b00923c00902300722900923b00902300902300700723b", + "0x900712e00700729200723b12e02c22912e22c00722900923b009229009", + "0x900702c00702e00923b00900722900700723b00901b00915500700723b", + "0x22500923b00903002e12e03000703000923b00903000902e00703000923b", + "0x4500904500704500923b00922503112e03100703100923b009007225007", + "0x1fd00923b0091fd00900e00700e00923b00900e00912500703300923b009", + "0x1fd00e00e00903300923b00903300903600712e00923b00912e009221007", + "0x922100903800722100923b00900721900700723b00900712e00703312e", + "0x12e00703a03812e29321903612e23b12e2211fd00e12503a00722100923b", + "0x3c00712600923b00900712600703b00923b00900703b00700723b009007", + "0x714100923b00900714100703e00923b00900703e00703c00923b009007", + "0x4300923b00900704300714500923b00900714500704100923b009007041", + "0x903600912500714800923b00904314504114103e03c12603b223148007", + "0x712e00923b00912e00922100721900923b00921900900e00703600923b", + "0x4904700e23b00901b14812e2190361fd1b300701b00923b00901b00902e", + "0x700723b00900712e00715300929415200923b12e04c0090c000704c150", + "0x12e23b00915500915900715500923b00900722900700723b0091520090c2", + "0x905a00705400923b00905200905800700723b009157009057007052157", + "0x923b00904700912500705700923b00915900915d00715900923b009054", + "0x903600715000923b00915000922100704900923b00904900900e007047", + "0x904500700723b00900712e00705715004904700e00905700923b009057", + "0x923b00904900900e00704700923b00904700912500705800923b009153", + "0x4700e00905800923b00905800903600715000923b009150009221007049", + "0x900722900700723b00901b00915500700723b00900712e007058150049", + "0x3000715d00923b00915d00902e00715d00923b00900705d00705a00923b", + "0x905d15e12e03100715e00923b00900722500705d00923b00915d05a12e", + "0x703800923b00903800912500715f00923b00906000904500706000923b", + "0x915f00903600712e00923b00912e00922100703a00923b00903a00900e", + "0x901f00905400700723b00900712e00715f12e03a03800e00915f00923b", + "0x900706000716000923b00900722900700723b00922300915e00700723b", + "0x16100923b00906416012e03000706400923b00906400902e00706400923b", + "0x6700904500706700923b00916116212e03100716200923b009007225007", + "0x1fd00923b0091fd00900e00700e00923b00900e00912500716400923b009", + "0x1fd00e00e00916400923b00916400903600712e00923b00912e009221007", + "0x23b00900722900700723b00912500915e00700723b00900712e00716412e", + "0x12e03000716800923b00916800902e00716800923b00900705d007166009", + "0x23b00916b06d12e03100706d00923b00900722500716b00923b009168166", + "0xe00701100923b00901100912500706f00923b00906e00904500706e009", + "0x23b00906f00903600712e00923b00912e0092210071db00923b0091db009", + "0x12e00900712e00900700723b00900700700706f12e1db01100e00906f009", + "0x23b00912500901b00700723b00900712e0071db01112e2951fd00e12e23b", + "0x701f01b12e23b00901800901500701800923b00922300901f007223009", + "0x12e23b00901500901500701500923b00900702500700723b00901b009020", + "0x902300702300923b00901f00902300700723b009020009020007025020", + "0x923b00900e00912500702300923b00902300902600702600923b009025", + "0x722900700723b00900712e00700729600723b12e02602312e22c00700e", + "0x723c00923b00923c00902e00723c00923b00900702c00722c00923b009", + "0x22902c12e03100702c00923b00900722500722900923b00923c22c12e030", + "0xe00923b00900e00912500703000923b00902e00904500702e00923b009", + "0x3000903600712e00923b00912e0092210071fd00923b0091fd00900e007", + "0x900721900700723b00900712e00703012e1fd00e00e00903000923b009", + "0x12e23b12e2251fd00e12503a00722500923b00922500903800722500923b", + "0x703600923b00900703b00700723b00900712e00722103312e297045031", + "0x3a00923b00900703e00703800923b00900703c00721900923b009007126", + "0x923b00900714500712600923b00900704100703b00923b009007141007", + "0x903e03c12603b03a03821903622314800703e00923b00900704300703c", + "0x704500923b00904500900e00703100923b00903100912500714100923b", + "0x4314504100e23b00914112e04503100e0c700712e00923b00912e009221", + "0xc200700723b00900712e00704900929804700923b12e1480090c0007148", + "0x4c12e23b00915000915900715000923b00900722900700723b009047009", + "0x15300905a00715300923b00915200905800700723b00904c009057007152", + "0x4100923b00904100912500715700923b00915500915d00715500923b009", + "0x15700903600704300923b00904300922100714500923b00914500900e007", + "0x4900904500700723b00900712e00715704314504100e00915700923b009", + "0x14500923b00914500900e00704100923b00904100912500705200923b009", + "0x14504100e00905200923b00905200903600704300923b009043009221007", + "0x23b00900705d00705400923b00900722900700723b00900712e007052043", + "0x705700923b00915905412e03000715900923b00915900902e007159009", + "0x905a00904500705a00923b00905705812e03100705800923b009007225", + "0x722100923b00922100900e00703300923b00903300912500715d00923b", + "0x12e22103300e00915d00923b00915d00903600712e00923b00912e009221", + "0x923b00900722900700723b00912500915e00700723b00900712e00715d", + "0x5d12e03000715e00923b00915e00902e00715e00923b00900705d00705d", + "0x923b00906015f12e03100715f00923b00900722500706000923b00915e", + "0x900e00701100923b00901100912500706400923b009160009045007160", + "0x923b00906400903600712e00923b00912e0092210071db00923b0091db", + "0x23b12e00900712e00900700723b00900700700706412e1db01100e009064", + "0x923b00912500901b00700723b00900712e0071db01112e2991fd00e12e", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b00900702500700723b00901b009", + "0x2500902300702300923b00901f00902300700723b009020009020007025", + "0xe00923b00900e00912500702300923b00902300902600702600923b009", + "0x900722900700723b00900712e00700729a00723b12e02602312e22c007", + "0x3000723c00923b00923c00902e00723c00923b00900702c00722c00923b", + "0x922902c12e03100702c00923b00900722500722900923b00923c22c12e", + "0x700e00923b00900e00912500703000923b00902e00904500702e00923b", + "0x903000903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703012e1fd00e00e00903000923b", + "0x3112e23b12e2251fd00e12503a00722500923b009225009038007225009", + "0x12600703600923b00900703b00700723b00900712e00722103312e29b045", + "0x703a00923b00900703e00703800923b00900703c00721900923b009007", + "0x3c00923b00900714500712600923b00900704100703b00923b009007141", + "0x23b00903e03c12603b03a03821903622314800703e00923b009007043007", + "0x22100704500923b00904500900e00703100923b009031009125007141009", + "0x14804314504100e23b00914112e04503100e1b700712e00923b00912e009", + "0x90c200700723b00900712e00704900929c04700923b12e1480090c0007", + "0x15204c12e23b00915000915900715000923b00900722900700723b009047", + "0x915300905a00715300923b00915200905800700723b00904c009057007", + "0x704100923b00904100912500715700923b00915500915d00715500923b", + "0x915700903600704300923b00904300922100714500923b00914500900e", + "0x904900904500700723b00900712e00715704314504100e00915700923b", + "0x714500923b00914500900e00704100923b00904100912500705200923b", + "0x4314504100e00905200923b00905200903600704300923b009043009221", + "0x923b00900705d00705400923b00900722900700723b00900712e007052", + "0x22500705700923b00915905412e03000715900923b00915900902e007159", + "0x23b00905a00904500705a00923b00905705812e03100705800923b009007", + "0x22100722100923b00922100900e00703300923b00903300912500715d009", + "0x15d12e22103300e00915d00923b00915d00903600712e00923b00912e009", + "0x5d00923b00900722900700723b00912500915e00700723b00900712e007", + "0x15e05d12e03000715e00923b00915e00902e00715e00923b00900705d007", + "0x16000923b00906015f12e03100715f00923b00900722500706000923b009", + "0x1db00900e00701100923b00901100912500706400923b009160009045007", + "0x6400923b00906400903600712e00923b00912e0092210071db00923b009", + "0x12e23b12e00900712e00900700723b00900700700706412e1db01100e009", + "0x22300923b00912500901b00700723b00900712e0071db01112e29d1fd00e", + "0x902000701f01b12e23b00901800901500701800923b00922300901f007", + "0x2502012e23b00901500901500701500923b00900702500700723b00901b", + "0x902500902300702300923b00901f00902300700723b009020009020007", + "0x700e00923b00900e00912500702300923b00902300902600702600923b", + "0x23b00900722900700723b00900712e00700729e00723b12e02602312e22c", + "0x12e03000723c00923b00923c00902e00723c00923b00900702c00722c009", + "0x23b00922902c12e03100702c00923b00900722500722900923b00923c22c", + "0xe00700e00923b00900e00912500703000923b00902e00904500702e009", + "0x23b00903000903600712e00923b00912e0092210071fd00923b0091fd009", + "0x923b00900721900700723b00900712e00703012e1fd00e00e009030009", + "0x4503112e23b12e2251fd00e12503a00722500923b009225009038007225", + "0x712600703600923b00900703b00700723b00900712e00722103312e29f", + "0x14100703a00923b00900703e00703800923b00900703c00721900923b009", + "0x703c00923b00900714500712600923b00900704100703b00923b009007", + "0x923b00903e03c12603b03a03821903622314800703e00923b009007043", + "0x922100704500923b00904500900e00703100923b009031009125007141", + "0x714804314504100e23b00914112e04503100e0c900712e00923b00912e", + "0x470090c200700723b00900712e0070490092a004700923b12e1480090c0", + "0x715204c12e23b00915000915900715000923b00900722900700723b009", + "0x23b00915300905a00715300923b00915200905800700723b00904c009057", + "0xe00704100923b00904100912500715700923b00915500915d007155009", + "0x23b00915700903600704300923b00904300922100714500923b009145009", + "0x23b00904900904500700723b00900712e00715704314504100e009157009", + "0x22100714500923b00914500900e00704100923b009041009125007052009", + "0x5204314504100e00905200923b00905200903600704300923b009043009", + "0x15900923b00900705d00705400923b00900722900700723b00900712e007", + "0x722500705700923b00915905412e03000715900923b00915900902e007", + "0x923b00905a00904500705a00923b00905705812e03100705800923b009", + "0x922100722100923b00922100900e00703300923b00903300912500715d", + "0x715d12e22103300e00915d00923b00915d00903600712e00923b00912e", + "0x705d00923b00900722900700723b00912500915e00700723b00900712e", + "0x915e05d12e03000715e00923b00915e00902e00715e00923b00900705d", + "0x716000923b00906015f12e03100715f00923b00900722500706000923b", + "0x91db00900e00701100923b00901100912500706400923b009160009045", + "0x906400923b00906400903600712e00923b00912e0092210071db00923b", + "0xe12e23b12e00900712e00900700723b00900700700706412e1db01100e", + "0x722300923b00912500901b00700723b00900712e0071db01112e2a11fd", + "0x1b00902000701f01b12e23b00901800901500701800923b00922300901f", + "0x702502012e23b00901500901500701500923b00900702500700723b009", + "0x23b00902500902300702300923b00901f00902300700723b009020009020", + "0x22c00700e00923b00900e00912500702300923b009023009026007026009", + "0x923b00900722900700723b00900712e0070072a200723b12e02602312e", + "0x22c12e03000723c00923b00923c00902e00723c00923b00900702c00722c", + "0x923b00922902c12e03100702c00923b00900722500722900923b00923c", + "0x900e00700e00923b00900e00912500703000923b00902e00904500702e", + "0x923b00903000903600712e00923b00912e0092210071fd00923b0091fd", + "0x22500923b00900721900700723b00900712e00703012e1fd00e00e009030", + "0x2a304503112e23b12e2251fd00e12503a00722500923b009225009038007", + "0x900712600703600923b00900703b00700723b00900712e00722103312e", + "0x714100703a00923b00900703e00703800923b00900703c00721900923b", + "0x4300703c00923b00900714500712600923b00900704100703b00923b009", + "0x14100923b00903e03c12603b03a03821903622314800703e00923b009007", + "0x4500900e00700723b00904100915200714504112e23b009141009078007", + "0x23b00914512e0451251ad00712e00923b00912e00922100704500923b009", + "0x4900923b12e04700907b00703100923b009031009125007047148043125", + "0x4900918700704c00923b00900722900700723b00900712e0071500092a4", + "0x723b00915300915500715515312e23b00915200915300715200923b009", + "0x15512e05200704c00923b00904c00915700715500923b00915500902e007", + "0x12e23b00915700915900700723b00905200905400705215712e23b00904c", + "0x905a00705700923b00915900905800700723b009054009057007159054", + "0x923b00903100912500705a00923b00905800915d00705800923b009057", + "0x903600714800923b00914800922100704300923b00904300900e007031", + "0x904500700723b00900712e00705a14804303100e00905a00923b00905a", + "0x923b00904300900e00703100923b00903100912500715d00923b009150", + "0x3100e00915d00923b00915d00903600714800923b009148009221007043", + "0x900705d00705d00923b00900722900700723b00900712e00715d148043", + "0x6000923b00915e05d12e03000715e00923b00915e00902e00715e00923b", + "0x16000904500716000923b00906015f12e03100715f00923b009007225007", + "0x22100923b00922100900e00703300923b00903300912500706400923b009", + "0x22103300e00906400923b00906400903600712e00923b00912e009221007", + "0x23b00900722900700723b00912500915e00700723b00900712e00706412e", + "0x12e03000716200923b00916200902e00716200923b00900705d007161009", + "0x23b00906716412e03100716400923b00900722500706700923b009162161", + "0xe00701100923b00901100912500716800923b009166009045007166009", + "0x23b00916800903600712e00923b00912e0092210071db00923b0091db009", + "0x12e00900712e00900700723b00900700700716812e1db01100e009168009", + "0x23b00912500901b00700723b00900712e0071db01112e2a51fd00e12e23b", + "0x701f01b12e23b00901800901500701800923b00922300901f007223009", + "0x12e23b00901500901500701500923b00900702500700723b00901b009020", + "0x902300702300923b00901f00902300700723b009020009020007025020", + "0x923b00900e00912500702300923b00902300902600702600923b009025", + "0x722900700723b00900712e0070072a600723b12e02602312e22c00700e", + "0x723c00923b00923c00902e00723c00923b00900702c00722c00923b009", + "0x22902c12e03100702c00923b00900722500722900923b00923c22c12e030", + "0xe00923b00900e00912500703000923b00902e00904500702e00923b009", + "0x3000903600712e00923b00912e0092210071fd00923b0091fd00900e007", + "0x900721900700723b00900712e00703012e1fd00e00e00903000923b009", + "0x12e23b12e2251fd00e12503a00722500923b00922500903800722500923b", + "0x703600923b00900703b00700723b00900712e00722103312e2a7045031", + "0x3a00923b00900703e00703800923b00900703c00721900923b009007126", + "0x923b00900714500712600923b00900704100703b00923b009007141007", + "0x903e03c12603b03a03821903622314800703e00923b00900704300703c", + "0x700723b00904100915200714504112e23b00914100907800714100923b", + "0x12e0451250cb00712e00923b00912e00922100704500923b00904500900e", + "0x12e04700907b00703100923b00903100912500704714804312523b009145", + "0x704c00923b00900722900700723b00900712e0071500092a804900923b", + "0x15300915500715515312e23b00915200915300715200923b009049009187", + "0x704c00923b00904c00915700715500923b00915500902e00700723b009", + "0x15700915900700723b00905200905400705215712e23b00904c15512e052", + "0x5700923b00915900905800700723b00905400905700715905412e23b009", + "0x3100912500705a00923b00905800915d00705800923b00905700905a007", + "0x14800923b00914800922100704300923b00904300900e00703100923b009", + "0x723b00900712e00705a14804303100e00905a00923b00905a009036007", + "0x4300900e00703100923b00903100912500715d00923b009150009045007", + "0x15d00923b00915d00903600714800923b00914800922100704300923b009", + "0x705d00923b00900722900700723b00900712e00715d14804303100e009", + "0x915e05d12e03000715e00923b00915e00902e00715e00923b00900705d", + "0x716000923b00906015f12e03100715f00923b00900722500706000923b", + "0x922100900e00703300923b00903300912500706400923b009160009045", + "0x906400923b00906400903600712e00923b00912e00922100722100923b", + "0x22900700723b00912500915e00700723b00900712e00706412e22103300e", + "0x16200923b00916200902e00716200923b00900705d00716100923b009007", + "0x16412e03100716400923b00900722500706700923b00916216112e030007", + "0x923b00901100912500716800923b00916600904500716600923b009067", + "0x903600712e00923b00912e0092210071db00923b0091db00900e007011", + "0x12e00900700723b00900700700716812e1db01100e00916800923b009168", + "0x901b00700723b00900712e0071db01112e2a91fd00e12e23b12e009007", + "0x12e23b00901800901500701800923b00922300901f00722300923b009125", + "0x1500901500701500923b00900702500700723b00901b00902000701f01b", + "0x2300923b00901f00902300700723b00902000902000702502012e23b009", + "0xe00912500702300923b00902300902600702600923b009025009023007", + "0x723b00900712e0070072aa00723b12e02602312e22c00700e00923b009", + "0x23b00923c00902e00723c00923b00900702c00722c00923b009007229007", + "0x3100702c00923b00900722500722900923b00923c22c12e03000723c009", + "0x900e00912500703000923b00902e00904500702e00923b00922902c12e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00703012e1fd00e00e00903000923b009030009036", + "0x2251fd00e12503a00722500923b00922500903800722500923b009007219", + "0x23b00900703b00700723b00900712e00722103312e2ab04503112e23b12e", + "0x900703e00703800923b00900703c00721900923b009007126007036009", + "0x714500712600923b00900704100703b00923b00900714100703a00923b", + "0x12603b03a03821903622314800703e00923b00900704300703c00923b009", + "0x904100915200714504112e23b00914100907800714100923b00903e03c", + "0xcd00712e00923b00912e00922100704500923b00904500900e00700723b", + "0x7b00703100923b00903100912500704714804312523b00914512e045125", + "0x23b00900722900700723b00900712e0071500092ac04900923b12e047009", + "0x715515312e23b00915200915300715200923b00904900918700704c009", + "0x23b00904c00915700715500923b00915500902e00700723b009153009155", + "0x700723b00905200905400705215712e23b00904c15512e05200704c009", + "0x915900905800700723b00905400905700715905412e23b009157009159", + "0x705a00923b00905800915d00705800923b00905700905a00705700923b", + "0x914800922100704300923b00904300900e00703100923b009031009125", + "0x712e00705a14804303100e00905a00923b00905a00903600714800923b", + "0x703100923b00903100912500715d00923b00915000904500700723b009", + "0x915d00903600714800923b00914800922100704300923b00904300900e", + "0x23b00900722900700723b00900712e00715d14804303100e00915d00923b", + "0x12e03000715e00923b00915e00902e00715e00923b00900705d00705d009", + "0x23b00906015f12e03100715f00923b00900722500706000923b00915e05d", + "0xe00703300923b00903300912500706400923b009160009045007160009", + "0x23b00906400903600712e00923b00912e00922100722100923b009221009", + "0x23b00912500915e00700723b00900712e00706412e22103300e009064009", + "0x916200902e00716200923b00900705d00716100923b009007229007007", + "0x716400923b00900722500706700923b00916216112e03000716200923b", + "0x1100912500716800923b00916600904500716600923b00906716412e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700716812e1db01100e00916800923b009168009036007", + "0x723b00900712e0071db01112e2ad1fd00e12e23b12e00900712e009007", + "0x1800901500701800923b00922300901f00722300923b00912500901b007", + "0x701500923b00900702500700723b00901b00902000701f01b12e23b009", + "0x901f00902300700723b00902000902000702502012e23b009015009015", + "0x702300923b00902300902600702600923b00902500902300702300923b", + "0x712e0070072ae00723b12e02602312e22c00700e00923b00900e009125", + "0x902e00723c00923b00900702c00722c00923b00900722900700723b009", + "0x923b00900722500722900923b00923c22c12e03000723c00923b00923c", + "0x12500703000923b00902e00904500702e00923b00922902c12e03100702c", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00703012e1fd00e00e00903000923b00903000903600712e009", + "0x12503a00722500923b00922500903800722500923b00900721900700723b", + "0x3b00700723b00900712e00722103312e2af04503112e23b12e2251fd00e", + "0x703800923b00900703c00721900923b00900712600703600923b009007", + "0x12600923b00900704100703b00923b00900714100703a00923b00900703e", + "0x3821903622314800703e00923b00900704300703c00923b009007145007", + "0x15200714504112e23b00914100907800714100923b00903e03c12603b03a", + "0x923b00904500900e00703100923b00903100912500700723b009041009", + "0x4300e23b00914512e04503100e1aa00712e00923b00912e009221007045", + "0x723b00900712e00704c0092b015000923b12e0490090cf007049047148", + "0x91530091a300715300923b0091500091a800715200923b009007229007", + "0x715700923b0091570091a100700723b0091550090d100715715512e23b", + "0x905400705405212e23b00915215712e1a000715200923b009152009157", + "0x723b00915900905700705715912e23b00905200915900700723b009054", + "0x5a00915d00705a00923b00905800905a00705800923b009057009058007", + "0x14800923b00914800900e00704300923b00904300912500715d00923b009", + "0x14804300e00915d00923b00915d00903600704700923b009047009221007", + "0x4300912500705d00923b00904c00904500700723b00900712e00715d047", + "0x4700923b00904700922100714800923b00914800900e00704300923b009", + "0x723b00900712e00705d04714804300e00905d00923b00905d009036007", + "0x23b00906000902e00706000923b00900705d00715e00923b009007229007", + "0x3100716000923b00900722500715f00923b00906015e12e030007060009", + "0x903300912500716100923b00906400904500706400923b00915f16012e", + "0x712e00923b00912e00922100722100923b00922100900e00703300923b", + "0x700723b00900712e00716112e22103300e00916100923b009161009036", + "0x6700923b00900705d00716200923b00900722900700723b00912500915e", + "0x722500716400923b00906716212e03000706700923b00906700902e007", + "0x923b00916800904500716800923b00916416612e03100716600923b009", + "0x92210071db00923b0091db00900e00701100923b00901100912500716b", + "0x716b12e1db01100e00916b00923b00916b00903600712e00923b00912e", + "0x71db01112e2b11fd00e12e23b12e00900712e00900700723b009007007", + "0x923b00922300901f00722300923b00912500901b00700723b00900712e", + "0x702500700723b00901b00902000701f01b12e23b009018009015007018", + "0x723b00902000902000702502012e23b00901500901500701500923b009", + "0x2300902600702600923b00902500902300702300923b00901f009023007", + "0x723b12e02602312e22c00700e00923b00900e00912500702300923b009", + "0x23b00900702c00722c00923b00900722900700723b00900712e0070072b2", + "0x722900923b00923c22c12e03000723c00923b00923c00902e00723c009", + "0x902e00904500702e00923b00922902c12e03100702c00923b009007225", + "0x71fd00923b0091fd00900e00700e00923b00900e00912500703000923b", + "0x12e1fd00e00e00903000923b00903000903600712e00923b00912e009221", + "0x23b00922500903800722500923b00900721900700723b00900712e007030", + "0x712e00722103312e2b304503112e23b12e2251fd00e12503a007225009", + "0x703c00721900923b00900712600703600923b00900703b00700723b009", + "0x4100703b00923b00900714100703a00923b00900703e00703800923b009", + "0x703e00923b00900704300703c00923b00900714500712600923b009007", + "0x23b00914100907800714100923b00903e03c12603b03a038219036223148", + "0x22900704300923b0091450090d500700723b00904100915200714504112e", + "0x23b00904700919b00704904712e23b00904300919f00714800923b009007", + "0x12e0da00714800923b00914800915700704900923b0090490090d8007007", + "0x23b00915000915900700723b00904c00905400704c15012e23b009148049", + "0x5a00715500923b00915300905800700723b00915200905700715315212e", + "0x23b00903100912500705200923b00915700915d00715700923b009155009", + "0x3600712e00923b00912e00922100704500923b00904500900e007031009", + "0x22900700723b00900712e00705212e04503100e00905200923b009052009", + "0x15900923b00915900902e00715900923b00900705d00705400923b009007", + "0x5812e03100705800923b00900722500705700923b00915905412e030007", + "0x923b00903300912500715d00923b00905a00904500705a00923b009057", + "0x903600712e00923b00912e00922100722100923b00922100900e007033", + "0x915e00700723b00900712e00715d12e22103300e00915d00923b00915d", + "0x2e00715e00923b00900705d00705d00923b00900722900700723b009125", + "0x23b00900722500706000923b00915e05d12e03000715e00923b00915e009", + "0x706400923b00916000904500716000923b00906015f12e03100715f009", + "0x912e0092210071db00923b0091db00900e00701100923b009011009125", + "0x700700706412e1db01100e00906400923b00906400903600712e00923b", + "0x712e0071db01112e2b41fd00e12e23b12e00900712e00900700723b009", + "0x701800923b00922300901f00722300923b00912500901b00700723b009", + "0x23b00900702500700723b00901b00902000701f01b12e23b009018009015", + "0x2300700723b00902000902000702502012e23b009015009015007015009", + "0x23b00902300902600702600923b00902500902300702300923b00901f009", + "0x72b500723b12e02602312e22c00700e00923b00900e009125007023009", + "0x23c00923b00900702c00722c00923b00900722900700723b00900712e007", + "0x722500722900923b00923c22c12e03000723c00923b00923c00902e007", + "0x923b00902e00904500702e00923b00922902c12e03100702c00923b009", + "0x92210071fd00923b0091fd00900e00700e00923b00900e009125007030", + "0x703012e1fd00e00e00903000923b00903000903600712e00923b00912e", + "0x22500923b00922500903800722500923b00900721900700723b00900712e", + "0x23b00900712e00722103312e2b604503112e23b12e2251fd00e12503a007", + "0x921900915300721900923b00900719800703600923b009007229007007", + "0x703a00923b00903a00902e00700723b00903800915500703a03812e23b", + "0x905400712603b12e23b00903603a12e05200703600923b009036009157", + "0x723b00903c00905700703e03c12e23b00903b00915900700723b009126", + "0x4100915d00704100923b00914100905a00714100923b00903e009058007", + "0x4500923b00904500900e00703100923b00903100912500714500923b009", + "0x4503100e00914500923b00914500903600712e00923b00912e009221007", + "0x23b00900705d00704300923b00900722900700723b00900712e00714512e", + "0x704700923b00914804312e03000714800923b00914800902e007148009", + "0x915000904500715000923b00904704912e03100704900923b009007225", + "0x722100923b00922100900e00703300923b00903300912500704c00923b", + "0x12e22103300e00904c00923b00904c00903600712e00923b00912e009221", + "0x923b00900722900700723b00912500915e00700723b00900712e00704c", + "0x15212e03000715300923b00915300902e00715300923b00900705d007152", + "0x923b00915515712e03100715700923b00900722500715500923b009153", + "0x900e00701100923b00901100912500705400923b009052009045007052", + "0x923b00905400903600712e00923b00912e0092210071db00923b0091db", + "0x23b12e00900712e00900700723b00900700700705412e1db01100e009054", + "0x923b00912500901b00700723b00900712e0071db01112e2b71fd00e12e", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b00900702500700723b00901b009", + "0x2500902300702300923b00901f00902300700723b009020009020007025", + "0xe00923b00900e00912500702300923b00902300902600702600923b009", + "0x900722900700723b00900712e0070072b800723b12e02602312e22c007", + "0x3000723c00923b00923c00902e00723c00923b00900702c00722c00923b", + "0x922902c12e03100702c00923b00900722500722900923b00923c22c12e", + "0x700e00923b00900e00912500703000923b00902e00904500702e00923b", + "0x903000903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703012e1fd00e00e00903000923b", + "0x3112e23b12e2251fd00e12503a00722500923b009225009038007225009", + "0x12600703600923b00900703b00700723b00900712e00722103312e2b9045", + "0x703a00923b00900703e00703800923b00900703c00721900923b009007", + "0x3c00923b00900714500712600923b00900704100703b00923b009007141", + "0x23b00903e03c12603b03a03821903622314800703e00923b009007043007", + "0x12500700723b00904100915200714504112e23b009141009078007141009", + "0x23b00912e00922100704500923b00904500900e00703100923b009031009", + "0x490090dd00704904714804300e23b00914512e04503100e19700712e009", + "0x15200923b00900722900700723b00900712e00704c0092ba15000923b12e", + "0x902000715715512e23b00915300901500715300923b00915000918e007", + "0x5400923b0090520090df00705200923b00915700902300700723b009155", + "0x5700705805712e23b00915900915900715900923b00905415212e030007", + "0x923b00905a00905a00705a00923b00905800905800700723b009057009", + "0x900e00704300923b00904300912500705d00923b00915d00915d00715d", + "0x923b00905d00903600704700923b00904700922100714800923b009148", + "0x923b00904c00904500700723b00900712e00705d04714804300e00905d", + "0x922100714800923b00914800900e00704300923b00904300912500715e", + "0x715e04714804300e00915e00923b00915e00903600704700923b009047", + "0x715f00923b00900705d00706000923b00900722900700723b00900712e", + "0x900722500716000923b00915f06012e03000715f00923b00915f00902e", + "0x16200923b00916100904500716100923b00916006412e03100706400923b", + "0x12e00922100722100923b00922100900e00703300923b009033009125007", + "0x12e00716212e22103300e00916200923b00916200903600712e00923b009", + "0x5d00706700923b00900722900700723b00912500915e00700723b009007", + "0x23b00916406712e03000716400923b00916400902e00716400923b009007", + "0x4500716b00923b00916616812e03100716800923b009007225007166009", + "0x23b0091db00900e00701100923b00901100912500706d00923b00916b009", + "0xe00906d00923b00906d00903600712e00923b00912e0092210071db009", + "0x1fd00e12e23b12e00900712e00900700723b00900700700706d12e1db011", + "0x1f00722300923b00912500901b00700723b00900712e0071db01112e2bb", + "0x901b00902000701f01b12e23b00901800901500701800923b009223009", + "0x2000702502012e23b00901500901500701500923b00900702500700723b", + "0x923b00902500902300702300923b00901f00902300700723b009020009", + "0x12e22c00700e00923b00900e00912500702300923b009023009026007026", + "0x22c00923b00900722900700723b00900712e0070072bc00723b12e026023", + "0x23c22c12e03000723c00923b00923c00902e00723c00923b00900702c007", + "0x2e00923b00922902c12e03100702c00923b00900722500722900923b009", + "0x1fd00900e00700e00923b00900e00912500703000923b00902e009045007", + "0x3000923b00903000903600712e00923b00912e0092210071fd00923b009", + "0x722500923b00900721900700723b00900712e00703012e1fd00e00e009", + "0x12e2bd04503112e23b12e2251fd00e12503a00722500923b009225009038", + "0x23b00900712600703600923b00900703b00700723b00900712e007221033", + "0x900714100703a00923b00900703e00703800923b00900703c007219009", + "0x704300703c00923b00900714500712600923b00900704100703b00923b", + "0x714100923b00903e03c12603b03a03821903622314800703e00923b009", + "0x903100912500700723b00904100915200714504112e23b009141009078", + "0x712e00923b00912e00922100704500923b00904500900e00703100923b", + "0x923b12e0490090dd00704904714804300e23b00914512e04503100e0e1", + "0x918e00715200923b00900722900700723b00900712e00704c0092be150", + "0x23b00915500902000715715512e23b00915300901500715300923b009150", + "0x12e03000705400923b0090520090df00705200923b009157009023007007", + "0x905700905700705805712e23b00915900915900715900923b009054152", + "0x15d00715d00923b00905a00905a00705a00923b00905800905800700723b", + "0x23b00914800900e00704300923b00904300912500705d00923b00915d009", + "0xe00905d00923b00905d00903600704700923b009047009221007148009", + "0x12500715e00923b00904c00904500700723b00900712e00705d047148043", + "0x23b00904700922100714800923b00914800900e00704300923b009043009", + "0x900712e00715e04714804300e00915e00923b00915e009036007047009", + "0x15f00902e00715f00923b00900705d00706000923b00900722900700723b", + "0x6400923b00900722500716000923b00915f06012e03000715f00923b009", + "0x912500716200923b00916100904500716100923b00916006412e031007", + "0x923b00912e00922100722100923b00922100900e00703300923b009033", + "0x23b00900712e00716212e22103300e00916200923b00916200903600712e", + "0x23b00900705d00706700923b00900722900700723b00912500915e007007", + "0x716600923b00916406712e03000716400923b00916400902e007164009", + "0x916b00904500716b00923b00916616812e03100716800923b009007225", + "0x71db00923b0091db00900e00701100923b00901100912500706d00923b", + "0x12e1db01100e00906d00923b00906d00903600712e00923b00912e009221", + "0x1112e2bf1fd00e12e23b12e00900712e00900700723b00900700700706d", + "0x922300901f00722300923b00912500901b00700723b00900712e0071db", + "0x700723b00901b00902000701f01b12e23b00901800901500701800923b", + "0x902000902000702502012e23b00901500901500701500923b009007025", + "0x2600702600923b00902500902300702300923b00901f00902300700723b", + "0x12e02602312e22c00700e00923b00900e00912500702300923b009023009", + "0x702c00722c00923b00900722900700723b00900712e0070072c000723b", + "0x923b00923c22c12e03000723c00923b00923c00902e00723c00923b009", + "0x904500702e00923b00922902c12e03100702c00923b009007225007229", + "0x923b0091fd00900e00700e00923b00900e00912500703000923b00902e", + "0xe00e00903000923b00903000903600712e00923b00912e0092210071fd", + "0x22500903800722500923b00900721900700723b00900712e00703012e1fd", + "0x722103312e2c104503112e23b12e2251fd00e12503a00722500923b009", + "0x721900923b00900712600703600923b00900703b00700723b00900712e", + "0x3b00923b00900714100703a00923b00900703e00703800923b00900703c", + "0x923b00900704300703c00923b00900714500712600923b009007041007", + "0x14100907800714100923b00903e03c12603b03a03821903622314800703e", + "0x3100923b00903100912500700723b00904100915200714504112e23b009", + "0x3100e18a00712e00923b00912e00922100704500923b00904500900e007", + "0x92c215000923b12e04900918900704904714804300e23b00914512e045", + "0x23b00915000918800715200923b00900722900700723b00900712e00704c", + "0xe500700723b00915500918b00715715512e23b00915300918c007153009", + "0x915215712e18400715200923b00915200915700715700923b009157009", + "0x5715912e23b00905200915900700723b00905400905400705405212e23b", + "0x905800905a00705800923b00905700905800700723b009159009057007", + "0x704300923b00904300912500715d00923b00905a00915d00705a00923b", + "0x915d00903600704700923b00904700922100714800923b00914800900e", + "0x904c00904500700723b00900712e00715d04714804300e00915d00923b", + "0x714800923b00914800900e00704300923b00904300912500705d00923b", + "0x4714804300e00905d00923b00905d00903600704700923b009047009221", + "0x923b00900705d00715e00923b00900722900700723b00900712e00705d", + "0x22500715f00923b00906015e12e03000706000923b00906000902e007060", + "0x23b00906400904500706400923b00915f16012e03100716000923b009007", + "0x22100722100923b00922100900e00703300923b009033009125007161009", + "0x16112e22103300e00916100923b00916100903600712e00923b00912e009", + "0x16200923b00900722900700723b00912500915e00700723b00900712e007", + "0x6716212e03000706700923b00906700902e00706700923b00900705d007", + "0x16800923b00916416612e03100716600923b00900722500716400923b009", + "0x1db00900e00701100923b00901100912500716b00923b009168009045007", + "0x16b00923b00916b00903600712e00923b00912e0092210071db00923b009", + "0x12e23b12e00900712e00900700723b00900700700716b12e1db01100e009", + "0x12500923b0091250091fd00700723b00900712e0071db01112e2c31fd00e", + "0x907200700e00923b00900e00912500701822312e23b00912500916e007", + "0x23b00922300901b00700723b00900712e00701f0092c401b00923b12e018", + "0x702302512e23b00902000901500702000923b00901500901f007015009", + "0x12e23b00902600901500702600923b00900702500700723b009025009020", + "0x902300722900923b00902300902300700723b00922c00902000723c22c", + "0x23b12e02c22912e22c00722900923b00922900902600702c00923b00923c", + "0x900722900700723b00901b00915500700723b00900712e0070072c5007", + "0x3000703000923b00903000902e00703000923b00900702c00702e00923b", + "0x922503112e03100703100923b00900722500722500923b00903002e12e", + "0x700e00923b00900e00912500703300923b00904500904500704500923b", + "0x903300903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703312e1fd00e00e00903300923b", + "0x3612e23b12e2211fd00e12503a00722100923b009221009038007221009", + "0x12600703b00923b00900703b00700723b00900712e00703a03812e2c6219", + "0x703e00923b00900703e00703c00923b00900703c00712600923b009007", + "0x14500923b00900714500704100923b00900704100714100923b009007141", + "0x23b00904314504114103e03c12603b22314800704300923b009007043007", + "0x2e00700723b00904700915200704904712e23b009148009078007148009", + "0x23b00900722900715000923b00901b04912e18300701b00923b00901b009", + "0xa500700723b00915200904a00715315212e23b0091500090a300704c009", + "0x904c15312e1b500704c00923b00904c00915700715300923b009153009", + "0x5405212e23b00915500915900700723b00915700905400715715512e23b", + "0x915900905a00715900923b00905400905800700723b009052009057007", + "0x703600923b00903600912500705800923b00905700915d00705700923b", + "0x905800903600712e00923b00912e00922100721900923b00921900900e", + "0x901b00915500700723b00900712e00705812e21903600e00905800923b", + "0x15d00902e00715d00923b00900705d00705a00923b00900722900700723b", + "0x15e00923b00900722500705d00923b00915d05a12e03000715d00923b009", + "0x912500715f00923b00906000904500706000923b00905d15e12e031007", + "0x923b00912e00922100703a00923b00903a00900e00703800923b009038", + "0x23b00900712e00715f12e03a03800e00915f00923b00915f00903600712e", + "0x23b00900722900700723b00922300915e00700723b00901f009054007007", + "0x12e03000706400923b00906400902e00706400923b009007060007160009", + "0x23b00916116212e03100716200923b00900722500716100923b009064160", + "0xe00700e00923b00900e00912500716400923b009067009045007067009", + "0x23b00916400903600712e00923b00912e0092210071fd00923b0091fd009", + "0x23b00912500915e00700723b00900712e00716412e1fd00e00e009164009", + "0x916800902e00716800923b00900705d00716600923b009007229007007", + "0x706d00923b00900722500716b00923b00916816612e03000716800923b", + "0x1100912500706f00923b00906e00904500706e00923b00916b06d12e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700706f12e1db01100e00906f00923b00906f009036007", + "0x723b00900712e0071db01112e2c71fd00e12e23b12e00900712e009007", + "0x1800901500701800923b00922300901f00722300923b00912500901b007", + "0x701500923b00900702500700723b00901b00902000701f01b12e23b009", + "0x901f00902300700723b00902000902000702502012e23b009015009015", + "0x702300923b00902300902600702600923b00902500902300702300923b", + "0x712e0070072c800723b12e02602312e22c00700e00923b00900e009125", + "0x902e00723c00923b00900702c00722c00923b00900722900700723b009", + "0x923b00900722500722900923b00923c22c12e03000723c00923b00923c", + "0x12500703000923b00902e00904500702e00923b00922902c12e03100702c", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00703012e1fd00e00e00903000923b00903000903600712e009", + "0x12503a00722500923b00922500903800722500923b00900721900700723b", + "0x22900700723b00900712e00722103312e2c904503112e23b12e2251fd00e", + "0x3812e23b00921900915300721900923b0090070a000703600923b009007", + "0x3600915700703a00923b00903a00902e00700723b00903800915500703a", + "0x23b00912600905400712603b12e23b00903603a12e05200703600923b009", + "0x905800700723b00903c00905700703e03c12e23b00903b009159007007", + "0x923b00904100915d00704100923b00914100905a00714100923b00903e", + "0x922100704500923b00904500900e00703100923b009031009125007145", + "0x714512e04503100e00914500923b00914500903600712e00923b00912e", + "0x714800923b00900705d00704300923b00900722900700723b00900712e", + "0x900722500704700923b00914804312e03000714800923b00914800902e", + "0x4c00923b00915000904500715000923b00904704912e03100704900923b", + "0x12e00922100722100923b00922100900e00703300923b009033009125007", + "0x12e00704c12e22103300e00904c00923b00904c00903600712e00923b009", + "0x5d00715200923b00900722900700723b00912500915e00700723b009007", + "0x23b00915315212e03000715300923b00915300902e00715300923b009007", + "0x4500705200923b00915515712e03100715700923b009007225007155009", + "0x23b0091db00900e00701100923b00901100912500705400923b009052009", + "0xe00905400923b00905400903600712e00923b00912e0092210071db009", + "0x1fd00e12e23b12e00900712e00900700723b00900700700705412e1db011", + "0x1f00722300923b00912500901b00700723b00900712e0071db01112e2ca", + "0x901b00902000701f01b12e23b00901800901500701800923b009223009", + "0x2000702502012e23b00901500901500701500923b00900702500700723b", + "0x923b00902500902300702300923b00901f00902300700723b009020009", + "0x12e22c00700e00923b00900e00912500702300923b009023009026007026", + "0x22c00923b00900722900700723b00900712e0070072cb00723b12e026023", + "0x23c22c12e03000723c00923b00923c00902e00723c00923b00900702c007", + "0x2e00923b00922902c12e03100702c00923b00900722500722900923b009", + "0x1fd00900e00700e00923b00900e00912500703000923b00902e009045007", + "0x3000923b00903000903600712e00923b00912e0092210071fd00923b009", + "0x722500923b00900721900700723b00900712e00703012e1fd00e00e009", + "0x12e2cc04503112e23b12e2251fd00e12503a00722500923b009225009038", + "0x23b00900719800703600923b00900722900700723b00900712e007221033", + "0x2e00700723b00903800915500703a03812e23b009219009153007219009", + "0x903603a12e05200703600923b00903600915700703a00923b00903a009", + "0x3e03c12e23b00903b00915900700723b00912600905400712603b12e23b", + "0x914100905a00714100923b00903e00905800700723b00903c009057007", + "0x703100923b00903100912500714500923b00904100915d00704100923b", + "0x914500903600712e00923b00912e00922100704500923b00904500900e", + "0x23b00900722900700723b00900712e00714512e04503100e00914500923b", + "0x12e03000714800923b00914800902e00714800923b00900705d007043009", + "0x23b00904704912e03100704900923b00900722500704700923b009148043", + "0xe00703300923b00903300912500704c00923b009150009045007150009", + "0x23b00904c00903600712e00923b00912e00922100722100923b009221009", + "0x23b00912500915e00700723b00900712e00704c12e22103300e00904c009", + "0x915300902e00715300923b00900705d00715200923b009007229007007", + "0x715700923b00900722500715500923b00915315212e03000715300923b", + "0x1100912500705400923b00905200904500705200923b00915515712e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700705412e1db01100e00905400923b009054009036007", + "0x723b00900712e0071db01112e2cd1fd00e12e23b12e00900712e009007", + "0x912500701822312e23b00912500916e00712500923b0091250091fd007", + "0x900712e00701f0092ce01b00923b12e01800907200700e00923b00900e", + "0x1500702000923b00901500901f00701500923b00922300901b00700723b", + "0x923b00900702500700723b00902500902000702302512e23b009020009", + "0x902300700723b00922c00902000723c22c12e23b009026009015007026", + "0x923b00922900902600702c00923b00923c00902300722900923b009023", + "0x915500700723b00900712e0070072cf00723b12e02c22912e22c007229", + "0x2e00703000923b00900702c00702e00923b00900722900700723b00901b", + "0x23b00900722500722500923b00903002e12e03000703000923b009030009", + "0x703300923b00904500904500704500923b00922503112e031007031009", + "0x912e0092210071fd00923b0091fd00900e00700e00923b00900e009125", + "0x712e00703312e1fd00e00e00903300923b00903300903600712e00923b", + "0x3a00722100923b00922100903800722100923b00900721900700723b009", + "0x700723b00900712e00703a03812e2d021903612e23b12e2211fd00e125", + "0x3c00923b00900703c00712600923b00900712600703b00923b00900703b", + "0x923b00900704100714100923b00900714100703e00923b00900703e007", + "0x12603b22314800704300923b00900704300714500923b009007145007041", + "0x704904712e23b00914800907800714800923b00904314504114103e03c", + "0x901b04912e0e800701b00923b00901b00902e00700723b009047009152", + "0x715315212e23b00915000915300704c00923b00900722900715000923b", + "0x23b00904c00915700715300923b00915300902e00700723b009152009155", + "0x700723b00915700905400715715512e23b00904c15312e05200704c009", + "0x905400905800700723b00905200905700705405212e23b009155009159", + "0x705800923b00905700915d00705700923b00915900905a00715900923b", + "0x912e00922100721900923b00921900900e00703600923b009036009125", + "0x712e00705812e21903600e00905800923b00905800903600712e00923b", + "0x705d00705a00923b00900722900700723b00901b00915500700723b009", + "0x923b00915d05a12e03000715d00923b00915d00902e00715d00923b009", + "0x904500706000923b00905d15e12e03100715e00923b00900722500705d", + "0x923b00903a00900e00703800923b00903800912500715f00923b009060", + "0x3800e00915f00923b00915f00903600712e00923b00912e00922100703a", + "0x22300915e00700723b00901f00905400700723b00900712e00715f12e03a", + "0x902e00706400923b00900706000716000923b00900722900700723b009", + "0x923b00900722500716100923b00906416012e03000706400923b009064", + "0x12500716400923b00906700904500706700923b00916116212e031007162", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00716412e1fd00e00e00916400923b00916400903600712e009", + "0x900705d00716600923b00900722900700723b00912500915e00700723b", + "0x16b00923b00916816612e03000716800923b00916800902e00716800923b", + "0x6e00904500706e00923b00916b06d12e03100706d00923b009007225007", + "0x1db00923b0091db00900e00701100923b00901100912500706f00923b009", + "0x1db01100e00906f00923b00906f00903600712e00923b00912e009221007", + "0x23b00900700700700723b00900716000701100923b00900707100706f12e", + "0x23b00900712e00701b01812e2d12231db12e23b12e12e00712e009007007", + "0x12500701501f12e23b00900e00916e00700e00923b00900e0091fd007007", + "0x712e0070200092d21fd00923b12e0150090720071db00923b0091db009", + "0x722300923b00922300900e0071db00923b0091db00912500700723b009", + "0x1db1251740071fd00923b0091fd01112e07400701f00923b00901f0091fd", + "0x723c0092d322c00923b12e02600907600702602302512523b00901f223", + "0x23b12e02c00907700702c22912e23b00922c00918000700723b00900712e", + "0x722500923b00922900901b00700723b00900712e0070300092d402e009", + "0x4500902000703304512e23b00903100901500703100923b00922500901f", + "0x721903612e23b00922100901500722100923b00900702500700723b009", + "0x23b00921900902300703800923b00903300902300700723b009036009020", + "0x72d500723b12e03a03812e22c00703800923b00903800902600703a009", + "0x723b0091fd00915500700723b00902e00905700700723b00900712e007", + "0x23b00912600902e00712600923b00900702c00703b00923b009007229007", + "0x3100703e00923b00900722500703c00923b00912603b12e030007126009", + "0x902500912500704100923b00914100904500714100923b00903c03e12e", + "0x702300923b00902300900e00700900923b00900900903300702500923b", + "0x230090251fd00904100923b00904100903600712500923b009125009221", + "0x914500903800714500923b00900721900700723b00900712e007041125", + "0x12e00704904712e2d614804312e23b12e14502302512503a00714500923b", + "0x3c00704c00923b00900712600715000923b00900703b00700723b009007", + "0x715500923b00900714100715300923b00900703e00715200923b009007", + "0x5400923b00900704300705200923b00900714500715700923b009007041", + "0x915900907800715900923b00905405215715515315204c150223148007", + "0x704300923b00904300912500700723b00905700915200705805712e23b", + "0x912500922100714800923b00914800900e00700900923b009009009033", + "0x702e00923b00902e0091570071fd00923b0091fd00902e00712500923b", + "0x907b00706015e05d15d05a1fd23b00902e1fd0581251480090431db179", + "0x923b00900722900700723b00900712e0071600092d715f00923b12e060", + "0x15500706716212e23b00916100915300716100923b00915f009187007064", + "0x923b00906400915700706700923b00906700902e00700723b009162009", + "0x15900700723b00916600905400716616412e23b00906406712e052007064", + "0x23b00916b00905800700723b00916800905700716b16812e23b009164009", + "0x12500706f00923b00906e00915d00706e00923b00906d00905a00706d009", + "0x23b00905d00900e00715d00923b00915d00903300705a00923b00905a009", + "0x1fd00906f00923b00906f00903600715e00923b00915e00922100705d009", + "0x707100923b00916000904500700723b00900712e00706f15e05d15d05a", + "0x905d00900e00715d00923b00915d00903300705a00923b00905a009125", + "0x907100923b00907100903600715e00923b00915e00922100705d00923b", + "0x700723b00902e00905700700723b00900712e00707115e05d15d05a1fd", + "0x7200923b00900705d00716e00923b00900722900700723b0091fd009155", + "0x722500707400923b00907216e12e03000707200923b00907200902e007", + "0x923b00907600904500707600923b00907417412e03100717400923b009", + "0x900e00700900923b00900900903300704700923b009047009125007180", + "0x923b00918000903600712500923b00912500922100704900923b009049", + "0x23b00903000905400700723b00900712e0071801250490090471fd009180", + "0x23b00900722900700723b0091fd00915500700723b00922900915e007007", + "0x12e03000707800923b00907800902e00707800923b00900708d007077009", + "0x23b00918607b12e03100707b00923b00900722500718600923b009078077", + "0x3300702500923b00902500912500708d00923b009187009045007187009", + "0x23b00912500922100702300923b00902300900e00700900923b009009009", + "0x712e00708d1250230090251fd00908d00923b00908d009036007125009", + "0x12500707f00923b00923c00904500700723b0091fd00915500700723b009", + "0x23b00902300900e00700900923b00900900903300702500923b009025009", + "0x1fd00907f00923b00907f00903600712500923b009125009221007023009", + "0x15e00700723b00902000905400700723b00900712e00707f125023009025", + "0x708e00923b00900722900700723b00901100907f00700723b00901f009", + "0x908f08e12e03000708f00923b00908f00902e00708f00923b009007060", + "0x709200923b00909009112e03100709100923b00900722500709000923b", + "0x90090090330071db00923b0091db00912500709300923b009092009045", + "0x712500923b00912500922100722300923b00922300900e00700900923b", + "0x723b00900712e0070931252230091db1fd00909300923b009093009036", + "0x923b00900722900700723b00901100907f00700723b00900e00915e007", + "0x9412e03000709500923b00909500902e00709500923b00900705d007094", + "0x923b00909609712e03100709700923b00900722500709600923b009095", + "0x903300701800923b00901800912500709900923b009098009045007098", + "0x923b00912500922100701b00923b00901b00900e00700900923b009009", + "0x900700700709912501b0090181fd00909900923b009099009036007125", + "0x900712e0071db01112e2d81fd00e12e23b12e00900712e00900700723b", + "0x701822312e23b00912500916e00712500923b0091250091fd00700723b", + "0x12e00701f0092d901b00923b12e01800907200700e00923b00900e009125", + "0x1512e23b00922300916e00722300923b0092230091fd00700723b009007", + "0x1b00700723b00900712e0070230092da02500923b12e020009072007020", + "0x23b00922c00901500722c00923b00902600901f00702600923b009015009", + "0x901500702c00923b00900702500700723b00923c00902000722923c12e", + "0x923b00922900902300700723b00902e00902000703002e12e23b00902c", + "0x12e22c00722500923b00922500902600703100923b009030009023007225", + "0x723b00902500915500700723b00900712e0070072db00723b12e031225", + "0x923b00900702c00704500923b00900722900700723b00901b009155007", + "0x22500722100923b00903304512e03000703300923b00903300902e007033", + "0x23b00921900904500721900923b00922103612e03100703600923b009007", + "0x2210071fd00923b0091fd00900e00700e00923b00900e009125007038009", + "0x3812e1fd00e00e00903800923b00903800903600712e00923b00912e009", + "0x923b00903a00903800703a00923b00900721900700723b00900712e007", + "0x900712e00703e03c12e2dc12603b12e23b12e03a1fd00e12503a00703a", + "0x900703c00704100923b00900712600714100923b00900703b00700723b", + "0x704100714800923b00900714100704300923b00900703e00714500923b", + "0x14800715000923b00900704300704900923b00900714500704700923b009", + "0x923b00903b00912500704c00923b009150049047148043145041141223", + "0x902e00712e00923b00912e00922100712600923b00912600900e00703b", + "0x4c12e12603b01117b00702500923b00902500902e00701b00923b00901b", + "0x540092dd05200923b12e1570090c000715715515315200e23b00902501b", + "0x15900923b00900722900700723b0090520090c200700723b00900712e007", + "0x5800905800700723b00905700905700705805712e23b009159009159007", + "0x5d00923b00915d00915d00715d00923b00905a00905a00705a00923b009", + "0x15500922100715300923b00915300900e00715200923b009152009125007", + "0x12e00705d15515315200e00905d00923b00905d00903600715500923b009", + "0x15200923b00915200912500715e00923b00905400904500700723b009007", + "0x15e00903600715500923b00915500922100715300923b00915300900e007", + "0x2500915500700723b00900712e00715e15515315200e00915e00923b009", + "0x705d00706000923b00900722900700723b00901b00915500700723b009", + "0x923b00915f06012e03000715f00923b00915f00902e00715f00923b009", + "0x904500716100923b00916006412e03100706400923b009007225007160", + "0x923b00903e00900e00703c00923b00903c00912500716200923b009161", + "0x3c00e00916200923b00916200903600712e00923b00912e00922100703e", + "0x1500915e00700723b00902300905400700723b00900712e00716212e03e", + "0x708d00706700923b00900722900700723b00901b00915500700723b009", + "0x923b00916406712e03000716400923b00916400902e00716400923b009", + "0x904500716b00923b00916616812e03100716800923b009007225007166", + "0x923b0091fd00900e00700e00923b00900e00912500706d00923b00916b", + "0xe00e00906d00923b00906d00903600712e00923b00912e0092210071fd", + "0x22300915e00700723b00901f00905400700723b00900712e00706d12e1fd", + "0x902e00706f00923b00900706000706e00923b00900722900700723b009", + "0x923b00900722500707100923b00906f06e12e03000706f00923b00906f", + "0x12500707400923b00907200904500707200923b00907116e12e03100716e", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00707412e1fd00e00e00907400923b00907400903600712e009", + "0x900705d00717400923b00900722900700723b00912500915e00700723b", + "0x18000923b00907617412e03000707600923b00907600902e00707600923b", + "0x7800904500707800923b00918007712e03100707700923b009007225007", + "0x1db00923b0091db00900e00701100923b00901100912500718600923b009", + "0x1db01100e00918600923b00918600903600712e00923b00912e009221007", + "0x12500917500712500923b00912e00901b00700723b0090070ea00718612e", + "0x23b0091fd00917100700723b00900712e0070110092de1fd00e12e23b12e", + "0xee00701800923b0091db0090ec00722300923b00900e0090b40071db009", + "0x90f000701b00923b00900716c00700723b00900712e0070072df009007", + "0x923b00901f0090ec00722300923b0090110090b400701f00923b00901b", + "0x916900701500923b0090150091fd00701500923b009223009058007018", + "0x23b00902000916500700723b00900712e0070250092e002000923b12e018", + "0x912500722c00923b00902300916300702600923b0090070f3007023009", + "0x923b0090150091fd00700900923b00900900900e00700700923b009007", + "0x1fd0f600722c00923b00922c00902e00702600923b009026009047007015", + "0x2e102e00923b12e02c0091db00702c22923c12523b00922c026015009007", + "0x12e0f800703122512e23b00902e00922300700723b00900712e007030009", + "0x23b00923c00912500703300923b00904500915c00704500923b009031225", + "0x12500903300923b0090330090fa00722900923b00922900900e00723c009", + "0x912500722100923b00903000915600700723b00900712e00703322923c", + "0x923b0092210090fa00722900923b00922900900e00723c00923b00923c", + "0x700723b00902500905400700723b00900712e00722122923c125009221", + "0x921901512e0f800721900923b00903600915400703600923b00900716c", + "0x700700923b00900700912500703a00923b00903800915c00703800923b", + "0x3a00900712500903a00923b00903a0090fa00700900923b00900900900e", + "0x23b00912500922100712e00923b00912e00900e00700723b0090070ea007", + "0x923b12e2230090fd0072231db01112523b00912512e12e158007125009", + "0x10700701f00923b00901800915100700723b00900712e00701b0092e2018", + "0x23b00902000910200700723b00901500910100702001512e23b00901f009", + "0x722c02612e23b00902300915300702300923b009025009104007025009", + "0x23b00923c00915300723c00923b00922c00916300700723b009026009155", + "0x915300702e00923b00900714c00700723b00922900915500702c22912e", + "0x923b00902c00916300700723b00903000915500722503012e23b00902e", + "0x2e00703300923b00904503112e14f00704500923b009225009163007031", + "0x900712e0072210092e300723b12e03300910600703300923b009033009", + "0x14d0071db00923b0091db00922100701100923b00901100900e00700723b", + "0x3b0092e403a00923b12e03800914e00703821903612523b0091db01112e", + "0x23b00912600910a00712600923b00903a00914900700723b00900712e007", + "0x15204c15004904714804314504114103e02023b00903c00910c00703c009", + "0x14800915500700723b00904100914700700723b009141009101007155153", + "0x914700700723b00904900914600700723b00904700915500700723b009", + "0x2000700723b00915200902000700723b00904c00915e00700723b009150", + "0x15712e23b00903e00915300700723b00915500915e00700723b009153009", + "0x915500705715912e23b00905400915300705400923b00900714b007052", + "0x5a00923b00905700916300705800923b00905200916300700723b009159", + "0x710f00715d00923b00905a05812e14f00705800923b00905800902e007", + "0x714500923b0091450091fd00715d00923b00915d00902e00700723b009", + "0x12e15d00910600715700923b00915700902e00704300923b00904300902e", + "0x14400715e00923b00900716c00700723b00900712e00705d0092e500723b", + "0x23b0090600090a500715f00923b00915700902e00706000923b00915e009", + "0x23b00905d00911100700723b00900712e0070072e60090070ee007160009", + "0x915300716200923b00900714300716106412e23b009157009153007007", + "0x923b00916100916300700723b00906700915500716406712e23b009162", + "0x2e00716b00923b00916816612e14f00716800923b009164009163007166", + "0x900712e00706d0092e700723b12e16b00910600716b00923b00916b009", + "0x90a500706f00923b00906e00914400706e00923b00900716c00700723b", + "0x911100700723b00900712e0070072e80090070ee00707100923b00906f", + "0x707200923b00916e00911300716e00923b00900716c00700723b00906d", + "0x90710090a500715f00923b00906400902e00707100923b0090720090a5", + "0x723b00900712e0071740092e907400923b12e16000914000716000923b", + "0x900711800718007612e23b00915f00915300700723b009074009054007", + "0x700723b00907800915500718607812e23b00907700915300707700923b", + "0x18707b12e14f00718700923b00918600916300707b00923b009180009163", + "0x2ea00723b12e08d00910600708d00923b00908d00902e00708d00923b009", + "0x908e00914400708e00923b00900716c00700723b00900712e00707f009", + "0x712e0070072eb0090070ee00709000923b00908f0090a500708f00923b", + "0x911300709100923b00900716c00700723b00907f00911100700723b009", + "0x923b00907600902e00709000923b0090920090a500709200923b009091", + "0x23b00900712e0070072ec0090070ee00709400923b0090900090a5007093", + "0x909500914400709500923b00900716c00700723b009174009054007007", + "0x709400923b0090960090a500709300923b00915f00902e00709600923b", + "0x9700905400700723b00900712e0070980092ed09700923b12e094009140", + "0x700723b0090990091550071a509912e23b00909300915300700723b009", + "0x91a70091550070371a712e23b00909c00915300709c00923b009007115", + "0x14f00709f00923b00903700916300705b00923b0091a500916300700723b", + "0x12e1ac0091060071ac00923b0091ac00902e0071ac00923b00909f05b12e", + "0x712e0070072ef0090070ee00700723b00900712e0071b00092ee00723b", + "0x1fd00923c00700723b0091b000911100700723b0090070ea00700723b009", + "0x915500700723b00914500915e00700723b00900e00915200700723b009", + "0x2e0070a300923b00900713b0071b200923b00900722900700723b009043", + "0x23b00900722500704a00923b0090a31b212e0300070a300923b0090a3009", + "0x70a700923b0091b50091390071b500923b00904a0a512e0310070a5009", + "0x903600900e00700900923b00900900903300700700923b009007009125", + "0x90a700923b0090a700913700721900923b00921900922100703600923b", + "0x700723b00909800905400700723b00900712e0070a72190360090071fd", + "0x23b00921900922100703600923b00903600900e00700723b009093009155", + "0x923b12e0ac00914e0070ac1b80a912523b00921903612e14d007219009", + "0x10a0070b000923b0090ae00914900700723b00900712e0071bc0092f00ae", + "0x1ba0ba0b81bb0b60b41bd02023b0090b200910c0070b200923b0090b0009", + "0x723b0090b400910100700723b0091bd0091550071b60c20c01b90be0bc", + "0x23b0090b800915500700723b0091bb00915e00700723b0090b6009147007", + "0x90bc00914600700723b0091ba00915500700723b0090ba009155007007", + "0xc200902000700723b0090c000902000700723b0090be00914700700723b", + "0xb40070c400923b0091b900901b00700723b0091b600915e00700723b009", + "0x23b0090c60090150070c600923b0090c400901f0070c400923b0090c4009", + "0x90150071b700923b00900702500700723b0091b30090200070c71b312e", + "0x923b0090c700902300700723b0090c90090200071ad0c912e23b0091b7", + "0x12e22c0070cb00923b0090cb0090260070cd00923b0091ad0090230070cb", + "0x700723b0090070ea00700723b00900712e0070072f100723b12e0cd0cb", + "0x723b00900e00915200700723b00904300915500700723b00914500915e", + "0x923b00900711a0071aa00923b00900722900700723b0091fd00923c007", + "0x2250071a800923b0090cf1aa12e0300070cf00923b0090cf00902e0070cf", + "0x23b0090d10091390070d100923b0091a81a312e0310071a300923b009007", + "0xe00700900923b00900900903300700700923b0090070091250071a1009", + "0x23b0091a10091370071b800923b0091b80092210070a900923b0090a9009", + "0x23b0090070ea00700723b00900712e0071a11b80a90090071fd0091a1009", + "0x912800700723b0091a000923c0070d51a012e23b0091fd00911c007007", + "0xd800923b00919b00911300719b00923b00900716c00719f00923b0090d5", + "0xa900900e00700900923b00900900903300700700923b009007009125007", + "0x19f00923b00919f0091230071b800923b0091b80092210070a900923b009", + "0xd80090a500714500923b0091450091fd00704300923b00904300902e007", + "0xda1fd23b0090d814504319f00e1b80a90090070180000070d800923b009", + "0x23b00900712e0070e10092f20df00923b12e18e0090c000718e0dd197198", + "0x72f400700723b00918900905400718918a12e23b0090df0092f3007007", + "0x923b00918c0092f600718c00923b00918818a12e2f500718800923b009", + "0x900e00719800923b0091980090330070da00923b0090da00912500718b", + "0x923b00918b0091370070dd00923b0090dd00922100719700923b009197", + "0x23b0090e100913900700723b00900712e00718b0dd1971980da1fd00918b", + "0xe00719800923b0091980090330070da00923b0090da0091250070e5009", + "0x23b0090e50091370070dd00923b0090dd00922100719700923b009197009", + "0x23b0090070ea00700723b00900712e0070e50dd1971980da1fd0090e5009", + "0x900e00915200700723b00904300915500700723b00914500915e007007", + "0x912500718400923b0091bc00913900700723b0091fd00923c00700723b", + "0x923b0090a900900e00700900923b00900900903300700700923b009007", + "0x71fd00918400923b0091840091370071b800923b0091b80092210070a9", + "0x915200700723b0091fd00923c00700723b00900712e0071841b80a9009", + "0x700923b00900700912500718300923b00903b00913900700723b00900e", + "0x21900922100703600923b00903600900e00700900923b009009009033007", + "0x71832190360090071fd00918300923b00918300913700721900923b009", + "0x700723b0091fd00923c00700723b00922100911100700723b00900712e", + "0xe800923b0090072f70070a000923b00900722900700723b00900e009152", + "0x722500717900923b0090e80a012e0300070e800923b0090e800902e007", + "0x923b0090ea0091390070ea00923b00917917b12e03100717b00923b009", + "0x900e00700900923b00900900903300700700923b009007009125007175", + "0x923b0091750091370071db00923b0091db00922100701100923b009011", + "0x23b0091fd00923c00700723b00900712e0071751db0110090071fd009175", + "0x700912500717100923b00901b00913900700723b00900e009152007007", + "0x1100923b00901100900e00700900923b00900900903300700700923b009", + "0x90071fd00917100923b0091710091370071db00923b0091db009221007", + "0x12500923b00912e00912e03000712e00923b0090070091630071711db011", + "0x700e12512e00912500923b00912500915700700e00923b00900716c007", + "0x700723b00900716000722300923b00900707100701100923b0090072f8", + "0x923b00912e00922100700900923b00900900900e00700723b0090070ea", + "0x1500923b12e01f0090fd00701f01b01812523b00912e00912e15800712e", + "0x910700702500923b00901500915100700723b00900712e0070200092f9", + "0x923b00902600910200700723b00902300910100702602312e23b009025", + "0x15500702c22912e23b00923c00915300723c00923b00922c00910400722c", + "0x12e23b00902e00915300702e00923b00902c00916300700723b009229009", + "0x3100915300703100923b00900714c00700723b009030009155007225030", + "0x22100923b00922500916300700723b00904500915500703304512e23b009", + "0x902e00721900923b00903622112e14f00703600923b009033009163007", + "0x23b00900712e0070380092fa00723b12e21900910600721900923b009219", + "0x12e14d00701b00923b00901b00922100701800923b00901800900e007007", + "0x703e0092fb03c00923b12e12600914e00712603b03a12523b00901b018", + "0x923b00914100910a00714100923b00903c00914900700723b00900712e", + "0x15715515315204c1500491db04714804314502023b00904100910c007041", + "0x904700915e00700723b00914800914700700723b009043009101007052", + "0x4c00914600700723b00915000915500700723b00904900915500700723b", + "0x902000700723b00915300915e00700723b00915200914700700723b009", + "0x15300700723b00905200915e00700723b00915700902000700723b009155", + "0x23b00905700915300705700923b00900714b00715905412e23b009145009", + "0x16300715d00923b00915900916300700723b00905800915500705a05812e", + "0x905d15d12e14f00715d00923b00915d00902e00705d00923b00905a009", + "0x12e07400715e00923b00915e00902e00700723b00900710f00715e00923b", + "0x23b12e15e00910600705400923b00905400902e0071db00923b0091db223", + "0x914400715f00923b00900716c00700723b00900712e0070600092fc007", + "0x923b0091600090a500706400923b00905400902e00716000923b00915f", + "0x723b00906000911100700723b00900712e0070072fd0090070ee007161", + "0x16400915300716400923b00900714300706716212e23b009054009153007", + "0x16b00923b00906700916300700723b00916600915500716816612e23b009", + "0x902e00706e00923b00906d16b12e14f00706d00923b009168009163007", + "0x23b00900712e00706f0092fe00723b12e06e00910600706e00923b00906e", + "0x16e0090a500716e00923b00907100914400707100923b00900716c007007", + "0x6f00911100700723b00900712e0070072ff0090070ee00707200923b009", + "0xa500717400923b00907400911300707400923b00900716c00700723b009", + "0x23b0090720090a500706400923b00916200902e00707200923b009174009", + "0x700723b00900712e00718000930007600923b12e161009140007161009", + "0x23b00900711800707807712e23b00906400915300700723b009076009054", + "0x16300700723b00907b00915500718707b12e23b009186009153007186009", + "0x907f08d12e14f00707f00923b00918700916300708d00923b009078009", + "0x930100723b12e08e00910600708e00923b00908e00902e00708e00923b", + "0x23b00909000914400709000923b00900716c00700723b00900712e00708f", + "0x900712e0070073020090070ee00709200923b0090910090a5007091009", + "0x9300911300709300923b00900716c00700723b00908f00911100700723b", + "0x9500923b00907700902e00709200923b0090940090a500709400923b009", + "0x723b00900712e0070073030090070ee00709600923b0090920090a5007", + "0x23b00909700914400709700923b00900716c00700723b009180009054007", + "0x14000709600923b0090980090a500709500923b00906400902e007098009", + "0x909900905400700723b00900712e0071a500930409900923b12e096009", + "0x11500700723b00909c0091550071a709c12e23b00909500915300700723b", + "0x23b00905b00915500709f05b12e23b00903700915300703700923b009007", + "0x12e14f0071b000923b00909f0091630071ac00923b0091a7009163007007", + "0x23b12e1b20091060071b200923b0091b200902e0071b200923b0091b01ac", + "0x900712e0070073060090070ee00700723b00900712e0070a3009305007", + "0x91db00915500700723b0090a300911100700723b0090070ea00700723b", + "0xe00923c00700723b00912500915200700723b00901100924200700723b", + "0x902e0070a500923b00900713b00704a00923b00900722900700723b009", + "0x923b0090072250071b500923b0090a504a12e0300070a500923b0090a5", + "0x1250071b800923b0090a90093070070a900923b0091b50a712e0310070a7", + "0x23b00903b00922100703a00923b00903a00900e00700700923b009007009", + "0x900712e0071b803b03a00700e0091b800923b0091b800930800703b009", + "0x90070ea00700723b00909500915500700723b0091a500905400700723b", + "0x12800700723b0090ac00923c0070ae0ac12e23b00900e00911c00700723b", + "0x23b00903a00900e00700700923b0090070091250071bc00923b0090ae009", + "0x3090071bc00923b0091bc00912300703b00923b00903b00922100703a009", + "0xb600923b12e0b400930a0070b41bd0b20b000e23b0091bc03b03a00700e", + "0x12e30d0071fd00923b0090b600930c00700723b00900712e0071bb00930b", + "0x90ba0092410070ba0b812e23b0091fd0091660071fd00923b0091fd011", + "0xb000923b0090b00091250070bc00923b0091ba1db12e30e0071ba00923b", + "0xbc00930f0071bd00923b0091bd0092210070b200923b0090b200900e007", + "0x70c20c01b90be00e23b0090bc1251bd0b20b01fd3100070bc00923b009", + "0x1b60092f300700723b00900712e0070c40093111b600923b12e0c20090c0", + "0x923b0090b80c612e31200700723b0091b30090540071b30c612e23b009", + "0x900e0070be00923b0090be0091250071b700923b0090c70093130070c7", + "0x923b0091b70093080070c000923b0090c00092210071b900923b0091b9", + "0x723b0090b800916800700723b00900712e0071b70c01b90be00e0091b7", + "0x1b900900e0070be00923b0090be0091250070c900923b0090c4009307007", + "0xc900923b0090c90093080070c000923b0090c00092210071b900923b009", + "0x700723b0091db00915500700723b00900712e0070c90c01b90be00e009", + "0x923b0091bb00930700700723b00901100924200700723b009125009152", + "0x92210070b200923b0090b200900e0070b000923b0090b00091250071ad", + "0x71ad1bd0b20b000e0091ad00923b0091ad0093080071bd00923b0091bd", + "0x700723b00901100924200700723b00900e00923c00700723b00900712e", + "0x923b00903e00930700700723b00922300907f00700723b009125009152", + "0x922100703a00923b00903a00900e00700700923b0090070091250070cb", + "0x70cb03b03a00700e0090cb00923b0090cb00930800703b00923b00903b", + "0x700723b00900e00923c00700723b00903800911100700723b00900712e", + "0x723b00922300907f00700723b00912500915200700723b009011009242", + "0x23b0091aa00902e0071aa00923b0090072f70070cd00923b009007229007", + "0x310071a800923b0090072250070cf00923b0091aa0cd12e0300071aa009", + "0x90070091250070d100923b0091a30093070071a300923b0090cf1a812e", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b00900712e0070d101b01800700e0090d100923b0090d1009308", + "0x723b00912500915200700723b00901100924200700723b00900e00923c", + "0x90070091250071a100923b00902000930700700723b00922300907f007", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b0090070ea0071a101b01800700e0091a100923b0091a1009308", + "0x1fd0090150071fd00923b00900e00924000700e12e12e23b00912e009314", + "0x22300923b0091db00902300700723b0090110090200071db01112e23b009", + "0x12512e03000701800923b00901800902e00701800923b0092230090df007", + "0x923b00900700912500701f00923b00912e00924100701b00923b009018", + "0x915700701f00923b00901f00931500700900923b00900900900e007007", + "0x6e00702502001512523b00901b01f00900700e31600701b00923b00901b", + "0x902300906f00700723b00900712e00702600931702300923b12e025009", + "0x31800722900923b00900716c00700723b00923c00905400723c22c12e23b", + "0x901500912500702e00923b00902c00931900702c00923b00922922c12e", + "0x902e00923b00902e00931a00702000923b00902000900e00701500923b", + "0x12500703000923b00902600931b00700723b00900712e00702e020015125", + "0x23b00903000931a00702000923b00902000900e00701500923b009015009", + "0x12e00900917500700900923b00900700901b007030020015125009030009", + "0x923b00912500917100700723b00900712e00700e00931c12512e12e23b", + "0x70ee0071db00923b0091fd0090ec00701100923b00912e0090b40071fd", + "0x2230090f000722300923b00900716c00700723b00900712e00700731d009", + "0x1db00923b0090180090ec00701100923b00900e0090b400701800923b009", + "0x1db00916900701b00923b00901b0091fd00701b00923b009011009058007", + "0x923b00901f00916500700723b00900712e00701500931e01f00923b12e", + "0x91fd00702300923b00902500931f00702500923b009020009163007020", + "0x712e00702301b12e00902300923b00902300932000701b00923b00901b", + "0x932100702600923b00900716c00700723b00901500905400700723b009", + "0x923b00922c00932000701b00923b00901b0091fd00722c00923b009026", + "0x712500923b00912e00901b00700723b0090070ea00722c01b12e00922c", + "0x917100700723b00900712e0070110093221fd00e12e23b12e125009175", + "0x923b0091db0090ec00722300923b00900e0090b40071db00923b0091fd", + "0x1b00923b00900716c00700723b00900712e0070073230090070ee007018", + "0x1f0090ec00722300923b0090110090b400701f00923b00901b0090f0007", + "0x1500923b0090150091fd00701500923b00922300905800701800923b009", + "0x916500700723b00900712e00702500932402000923b12e018009169007", + "0x22c00923b00902300916300702600923b00900722900702300923b009020", + "0x150091fd00700900923b00900900900e00700700923b009007009125007", + "0x22c00923b00922c00902e00702600923b00902600915700701500923b009", + "0x23b12e02c00907600702c22923c12523b00922c0260150090071fd325007", + "0x3122512e23b00902e00918000700723b00900712e00703000932602e009", + "0x912500703300923b00904500932800704500923b00903122512e327007", + "0x923b00903300932900722900923b00922900900e00723c00923b00923c", + "0x22100923b00903000932a00700723b00900712e00703322923c125009033", + "0x22100932900722900923b00922900900e00723c00923b00923c009125007", + "0x902500905400700723b00900712e00722122923c12500922100923b009", + "0x12e32700721900923b00903600923f00703600923b00900716c00700723b", + "0x23b00900700912500703a00923b00903800932800703800923b009219015", + "0x12500903a00923b00903a00932900700900923b00900900900e007007009", + "0x700723b0091db0090570072231db12e23b00901100915900703a009007", + "0x900900903300700700923b00900700912500701800923b009223009058", + "0x712500923b00912500922100712e00923b00912e00900e00700900923b", + "0x90071db32b00701800923b0090180091fd0071fd00923b0091fd00902e", + "0x923b12e0250091b000702502001501f01b1fd23b0090181fd00e12512e", + "0x14000722c00923b0090230091b200700723b00900712e00702600932c023", + "0x923c00905400700723b00900712e00722900932d23c00923b12e22c009", + "0x70ee00702e00923b00902c00902e00702c00923b00900714c00700723b", + "0x90072f400700723b00922900905400700723b00900712e00700732e009", + "0x722500923b00902e00932f00702e00923b00903000902e00703000923b", + "0x901f00903300701b00923b00901b00912500703100923b009225009330", + "0x702000923b00902000922100701500923b00901500900e00701f00923b", + "0x723b00900712e00703102001501f01b1fd00903100923b009031009331", + "0x1f00903300701b00923b00901b00912500704500923b009026009332007", + "0x2000923b00902000922100701500923b00901500900e00701f00923b009", + "0x23b00900733300704502001501f01b1fd00904500923b009045009331007", + "0x900733400722300923b00900707100701100923b00900733300700e009", + "0x900700912500700723b0090070ea00700723b00900716000701b00923b", + "0x1f12523b00912e00712e33500712e00923b00912e0091fd00700700923b", + "0x700723b00900712e00702500933701800923b12e020009336007020015", + "0x1b12e33800702602312e23b00901500916e00701500923b0090150091fd", + "0x900712e00722c0093391db00923b12e02600907200701800923b009018", + "0x22312e07400700723b00900710f00723c00923b00902300901b00700723b", + "0x712e00702e00933a02c22912e23b12e23c0091750071db00923b0091db", + "0x722500923b0092290090b400703000923b00902c00917100700723b009", + "0x700723b00900712e00700733b0090070ee00703100923b0090300090ec", + "0x23b00902e0090b400703300923b0090450090f000704500923b00900716c", + "0x1fd00722100923b00922500905800703100923b0090330090ec007225009", + "0x712e00721900933c03600923b12e03100916900722100923b009221009", + "0x703a00923b00903800916300703800923b00903600916500700723b009", + "0x3a01f12e33d00703a00923b00903a00902e00701f00923b00901f009125", + "0x900712e00703c00933f1fd00923b12e12600933e00712603b12e23b009", + "0x71fd00923b0091fd01112e34000703e00923b00922100901b00700723b", + "0x917100700723b00900712e00714500934104114112e23b12e03e009175", + "0x923b0090430090ec00714800923b0091410090b400704300923b009041", + "0x4900923b00900716c00700723b00900712e0070073420090070ee007047", + "0x1500090ec00714800923b0091450090b400715000923b0090490090f0007", + "0x4c00923b00904c0091fd00704c00923b00914800905800704700923b009", + "0x916500700723b00900712e00715300934315200923b12e047009169007", + "0x923b00903b00912500715700923b00915500916300715500923b009152", + "0x705405212e23b00915703b12e33d00715700923b00915700902e00703b", + "0x90070ea00700723b00900712e00715900934412500923b12e05400933e", + "0x1fd00700900923b00900900900e00705200923b00905200912500700723b", + "0x905212534500712500923b00912500e12e34000704c00923b00904c009", + "0x12e00705d00934715d00923b12e05a00934600705a05805712523b00904c", + "0x923b12e06000934800706015e12e23b00915d00923e00700723b009007", + "0x23b00915f1251fd1db0181fd34a00700723b00900712e00716000934915f", + "0x716200923b00916115e12e34c00716100923b00906400934b007064009", + "0x905800900e00705700923b00905700912500706700923b00916200934d", + "0x900712e00706705805712500906700923b00906700934e00705800923b", + "0x1fd00934f00700723b00912500934f00700723b00901800910100700723b", + "0x34c00716400923b00916000923d00700723b0091db00915500700723b009", + "0x905700912500716800923b00916600934d00716600923b00916415e12e", + "0x916800923b00916800934e00705800923b00905800900e00705700923b", + "0x910100700723b0091db00915500700723b00900712e007168058057125", + "0x35000700723b0091fd00934f00700723b00912500934f00700723b009018", + "0x23b00905800900e00705700923b00905700912500716b00923b00905d009", + "0x23b00900712e00716b05805712500916b00923b00916b00934e007058009", + "0x901800910100700723b0091db00915500700723b0091fd00934f007007", + "0x935200706d00923b00905200912500700723b00900e00935100700723b", + "0x905400700723b00900712e0070073530090070ee00706e00923b009159", + "0x15500700723b0091fd00934f00700723b00900e00935100700723b009153", + "0x706f00923b00900716c00700723b00901800910100700723b0091db009", + "0x23b0090070ea00706e00923b00906f00935200706d00923b00903b009125", + "0x34d00716e00923b00907104c12e34c00707100923b00906e00923d007007", + "0x23b00907200934e00700900923b00900900900e00707200923b00916e009", + "0x723b00900e00935100700723b00900712e00707200906d125009072009", + "0x23b00901100935100700723b00901800910100700723b0091db009155007", + "0x70ee00717400923b00903c00935200707400923b00903b009125007007", + "0xe00935100700723b00921900905400700723b00900712e007007354009", + "0x935100700723b00901800910100700723b0091db00915500700723b009", + "0x707400923b00901f00912500707600923b00900716c00700723b009011", + "0x923b00917400923d00700723b0090070ea00717400923b009076009352", + "0xe00707800923b00907700934d00707700923b00918022112e34c007180", + "0x707800907412500907800923b00907800934e00700900923b009009009", + "0x700723b00901800910100700723b00900e00935100700723b00900712e", + "0x923b00922c00923d00700723b00922300907f00700723b009011009351", + "0x12500718700923b00907b00934d00707b00923b00918602312e34c007186", + "0x23b00918700934e00700900923b00900900900e00701f00923b00901f009", + "0x723b00900e00935100700723b00900712e00718700901f125009187009", + "0x23b00901b00935500700723b00901100935100700723b00922300907f007", + "0x34d00707f00923b00908d01512e34c00708d00923b00902500923d007007", + "0x23b00900900900e00701f00923b00901f00912500708e00923b00907f009", + "0x23b0090072f800708e00901f12500908e00923b00908e00934e007009009", + "0x900707100702000923b00900708e00701f00923b00900708f007018009", + "0x715f00722900923b00900709000722c00923b00900708e00702300923b", + "0x70ea00700723b00900716000722500923b00900707100702e00923b009", + "0x90310093570070362210330450311fd23b00901100935600700723b009", + "0x3a12e23b00903800915300703800923b00921900910400721903112e23b", + "0x912600915300712600923b00900735800700723b00903a00915500703b", + "0x714100923b00903b00916300700723b00903c00915500703e03c12e23b", + "0x903e00916300700723b00904100915500714504112e23b009141009153", + "0x700723b00914800915500704714812e23b00904300915300704300923b", + "0x15004912e14f00715000923b00904700916300704900923b009145009163", + "0x35900723b12e04c00910600704c00923b00904c00902e00704c00923b009", + "0xe00922100715300923b00912e00900e00700723b00900712e007152009", + "0x12e00700735b0090070ee00715700923b00903100935a00715500923b009", + "0x712e00923b00912e00900e00700723b00915200911100700723b009007", + "0xfd00715905405212523b00900e12e12e15800700e00923b00900e009221", + "0x903100910700700723b00900712e00705800935c05700923b12e159009", + "0x15e12e23b00905d00910700705d00923b00905700915100715d05a12e23b", + "0x15f00910400715f00923b00906000910200700723b00915e009101007060", + "0x16100923b00906400910400706400923b00915d00910200716000923b009", + "0x16100915300700723b00916200915500706716212e23b009160009153007", + "0x16800923b00906700916300700723b00916400915500716616412e23b009", + "0x902e00706d00923b00916b16812e14f00716b00923b009166009163007", + "0x23b00900712e00706e00935d00723b12e06d00910600706d00923b00906d", + "0x935a00715500923b00905400922100715300923b00905200900e007007", + "0x923b00915500922100715300923b00915300900e00715700923b00905a", + "0x7200923b12e16e00935f00716e07106f12523b00915515312e35e007155", + "0x710f00717400923b00907200936100700723b00900712e007074009360", + "0x17412e23b00917400936200707603312e23b00903300936200700723b009", + "0x900712e00707b18612e36407807712e23b12e180076007125363007180", + "0x22100934f00700723b00903600936500700723b00907800934f00700723b", + "0x924200700723b00915700910100700723b00903300934f00700723b009", + "0x15500700723b00902000909700700723b0091db00905700700723b009018", + "0x700723b00901f00909600700723b00902300907f00700723b009045009", + "0x723b00902e00906400700723b00922c00909700700723b00922500907f", + "0x23b00917400934f00700723b00922900905b00700723b0091fd009152007", + "0x23b00900712e0070073660090070ee00718700923b009077009125007007", + "0x12536300708d22112e23b00922100936200700723b00907b00934f007007", + "0x34f00700723b00900712e00709008f12e36708e07f12e23b12e08d174186", + "0x700723b00922100934f00700723b00903600936500700723b00908e009", + "0x723b00901800924200700723b00915700910100700723b00903300934f", + "0x23b00904500915500700723b00902000909700700723b0091db009057007", + "0x922500907f00700723b00901f00909600700723b00902300907f007007", + "0x1fd00915200700723b00902e00906400700723b00922c00909700700723b", + "0xea00718700923b00907f00912500700723b00922900905b00700723b009", + "0x2e00709200923b00900736800709100923b00900722900700723b009007", + "0x23b00900722500709300923b00909209112e03000709200923b009092009", + "0x709600923b00909500930700709500923b00909309412e031007094009", + "0x906f00900e00700900923b00900900903300718700923b009187009125", + "0x707100923b00907100922100712500923b00912500909900706f00923b", + "0x23b00900712e00709607112506f00918701100909600923b009096009308", + "0x23b0091fd00936900700723b00909000934f00700723b0090070ea007007", + "0x1250071ac09f12e23b0091a700936a00705b0371a709c1a5099098097223", + "0x23b00912500909900706f00923b00906f00900e00708f00923b00908f009", + "0x71b004512e23b00904500936b00707100923b009071009221007125009", + "0x1b21fd23b0091b01ac07112506f08f01136c0071b000923b0091b000902e", + "0x23b00900712e0070a900936d0a700923b12e1b50091b00071b50a504a0a3", + "0x90a50070ac00923b0091b800936e0071b800923b0090a70091b2007007", + "0x900712e0071bc00936f0ae00923b12e0ac0091400070ac00923b0090ac", + "0x1db00905700700723b00901800924200700723b0090ae00905400700723b", + "0x907f00700723b00904500915500700723b00902000909700700723b009", + "0x37100700723b00909700937000700723b00901f00909600700723b009023", + "0x700723b00902e00906400700723b00922c00909700700723b009098009", + "0x723b00909f00937400700723b00903700937300700723b00905b009372", + "0x23b00909900937700700723b0091a500937600700723b00909c009375007", + "0x903600936500700723b00922900905b00700723b00922500907f007007", + "0x15700910100700723b00903300934f00700723b00922100934f00700723b", + "0x902e0070b200923b0090073780070b000923b00900722900700723b009", + "0x923b0090072250071bd00923b0090b20b012e0300070b200923b0090b2", + "0x1250071bb00923b0090b60093070070b600923b0091bd0b412e0310070b4", + "0x23b0090a300900e00700900923b0090090090330071b200923b0091b2009", + "0x3080070a500923b0090a500922100704a00923b00904a0090990070a3009", + "0x723b00900712e0071bb0a504a0a30091b20110091bb00923b0091bb009", + "0x1571fd34a0070b804512e23b00904500936b00700723b0091bc009054007", + "0x937900723c00923b00923c22912e09500723c00923b0090362210330b8", + "0x23b0090a50092210070a300923b0090a300900e0071ba0ba12e23b00923c", + "0x923b12e1b900914e0071b90be0bc12523b0090a50a312e14d0070a5009", + "0x10a0071b600923b0090c000914900700723b00900712e0070c200937a0c0", + "0x923b0090c600937b0070c600923b00900714c0070c400923b0091b6009", + "0x1b700902e0071b700923b0091b300937d0070c700923b00900737c0071b3", + "0x23b0090c71b704a12537e0070c700923b0090c700902e0071b700923b009", + "0x37f0070cd00923b0090cb00937b0070cb00923b00900714c0071ad0c912e", + "0x923b0090cf00902e0070cf00923b0090cd00937d0071aa00923b009007", + "0x1a31a812e23b0091aa0cf0c912537e0071aa00923b0091aa00902e0070cf", + "0x23b0090c400910c0071a100923b0090071430070d100923b009007380007", + "0x23b0091a000915500718a0e10df18e0dd1971980da0d819b19f0d51a0020", + "0x919b00915e00700723b00919f00914700700723b0090d5009101007007", + "0x19700914600700723b00919800915500700723b0090d800915500700723b", + "0x902000700723b00918e00915e00700723b0090dd00914700700723b009", + "0x38100700723b00918a00915e00700723b0090e100902000700723b0090df", + "0x938300718c18812e23b00918900938200718900923b0090da1a10d1125", + "0xe512523b00918b00938500718b00923b00918c00938400700723b009188", + "0x2e0070e800923b0090a000937d0070a000923b0091a300937b007183184", + "0xe50e81a812537e0070e500923b0090e500902e0070e800923b0090e8009", + "0x923b0090ea00937d0070ea00923b00917b00937b00717b17912e23b009", + "0x12537e00718400923b00918400902e00717500923b00917500902e007175", + "0xee00937d0070ee00923b0090ec00937b0070ec17112e23b009184175179", + "0x18300923b00918300902e00716c00923b00916c00902e00716c00923b009", + "0x716500923b00916900937b0071690f012e23b00918316c17112537e007", + "0x23b00916300902e00716300923b00916500937d0070f300923b009007386", + "0xf612e23b0090f31630f012537e0070f300923b0090f300902e007163009", + "0x937d0070fa00923b0090f800937b00715c00923b0091ad00937b0070f8", + "0x923b00915400902e00715400923b00915c00937d00715600923b0090fa", + "0xfd15812e23b0091561540f612537e00715600923b00915600902e007154", + "0xbc12e3870070be00923b0090be0092210070bc00923b0090bc00900e007", + "0x90fd00902e00715800923b00915800909900710702c15112523b0090be", + "0x10100923b12e1070090fd00702c00923b00902c02e12e1620070fd00923b", + "0x910400710400923b00910100915100700723b00900712e007102009388", + "0x923b00914f00937d00714f00923b0090fd00937b00714c00923b009104", + "0x3014d12e23b00914c10615812537e00710600923b00910600902e007106", + "0x14d00909900715100923b00915100900e0071b200923b0091b2009125007", + "0x923b00903022512e0740071ba00923b0091ba0091a500714d00923b009", + "0x12e10c00907b00710c10a14914e00e23b0091ba14d1511b200e389007030", + "0x14b00923b00903000937b00700723b00900712e00714600938a14700923b", + "0x14400902e00714400923b00914b00937d00710f00923b009147009187007", + "0x914300937b00714311112e23b00910f14410a12537e00714400923b009", + "0x2e00711800923b00911300937d00714000923b00900738600711300923b", + "0x14011811112537e00714000923b00914000902e00711800923b009118009", + "0x923b00913b00937d00713b00923b00911500937b00711502612e23b009", + "0x723b00913900910100712811c11a1371391fd23b0090ba009356007025", + "0x23b00911c00934f00700723b00911a00934f00700723b009137009155007", + "0x905800700723b00912300905700700012312e23b0091db009159007007", + "0x2f500923b0092f40091440072f400923b00900716c0072f300923b009000", + "0x914e0091250072f600923b00905b03709f09c1a5099098097223148007", + "0x714900923b00914900900e00700900923b00900900903300714e00923b", + "0x2f70091230072f712812e23b00912800938b00702c00923b00902c009221", + "0x12e23b00902500936b00702500923b00902502312e0740072f700923b009", + "0xa50072f300923b0092f30091fd0072f800923b0092f800902e0072f8025", + "0x914e01800000702600923b00902622c12e0370072f500923b0092f5009", + "0x1b01f12e1a700730930830701b2421fd23b0092f52f32f82f72f602c149", + "0x23b00900712e00730c00938c30a00923b12e3090090c000701b00923b009", + "0x936900700723b00924100905400724130d12e23b00930a0092f3007007", + "0x731600923b00900716c00731524031431331231030f30e22323b00930d", + "0x930700900e00724200923b00924200912500731800923b009316009144", + "0x730800923b00930800922100702600923b00902600909900730700923b", + "0x3072421db38d00731800923b0093180090a500704500923b00904500902e", + "0x23b00901502012e03700731f31b01531a3191fd23b009318045314308026", + "0x700723b00900712e00732100938f32000923b12e31f00938e007015009", + "0x931b00922100731a00923b00931a00900e00731900923b009319009125", + "0x23b00912831b31a31900e30900712800923b00912800912300731b00923b", + "0x900712e00723f00939032a00923b12e32900930a00732932832732500e", + "0x722300923b00922301812e30d00722300923b00932a00930c00700723b", + "0x905400733133012e23b00932000939100732f32b12e23b009223009166", + "0x923b00933202512e30e00733200923b00932f00924100700723b009331", + "0x32500912500733400923b00931524033031331231030f30e223148007333", + "0x32800923b00932800922100732700923b00932700900e00732500923b009", + "0x33500e23b0093333343283273251fd31000733300923b00933300930f007", + "0x723b00900712e00734000939233e00923b12e33d0090c000733d338336", + "0x34512e31200700723b00934600905400734634512e23b00933e0092f3007", + "0x923b00933500912500734800923b00923e00931300723e00923b00932b", + "0x909900733600923b00933600900e00701b00923b00901b009033007335", + "0x923b00934800930800733800923b00933800922100701500923b009015", + "0x932b00916800700723b00900712e00734833801533601b335011009348", + "0x3300733500923b00933500912500734a00923b00934000930700700723b", + "0x23b00901500909900733600923b00933600900e00701b00923b00901b009", + "0x1100934a00923b00934a00930800733800923b009338009221007015009", + "0x700723b00932000939300700723b00900712e00734a33801533601b335", + "0x723b00924000937300700723b00931500937200700723b00930e009370", + "0x23b00931200937600700723b00931300937500700723b009025009155007", + "0x901800924200700723b00930f00937100700723b009310009377007007", + "0x3300732500923b00932500912500734b00923b00923f00930700700723b", + "0x23b00901500909900732700923b00932700900e00701b00923b00901b009", + "0x1100934b00923b00934b00930800732800923b009328009221007015009", + "0x700723b00930e00937000700723b00900712e00734b32801532701b325", + "0x723b00901800924200700723b00930f00937100700723b009310009377", + "0x23b00902500915500700723b00924000937300700723b009315009372007", + "0x912800936500700723b00931200937600700723b009313009375007007", + "0x3300731900923b00931900912500734c00923b00932100930700700723b", + "0x23b00901500909900731a00923b00931a00900e00701b00923b00901b009", + "0x1100934c00923b00934c00930800731b00923b00931b009221007015009", + "0x700723b00912800936500700723b00900712e00734c31b01531a01b319", + "0x723b00902000909700700723b00904500915500700723b009018009242", + "0x924200912500734d00923b00930c00930700700723b009025009155007", + "0x730700923b00930700900e00701b00923b00901b00903300724200923b", + "0x934d00930800730800923b00930800922100702600923b009026009099", + "0x924200700723b00900712e00734d30802630701b24201100934d00923b", + "0x9700700723b0091db00905700700723b0090ba00909800700723b009018", + "0x700723b00902300907f00700723b00904500915500700723b009020009", + "0x723b00909800937100700723b00909700937000700723b00901f009096", + "0x23b00909f00937400700723b00903700937300700723b00905b009372007", + "0x909900937700700723b0091a500937600700723b00909c009375007007", + "0x14600930700700723b00903000915500700723b00922c00909700700723b", + "0x900923b00900900903300714e00923b00914e00912500734e00923b009", + "0x2c00922100710a00923b00910a00909900714900923b00914900900e007", + "0x34e02c10a14900914e01100934e00923b00934e00930800702c00923b009", + "0x723b0090ba00909800700723b00901800924200700723b00900712e007", + "0x23b00904500915500700723b00902000909700700723b0091db009057007", + "0x909700937000700723b00901f00909600700723b00902300907f007007", + "0x5b00937200700723b00922c00909700700723b00909800937100700723b", + "0x937500700723b00909f00937400700723b00903700937300700723b009", + "0x9800700723b00909900937700700723b0091a500937600700723b00909c", + "0x700723b0090fd00915500700723b00922500907f00700723b0091ba009", + "0x90090090330071b200923b0091b200912500734f00923b009102009307", + "0x715800923b00915800909900715100923b00915100900e00700900923b", + "0x1510091b201100934f00923b00934f00930800702c00923b00902c009221", + "0xba00909800700723b00901800924200700723b00900712e00734f02c158", + "0x915500700723b00902000909700700723b0091db00905700700723b009", + "0x37000700723b00901f00909600700723b00902300907f00700723b009045", + "0x700723b00922c00909700700723b00909800937100700723b009097009", + "0x723b00909f00937400700723b00903700937300700723b00905b009372", + "0x23b00909900937700700723b0091a500937600700723b00909c009375007", + "0x902e00906400700723b00922500907f00700723b0091ba009098007007", + "0x330071b200923b0091b200912500723d00923b0090c200930700700723b", + "0x23b00904a0090990070bc00923b0090bc00900e00700900923b009009009", + "0x1100923d00923b00923d0093080070be00923b0090be00922100704a009", + "0x700723b00901800924200700723b00900712e00723d0be04a0bc0091b2", + "0x723b00904500915500700723b00902000909700700723b0091db009057", + "0x23b00909700937000700723b00901f00909600700723b00902300907f007", + "0x902e00906400700723b00922c00909700700723b009098009371007007", + "0x9f00937400700723b00903700937300700723b00905b00937200700723b", + "0x937700700723b0091a500937600700723b00909c00937500700723b009", + "0x36500700723b00922900905b00700723b00922500907f00700723b009099", + "0x700723b00903300934f00700723b00922100934f00700723b009036009", + "0x23b0091b200912500735000923b0090a900930700700723b009157009101", + "0x990070a300923b0090a300900e00700900923b0090090090330071b2009", + "0x23b0093500093080070a500923b0090a500922100704a00923b00904a009", + "0x3600936500700723b00900712e0073500a504a0a30091b2011009350009", + "0x910100700723b00903300934f00700723b00922100934f00700723b009", + "0x9700700723b0091db00905700700723b00901800924200700723b009157", + "0x700723b00902300907f00700723b00904500915500700723b009020009", + "0x723b00922c00909700700723b00922500907f00700723b00901f009096", + "0x23b00922900905b00700723b0091fd00915200700723b00902e009064007", + "0x903300700700923b00900700912500735100923b009074009307007007", + "0x923b00912500909900706f00923b00906f00900e00700900923b009009", + "0x701100935100923b00935100930800707100923b009071009221007125", + "0x5b00700723b00906e00911100700723b00900712e00735107112506f009", + "0x700723b00922100934f00700723b00903600936500700723b009229009", + "0x723b0091db00905700700723b00901800924200700723b00903300934f", + "0x23b00902300907f00700723b00904500915500700723b009020009097007", + "0x922c00909700700723b00922500907f00700723b00901f009096007007", + "0x5a00910100700723b0091fd00915200700723b00902e00906400700723b", + "0x902e00735500923b00900739400735200923b00900722900700723b009", + "0x923b00900722500735600923b00935535212e03000735500923b009355", + "0x12500735a00923b00935800930700735800923b00935635712e031007357", + "0x23b00905200900e00700900923b00900900903300700700923b009007009", + "0x30800705400923b00905400922100712500923b009125009099007052009", + "0x723b00900712e00735a05412505200900701100935a00923b00935a009", + "0x23b00922100934f00700723b00903600936500700723b00922900905b007", + "0x91db00905700700723b00901800924200700723b00903300934f007007", + "0x2300907f00700723b00904500915500700723b00902000909700700723b", + "0x909700700723b00922500907f00700723b00901f00909600700723b009", + "0x10100700723b0091fd00915200700723b00902e00906400700723b00922c", + "0x923b00900700912500735e00923b00905800930700700723b009031009", + "0x909900705200923b00905200900e00700900923b009009009033007007", + "0x923b00935e00930800705400923b00905400922100712500923b009125", + "0x900715f0071db00923b00900707100735e05412505200900701100935e", + "0x900e00915200700723b0090070ea00700723b00900716000701800923b", + "0x14d00712500923b00912500922100700900923b00900900900e00700723b", + "0x2500939502000923b12e01500914e00701501f01b12523b00912500912e", + "0x23b00902300910a00702300923b00902000914900700723b00900712e007", + "0x737c00723c00923b00922c00937b00722c00923b00900714c007026009", + "0x2c00923b00902c00902e00702c00923b00923c00937d00722900923b009", + "0x703002e12e23b00922902c12e12537e00722900923b00922900902e007", + "0x923b00900737f00703100923b00922500937b00722500923b00900714c", + "0x902e00703300923b00903300902e00703300923b00903100937d007045", + "0x900738000703622112e23b00904503302e12537e00704500923b009045", + "0x12603b03a02023b00902600910c00703800923b00900714300721900923b", + "0x910100700723b00903a00915500715004904714804314504114103e03c", + "0x15500700723b00903c00915e00700723b00912600914700700723b00903b", + "0x700723b00914500914600700723b00904100915500700723b00903e009", + "0x723b00904700902000700723b00914800915e00700723b009043009147", + "0x14103821912538100700723b00915000915e00700723b009049009020007", + "0x723b00915200938300715315212e23b00904c00938200704c00923b009", + "0x37b00705405215712523b00915500938500715500923b009153009384007", + "0x23b00905700902e00705700923b00915900937d00715900923b009036009", + "0x5812e23b00915705722112537e00715700923b00915700902e007057009", + "0x902e00705d00923b00915d00937d00715d00923b00905a00937b00705a", + "0x905205d05812537e00705200923b00905200902e00705d00923b00905d", + "0x16000923b00915f00937d00715f00923b00906000937b00706015e12e23b", + "0x15e12537e00705400923b00905400902e00716000923b00916000902e007", + "0x23b00900738600716200923b00916100937b00716106412e23b009054160", + "0x2e00716400923b00916400902e00716400923b00916200937d007067009", + "0x937b00716816612e23b00906716406412537e00706700923b009067009", + "0x923b00906d00937d00706d00923b00916800937b00716b00923b009030", + "0x902e00706f00923b00906f00902e00706f00923b00916b00937d00706e", + "0x1b00900e00716e07112e23b00906e06f16612537e00706e00923b00906e", + "0x12523b00901f01b12e38700701f00923b00901f00922100701b00923b009", + "0x716e00923b00916e00902e00707100923b009071009099007074223072", + "0x707600939617400923b12e0740090fd00722300923b00922301812e162", + "0x923b00918000910400718000923b00917400915100700723b00900712e", + "0x902e00718600923b00907800937d00707800923b00916e00937b007077", + "0x1fd00937900701107b12e23b00907718607112537e00718600923b009186", + "0x700923b00900700912500700723b00918700909800708d18712e23b009", + "0x8d0091a500707b00923b00907b00909900707200923b00907200900e007", + "0x8d07b07200700e38900701100923b0090111db12e07400708d00923b009", + "0x12e00709200939709100923b12e09000907b00709008f08e07f00e23b009", + "0x9400923b00909100918700709300923b00901100937b00700723b009007", + "0x8f12537e00709500923b00909500902e00709500923b00909300937d007", + "0x23b00900738600709800923b00909700937b00709709612e23b009094095", + "0x2e0071a500923b0091a500902e0071a500923b00909800937d007099009", + "0x937b0071a709c12e23b0090991a509612537e00709900923b009099009", + "0x923b00905b00932f00705b00923b00903700937d00703700923b0091a7", + "0x900e00707f00923b00907f0091250071ac00923b00909f00933000709f", + "0x923b00922300922100709c00923b00909c00909900708e00923b00908e", + "0x900712e0071ac22309c08e07f1fd0091ac00923b0091ac009331007223", + "0x91250071b000923b00909200933200700723b00901100915500700723b", + "0x923b00908f00909900708e00923b00908e00900e00707f00923b00907f", + "0x7f1fd0091b000923b0091b000933100722300923b00922300922100708f", + "0x907f00700723b0091fd00909800700723b00900712e0071b022308f08e", + "0x71b200923b00907600933200700723b00916e00915500700723b0091db", + "0x907100909900707200923b00907200900e00700700923b009007009125", + "0x91b200923b0091b200933100722300923b00922300922100707100923b", + "0x700723b0091fd00909800700723b00900712e0071b22230710720071fd", + "0x923b00902500933200700723b00901800906400700723b0091db00907f", + "0x909900701b00923b00901b00900e00700700923b0090070091250070a3", + "0x923b0090a300933100701f00923b00901f00922100712e00923b00912e", + "0x1b0182231db01122323b00900e0093690070a301f12e01b0071fd0090a3", + "0x937700700723b0091db00937100700723b00901100937000702001501f", + "0x37300700723b00901b00937500700723b00901800937600700723b009223", + "0x700923b00900700912500700723b00902000937200700723b009015009", + "0x12500922100712e00923b00912e00909900700900923b00900900900e007", + "0x1f12512e00900701136c0071fd00923b0091fd00902e00712500923b009", + "0x2c00939822900923b12e23c0091b000723c22c0260230251fd23b0091fd", + "0x23b00902e00936e00702e00923b0092290091b200700723b00900712e007", + "0x12500703100923b00922500939a00722500923b009030009399007030009", + "0x23b00902600909900702300923b00902300900e00702500923b009025009", + "0x1fd00903100923b00903100939b00722c00923b00922c009221007026009", + "0x704500923b00902c00939c00700723b00900712e00703122c026023025", + "0x902600909900702300923b00902300900e00702500923b009025009125", + "0x904500923b00904500939b00722c00923b00922c00922100702600923b", + "0x23b12e12e00914000712e00923b00900700939d00704522c0260230251fd", + "0x14c00700723b00912500905400700723b00900712e00700e00939e125009", + "0x700739f0090070ee00701100923b0091fd00902e0071fd00923b009007", + "0x71db00923b00900714300700723b00900e00905400700723b00900712e", + "0x22300915500701822312e23b00901100915300701100923b0091db00902e", + "0x1b12e23b00900901812e05200700900923b00900900915700700723b009", + "0x701501b12e00901500923b00900716c00700723b00901f00905400701f", + "0x12500907200712512e12e23b00900900916e00700900923b0090090091fd", + "0x23b12e00e00712e3a100700723b00900712e0071fd0093a000e00923b12e", + "0x1800923b0091db0093a300700723b00900712e0072230093a21db01112e", + "0x180093a400712e00923b00912e0091fd00701100923b009011009125007", + "0x23b00900716c00700723b00900712e00701812e01112500901800923b009", + "0x1fd00722300923b00922300912500701f00923b00901b0093a500701b009", + "0x701f12e22312500901f00923b00901f0093a400712e00923b00912e009", + "0x923b00900700912500701500923b0091fd0093a500700723b00900712e", + "0x712500901500923b0090150093a400712e00923b00912e0091fd007007", + "0x12e00922100700900923b00900900900e00700723b0090070ea00701512e", + "0x12e2230090fd0072231db01112523b00912e00912e38700712e00923b009", + "0x1100923b00901100900e00700723b00900712e00701b0093a601800923b", + "0x702001501f12523b0091db01112e1580071db00923b0091db009221007", + "0x1800915100700723b00900712e0070230093a702500923b12e0200090fd", + "0x723b00922c00910100723c22c12e23b00902600910700702600923b009", + "0x2500915100702c00923b00922900910400722900923b00923c009102007", + "0x723b00903000910100722503012e23b00902e00910700702e00923b009", + "0x2c00915300704500923b00903100910400703100923b009225009102007", + "0x3612e23b00904500915300700723b00903300915500722103312e23b009", + "0x21900916300703800923b00922100916300700723b009036009155007219", + "0x923b00903b00902e00703b00923b00903a03812e14f00703a00923b009", + "0x93a900700723b00900712e0071260093a800723b12e03b00910600703b", + "0x923b00900724700703e00923b00903c0093aa00703c00e12e23b00900e", + "0x93ab00701500923b00901500922100701f00923b00901f00900e007141", + "0x14103e01501f00e3ac00714100923b00914100902e00703e00923b00903e", + "0x712e0070470093ad14800923b12e0430091b000704314504112523b009", + "0x3ae15000923b12e04900914000704900923b0091480091b200700723b009", + "0x900e0090ae00700723b00915000905400700723b00900712e00704c009", + "0x900722900700723b00912500915200700723b0091fd00905700700723b", + "0x3000715300923b00915300902e00715300923b0090073af00715200923b", + "0x915515712e03100715700923b00900722500715500923b00915315212e", + "0x700700923b00900700912500705400923b0090520093b000705200923b", + "0x90540093b100714500923b00914500922100704100923b00904100900e", + "0x904c00905400700723b00900712e00705414504100700e00905400923b", + "0x12e23b12e1591450411253b200715900e12e23b00900e0093a900700723b", + "0x15e00923b00900716c00700723b00900712e00705d15d05a1253b3058057", + "0x5800922100715f00923b00905700900e00706000923b00915e0093b4007", + "0x12e0070073b60090070ee00706400923b0090600093b500716000923b009", + "0x15f00923b00905a00900e00716100923b00905d0093b700700723b009007", + "0x640093b800706400923b0091610093b500716000923b00915d009221007", + "0x23b00900712e0071640093ba06700923b12e1620093b900716200923b009", + "0x93bc00716600e12e23b00900e0093a900700723b0090670093bb007007", + "0x923b00915f00900e00700700923b00900700912500716800923b009166", + "0x1fd3be00716800923b0091680093bd00716000923b00916000922100715f", + "0x7100923b12e06f0090c000706f06e06d16b00e23b00916812516015f007", + "0x912500707200923b00900e0093c000700723b00900712e00716e0093bf", + "0x923b00906e00922100706d00923b00906d00900e00716b00923b00916b", + "0x1fd3c20071fd00923b0091fd00915700707200923b0090720093c100706e", + "0x7700923b12e1800093c300718007617407400e23b0091fd07206e06d16b", + "0x5400707b18612e23b0090710092f300700723b00900712e0070780093c4", + "0x23b00918718612e3c600718700923b0090770093c500700723b00907b009", + "0xe00707400923b00907400912500707f00923b00908d0093c700708d009", + "0x23b00907f0093b100707600923b00907600922100717400923b009174009", + "0x23b0090710090c200700723b00900712e00707f07617407400e00907f009", + "0x900e00707400923b00907400912500708e00923b0090780093b0007007", + "0x923b00908e0093b100707600923b00907600922100717400923b009174", + "0x723b00900e0090ae00700723b00900712e00708e07617407400e00908e", + "0x916b00912500708f00923b00916e0093b000700723b0091fd009057007", + "0x706e00923b00906e00922100706d00923b00906d00900e00716b00923b", + "0x700723b00900712e00708f06e06d16b00e00908f00923b00908f0093b1", + "0x723b00912500915200700723b0091fd00905700700723b00900e0090ae", + "0x15f00900e00700700923b00900700912500709000923b0091640093b0007", + "0x9000923b0090900093b100716000923b00916000922100715f00923b009", + "0x700723b00900e0090ae00700723b00900712e00709016015f00700e009", + "0x923b0090470093b000700723b00912500915200700723b0091fd009057", + "0x922100704100923b00904100900e00700700923b009007009125007091", + "0x709114504100700e00909100923b0090910093b100714500923b009145", + "0x700723b00912500915200700723b00912600911100700723b00900712e", + "0x9200923b00900722900700723b00900e0090ae00700723b0091fd009057", + "0x9309212e03000709300923b00909300902e00709300923b0090073c8007", + "0x9600923b00909409512e03100709500923b00900722500709400923b009", + "0x1f00900e00700700923b00900700912500709700923b0090960093b0007", + "0x9700923b0090970093b100701500923b00901500922100701f00923b009", + "0x700723b00912500915200700723b00900712e00709701501f00700e009", + "0x723b0090180093c900700723b00900e0090ae00700723b0091fd009057", + "0x1f00900e00700700923b00900700912500709800923b0090230093b0007", + "0x9800923b0090980093b100701500923b00901500922100701f00923b009", + "0x700723b00912500915200700723b00900712e00709801501f00700e009", + "0x923b00901b0093b000700723b00900e0090ae00700723b0091fd009057", + "0x922100701100923b00901100900e00700700923b009007009125007099", + "0x70991db01100700e00909900923b0090990093b10071db00923b0091db", + "0x23b00900e00901f00700e12e12e23b00912e0093ca00700723b0090070ea", + "0x2300700723b0090110090200071db01112e23b0091fd0090150071fd009", + "0x23b00901800902e00701800923b0092230090df00722300923b0091db009", + "0x701f00923b00912e00905800701b00923b00901812512e030007018009", + "0x901f0091fd00700900923b00900900900e00700700923b009007009125", + "0x23b00901b01f00900700e3cb00701b00923b00901b00915700701f00923b", + "0x23b00900712e0070260093cc02300923b12e02500906e007025020015125", + "0x716c00700723b00923c00905400723c22c12e23b00902300906f007007", + "0x923b00902c00931900702c00923b00922922c12e31800722900923b009", + "0x931a00702000923b00902000900e00701500923b00901500912500702e", + "0x2600931b00700723b00900712e00702e02001512500902e00923b00902e", + "0x2000923b00902000900e00701500923b00901500912500703000923b009", + "0x1100923b00900715f00703002001512500903000923b00903000931a007", + "0x923b00900715f00701b00923b00900715f00722300923b0090073cd007", + "0x923b00900900900e00700723b0090070ea00700723b009007160007015", + "0x2302502012523b00912e00912e38700712e00923b00912e009221007009", + "0x900e00700723b00900712e00722c0093ce02600923b12e0230090fd007", + "0x23b00902502012e15800702500923b00902500922100702000923b009020", + "0x23b00900712e0070300093cf02e00923b12e02c0090fd00702c22923c125", + "0x10100704503112e23b00922500910700722500923b009026009151007007", + "0x923b00903300910400703300923b00904500910200700723b009031009", + "0x10100703821912e23b00903600910700703600923b00902e009151007221", + "0x923b00903a00910400703a00923b00903800910200700723b009219009", + "0x915300700723b00912600915500703c12612e23b00922100915300703b", + "0x923b00903c00916300700723b00903e00915500714103e12e23b00903b", + "0x2e00704300923b00914504112e14f00714500923b009141009163007041", + "0x900712e0071480093d000723b12e04300910600704300923b009043009", + "0x93d100715715515315204c15004904722323b00912500936900700723b", + "0x23b00922900922100723c00923b00923c00900e00705405212e23b009049", + "0x23b12e05800907b00705805715912523b00905422923c1253d2007229009", + "0x705d00923b00905a00918700700723b00900712e00715d0093d305a009", + "0x23b00900714c00700723b00915e00915500706015e12e23b00905d009153", + "0x16300700723b00916000915500706416012e23b00915f00915300715f009", + "0x916200915500706716212e23b00916100915300716100923b009060009", + "0x716816612e23b00916400915300716400923b00906400916300700723b", + "0x23b00916800916300716b00923b00906700916300700723b009166009155", + "0x902e00700723b00900710f00706e00923b00906d16b12e14f00706d009", + "0x23b00900712e00706f0093d400723b12e06e00910600706e00923b00906e", + "0x16e0090a500716e00923b00907100914400707100923b00900716c007007", + "0x6f00911100700723b00900712e0070073d50090070ee00707200923b009", + "0xa500717400923b00907400911300707400923b00900716c00700723b009", + "0x23b0090760090a500707600923b00907200936e00707200923b009174009", + "0x700723b00900712e0070770093d618000923b12e076009140007076009", + "0x700723b00901b00906400700723b00918000905400700723b0090070ea", + "0x723b00900e00905700700723b0092230093d700700723b009015009064", + "0x23b00904700937000700723b00905200937100700723b009011009064007", + "0x915300937400700723b00915500937300700723b009157009372007007", + "0x15000937700700723b00904c00937600700723b00915200937500700723b", + "0x902e00718600923b0090073d800707800923b00900722900700723b009", + "0x923b00900722500707b00923b00918607812e03000718600923b009186", + "0x12500707f00923b00908d0093b000708d00923b00907b18712e031007187", + "0x23b00905700922100715900923b00915900900e00700700923b009007009", + "0x900712e00707f05715900700e00907f00923b00907f0093b1007057009", + "0x91500093d900700723b00907700905400700723b0090070ea00700723b", + "0x5700923b00905700922100715900923b00915900900e00708f08e12e23b", + "0x9300923b12e09200907b00709209109012523b00908f0571591253da007", + "0x910600709500923b00909300918700700723b00900712e0070940093db", + "0x12e23b00904c0093dd00700723b00900712e0070960093dc00723b12e095", + "0x3de00709100923b00909100922100709000923b00909000900e007098097", + "0x93df1a700923b12e09c00907b00709c1a509912523b009098091090125", + "0x905b00915300705b00923b0091a700918700700723b00900712e007037", + "0x1530071b000923b00900714c00700723b00909f0091550071ac09f12e23b", + "0x23b0091ac00916300700723b0091b20091550070a31b212e23b0091b0009", + "0x71b500923b0090a504a12e14f0070a500923b0090a300916300704a009", + "0x712e0070a70093e000723b12e1b50091060071b500923b0091b500902e", + "0x71b800923b0091a50092210070a900923b00909900900e00700723b009", + "0x700723b00900712e0070073e20090070ee0070ac00923b0090970093e1", + "0x723b00901500906400700723b00901b00906400700723b0090a7009111", + "0x23b00901100906400700723b00900e00905700700723b0092230093d7007", + "0x908e00937700700723b00904700937000700723b009052009371007007", + "0x15300937400700723b00915500937300700723b00915700937200700723b", + "0x722900700723b00909700937600700723b00915200937500700723b009", + "0x71bc00923b0091bc00902e0071bc00923b0090073e30070ae00923b009", + "0xb00b212e0310070b200923b0090072250070b000923b0091bc0ae12e030", + "0x700923b0090070091250070b400923b0091bd0093b00071bd00923b009", + "0xb40093b10071a500923b0091a500922100709900923b00909900900e007", + "0x1b00906400700723b00900712e0070b41a509900700e0090b400923b009", + "0x905700700723b0092230093d700700723b00901500906400700723b009", + "0x37000700723b00905200937100700723b00901100906400700723b00900e", + "0x700723b00915700937200700723b00908e00937700700723b009047009", + "0x723b00915200937500700723b00915300937400700723b009155009373", + "0x90070091250070b600923b0090370093b000700723b009097009376007", + "0x71a500923b0091a500922100709900923b00909900900e00700700923b", + "0x700723b00900712e0070b61a509900700e0090b600923b0090b60093b1", + "0x23b0090910092210070a900923b00909000900e00700723b009096009111", + "0x70b81bb12e23b0090470093e40070ac00923b00904c0093e10071b8009", + "0x91b80092210070a900923b0090a900900e00700700923b009007009125", + "0x93e60070be0bc1ba0ba00e23b0090b81b80a900700e3e50071b800923b", + "0x23b0091b90093e800700723b00900712e0070c00093e71b900923b12e0be", + "0x3e90070c600923b0090073ea0070c41b612e23b0090c20093e90070c2009", + "0x23b0090c40093e900700723b0091b30090ae0070c71b312e23b0090c6009", + "0x70cb1ad12e23b0090c70093e900700723b0091b70090ae0070c91b712e", + "0x23b0090cb0091bc0070c900923b0090c90091bc00700723b0091ad0090ae", + "0x3eb1aa00923b12e0cd0091400070cd00923b0090cb0c912e2490070cb009", + "0x23b00900710f00700723b0091aa00905400700723b00900712e0070cf009", + "0x712e0071a01a10d11253ec1a31a812e23b12e1b60bc1ba1253b2007007", + "0xe00719f00923b0090d50093b40070d500923b00900716c00700723b009", + "0x23b00919f0093b50070d800923b0091a300922100719b00923b0091a8009", + "0x23b0091a00093b700700723b00900712e0070073ed0090070ee0070da009", + "0x3b50070d800923b0091a100922100719b00923b0090d100900e007198009", + "0x23b12e1970093b900719700923b0090da0093b80070da00923b009198009", + "0x3ea00700723b0090dd0093bb00700723b00900712e00718e0093ee0dd009", + "0x923b0090d800922100719b00923b00919b00900e0070df00923b009007", + "0xe112523b0090df1bb0d819b00e3ef0070df00923b0090df0091bc0070d8", + "0x700723b00900712e00718c0093f118800923b12e1890093f000718918a", + "0x18a0092210070e100923b0090e100900e0070e518b12e23b0090520093d1", + "0xa000907b0070a018318412523b0090e518a0e11253d200718a00923b009", + "0x700723b0090070ea00700723b00900712e0071790093f20e800923b12e", + "0x90e800918700700723b0090ea0090540070ea17b12e23b0091880093f3", + "0x1531520ac08e18b17b22314800717100923b0091750093f400717500923b", + "0x23b00918400900e0070ba00923b0090ba0091250070ec00923b009157155", + "0x3f600717100923b0091710093f500718300923b009183009221007184009", + "0x923b12e1690090c00071690f016c0ee00e23b0091710ec1831840ba1fd", + "0x70f616312e23b0091650092f300700723b00900712e0070f30093f7165", + "0x23b00916c00900e0070f800923b0090ee00912500700723b0090f6009054", + "0xee0070fa00923b0091630093f800701f00923b0090f000922100715c009", + "0x906400700723b00901b00906400700723b00900712e0070073f9009007", + "0x6400700723b00900e00905700700723b0092230093d700700723b009015", + "0x923b0090ee00912500715600923b0090f30093b000700723b009011009", + "0x93b10070f000923b0090f000922100716c00923b00916c00900e0070ee", + "0x70ea00700723b00900712e0071560f016c0ee00e00915600923b009156", + "0x93d700700723b00901500906400700723b00901b00906400700723b009", + "0x24800700723b00901100906400700723b00900e00905700700723b009223", + "0x700723b00915500937300700723b00915700937200700723b009188009", + "0x723b0090ac00937600700723b00915200937500700723b009153009374", + "0x23b0091790093b000700723b00918b00937100700723b00908e009377007", + "0x22100718400923b00918400900e0070ba00923b0090ba009125007154009", + "0x1541831840ba00e00915400923b0091540093b100718300923b009183009", + "0x700723b00901b00906400700723b0090070ea00700723b00900712e007", + "0x723b00900e00905700700723b0092230093d700700723b009015009064", + "0x23b00908e00937700700723b00905200937100700723b009011009064007", + "0x915300937400700723b00915500937300700723b009157009372007007", + "0x18c0093b000700723b0090ac00937600700723b00915200937500700723b", + "0xe100923b0090e100900e0070ba00923b0090ba00912500715800923b009", + "0xe10ba00e00915800923b0091580093b100718a00923b00918a009221007", + "0x23b00901b00906400700723b0090070ea00700723b00900712e00715818a", + "0x900e00905700700723b0092230093d700700723b009015009064007007", + "0xac00937600700723b00905200937100700723b00901100906400700723b", + "0x937300700723b00915700937200700723b00908e00937700700723b009", + "0x37000700723b00915200937500700723b00915300937400700723b009155", + "0x923b0090ba0091250070fd00923b00918e0093b000700723b0091bb009", + "0x93b10070d800923b0090d800922100719b00923b00919b00900e0070ba", + "0x905400700723b00900712e0070fd0d819b0ba00e0090fd00923b0090fd", + "0x1531520ac08e0521bb22314800700723b0091b60090ae00700723b0090cf", + "0x23b0091ba00900e0070f800923b0090ba00912500715100923b009157155", + "0x1590070fa00923b0091510093f800701f00923b0090bc00922100715c009", + "0x910200901500710200923b00910100901f00710110712e23b00900e009", + "0x1500714f00923b00900702500700723b00910400902000714c10412e23b", + "0x23b00914c00902300700723b00910600902000714d10612e23b00914f009", + "0x16200714e00923b00914e00902600714900923b00914d00902300714e009", + "0x712e0070073fa00723b12e14914e12e22c00701f00923b00901f01512e", + "0x700723b00910a00905700710c10a12e23b00910700915900700723b009", + "0x915c00900e0070f800923b0090f800912500714700923b00910c009058", + "0x12523b00914715c0f812501100714700923b0091470091fd00715c00923b", + "0x723b00900712e0071110093fb14400923b12e10f0091db00710f14b146", + "0x1400093fc1db00923b12e11300901800711314312e23b009144009223007", + "0x23b00911800901f00711800923b00914300901b00700723b00900712e007", + "0x2500700723b00913b00902000713913b12e23b009115009015007115009", + "0x23b00911a00902000711c11a12e23b00913700901500713700923b009007", + "0x902600712300923b00911c00902300712800923b009139009023007007", + "0x12e12312812e22c0071db00923b0091db22312e3fd00712800923b009128", + "0x906400700723b0090fa00915200700723b00900712e0070073fe00723b", + "0x22900700723b0091db00923c00700723b00901b00906400700723b009011", + "0x2f300923b0092f300902e0072f300923b0090073ff00700000923b009007", + "0x2f512e0310072f500923b0090072250072f400923b0092f300012e030007", + "0x923b0091460091250072f700923b0092f60093b00072f600923b0092f4", + "0x93b100701f00923b00901f00922100714b00923b00914b00900e007146", + "0x911c00700723b00900712e0072f701f14b14600e0092f700923b0092f7", + "0x23b00901f00922100714b00923b00914b00900e0072422f812e23b0091db", + "0x23b00901801b12e16200730801830712523b00901f14b12e38700701f009", + "0x700723b00900712e00730a00940030900923b12e3080090fd007018009", + "0x914600912500730d00923b00930900915100730c00923b009242009128", + "0x730c00923b00930c00912300730700923b00930700900e00714600923b", + "0x30f30e24112523b00930d30c30714600e40100730d00923b00930d00935a", + "0x940400700723b00900712e00731200940331000923b12e30f009402007", + "0x723b00931300923c00731431312e23b0092f800911c00700723b009310", + "0x30e00900e00724100923b00924100912500724000923b009314009128007", + "0x24000923b00924000912300701800923b00901800922100730e00923b009", + "0x91fd01112e1620073181fd31631500e23b00924001830e24100e309007", + "0x723b00900712e00731a00940531900923b12e31800930a0071fd00923b", + "0x931f00916600731f00923b00931900930c00731b00923b009007229007", + "0x731500923b00931500912500700723b00932000916800732132012e23b", + "0x931b00915700732100923b00932100916b00731600923b00931600900e", + "0x32800906e00732832732512523b00931b32131631500e06d00731b00923b", + "0x12e23b00932900906f00700723b00900712e00732a00940632900923b12e", + "0x3c700732f00923b00923f0fa12e3c600700723b00932b00905400732b23f", + "0x23b00932700900e00732500923b00932500912500733000923b00932f009", + "0xe00933000923b0093300093b10071fd00923b0091fd009221007327009", + "0x93b000700723b0090fa00915200700723b00900712e0073301fd327325", + "0x923b00932700900e00732500923b00932500912500733100923b00932a", + "0x32500e00933100923b0093310093b10071fd00923b0091fd009221007327", + "0x31a0093b000700723b0090fa00915200700723b00900712e0073311fd327", + "0x31600923b00931600900e00731500923b00931500912500733200923b009", + "0x31631500e00933200923b0093320093b10071fd00923b0091fd009221007", + "0x901100906400700723b0090fa00915200700723b00900712e0073321fd", + "0x912500733300923b0093120093b000700723b0092f800923c00700723b", + "0x923b00901800922100730e00923b00930e00900e00724100923b009241", + "0x23b00900712e00733301830e24100e00933300923b0093330093b1007018", + "0x92f800923c00700723b00901100906400700723b0090fa009152007007", + "0x912500733400923b00930a0093b000700723b00924200940700700723b", + "0x923b00901800922100730700923b00930700900e00714600923b009146", + "0x23b00900712e00733401830714600e00933400923b0093340093b1007018", + "0x901100906400700723b0090fa00915200700723b009140009054007007", + "0x2230093d700700723b00914300915e00700723b00901b00906400700723b", + "0x902e00733600923b0090073ff00733500923b00900722900700723b009", + "0x923b00900722500733800923b00933633512e03000733600923b009336", + "0x12500734000923b00933e0093b000733e00923b00933833d12e03100733d", + "0x23b00901f00922100714b00923b00914b00900e00714600923b009146009", + "0x900712e00734001f14b14600e00934000923b0093400093b100701f009", + "0x1b00906400700723b00901100906400700723b0090fa00915200700723b", + "0x12500734500923b0091110093b000700723b0092230093d700700723b009", + "0x23b00901f00922100714b00923b00914b00900e00714600923b009146009", + "0x900712e00734501f14b14600e00934500923b0093450093b100701f009", + "0x1100906400700723b0092230093d700700723b00901b00906400700723b", + "0x12e3c600734600923b00900722900700723b00910700905700700723b009", + "0x23b0090f800912500734800923b00923e0093c700723e00923b0093460fa", + "0x3b100701f00923b00901f00922100715c00923b00915c00900e0070f8009", + "0x6400700723b00900712e00734801f15c0f800e00934800923b009348009", + "0x700723b0092230093d700700723b00901500906400700723b00901b009", + "0x723b00905200937100700723b00901100906400700723b00900e009057", + "0x23b00915700937200700723b00908e00937700700723b0090ac009376007", + "0x915200937500700723b00915300937400700723b009155009373007007", + "0x912500734a00923b0090c00093b000700723b0091bb00937000700723b", + "0x923b0090bc0092210071ba00923b0091ba00900e0070ba00923b0090ba", + "0x23b00900712e00734a0bc1ba0ba00e00934a00923b00934a0093b10070bc", + "0x92230093d700700723b00901500906400700723b00901b009064007007", + "0x5200937100700723b00901100906400700723b00900e00905700700723b", + "0x937200700723b00908e00937700700723b00904700937000700723b009", + "0x37500700723b00915300937400700723b00915500937300700723b009157", + "0x34b00923b0090940093b000700723b00904c00937600700723b009152009", + "0x9100922100709000923b00909000900e00700700923b009007009125007", + "0x12e00734b09109000700e00934b00923b00934b0093b100709100923b009", + "0x3d700700723b00901500906400700723b00901b00906400700723b009007", + "0x700723b00901100906400700723b00900e00905700700723b009223009", + "0x723b00915700937200700723b00904700937000700723b009052009371", + "0x23b00915200937500700723b00915300937400700723b009155009373007", + "0x915d0093b000700723b00915000937700700723b00904c009376007007", + "0x715900923b00915900900e00700700923b00900700912500734c00923b", + "0x5715900700e00934c00923b00934c0093b100705700923b009057009221", + "0x23b00901b00906400700723b00914800911100700723b00900712e00734c", + "0x900e00905700700723b0092230093d700700723b009015009064007007", + "0x900722900700723b00912500915200700723b00901100906400700723b", + "0x3000734e00923b00934e00902e00734e00923b0090073c800734d00923b", + "0x934f23d12e03100723d00923b00900722500734f00923b00934e34d12e", + "0x700700923b00900700912500735100923b0093500093b000735000923b", + "0x93510093b100722900923b00922900922100723c00923b00923c00900e", + "0x901b00906400700723b00900712e00735122923c00700e00935100923b", + "0xe00905700700723b0092230093d700700723b00901500906400700723b", + "0x93c900700723b00912500915200700723b00901100906400700723b009", + "0x700923b00900700912500735200923b0090300093b000700723b009026", + "0x3520093b100722900923b00922900922100723c00923b00923c00900e007", + "0x12500915200700723b00900712e00735222923c00700e00935200923b009", + "0x93d700700723b00901500906400700723b00901b00906400700723b009", + "0x3b000700723b00901100906400700723b00900e00905700700723b009223", + "0x23b00902000900e00700700923b00900700912500735500923b00922c009", + "0xe00935500923b0093550093b100702500923b009025009221007020009", + "0x712e00923b00912e00900e00700723b0091fd009155007355025020007", + "0x14e0072231db01112523b00912512e12e14d00712500923b009125009221", + "0x901800914900700723b00900712e00701b00940801800923b12e223009", + "0x2502002023b00901500910c00701500923b00901f00910a00701f00923b", + "0x14700700723b00902500910100704503122503002e02c22923c22c026023", + "0x700723b00922900915500700723b00923c00915500700723b009023009", + "0x723b00903000915e00700723b00902e00914700700723b00902c009146", + "0x23b00904500915e00700723b00903100902000700723b009225009020007", + "0x915300703600923b00900714b00722103312e23b009020009153007007", + "0x923b00922100916300700723b00921900915500703821912e23b009036", + "0x12e14f00703a00923b00903a00902e00703b00923b00903800916300703a", + "0x23b0090260091fd00712600923b00912600902e00712600923b00903b03a", + "0x10600703300923b00903300902e00722c00923b00922c00902e007026009", + "0x923b00900716c00700723b00900712e00703c00940900723b12e126009", + "0x90a500704100923b00903300902e00714100923b00903e00914400703e", + "0x911100700723b00900712e00700740a0090070ee00714500923b009141", + "0x4700923b00900740b00714804312e23b00903300915300700723b00903c", + "0x14800916300700723b00904900915500715004912e23b009047009153007", + "0x923b00915204c12e14f00715200923b00915000916300704c00923b009", + "0x715500940c00723b12e15300910600715300923b00915300902e007153", + "0x5200923b00915700914400715700923b00900716c00700723b00900712e", + "0x723b00900712e00700740d0090070ee00705400923b0090520090a5007", + "0x23b00915900911300715900923b00900716c00700723b009155009111007", + "0xa500704100923b00904300902e00705400923b0090570090a5007057009", + "0x712e00705a00940e05800923b12e14500914000714500923b009054009", + "0x705d15d12e23b00904100915300700723b00905800905400700723b009", + "0x906000915500715f06012e23b00915e00915300715e00923b009007118", + "0x14f00706400923b00915f00916300716000923b00905d00916300700723b", + "0x12e16100910600716100923b00916100902e00716100923b00906416012e", + "0x14400706700923b00900716c00700723b00900712e00716200940f00723b", + "0x74100090070ee00716600923b0091640090a500716400923b009067009", + "0x16800923b00900716c00700723b00916200911100700723b00900712e007", + "0x15d00902e00716600923b00916b0090a500716b00923b009168009113007", + "0x12e0070074110090070ee00706e00923b0091660090a500706d00923b009", + "0x14400706f00923b00900716c00700723b00905a00905400700723b009007", + "0x23b0090710090a500706d00923b00904100902e00707100923b00906f009", + "0x700723b00900712e00707200941216e00923b12e06e00914000706e009", + "0x907400915500717407412e23b00906d00915300700723b00916e009054", + "0x15500707718012e23b00907600915300707600923b00900741300700723b", + "0x923b00907700916300707800923b00917400916300700723b009180009", + "0x10600707b00923b00907b00902e00707b00923b00918607812e14f007186", + "0x74150090070ee00700723b00900712e00718700941400723b12e07b009", + "0x723b00900e00915200700723b00918700911100700723b00900712e007", + "0x923b00900722900700723b00902600915e00700723b00922c009155007", + "0x8d12e03000707f00923b00907f00902e00707f00923b00900741600708d", + "0x923b00908e08f12e03100708f00923b00900722500708e00923b00907f", + "0x903300700700923b00900700912500709100923b009090009332007090", + "0x923b0091db00922100701100923b00901100900e00700900923b009009", + "0x900712e0070911db0110090071fd00909100923b0090910093310071db", + "0x1100900e00700723b00906d00915500700723b00907200905400700723b", + "0x12523b0091db01112e14d0071db00923b0091db00922100701100923b009", + "0x723b00900712e00709600941709500923b12e09400914e007094093092", + "0x9800910c00709800923b00909700910a00709700923b009095009149007", + "0x990091550070a504a0a31b21b01ac09f05b0371a709c1a509902023b009", + "0x915e00700723b00909c00914700700723b0091a500910100700723b009", + "0x15500700723b00905b00915500700723b00903700915500700723b0091a7", + "0x700723b0091b000914700700723b0091ac00914600700723b00909f009", + "0x723b0090a500915e00700723b00904a00902000700723b0090a3009020", + "0x1b500901f0071b500923b0091b50090b40071b500923b0091b200901b007", + "0x723b0090a90090200071b80a912e23b0090a70090150070a700923b009", + "0xae0090200071bc0ae12e23b0090ac0090150070ac00923b009007025007", + "0x70b200923b0091bc0090230070b000923b0091b800902300700723b009", + "0x712e00700741800723b12e0b20b012e22c0070b000923b0090b0009026", + "0x915200700723b00922c00915500700723b00902600915e00700723b009", + "0x2e0070b400923b00900711a0071bd00923b00900722900700723b00900e", + "0x23b0090072250070b600923b0090b41bd12e0300070b400923b0090b4009", + "0x70ba00923b0090b80093320070b800923b0090b61bb12e0310071bb009", + "0x909200900e00700900923b00900900903300700700923b009007009125", + "0x90ba00923b0090ba00933100709300923b00909300922100709200923b", + "0x700923b00900700912500700723b00900712e0070ba0930920090071fd", + "0x9300922100709200923b00909200900e00700900923b009009009033007", + "0x2600923b0090260091fd00722c00923b00922c00902e00709300923b009", + "0x3b90070c01b90be0bc1ba1fd23b00902622c00e0930920090071db419007", + "0x90c20093bb00700723b00900712e0071b600941a0c200923b12e0c0009", + "0x93300070c600923b0090c400932f0070c400923b0090072f400700723b", + "0x923b0090bc0090330071ba00923b0091ba0091250071b300923b0090c6", + "0x93310071b900923b0091b90092210070be00923b0090be00900e0070bc", + "0x33200700723b00900712e0071b31b90be0bc1ba1fd0091b300923b0091b3", + "0x23b0090bc0090330071ba00923b0091ba0091250070c700923b0091b6009", + "0x3310071b900923b0091b90092210070be00923b0090be00900e0070bc009", + "0x700723b00900712e0070c71b90be0bc1ba1fd0090c700923b0090c7009", + "0x723b00900e00915200700723b00922c00915500700723b00902600915e", + "0x900903300700700923b0090070091250071b700923b009096009332007", + "0x9300923b00909300922100709200923b00909200900e00700900923b009", + "0x23b00900712e0071b70930920090071fd0091b700923b0091b7009331007", + "0x70091250070c900923b00901b00933200700723b00900e009152007007", + "0x1100923b00901100900e00700900923b00900900903300700700923b009", + "0x90071fd0090c900923b0090c90093310071db00923b0091db009221007", + "0x915500700723b00901100915500700723b0091fd0091550070c91db011", + "0x712e00923b00912e00900e00700723b00922300915500700723b0091db", + "0x14e00701f01b01812523b00912512e12e14d00712500923b009125009221", + "0x901500914900700723b00900712e00702000941b01500923b12e01f009", + "0x22c02602023b00902300910c00702300923b00902500910a00702500923b", + "0x14700700723b00922c00910100703622103304503122503002e02c22923c", + "0x700723b00903000915500700723b00902e00915500700723b00923c009", + "0x723b00904500915e00700723b00903100914700700723b009225009146", + "0x23b00903600915e00700723b00922100902000700723b009033009020007", + "0x915300703a00923b00900714b00703821912e23b009026009153007007", + "0x923b00903800916300700723b00903b00915500712603b12e23b00903a", + "0x12e14f00703c00923b00903c00902e00703e00923b00912600916300703c", + "0x23b0092290091fd00714100923b00914100902e00714100923b00903e03c", + "0x10600721900923b00921900902e00702c00923b00902c00902e007229009", + "0x923b00900716c00700723b00900712e00704100941c00723b12e141009", + "0x90a500714800923b00921900902e00704300923b009145009144007145", + "0x911100700723b00900712e00700741d0090070ee00704700923b009043", + "0x4c00923b00900714300715004912e23b00921900915300700723b009041", + "0x15000916300700723b00915200915500715315212e23b00904c009153007", + "0x923b00915715512e14f00715700923b00915300916300715500923b009", + "0x705400941e00723b12e05200910600705200923b00905200902e007052", + "0x5700923b00915900914400715900923b00900716c00700723b00900712e", + "0x723b00900712e00700741f0090070ee00705800923b0090570090a5007", + "0x23b00905a00911300705a00923b00900716c00700723b009054009111007", + "0xa500714800923b00904900902e00705800923b00915d0090a500715d009", + "0x712e00715e00942005d00923b12e04700914000704700923b009058009", + "0x715f06012e23b00914800915300700723b00905d00905400700723b009", + "0x906400915500716106412e23b00916000915300716000923b009007118", + "0x14f00706700923b00916100916300716200923b00915f00916300700723b", + "0x12e16400910600716400923b00916400902e00716400923b00906716212e", + "0x14400716800923b00900716c00700723b00900712e00716600942100723b", + "0x74220090070ee00706d00923b00916b0090a500716b00923b009168009", + "0x6e00923b00900716c00700723b00916600911100700723b00900712e007", + "0x6000902e00706d00923b00906f0090a500706f00923b00906e009113007", + "0x12e0070074230090070ee00716e00923b00906d0090a500707100923b009", + "0x14400707200923b00900716c00700723b00915e00905400700723b009007", + "0x23b0090740090a500707100923b00914800902e00707400923b009072009", + "0x700723b00900712e00707600942417400923b12e16e00914000716e009", + "0x918000915500707718012e23b00907100915300700723b009174009054", + "0x15500707b18612e23b00907800915300707800923b00900711500700723b", + "0x923b00907b00916300718700923b00907700916300700723b009186009", + "0x10600707f00923b00907f00902e00707f00923b00908d18712e14f00708d", + "0x74260090070ee00700723b00900712e00708e00942500723b12e07f009", + "0x723b00900e00915200700723b00908e00911100700723b00900712e007", + "0x923b00900722900700723b00922900915e00700723b00902c009155007", + "0x8f12e03000709000923b00909000902e00709000923b00900742700708f", + "0x923b00909109212e03100709200923b00900722500709100923b009090", + "0x903300700700923b00900700912500709400923b009093009332007093", + "0x923b00901b00922100701800923b00901800900e00700900923b009009", + "0x900712e00709401b0180090071fd00909400923b00909400933100701b", + "0x1800900e00700723b00907100915500700723b00907600905400700723b", + "0x12523b00901b01812e14d00701b00923b00901b00922100701800923b009", + "0x723b00900712e00709900942809800923b12e09700914e007097096095", + "0x9c00910c00709c00923b0091a500910a0071a500923b009098009149007", + "0x1a70091550070a90a71b50a504a0a31b21b01ac09f05b0371a702023b009", + "0x915e00700723b00905b00914700700723b00903700910100700723b009", + "0x15500700723b0091b000915500700723b0091ac00915500700723b00909f", + "0x700723b00904a00914700700723b0090a300914600700723b0091b2009", + "0x723b0090a900915e00700723b0090a700902000700723b0091b5009020", + "0x1b800901f0071b800923b0091b80090b40071b800923b0090a500901b007", + "0x723b0090ae0090200071bc0ae12e23b0090ac0090150070ac00923b009", + "0xb20090200071bd0b212e23b0090b00090150070b000923b009007025007", + "0x70b600923b0091bd0090230070b400923b0091bc00902300700723b009", + "0x712e00700742900723b12e0b60b412e22c0070b400923b0090b4009026", + "0x915200700723b00902c00915500700723b00922900915e00700723b009", + "0x2e0070b800923b00900711a0071bb00923b00900722900700723b00900e", + "0x23b0090072250070ba00923b0090b81bb12e0300070b800923b0090b8009", + "0x70be00923b0090bc0093320070bc00923b0090ba1ba12e0310071ba009", + "0x909500900e00700900923b00900900903300700700923b009007009125", + "0x90be00923b0090be00933100709600923b00909600922100709500923b", + "0x700923b00900700912500700723b00900712e0070be0960950090071fd", + "0x9600922100709500923b00909500900e00700900923b009009009033007", + "0x22900923b0092290091fd00702c00923b00902c00902e00709600923b009", + "0x3b90070c41b60c20c01b91fd23b00922902c00e0960950090071db419007", + "0x90c60093bb00700723b00900712e0071b300942a0c600923b12e0c4009", + "0x93300071b700923b0090c700932f0070c700923b0090072f400700723b", + "0x923b0090c00090330071b900923b0091b90091250070c900923b0091b7", + "0x93310071b600923b0091b60092210070c200923b0090c200900e0070c0", + "0x33200700723b00900712e0070c91b60c20c01b91fd0090c900923b0090c9", + "0x23b0090c00090330071b900923b0091b90091250071ad00923b0091b3009", + "0x3310071b600923b0091b60092210070c200923b0090c200900e0070c0009", + "0x700723b00900712e0071ad1b60c20c01b91fd0091ad00923b0091ad009", + "0x723b00900e00915200700723b00902c00915500700723b00922900915e", + "0x900903300700700923b0090070091250070cb00923b009099009332007", + "0x9600923b00909600922100709500923b00909500900e00700900923b009", + "0x23b00900712e0070cb0960950090071fd0090cb00923b0090cb009331007", + "0x70091250070cd00923b00902000933200700723b00900e009152007007", + "0x1800923b00901800900e00700900923b00900900903300700700923b009", + "0x90071fd0090cd00923b0090cd00933100701b00923b00901b009221007", + "0x742b00701500923b00900708f00701b00923b00900708e0070cd01b018", + "0x12e00900e00700723b0090070ea00700723b00900716000702500923b009", + "0x12523b00900e12e12e38700700e00923b00900e00922100712e00923b009", + "0x723b00900712e00722900942c23c00923b12e22c0090fd00722c026023", + "0x2312e15800702600923b00902600922100702300923b00902300900e007", + "0x12e00703100942d22500923b12e0300090fd00703002e02c12523b009026", + "0x3312e23b00904500910700704500923b00923c00915100700723b009007", + "0x3600910400703600923b00922100910200700723b009033009101007221", + "0x3a12e23b00903800910700703800923b00922500915100721900923b009", + "0x12600910400712600923b00903b00910200700723b00903a00910100703b", + "0x723b00903e00915500714103e12e23b00921900915300703c00923b009", + "0x14100916300700723b00904100915500714504112e23b00903c009153007", + "0x923b00914804312e14f00714800923b00914500916300704300923b009", + "0x704900942e00723b12e04700910600704700923b00904700902e007047", + "0x23b00900700912500704c15012e23b0091fd00907800700723b00900712e", + "0x9900702c00923b00902c00900e00700900923b009009009033007007009", + "0x23b00901100936b00702e00923b00902e00922100712500923b009125009", + "0x71db00923b0091db00902e00715200923b00915200902e00715201112e", + "0x92231db15204c02e12502c00900701842f00722300923b00922300902e", + "0x12e03700701f00923b00901f01512e1a700705215701815501f15301123b", + "0x712e00715900943005400923b12e0520093b900701800923b00901801b", + "0x5a05805722323b00915000936900700723b0090540093bb00700723b009", + "0x23b00915300912500706416012e23b00905d00943100715f06015e05d15d", + "0x43200715700923b00915700922100715500923b00915500900e007153009", + "0x16600923b12e1640090cf00716406716216100e23b00906415715515300e", + "0x924600716b00923b0091660091a800700723b00900712e007168009433", + "0x23b00906f00915500700723b00906e00915500706f06e06d12523b00916b", + "0x922100716200923b00916200900e00716100923b009161009125007007", + "0x6d06716216100e43500706d00923b00906d00943400706700923b009067", + "0x12e00707600943717400923b12e07400943600707407216e07100e23b009", + "0x7712e23b00918000943900718000923b00917400943800700723b009007", + "0x7b00943900707b00923b00918600943a00718600923b00900716c007078", + "0x7800923b00907800943c00700723b00918700943b00708d18712e23b009", + "0x914000707f00923b00908d07812e43d00708d00923b00908d00943c007", + "0x23b00908e00905400700723b00900712e00708f00943e08e00923b12e07f", + "0x23b00900714c00709100923b00900714c00709000923b00900743f007007", + "0x7100923b00907100912500709300923b009092091090125440007092009", + "0x930091a100707200923b00907200922100716e00923b00916e00900e007", + "0x709709609509400e23b00909316007216e0711fd44100709300923b009", + "0x7700943900700723b00900712e00709900944309800923b12e097009442", + "0x71a700923b00900716c00700723b0091a500943b00709c1a512e23b009", + "0x5b00943b00709f05b12e23b00903700943900703700923b0091a7009444", + "0x700723b0091ac00943b0071b01ac12e23b00909c00943900700723b009", + "0x91b000943c00700723b0091b200943b0070a31b212e23b00909f009439", + "0x4a00923b0090a31b012e4450070a300923b0090a300943c0071b000923b", + "0x4a00914000700723b0091b50090540071b50a512e23b009098009446007", + "0x723b0090a700905400700723b00900712e0070a90094470a700923b12e", + "0x23b00915f06015e0a515d05a0580572231480071b800923b009007245007", + "0x22100709500923b00909500900e00709400923b0090940091250070ac009", + "0xb01bc0ae00e23b0091b80ac0960950941fd44800709600923b009096009", + "0x2f300700723b00900712e0070b40094491bd00923b12e0b20090c00070b2", + "0x23b0090ae00912500700723b0091bb0090540071bb0b612e23b0091bd009", + "0x3f80071ba00923b0090b00092210070ba00923b0091bc00900e0070b8009", + "0x15500700723b00900712e00700744a0090070ee0070bc00923b0090b6009", + "0xbe00923b0090b400944c00700723b00902500944b00700723b009011009", + "0x1bc00900e00701f00923b00901f0090330070ae00923b0090ae009125007", + "0xb000923b0090b000922100701800923b0090180090990071bc00923b009", + "0x900712e0070be0b00181bc01f0ae0110090be00923b0090be00944d007", + "0x15f06015e0a515d05a05805722314800700723b0090a900905400700723b", + "0xba00923b00909500900e0070b800923b0090940091250071b900923b009", + "0xb800944e0070bc00923b0091b90093f80071ba00923b009096009221007", + "0x1b600923b0091ba0094500070c200923b0090ba00944f0070c000923b009", + "0x723b00900712e0070074510090070ee0070c400923b0090bc0093f8007", + "0x23b00905700937000700723b00902500944b00700723b009011009155007", + "0x915e00937400700723b00906000937300700723b00915f009372007007", + "0x5a00937700700723b00915d00937600700723b00907700943b00700723b", + "0x1250070c600923b00909900944c00700723b00905800937100700723b009", + "0x23b00909500900e00701f00923b00901f00903300709400923b009094009", + "0x44d00709600923b00909600922100701800923b009018009099007095009", + "0x723b00900712e0070c609601809501f0940110090c600923b0090c6009", + "0x5a05805722314800700723b00907700943b00700723b00908f009054007", + "0x900e0070c000923b0090710091250071b300923b00915f06015e16015d", + "0x923b0091b30093f80071b600923b0090720092210070c200923b00916e", + "0x90070250070cf1aa0cd0cb1ad0c91b70c722323b0090c40093690070c4", + "0x23b0091a80cf1b60c200e4520071a800923b0091a80090260071a800923b", + "0x23b00900712e0070d50094531a000923b12e1a10092440071a10d11a3125", + "0xd10092210071a300923b0091a300900e00719f00923b009007025007007", + "0x919f1aa0d11a300e45400719f00923b00919f0090260070d100923b009", + "0x900712e00719700945619800923b12e0da0094550070da0d819b12523b", + "0x45800700723b00918e00905400718e0dd12e23b0091a000945700700723b", + "0xc91b70c722314800700723b0090e10090540070e10df12e23b009198009", + "0x18b18c18818922323b00918a00936900718a00923b0090dd0df0cd0cb1ad", + "0x923b00919b00900e0071790e812e23b0091880093d10070a01831840e5", + "0xea17b12523b0091790d819b1253d20070d800923b0090d800922100719b", + "0xe00700723b00900712e00717100945902000923b12e17500907b007175", + "0x23b00901100936b0070ea00923b0090ea00922100717b00923b00917b009", + "0x23b0090ec0e80ea17b00e45a0070ec00923b0090ec00902e0070ec01112e", + "0x923b12e0f000945c00702000923b00902002512e45b0070f016c0ee125", + "0x71630f312e23b00916900945e00700723b00900712e00716500945d169", + "0x90f600945f0070f601112e23b00901100936b00700723b009163009054", + "0x12500715c00923b0090a01831840e518b18c0f31892231480070f800923b", + "0x23b00916c0092210070ee00923b0090ee00900e0070c000923b0090c0009", + "0x23b0090f815c16c0ee0c01fd4610070f800923b0090f800946000716c009", + "0x900712e0071510094620fd00923b12e1580090c00071581541560fa00e", + "0x710210112e23b0090fd0092f300710700923b00902000918700700723b", + "0x23b0090fa00912500710400923b00910700946300700723b009102009054", + "0x46400715400923b00915400922100715600923b00915600900e0070fa009", + "0x10614f14c00e23b0091041011541560fa1fd46500710400923b009104009", + "0x2f300700723b00900712e00714900946614e00923b12e14d0090c000714d", + "0x23b0090110093f400700723b00910c00905400710c10a12e23b00914e009", + "0x22100714f00923b00914f00900e00714c00923b00914c009125007147009", + "0x10614f14c1fd3f600714700923b0091470093f500710600923b009106009", + "0x14300946711100923b12e1440090c000714410f14b14600e23b00914710a", + "0x914000905400714011312e23b0091110092f300700723b00900712e007", + "0x46900711500923b00911811312e46800711800923b00900716c00700723b", + "0x23b00901f00903300714600923b00914600912500713b00923b009115009", + "0x22100701800923b00901800909900714b00923b00914b00900e00701f009", + "0x1814b01f14601100913b00923b00913b00944d00710f00923b00910f009", + "0x14600912500713900923b00914300944c00700723b00900712e00713b10f", + "0x14b00923b00914b00900e00701f00923b00901f00903300714600923b009", + "0x13900944d00710f00923b00910f00922100701800923b009018009099007", + "0x15500700723b00900712e00713910f01814b01f14601100913900923b009", + "0x923b00914c00912500713700923b00914900944c00700723b009011009", + "0x909900714f00923b00914f00900e00701f00923b00901f00903300714c", + "0x923b00913700944d00710600923b00910600922100701800923b009018", + "0x901100915500700723b00900712e00713710601814f01f14c011009137", + "0x912500711a00923b00915100944c00700723b00902000924300700723b", + "0x923b00915600900e00701f00923b00901f0090330070fa00923b0090fa", + "0x944d00715400923b00915400922100701800923b009018009099007156", + "0x700723b00900712e00711a15401815601f0fa01100911a00923b00911a", + "0x723b00918900937000700723b00902000924300700723b009011009155", + "0x23b00918400937400700723b00918300937300700723b0090a0009372007", + "0x918c00937700700723b00918b00937600700723b0090e5009375007007", + "0x330070c000923b0090c000912500711c00923b00916500944c00700723b", + "0x23b0090180090990070ee00923b0090ee00900e00701f00923b00901f009", + "0x1100911c00923b00911c00944d00716c00923b00916c009221007018009", + "0x700723b00901100915500700723b00900712e00711c16c0180ee01f0c0", + "0x723b00918b00937600700723b00918c00937700700723b009189009370", + "0x23b00918400937400700723b00918300937300700723b0090a0009372007", + "0x902500944b00700723b0090e800937100700723b0090e5009375007007", + "0x330070c000923b0090c000912500712800923b00917100944c00700723b", + "0x23b00901800909900717b00923b00917b00900e00701f00923b00901f009", + "0x1100912800923b00912800944d0070ea00923b0090ea009221007018009", + "0x700723b00901100915500700723b00900712e0071280ea01817b01f0c0", + "0x723b0090c700937000700723b0091a000946a00700723b00902500944b", + "0x23b0091ad00937600700723b0090cb00937500700723b0090cd009374007", + "0x919700944c00700723b0091b700937100700723b0090c9009377007007", + "0x701f00923b00901f0090330070c000923b0090c000912500712300923b", + "0x90d800922100701800923b00901800909900719b00923b00919b00900e", + "0x71230d801819b01f0c001100912300923b00912300944d0070d800923b", + "0x700723b00902500944b00700723b00901100915500700723b00900712e", + "0x723b0090c700937000700723b0090c900937700700723b0091b7009371", + "0x23b0091ad00937600700723b0090cb00937500700723b0090cd009374007", + "0xc000912500700000923b0090d500944c00700723b0091aa009373007007", + "0x1a300923b0091a300900e00701f00923b00901f0090330070c000923b009", + "0x944d0070d100923b0090d100922100701800923b009018009099007", + "0x15500700723b00900712e0070000d10181a301f0c001100900000923b009", + "0x700723b00905700937000700723b00902500944b00700723b009011009", + "0x723b00905800937100700723b00905a00937700700723b00915d009376", + "0x23b00915e00937400700723b00906000937300700723b00915f009372007", + "0x710091250072f300923b00907600944c00700723b009160009375007007", + "0x16e00923b00916e00900e00701f00923b00901f00903300707100923b009", + "0x2f300944d00707200923b00907200922100701800923b009018009099007", + "0x15500700723b00900712e0072f307201816e01f0710110092f300923b009", + "0x700723b00905700937000700723b00902500944b00700723b009011009", + "0x723b00905800937100700723b00905a00937700700723b00915d009376", + "0x23b00915e00937400700723b00906000937300700723b00915f009372007", + "0x1610091250072f400923b00916800944c00700723b009160009375007007", + "0x16200923b00916200900e00701f00923b00901f00903300716100923b009", + "0x2f400944d00706700923b00906700922100701800923b009018009099007", + "0x15500700723b00900712e0072f406701816201f1610110092f400923b009", + "0x700723b00915000915200700723b00902500944b00700723b009011009", + "0x901f00903300715300923b0091530091250072f500923b00915900944c", + "0x701800923b00901800909900715500923b00915500900e00701f00923b", + "0x15501f1530110092f500923b0092f500944d00715700923b009157009221", + "0x2500944b00700723b00904900911100700723b00900712e0072f5157018", + "0x909700700723b00901500909600700723b00901100915500700723b009", + "0x15200700723b0091db00915500700723b00922300915500700723b00901b", + "0x72f700923b0090073c80072f600923b00900722900700723b0091fd009", + "0x90072250072f800923b0092f72f612e0300072f700923b0092f700902e", + "0x30800923b00930700944c00730700923b0092f824212e03100724200923b", + "0x2c00900e00700900923b00900900903300700700923b009007009125007", + "0x2e00923b00902e00922100712500923b00912500909900702c00923b009", + "0x900712e00730802e12502c00900701100930800923b00930800944d007", + "0x1500909600700723b00901100915500700723b00902500944b00700723b", + "0x915500700723b00922300915500700723b00901b00909700700723b009", + "0x44c00700723b00923c0093c900700723b0091fd00915200700723b0091db", + "0x23b00900900903300700700923b00900700912500730900923b009031009", + "0x22100712500923b00912500909900702c00923b00902c00900e007009009", + "0x12502c00900701100930900923b00930900944d00702e00923b00902e009", + "0x901100915500700723b00902500944b00700723b00900712e00730902e", + "0x22300915500700723b00901b00909700700723b00901500909600700723b", + "0x944c00700723b0091fd00915200700723b0091db00915500700723b009", + "0x923b00900900903300700700923b00900700912500730a00923b009229", + "0x922100712500923b00912500909900702300923b00902300900e007009", + "0x2612502300900701100930a00923b00930a00944d00702600923b009026", + "0x912e00922100700900923b00900900900e00700723b0090070ea00730a", + "0x23b12e1db0090fd0071db0111fd12523b00912e00912e38700712e00923b", + "0x71fd00923b0091fd00900e00700723b00900712e00701800946b223009", + "0xfd00701501f01b12523b0090111fd12e15800701100923b009011009221", + "0x922300915100700723b00900712e00702500946c02000923b12e015009", + "0x700723b00902600910100722c02612e23b00902300910700702300923b", + "0x902000915100722900923b00923c00910400723c00923b00922c009102", + "0x700723b00902e00910100703002e12e23b00902c00910700702c00923b", + "0x922900915300703100923b00922500910400722500923b009030009102", + "0x3622112e23b00903100915300700723b00904500915500703304512e23b", + "0x903600916300721900923b00903300916300700723b009221009155007", + "0x3a00923b00903a00902e00703a00923b00903821912e14f00703800923b", + "0xe00936b00700723b00900712e00703b00946d00723b12e03a009106007", + "0x23b00900712e00703c00946e00723b12e12600910600712600e12e23b009", + "0x1450093dd00704904714804314504114103e22323b009125009369007007", + "0x923b00901f00922100701b00923b00901b00900e00704c15012e23b009", + "0x923b12e15500907b00715515315212523b00904c01f01b1253de00701f", + "0x15300705400923b00915700918700700723b00900712e00705200946f157", + "0x923b00900714c00700723b00915900915500705715912e23b009054009", + "0x916300700723b00905a00915500715d05a12e23b009058009153007058", + "0x23b00915e05d12e14f00715e00923b00915d00916300705d00923b009057", + "0x15f00947000723b12e06000910600706000923b00906000902e007060009", + "0x923b00904904714804315004114103e22314800700723b00900712e007", + "0x93f800716100923b00915300922100706400923b00915200900e007160", + "0x911100700723b00900712e0070074710090070ee00716200923b009160", + "0x37300700723b00904900937200700723b00900e00915500700723b00915f", + "0x700723b00904300937500700723b00914800937400700723b009047009", + "0x723b00914100937100700723b00904100937700700723b009150009376", + "0x923b0090073e300706700923b00900722900700723b00903e009370007", + "0x22500716600923b00916406712e03000716400923b00916400902e007164", + "0x23b00916b00944c00716b00923b00916616812e03100716800923b009007", + "0x22100715200923b00915200900e00700700923b00900700912500706d009", + "0x6d15315200700e00906d00923b00906d00944d00715300923b009153009", + "0x723b00904900937200700723b00900e00915500700723b00900712e007", + "0x23b00904300937500700723b00914800937400700723b009047009373007", + "0x914100937100700723b00904100937700700723b009150009376007007", + "0x912500706e00923b00905200944c00700723b00903e00937000700723b", + "0x923b00915300922100715200923b00915200900e00700700923b009007", + "0x23b00900712e00706e15315200700e00906e00923b00906e00944d007153", + "0x1f00922100706400923b00901b00900e00700723b00903c009111007007", + "0x6f22323b00916200936900716200923b0091250093f800716100923b009", + "0x700912500707807712e23b00907400943100718007617407407216e071", + "0x16100923b00916100922100706400923b00906400900e00700700923b009", + "0x23b12e08d0090cf00708d18707b18600e23b00907816106400700e432007", + "0x708f00923b00907f0091a800700723b00900712e00708e00947207f009", + "0x9200915500700723b00909100915500709209109012523b00908f009246", + "0x707b00923b00907b00900e00718600923b00918600912500700723b009", + "0x7b18600e43500709000923b00909000943400718700923b009187009221", + "0x9800947309700923b12e09600943600709609509409300e23b009090187", + "0x23b00909900943900709900923b00909700943800700723b00900712e007", + "0x43900703700923b0091a700943a0071a700923b00900716c00709c1a512e", + "0x23b00909c00943c00700723b00905b00943b00709f05b12e23b009037009", + "0x71ac00923b00909f09c12e43d00709f00923b00909f00943c00709c009", + "0x1b000905400700723b00900712e0071b20094741b000923b12e1ac009140", + "0x714c00704a00923b00900714c0070a300923b00900743f00700723b009", + "0x23b0090930091250071b500923b0090a504a0a31254400070a500923b009", + "0x1a100709500923b00909500922100709400923b00909400900e007093009", + "0x1b80a90a700e23b0091b50770950940931fd4410071b500923b0091b5009", + "0x43900700723b00900712e0071bc0094750ae00923b12e0ac0094420070ac", + "0x923b00900716c00700723b0090b000943b0070b20b012e23b0091a5009", + "0x43b0071bb0b612e23b0090b40094390070b400923b0091bd0094440071bd", + "0x23b0090b800943b0070ba0b812e23b0090b200943900700723b0090b6009", + "0x943c00700723b0091ba00943b0070bc1ba12e23b0091bb009439007007", + "0x23b0090bc0ba12e4450070bc00923b0090bc00943c0070ba00923b0090ba", + "0x14000700723b0090c00090540070c01b912e23b0090ae0094460070be009", + "0x90c200905400700723b00900712e0071b60094760c200923b12e0be009", + "0x1800761741b907216e07106f2231480070c400923b00900724500700723b", + "0xa900923b0090a900900e0070a700923b0090a70091250070c600923b009", + "0x1b300e23b0090c40c61b80a90a71fd4480071b800923b0091b8009221007", + "0x723b00900712e0070cb0094771ad00923b12e0c90090c00070c91b70c7", + "0x1b300912500700723b0091aa0090540071aa0cd12e23b0091ad0092f3007", + "0x1a300923b0091b70092210071a800923b0090c700900e0070cf00923b009", + "0x723b00900712e0070074780090070ee0070d100923b0090cd0093f8007", + "0x91b30091250071a100923b0090cb00944c00700723b00900e009155007", + "0x71b700923b0091b70092210070c700923b0090c700900e0071b300923b", + "0x700723b00900712e0071a11b70c71b300e0091a100923b0091a100944d", + "0x923b0091800761741b907216e07106f22314800700723b0091b6009054", + "0x92210071a800923b0090a900900e0070cf00923b0090a70091250071a0", + "0x923b0090cf00944e0070d100923b0091a00093f80071a300923b0091b8", + "0x93f800719b00923b0091a300945000719f00923b0091a800944f0070d5", + "0x915500700723b00900712e0070074790090070ee0070d800923b0090d1", + "0x37300700723b00918000937200700723b00906f00937000700723b00900e", + "0x700723b0091a500943b00700723b00917400937400700723b009076009", + "0x723b00907100937100700723b00916e00937700700723b009072009376", + "0xa900900e0070a700923b0090a70091250070da00923b0091bc00944c007", + "0xda00923b0090da00944d0071b800923b0091b80092210070a900923b009", + "0x700723b0091b200905400700723b00900712e0070da1b80a90a700e009", + "0x923b00918007617407707216e07106f22314800700723b0091a500943b", + "0x922100719f00923b00909400900e0070d500923b009093009125007198", + "0x22323b0090d80093690070d800923b0091980093f800719b00923b009095", + "0x918c00902600718c00923b00900702500718818918a0e10df18e0dd197", + "0x1840092440071840e518b12523b00918c18819b19f00e45200718c00923b", + "0xe800923b00900702500700723b00900712e0070a000947a18300923b12e", + "0xe80090260070e500923b0090e500922100718b00923b00918b00900e007", + "0x94550070ea17b17912523b0090e81890e518b00e4540070e800923b009", + "0x23b00918300945700700723b00900712e00717100947b17500923b12e0ea", + "0x70f016c12e23b00917500945800700723b0090ee0090540070ee0ec12e", + "0x923b0090ec16c18a0e10df18e0dd19722314800700723b0090f0009054", + "0x17900900e0071560fa15c0f80f61630f316522323b009169009369007169", + "0xe12e23b00900e00936b00717b00923b00917b00922100717900923b009", + "0x15812523b00915416317b17900e47c00715400923b00915400902e007154", + "0x700723b00900712e00710100947e10700923b12e15100947d0071510fd", + "0x900e00948000700723b00910400905400710410212e23b00910700947f", + "0x12500714f00923b0091560fa15c0f80f61020f316522314800714c00923b", + "0x23b0090fd00922100715800923b00915800900e0070d500923b0090d5009", + "0x23b00914c14f0fd1580d51fd48200714c00923b00914c0094810070fd009", + "0x900712e00710c00948310a00923b12e1490090c000714914e14d10600e", + "0x16c00700723b00914600905400714614712e23b00910a0092f300700723b", + "0x23b00910f00946900710f00923b00914b14712e46800714b00923b009007", + "0x22100714d00923b00914d00900e00710600923b009106009125007144009", + "0x14414e14d10600e00914400923b00914400944d00714e00923b00914e009", + "0x23b00910600912500711100923b00910c00944c00700723b00900712e007", + "0x44d00714e00923b00914e00922100714d00923b00914d00900e007106009", + "0x37000700723b00900712e00711114e14d10600e00911100923b009111009", + "0x700723b0090fa00937300700723b00915600937200700723b009165009", + "0x723b0090f600937600700723b0090f800937500700723b00915c009374", + "0x23b00910100944c00700723b0090f300937100700723b00900e009155007", + "0x22100715800923b00915800900e0070d500923b0090d5009125007143009", + "0x1430fd1580d500e00914300923b00914300944d0070fd00923b0090fd009", + "0x723b00918300946a00700723b00900e00915500700723b00900712e007", + "0x23b0090e100937500700723b00918a00937400700723b009197009370007", + "0x90dd00937100700723b00918e00937700700723b0090df009376007007", + "0xe0070d500923b0090d500912500711300923b00917100944c00700723b", + "0x23b00911300944d00717b00923b00917b00922100717900923b009179009", + "0x23b00918e00937700700723b00900712e00711317b1790d500e009113009", + "0x919700937000700723b00900e00915500700723b0090dd009371007007", + "0xdf00937600700723b0090e100937500700723b00918a00937400700723b", + "0x12500714000923b0090a000944c00700723b00918900937300700723b009", + "0x23b0090e500922100718b00923b00918b00900e0070d500923b0090d5009", + "0x900712e0071400e518b0d500e00914000923b00914000944d0070e5009", + "0x7200937600700723b00906f00937000700723b00900e00915500700723b", + "0x937200700723b00907100937100700723b00916e00937700700723b009", + "0x37500700723b00917400937400700723b00907600937300700723b009180", + "0x923b00909300912500711800923b00909800944c00700723b009077009", + "0x944d00709500923b00909500922100709400923b00909400900e007093", + "0x915500700723b00900712e00711809509409300e00911800923b009118", + "0x37700700723b00907200937600700723b00906f00937000700723b00900e", + "0x700723b00918000937200700723b00907100937100700723b00916e009", + "0x723b00907700937500700723b00917400937400700723b009076009373", + "0x7b00900e00718600923b00918600912500711500923b00908e00944c007", + "0x11500923b00911500944d00718700923b00918700922100707b00923b009", + "0x700723b00903b00911100700723b00900712e00711518707b18600e009", + "0x13b00923b00900722900700723b00912500915200700723b00900e009155", + "0x13913b12e03000713900923b00913900902e00713900923b0090073c8007", + "0x11c00923b00913711a12e03100711a00923b00900722500713700923b009", + "0x1b00900e00700700923b00900700912500712800923b00911c00944c007", + "0x12800923b00912800944d00701f00923b00901f00922100701b00923b009", + "0x700723b00900e00915500700723b00900712e00712801f01b00700e009", + "0x923b00902500944c00700723b0092230093c900700723b009125009152", + "0x922100701b00923b00901b00900e00700700923b009007009125007123", + "0x712301f01b00700e00912300923b00912300944d00701f00923b00901f", + "0x700723b00912500915200700723b00900e00915500700723b00900712e", + "0x91fd00900e00700700923b00900700912500700000923b00901800944c", + "0x900000923b00900000944d00701100923b0090110092210071fd00923b", + "0x700900923b00900900900e00700723b0090070ea0070000111fd00700e", + "0xfd0071db0111fd12523b00912e00912e38700712e00923b00912e009221", + "0x91fd00900e00700723b00900712e00701800948422300923b12e1db009", + "0x1b12523b0090111fd12e15800701100923b0090110092210071fd00923b", + "0x700723b00900712e00702500948502000923b12e0150090fd00701501f", + "0x2600910100722c02612e23b00902300910700702300923b009223009151", + "0x722900923b00923c00910400723c00923b00922c00910200700723b009", + "0x2e00910100703002e12e23b00902c00910700702c00923b009020009151", + "0x703100923b00922500910400722500923b00903000910200700723b009", + "0x903100915300700723b00904500915500703304512e23b009229009153", + "0x721900923b00903300916300700723b00922100915500703622112e23b", + "0x3a00902e00703a00923b00903821912e14f00703800923b009036009163", + "0x723b00900712e00703b00948600723b12e03a00910600703a00923b009", + "0x14504114103e22323b00903c00936900703c12612e23b009125009078007", + "0x37600700723b00914100937100700723b00903e009370007049047148043", + "0x700723b00914800937400700723b00904300937500700723b009145009", + "0x923b00901b00900e00700723b00904900937200700723b009047009373", + "0x4c15012523b00904101f01b1253da00701f00923b00901f00922100701b", + "0x18700700723b00900712e00715500948715300923b12e15200907b007152", + "0x905200915500705405212e23b00915700915300715700923b009153009", + "0x15500705805712e23b00915900915300715900923b00900714c00700723b", + "0x12e23b00905a00915300705a00923b00905400916300700723b009057009", + "0x915300715e00923b00905800916300700723b00915d00915500705d15d", + "0x923b00905d00916300700723b00906000915500715f06012e23b00915e", + "0x10f00716100923b00906416012e14f00706400923b00915f009163007160", + "0x48800723b12e16100910600716100923b00916100902e00700723b009007", + "0x906700914400706700923b00900716c00700723b00900712e007162009", + "0x712e0070074890090070ee00716600923b0091640090a500716400923b", + "0x911300716800923b00900716c00700723b00916200911100700723b009", + "0x923b00916600936e00716600923b00916b0090a500716b00923b009168", + "0x6f00948a06e00923b12e06d00914000706d00923b00906d0090a500706d", + "0x700723b00906e00905400700723b0090070ea00700723b00900712e007", + "0x7100923b00900722900700723b00912600915200700723b00900e009155", + "0x16e07112e03000716e00923b00916e00902e00716e00923b00900748b007", + "0x17400923b00907207412e03100707400923b00900722500707200923b009", + "0x15000900e00700700923b00900700912500707600923b00917400944c007", + "0x7600923b00907600944d00704c00923b00904c00922100715000923b009", + "0x5400700723b0090070ea00700723b00900712e00707604c15000700e009", + "0x7f08d18707b18607807718022323b00912600936900700723b00906f009", + "0x900e00700700923b00900700912500708f08e12e23b00907b009431007", + "0x8f04c15000700e43200704c00923b00904c00922100715000923b009150", + "0x12e00709500948c09400923b12e0930090cf00709309209109000e23b009", + "0x9712523b00909600924600709600923b0090940091a800700723b009007", + "0x9000912500700723b00909900915500700723b009098009155007099098", + "0x9200923b00909200922100709100923b00909100900e00709000923b009", + "0x9c1a500e23b00909709209109000e43500709700923b009097009434007", + "0x700723b00900712e00709f00948d05b00923b12e0370094360070371a7", + "0x900716c0071b21b012e23b0091ac0094390071ac00923b00905b009438", + "0x1b50a512e23b00904a00943900704a00923b0090a300943a0070a300923b", + "0x91b500943c0071b200923b0091b200943c00700723b0090a500943b007", + "0xa900923b12e0a70091400070a700923b0091b51b212e43d0071b500923b", + "0x900743f00700723b0090a900905400700723b00900712e0071b800948e", + "0x1254400071bc00923b00900714c0070ae00923b00900714c0070ac00923b", + "0x909c00900e0071a500923b0091a50091250070b000923b0091bc0ae0ac", + "0x70b000923b0090b00091a10071a700923b0091a700922100709c00923b", + "0x23b12e0b60094420070b60b41bd0b200e23b0090b008e1a709c1a51fd441", + "0x1ba0ba12e23b0091b000943900700723b00900712e0070b800948f1bb009", + "0x23b0090bc0094440070bc00923b00900716c00700723b0090ba00943b007", + "0x43900700723b0091b900943b0070c01b912e23b0090be0094390070be009", + "0x23b0090c000943900700723b0090c200943b0071b60c212e23b0091ba009", + "0x43c0071b600923b0091b600943c00700723b0090c400943b0070c60c412e", + "0x91bb0094460071b300923b0090c61b612e4450070c600923b0090c6009", + "0x4900c900923b12e1b300914000700723b0091b70090540071b70c712e23b", + "0x23b00900724500700723b0090c900905400700723b00900712e0071ad009", + "0x91250070cd00923b00907f08d1870c71860780771802231480070cb009", + "0x923b0090b40092210071bd00923b0091bd00900e0070b200923b0090b2", + "0x1a30090c00071a31a80cf1aa00e23b0090cb0cd0b41bd0b21fd4480070b4", + "0x12e23b0090d10092f300700723b00900712e0071a10094910d100923b12e", + "0x900e00719f00923b0091aa00912500700723b0090d50090540070d51a0", + "0x923b0091a00093f80070d800923b0091a800922100719b00923b0090cf", + "0x723b00900e00915500700723b00900712e0070074920090070ee0070da", + "0xcf00900e0071aa00923b0091aa00912500719800923b0091a100944c007", + "0x19800923b00919800944d0071a800923b0091a80092210070cf00923b009", + "0x700723b0091ad00905400700723b00900712e0071981a80cf1aa00e009", + "0x23b0090b200912500719700923b00907f08d1870c7186078077180223148", + "0x3f80070d800923b0090b400922100719b00923b0091bd00900e00719f009", + "0x23b00919b00944f0070dd00923b00919f00944e0070da00923b009197009", + "0xee0070e100923b0090da0093f80070df00923b0090d800945000718e009", + "0x937000700723b00900e00915500700723b00900712e007007493009007", + "0x37400700723b00908d00937300700723b00907f00937200700723b009180", + "0x700723b00918600937600700723b0091b000943b00700723b009187009", + "0x923b0090b800944c00700723b00907700937100700723b009078009377", + "0x92210071bd00923b0091bd00900e0070b200923b0090b200912500718a", + "0x718a0b41bd0b200e00918a00923b00918a00944d0070b400923b0090b4", + "0x700723b0091b000943b00700723b0091b800905400700723b00900712e", + "0x23b0091a500912500718900923b00907f08d18708e186078077180223148", + "0x3f80070df00923b0091a700922100718e00923b00909c00900e0070dd009", + "0xa01831840e518b18c18822323b0090e10093690070e100923b009189009", + "0x18e00e45200717900923b00917900902600717900923b0090070250070e8", + "0xec00949417100923b12e1750092440071750ea17b12523b0091790e80df", + "0x923b00917b00900e0070ee00923b00900702500700723b00900712e007", + "0xe4540070ee00923b0090ee0090260070ea00923b0090ea00922100717b", + "0x949516500923b12e1690094550071690f016c12523b0090ee0a00ea17b", + "0xf60090540070f616312e23b00917100945700700723b00900712e0070f3", + "0x700723b00915c00905400715c0f812e23b00916500945800700723b009", + "0x23b0090fa0093690070fa00923b0091630f81831840e518b18c188223148", + "0x922100716c00923b00916c00900e0071021011071510fd158154156223", + "0x23b00910400902e00710400e12e23b00900e00936b0070f000923b0090f0", + "0x12e10600949700710614f14c12523b0091040fd0f016c00e496007104009", + "0x14912e23b00914d00949900700723b00900712e00714e00949814d00923b", + "0x15622314800710c00923b00900e00949a00700723b00910a00905400710a", + "0x70dd00923b0090dd00912500714700923b009102101107151149158154", + "0x910c00949b00714f00923b00914f00922100714c00923b00914c00900e", + "0xc000714410f14b14600e23b00910c14714f14c0dd1fd49c00710c00923b", + "0x91110092f300700723b00900712e00714300949d11100923b12e144009", + "0x46800711800923b00900716c00700723b00914000905400714011312e23b", + "0x914600912500713b00923b00911500946900711500923b00911811312e", + "0x710f00923b00910f00922100714b00923b00914b00900e00714600923b", + "0x700723b00900712e00713b10f14b14600e00913b00923b00913b00944d", + "0x914b00900e00714600923b00914600912500713900923b00914300944c", + "0x913900923b00913900944d00710f00923b00910f00922100714b00923b", + "0x37200700723b00915600937000700723b00900712e00713910f14b14600e", + "0x700723b00910700937400700723b00910100937300700723b009102009", + "0x723b00915800937700700723b00900e00915500700723b009151009375", + "0x90dd00912500713700923b00914e00944c00700723b009154009371007", + "0x714f00923b00914f00922100714c00923b00914c00900e0070dd00923b", + "0x700723b00900712e00713714f14c0dd00e00913700923b00913700944d", + "0x723b00918800937000700723b00917100946a00700723b00900e009155", + "0x23b0090e500937600700723b00918400937500700723b009183009374007", + "0x90f300944c00700723b00918c00937100700723b00918b009377007007", + "0x716c00923b00916c00900e0070dd00923b0090dd00912500711a00923b", + "0xf016c0dd00e00911a00923b00911a00944d0070f000923b0090f0009221", + "0x23b00918c00937100700723b00918b00937700700723b00900712e00711a", + "0x918300937400700723b00918800937000700723b00900e009155007007", + "0xa000937300700723b0090e500937600700723b00918400937500700723b", + "0x70dd00923b0090dd00912500711c00923b0090ec00944c00700723b009", + "0x911c00944d0070ea00923b0090ea00922100717b00923b00917b00900e", + "0x900e00915500700723b00900712e00711c0ea17b0dd00e00911c00923b", + "0x7800937700700723b00918600937600700723b00918000937000700723b", + "0x937300700723b00907f00937200700723b00907700937100700723b009", + "0x44c00700723b00908e00937500700723b00918700937400700723b00908d", + "0x23b00909c00900e0071a500923b0091a500912500712800923b00909f009", + "0xe00912800923b00912800944d0071a700923b0091a700922100709c009", + "0x937000700723b00900e00915500700723b00900712e0071281a709c1a5", + "0x37100700723b00907800937700700723b00918600937600700723b009180", + "0x700723b00908d00937300700723b00907f00937200700723b009077009", + "0x923b00909500944c00700723b00908e00937500700723b009187009374", + "0x922100709100923b00909100900e00709000923b009090009125007123", + "0x712309209109000e00912300923b00912300944d00709200923b009092", + "0x700723b00912600915200700723b00900e00915500700723b00900712e", + "0x915000900e00700700923b00900700912500700000923b00915500944c", + "0x900000923b00900000944d00704c00923b00904c00922100715000923b", + "0x15500700723b00903b00911100700723b00900712e00700004c15000700e", + "0x72f300923b00900722900700723b00912500915200700723b00900e009", + "0x92f42f312e0300072f400923b0092f400902e0072f400923b0090073c8", + "0x72f700923b0092f52f612e0310072f600923b0090072250072f500923b", + "0x901b00900e00700700923b0090070091250072f800923b0092f700944c", + "0x92f800923b0092f800944d00701f00923b00901f00922100701b00923b", + "0x15200700723b00900e00915500700723b00900712e0072f801f01b00700e", + "0x24200923b00902500944c00700723b0092230093c900700723b009125009", + "0x1f00922100701b00923b00901b00900e00700700923b009007009125007", + "0x12e00724201f01b00700e00924200923b00924200944d00701f00923b009", + "0x44c00700723b00912500915200700723b00900e00915500700723b009007", + "0x23b0091fd00900e00700700923b00900700912500730700923b009018009", + "0xe00930700923b00930700944d00701100923b0090110092210071fd009", + "0x22100700900923b00900900900e00700723b0090070ea0073070111fd007", + "0x90fd0071db0111fd12523b00912e00912e38700712e00923b00912e009", + "0x23b0091fd00900e00700723b00900712e00701800949e22300923b12e1db", + "0x1f01b12523b0090111fd12e15800701100923b0090110092210071fd009", + "0x15100700723b00900712e00702500949f02000923b12e0150090fd007015", + "0x902600910100722c02612e23b00902300910700702300923b009223009", + "0x15100722900923b00923c00910400723c00923b00922c00910200700723b", + "0x902e00910100703002e12e23b00902c00910700702c00923b009020009", + "0x15300703100923b00922500910400722500923b00903000910200700723b", + "0x23b00903100915300700723b00904500915500703304512e23b009229009", + "0x16300721900923b00903300916300700723b00922100915500703622112e", + "0x903a00902e00703a00923b00903821912e14f00703800923b009036009", + "0x700723b00900712e00703b0094a000723b12e03a00910600703a00923b", + "0x23b00904100943100714804314504114103e03c12622323b009125009369", + "0x701b00923b00901b00900e00700700923b00900700912500704904712e", + "0x15204c15000e23b00904901f01b00700e43200701f00923b00901f009221", + "0x1a800700723b00900712e0071570094a115500923b12e1530090cf007153", + "0x5700915500705715905412523b00905200924600705200923b009155009", + "0x705a00923b00905815912e14f00705800923b00900714300700723b009", + "0x712e00715d0094a200723b12e05a00910600705a00923b00905a00902e", + "0x704c00923b00904c00900e00715000923b00915000912500700723b009", + "0x4c15000e43500705400923b00905400943400715200923b009152009221", + "0x640094a316000923b12e15f00943600715f06015e05d00e23b009054152", + "0x23b00916100943900716100923b00916000943800700723b00900712e007", + "0x944400716400923b00900716c00700723b00916200943b00706716212e", + "0x23b00916800943b00716b16812e23b00916600943900716600923b009164", + "0x12e43d00716b00923b00916b00943c00706700923b00906700943c007007", + "0x712e00706f0094a406e00923b12e06d00914000706d00923b00916b067", + "0x937000700723b00900e00915500700723b00906e00905400700723b009", + "0x37400700723b00904300937300700723b00914800937200700723b009126", + "0x700723b00914100937600700723b00904700937500700723b009145009", + "0x7100923b00900722900700723b00903c00937100700723b00903e009377", + "0x16e07112e03000716e00923b00916e00902e00716e00923b0090074a5007", + "0x17400923b00907207412e03100707400923b00900722500707200923b009", + "0x15e00900e00705d00923b00905d00912500707600923b00917400944c007", + "0x7600923b00907600944d00706000923b00906000922100715e00923b009", + "0x700723b00906f00905400700723b00900712e00707606015e05d00e009", + "0x906000922100707700923b00915e00900e00718000923b00905d009125", + "0x900e00915500700723b00900712e0070074a60090070ee00707800923b", + "0x4300937300700723b00914800937200700723b00912600937000700723b", + "0x937600700723b00904700937500700723b00914500937400700723b009", + "0x44c00700723b00903c00937100700723b00903e00937700700723b009141", + "0x23b00915e00900e00705d00923b00905d00912500718600923b009064009", + "0xe00918600923b00918600944d00706000923b00906000922100715e009", + "0x934f00700723b00915d00911100700723b00900712e00718606015e05d", + "0x7700923b00904c00900e00718000923b00915000912500700723b009054", + "0x914804314504714103e03c12622314800707800923b009152009221007", + "0x43100709209109008f08e07f08d18722323b00907b00936900707b00923b", + "0x9709609500e23b00909407807718000e43200709409312e23b00908f009", + "0x1a800700723b00900712e0071a50094a709900923b12e0980090cf007098", + "0x3700915500705b0371a712523b00909c00924600709c00923b009099009", + "0xe00709500923b00909500912500700723b00905b00915500700723b009", + "0x23b0091a700943400709700923b00909700922100709600923b009096009", + "0x1b20094360071b21b01ac09f00e23b0091a709709609500e4350071a7009", + "0x923b0090a300943800700723b00900712e00704a0094a80a300923b12e", + "0x943a0070a900923b00900716c0070a71b512e23b0090a50094390070a5", + "0x23b0090ac00943b0070ae0ac12e23b0091b80094390071b800923b0090a9", + "0x12e43d0070ae00923b0090ae00943c0070a700923b0090a700943c007007", + "0x712e0070b20094a90b000923b12e1bc0091400071bc00923b0090ae0a7", + "0x714c0071bd00923b00900743f00700723b0090b000905400700723b009", + "0x923b0090b60b41bd1254400070b600923b00900714c0070b400923b009", + "0x92210071ac00923b0091ac00900e00709f00923b00909f0091250071bb", + "0x931b01ac09f1fd4410071bb00923b0091bb0091a10071b000923b0091b0", + "0x71b90094aa0be00923b12e0bc0094420070bc1ba0ba0b800e23b0091bb", + "0x23b0090c000943b0070c20c012e23b0091b500943900700723b00900712e", + "0xc40094390070c400923b0091b60094440071b600923b00900716c007007", + "0xc712e23b0090c200943900700723b0090c600943b0071b30c612e23b009", + "0x943b0071ad0c912e23b0091b300943900700723b0090c700943b0071b7", + "0x1ad00923b0091ad00943c0071b700923b0091b700943c00700723b0090c9", + "0x540071aa0cd12e23b0090be0094460070cb00923b0091ad1b712e445007", + "0x900712e0071a80094ab0cf00923b12e0cb00914000700723b0091aa009", + "0x1872231480071a300923b00900724500700723b0090cf00905400700723b", + "0x70b800923b0090b80091250070d100923b0090920910900cd08e07f08d", + "0xba0b81fd4480071ba00923b0091ba0092210070ba00923b0090ba00900e", + "0x94ac19b00923b12e19f0090c000719f0d51a01a100e23b0091a30d11ba", + "0x1980090540071980da12e23b00919b0092f300700723b00900712e0070d8", + "0x70dd00923b0091a000900e00719700923b0091a100912500700723b009", + "0x4ad0090070ee0070df00923b0090da0093f800718e00923b0090d5009221", + "0x23b0090d800944c00700723b00900e00915500700723b00900712e007007", + "0x2210071a000923b0091a000900e0071a100923b0091a10091250070e1009", + "0xe10d51a01a100e0090e100923b0090e100944d0070d500923b0090d5009", + "0x8e07f08d18722314800700723b0091a800905400700723b00900712e007", + "0xba00900e00719700923b0090b800912500718a00923b0090920910900cd", + "0xdf00923b00918a0093f800718e00923b0091ba0092210070dd00923b009", + "0x18e00945000718800923b0090dd00944f00718900923b00919700944e007", + "0x12e0070074ae0090070ee00718b00923b0090df0093f800718c00923b009", + "0x37200700723b00918700937000700723b00900e00915500700723b009007", + "0x700723b00909000937400700723b00909100937300700723b009092009", + "0x723b00907f00937700700723b00908e00937600700723b0091b500943b", + "0x90b80091250070e500923b0091b900944c00700723b00908d009371007", + "0x71ba00923b0091ba0092210070ba00923b0090ba00900e0070b800923b", + "0x700723b00900712e0070e51ba0ba0b800e0090e500923b0090e500944d", + "0x8e07f08d18722314800700723b0091b500943b00700723b0090b2009054", + "0x1ac00900e00718900923b00909f00912500718400923b009092091090093", + "0x18b00923b0091840093f800718c00923b0091b000922100718800923b009", + "0x4af17900923b12e0e800935f0070e80a018312523b00918c18812e35e007", + "0x90074b00070ea00923b00917900936100700723b00900712e00717b009", + "0x70ea00923b0090ea00943400718900923b00918900912500717500923b", + "0x35f0070ec17112e23b0091750ea1891254b100717500923b009175009434", + "0x918b00936900700723b00900712e00716c0094b20ee00923b12e0ec009", + "0x40b0070fa00923b0090ee00936100715c0f80f61630f31651690f022323b", + "0x23b00900e00936b0071540fa12e23b0090fa00936200715600923b009007", + "0x923b0091710091250070fd00923b00915815615412544000715800e12e", + "0x91a10070a000923b0090a000922100718300923b00918300900e007171", + "0x10210110715100e23b0090fd1630a01831711fd4410070fd00923b0090fd", + "0x944600700723b00900712e00714c0094b310400923b12e102009442007", + "0x23b00900e0fa12e4b400700723b00910600905400710614f12e23b009104", + "0x912500714e00923b00915c0f80f614f0f31651690f022314800714d009", + "0x923b00910100922100710700923b00910700900e00715100923b009151", + "0xe23b00914d14e1011071511fd4b600714d00923b00914d0094b5007101", + "0x23b00900712e00714b0094b714600923b12e1470090c000714710c10a149", + "0x716c00700723b00914400905400714410f12e23b0091460092f3007007", + "0x923b00914300946900714300923b00911110f12e46800711100923b009", + "0x922100710a00923b00910a00900e00714900923b009149009125007113", + "0x711310c10a14900e00911300923b00911300944d00710c00923b00910c", + "0x923b00914900912500714000923b00914b00944c00700723b00900712e", + "0x944d00710c00923b00910c00922100710a00923b00910a00900e007149", + "0x937000700723b00900712e00714010c10a14900e00914000923b009140", + "0x37400700723b0090f800937300700723b00915c00937200700723b0090f0", + "0x700723b0090f300937600700723b0090fa00934f00700723b0090f6009", + "0x723b00900e00915500700723b00916900937100700723b009165009377", + "0x10700900e00715100923b00915100912500711800923b00914c00944c007", + "0x11800923b00911800944d00710100923b00910100922100710700923b009", + "0x700723b00918b00915200700723b00900712e00711810110715100e009", + "0x23b00917100912500711500923b00916c00944c00700723b00900e009155", + "0x44d0070a000923b0090a000922100718300923b00918300900e007171009", + "0x15200700723b00900712e0071150a018317100e00911500923b009115009", + "0x13b00923b00917b00944c00700723b00900e00915500700723b00918b009", + "0xa000922100718300923b00918300900e00718900923b009189009125007", + "0x12e00713b0a018318900e00913b00923b00913b00944d0070a000923b009", + "0x37600700723b00918700937000700723b00900e00915500700723b009007", + "0x700723b00908d00937100700723b00907f00937700700723b00908e009", + "0x723b00909000937400700723b00909100937300700723b009092009372", + "0x909f00912500713900923b00904a00944c00700723b009093009375007", + "0x71b000923b0091b00092210071ac00923b0091ac00900e00709f00923b", + "0x700723b00900712e0071391b01ac09f00e00913900923b00913900944d", + "0x723b00908e00937600700723b00918700937000700723b00900e009155", + "0x23b00909200937200700723b00908d00937100700723b00907f009377007", + "0x909300937500700723b00909000937400700723b009091009373007007", + "0xe00709500923b00909500912500713700923b0091a500944c00700723b", + "0x23b00913700944d00709700923b00909700922100709600923b009096009", + "0x23b00914100937600700723b00900712e00713709709609500e009137009", + "0x900e00915500700723b00903c00937100700723b00903e009377007007", + "0x4300937300700723b00914800937200700723b00912600937000700723b", + "0x944c00700723b00904700937500700723b00914500937400700723b009", + "0x923b00904c00900e00715000923b00915000912500711a00923b009157", + "0x15000e00911a00923b00911a00944d00715200923b00915200922100704c", + "0xe00915500700723b00903b00911100700723b00900712e00711a15204c", + "0x73c800711c00923b00900722900700723b00912500915200700723b009", + "0x923b00912811c12e03000712800923b00912800902e00712800923b009", + "0x944c0072f300923b00912300012e03100700000923b009007225007123", + "0x923b00901b00900e00700700923b0090070091250072f400923b0092f3", + "0x700e0092f400923b0092f400944d00701f00923b00901f00922100701b", + "0x12500915200700723b00900e00915500700723b00900712e0072f401f01b", + "0x1250072f500923b00902500944c00700723b0092230093c900700723b009", + "0x23b00901f00922100701b00923b00901b00900e00700700923b009007009", + "0x900712e0072f501f01b00700e0092f500923b0092f500944d00701f009", + "0x1800944c00700723b00900e00915500700723b00912500915200700723b", + "0x1fd00923b0091fd00900e00700700923b0090070091250072f600923b009", + "0x1fd00700e0092f600923b0092f600944d00701100923b009011009221007", + "0x12e00922100700900923b00900900900e00700723b0090070ea0072f6011", + "0x12e1db0090fd0071db0111fd12523b00912e00912e38700712e00923b009", + "0x1fd00923b0091fd00900e00700723b00900712e0070180094b822300923b", + "0x701501f01b12523b0090111fd12e15800701100923b009011009221007", + "0x22300915100700723b00900712e0070250094b902000923b12e0150090fd", + "0x723b00902600910100722c02612e23b00902300910700702300923b009", + "0x2000915100722900923b00923c00910400723c00923b00922c009102007", + "0x723b00902e00910100703002e12e23b00902c00910700702c00923b009", + "0x22900915300703100923b00922500910400722500923b009030009102007", + "0x22112e23b00903100915300700723b00904500915500703304512e23b009", + "0x3600916300721900923b00903300916300700723b009221009155007036", + "0x923b00903a00902e00703a00923b00903821912e14f00703800923b009", + "0x936900700723b00900712e00703b0094ba00723b12e03a00910600703a", + "0x4712e23b00904100943100714804314504114103e03c12622323b009125", + "0x922100701b00923b00901b00900e00700700923b009007009125007049", + "0x715315204c15000e23b00904901f01b00700e43200701f00923b00901f", + "0x1550091a800700723b00900712e0071570094bb15500923b12e1530090cf", + "0x23b00915900915500705715905412523b00905200924600705200923b009", + "0x4c00900e00715000923b00915000912500700723b009057009155007007", + "0x5400923b00905400943400715200923b00915200922100704c00923b009", + "0x23b12e05d00943600705d15d05a05800e23b00905415204c15000e435007", + "0x715f00923b00915e00943800700723b00900712e0070600094bc15e009", + "0x916100943a00716100923b00900716c00706416012e23b00915f009439", + "0x700723b00906700943b00716406712e23b00916200943900716200923b", + "0x16406412e43d00716400923b00916400943c00706400923b00906400943c", + "0x23b00900712e00716b0094bd16800923b12e16600914000716600923b009", + "0x23b00900714c00706d00923b00900743f00700723b009168009054007007", + "0x707100923b00906f06e06d12544000706f00923b00900714c00706e009", + "0x915d00922100705a00923b00905a00900e00705800923b009058009125", + "0x907104715d05a0581fd44100707100923b0090710091a100715d00923b", + "0x712e0071800094be07600923b12e17400944200717407407216e00e23b", + "0x700723b00907700943b00707807712e23b00916000943900700723b009", + "0x23b00907b00943900707b00923b00918600944400718600923b00900716c", + "0x708e07f12e23b00907800943900700723b00918700943b00708d18712e", + "0x908f00943b00709008f12e23b00908d00943900700723b00907f00943b", + "0x44500709000923b00909000943c00708e00923b00908e00943c00700723b", + "0x9300905400709309212e23b00907600944600709100923b00909008e12e", + "0x723b00900712e0070950094bf09400923b12e09100914000700723b009", + "0x3e03c12622314800709600923b00900724500700723b009094009054007", + "0x900e00716e00923b00916e00912500709700923b009148043145092141", + "0x9707407216e1fd44800707400923b00907400922100707200923b009072", + "0x70370094c01a700923b12e09c0090c000709c1a509909800e23b009096", + "0x23b00909f00905400709f05b12e23b0091a70092f300700723b00900712e", + "0x92210071b000923b00909900900e0071ac00923b009098009125007007", + "0x70074c10090070ee0070a300923b00905b0093f80071b200923b0091a5", + "0x4a00923b00903700944c00700723b00900e00915500700723b00900712e", + "0x1a500922100709900923b00909900900e00709800923b009098009125007", + "0x12e00704a1a509909800e00904a00923b00904a00944d0071a500923b009", + "0x14509214103e03c12622314800700723b00909500905400700723b009007", + "0x23b00907200900e0071ac00923b00916e0091250070a500923b009148043", + "0x44e0070a300923b0090a50093f80071b200923b0090740092210071b0009", + "0x23b0091b20094500070a700923b0091b000944f0071b500923b0091ac009", + "0x900712e0070074c20090070ee0071b800923b0090a30093f80070a9009", + "0x14800937200700723b00912600937000700723b00900e00915500700723b", + "0x943b00700723b00914500937400700723b00904300937300700723b009", + "0x37100700723b00903e00937700700723b00914100937600700723b009160", + "0x923b00916e0091250070ac00923b00918000944c00700723b00903c009", + "0x944d00707400923b00907400922100707200923b00907200900e00716e", + "0x905400700723b00900712e0070ac07407216e00e0090ac00923b0090ac", + "0x14504714103e03c12622314800700723b00916000943b00700723b00916b", + "0x23b00905a00900e0071b500923b0090580091250070ae00923b009148043", + "0x35e0071b800923b0090ae0093f80070a900923b00915d0092210070a7009", + "0xb40094c31bd00923b12e0b200935f0070b20b01bc12523b0090a90a712e", + "0x923b0090074b00070b600923b0091bd00936100700723b00900712e007", + "0x94340070b600923b0090b60094340071b500923b0091b50091250071bb", + "0xba00935f0070ba0b812e23b0091bb0b61b51254b10071bb00923b0091bb", + "0x22323b0091b800936900700723b00900712e0070bc0094c41ba00923b12e", + "0x90071430070c700923b0091ba0093610071b30c60c41b60c20c01b90be", + "0xe12e23b00900e00936b0070c90c712e23b0090c70093620071b700923b", + "0x70b800923b0090b80091250070cb00923b0091ad1b70c91254400071ad", + "0x90cb0091a10070b000923b0090b00092210071bc00923b0091bc00900e", + "0x4420071a80cf1aa0cd00e23b0090cb1b60b01bc0b81fd4410070cb00923b", + "0x91a300944600700723b00900712e0070d10094c51a300923b12e1a8009", + "0xd500923b00900e0c712e4c600700723b0091a00090540071a01a112e23b", + "0x90cd00912500719f00923b0091b30c60c41a10c20c01b90be223148007", + "0x70cf00923b0090cf0092210071aa00923b0091aa00900e0070cd00923b", + "0xd819b00e23b0090d519f0cf1aa0cd1fd4c80070d500923b0090d50094c7", + "0x700723b00900712e0070dd0094c919700923b12e1980090c00071980da", + "0x23b00900716c00700723b0090df0090540070df18e12e23b0091970092f3", + "0x718900923b00918a00946900718a00923b0090e118e12e4680070e1009", + "0x90da0092210070d800923b0090d800900e00719b00923b00919b009125", + "0x712e0071890da0d819b00e00918900923b00918900944d0070da00923b", + "0x719b00923b00919b00912500718800923b0090dd00944c00700723b009", + "0x918800944d0070da00923b0090da0092210070d800923b0090d800900e", + "0x90be00937000700723b00900712e0071880da0d819b00e00918800923b", + "0xc400937400700723b0090c600937300700723b0091b300937200700723b", + "0x937700700723b0090c200937600700723b0090c700934f00700723b009", + "0x44c00700723b00900e00915500700723b0091b900937100700723b0090c0", + "0x23b0091aa00900e0070cd00923b0090cd00912500718c00923b0090d1009", + "0xe00918c00923b00918c00944d0070cf00923b0090cf0092210071aa009", + "0x915500700723b0091b800915200700723b00900712e00718c0cf1aa0cd", + "0xb800923b0090b800912500718b00923b0090bc00944c00700723b00900e", + "0x18b00944d0070b000923b0090b00092210071bc00923b0091bc00900e007", + "0x1b800915200700723b00900712e00718b0b01bc0b800e00918b00923b009", + "0x1250070e500923b0090b400944c00700723b00900e00915500700723b009", + "0x23b0090b00092210071bc00923b0091bc00900e0071b500923b0091b5009", + "0x900712e0070e50b01bc1b500e0090e500923b0090e500944d0070b0009", + "0x14100937600700723b00912600937000700723b00900e00915500700723b", + "0x937200700723b00903c00937100700723b00903e00937700700723b009", + "0x37500700723b00914500937400700723b00904300937300700723b009148", + "0x923b00905800912500718400923b00906000944c00700723b009047009", + "0x944d00715d00923b00915d00922100705a00923b00905a00900e007058", + "0x915500700723b00900712e00718415d05a05800e00918400923b009184", + "0x37700700723b00914100937600700723b00912600937000700723b00900e", + "0x700723b00914800937200700723b00903c00937100700723b00903e009", + "0x723b00904700937500700723b00914500937400700723b009043009373", + "0x4c00900e00715000923b00915000912500718300923b00915700944c007", + "0x18300923b00918300944d00715200923b00915200922100704c00923b009", + "0x700723b00903b00911100700723b00900712e00718315204c15000e009", + "0xa000923b00900722900700723b00912500915200700723b00900e009155", + "0xe80a012e0300070e800923b0090e800902e0070e800923b0090073c8007", + "0xea00923b00917917b12e03100717b00923b00900722500717900923b009", + "0x1b00900e00700700923b00900700912500717500923b0090ea00944c007", + "0x17500923b00917500944d00701f00923b00901f00922100701b00923b009", + "0x700723b00900e00915500700723b00900712e00717501f01b00700e009", + "0x923b00902500944c00700723b0092230093c900700723b009125009152", + "0x922100701b00923b00901b00900e00700700923b009007009125007171", + "0x717101f01b00700e00917100923b00917100944d00701f00923b00901f", + "0x700723b00912500915200700723b00900e00915500700723b00900712e", + "0x91fd00900e00700700923b0090070091250070ec00923b00901800944c", + "0x90ec00923b0090ec00944d00701100923b0090110092210071fd00923b", + "0x71db00923b00900742b0071fd00923b0090070710070ec0111fd00700e", + "0x700900923b00900900900e00700723b0090070ea00700723b009007160", + "0xfd00701b01822312523b00912e00912e38700712e00923b00912e009221", + "0x922300900e00700723b00900712e0070150094ca01f00923b12e01b009", + "0x2012523b00901822312e15800701800923b00901800922100722300923b", + "0x700723b00900712e00722c0094cb02600923b12e0230090fd007023025", + "0x22900910100702c22912e23b00923c00910700723c00923b00901f009151", + "0x703000923b00902e00910400702e00923b00902c00910200700723b009", + "0x3100910100704503112e23b00922500910700722500923b009026009151", + "0x722100923b00903300910400703300923b00904500910200700723b009", + "0x922100915300700723b00903600915500721903612e23b009030009153", + "0x703b00923b00921900916300700723b00903800915500703a03812e23b", + "0x3c00902e00703c00923b00912603b12e14f00712600923b00903a009163", + "0x723b00900712e00703e0094cc00723b12e03c00910600703c00923b009", + "0x914800943100715004904714804314504114122323b009125009369007", + "0x2000923b00902000900e00700700923b00900700912500715204c12e23b", + "0x15515300e23b00915202502000700e43200702500923b009025009221007", + "0x700723b00900712e0071590094cd05400923b12e0520090cf007052157", + "0x915500700e05a05812523b00905700924600705700923b0090540091a8", + "0x15500923b00915500900e00715300923b00915300912500700723b00905a", + "0x15300e43500705800923b00905800943400715700923b009157009221007", + "0x700e00923b00900e1fd12e07400706015e05d15d00e23b009058157155", + "0x15f00943800700723b00900712e0071600094ce15f00923b12e060009436", + "0x723b00916100943b00716216112e23b00906400943900706400923b009", + "0x916400943900716400923b0090670094cf00706700923b00900716c007", + "0x716200923b00916200943c00700723b00916600943b00716816612e23b", + "0x16b00914000716b00923b00916816212e43d00716800923b00916800943c", + "0x723b00906d00905400700723b00900712e00706e0094d006d00923b12e", + "0x23b00915000937200700723b0091db00944b00700723b00900e009155007", + "0x904c00937500700723b00904700937400700723b009049009373007007", + "0x4100937100700723b00914500937700700723b00904300937600700723b", + "0x74d100706f00923b00900722900700723b00914100937000700723b009", + "0x923b00907106f12e03000707100923b00907100902e00707100923b009", + "0x944c00707400923b00916e07212e03100707200923b00900722500716e", + "0x923b00905d00900e00715d00923b00915d00912500717400923b009074", + "0x15d00e00917400923b00917400944d00715e00923b00915e00922100705d", + "0x14122314800700723b00906e00905400700723b00900712e00717415e05d", + "0x7718022323b00907600936900707600923b00915004904704c043145041", + "0x923b00905d00900e00708e00923b00900702500707f08d18707b186078", + "0xe45200708e00923b00908e00902600715e00923b00915e00922100705d", + "0x94d209200923b12e09100924400709109008f12523b00908e07f15e05d", + "0x23b00908f00900e00709400923b00900702500700723b00900712e007093", + "0x45400709400923b00909400902600709000923b00909000922100708f009", + "0x4d309800923b12e09700945500709709609512523b00909408d09008f00e", + "0x905400709c1a512e23b00909200945700700723b00900712e007099009", + "0x723b0090370090540070371a712e23b00909800945800700723b00909c", + "0x905b00936900705b00923b0091a51a718707b186078077180223148007", + "0x70a90a712e23b0091ac0093d10071b50a504a0a31b21b01ac09f22323b", + "0x960951253d200709600923b00909600922100709500923b00909500900e", + "0x12e0071bc0094d401100923b12e0ae00907b0070ae0ac1b812523b0090a9", + "0xac00923b0090ac0092210071b800923b0091b800900e00700723b009007", + "0xe45a0070b000923b0090b000902e0070b000e12e23b00900e00936b007", + "0x701100923b0090111db12e45b0070b41bd0b212523b0090b00a70ac1b8", + "0xb600945e00700723b00900712e0071bb0094d50b600923b12e0b400945c", + "0xe12e23b00900e00936b00700723b0090ba0090540070ba0b812e23b009", + "0x1b50a504a0a31b21b00b809f2231480070bc00923b0091ba0094d60071ba", + "0xb200923b0090b200900e00715d00923b00915d0091250070be00923b009", + "0x15d1fd4d80070bc00923b0090bc0094d70071bd00923b0091bd009221007", + "0x4d90c400923b12e1b60090c00071b60c20c01b900e23b0090bc0be1bd0b2", + "0xc40092f30071b300923b00901100918700700723b00900712e0070c6009", + "0xc900923b0091b300946300700723b0091b70090540071b70c712e23b009", + "0xc20092210070c000923b0090c000900e0071b900923b0091b9009125007", + "0xc90c70c20c01b91fd4650070c900923b0090c90094640070c200923b009", + "0x12e0071a80094da0cf00923b12e1aa0090c00071aa0cd0cb1ad00e23b009", + "0x723b0090d10090540070d11a312e23b0090cf0092f300700723b009007", + "0xcb00900e0071ad00923b0091ad0091250071a100923b00900e0093f4007", + "0x1a100923b0091a10093f50070cd00923b0090cd0092210070cb00923b009", + "0x12e19b0090c000719b19f0d51a000e23b0091a11a30cd0cb1ad1fd3f6007", + "0x19812e23b0090d80092f300700723b00900712e0070da0094db0d800923b", + "0x18a0e10df18e0dd22323b00919800936900700723b009197009054007197", + "0x714c0070e500923b00900714c00718b00923b00900743f00718c188189", + "0x23b0091a000912500718300923b0091840e518b12544000718400923b009", + "0x1a100719f00923b00919f0092210070d500923b0090d500900e0071a0009", + "0x1790e80a000e23b00918318a19f0d51a01fd44100718300923b009183009", + "0x44600700723b00900712e0071750094dc0ea00923b12e17b00944200717b", + "0x923b00900716c00700723b0090ec0090540070ec17112e23b0090ea009", + "0x16c12e46800716c00923b00918c1881891710e10df18e0dd2231480070ee", + "0x923b0090a000912500716900923b0090f00094690070f000923b0090ee", + "0x944d00717900923b0091790092210070e800923b0090e800900e0070a0", + "0x937000700723b00900712e0071691790e80a000e00916900923b009169", + "0x37400700723b00918800937300700723b00918c00937200700723b0090dd", + "0x700723b0090e100937600700723b00918e00937100700723b009189009", + "0x23b0090a000912500716500923b00917500944c00700723b0090df009377", + "0x44d00717900923b0091790092210070e800923b0090e800900e0070a0009", + "0x44c00700723b00900712e0071651790e80a000e00916500923b009165009", + "0x23b0090d500900e0071a000923b0091a00091250070f300923b0090da009", + "0xe0090f300923b0090f300944d00719f00923b00919f0092210070d5009", + "0x944c00700723b00900e00915500700723b00900712e0070f319f0d51a0", + "0x923b0090cb00900e0071ad00923b0091ad00912500716300923b0091a8", + "0x1ad00e00916300923b00916300944d0070cd00923b0090cd0092210070cb", + "0x1100924300700723b00900e00915500700723b00900712e0071630cd0cb", + "0x71b900923b0091b90091250070f600923b0090c600944c00700723b009", + "0x90f600944d0070c200923b0090c20092210070c000923b0090c000900e", + "0x900e00915500700723b00900712e0070f60c20c01b900e0090f600923b", + "0x1b500937200700723b00909f00937000700723b00901100924300700723b", + "0x937500700723b00904a00937400700723b0090a500937300700723b009", + "0x44c00700723b0091b000937700700723b0091b200937600700723b0090a3", + "0x23b0090b200900e00715d00923b00915d0091250070f800923b0091bb009", + "0xe0090f800923b0090f800944d0071bd00923b0091bd0092210070b2009", + "0x937000700723b00900e00915500700723b00900712e0070f81bd0b215d", + "0x37200700723b0091b200937600700723b0091b000937700700723b00909f", + "0x700723b00904a00937400700723b0090a500937300700723b0091b5009", + "0x723b0091db00944b00700723b0090a700937100700723b0090a3009375", + "0x1b800900e00715d00923b00915d00912500715c00923b0091bc00944c007", + "0x15c00923b00915c00944d0070ac00923b0090ac0092210071b800923b009", + "0x700723b00900e00915500700723b00900712e00715c0ac1b815d00e009", + "0x723b00918000937000700723b00909200946a00700723b0091db00944b", + "0x23b00918600937600700723b00907b00937500700723b009187009374007", + "0x909900944c00700723b00907700937100700723b009078009377007007", + "0x709500923b00909500900e00715d00923b00915d0091250070fa00923b", + "0x9609515d00e0090fa00923b0090fa00944d00709600923b009096009221", + "0x23b0091db00944b00700723b00900e00915500700723b00900712e0070fa", + "0x918000937000700723b00907800937700700723b009077009371007007", + "0x18600937600700723b00907b00937500700723b00918700937400700723b", + "0x12500715600923b00909300944c00700723b00908d00937300700723b009", + "0x23b00909000922100708f00923b00908f00900e00715d00923b00915d009", + "0x900712e00715609008f15d00e00915600923b00915600944d007090009", + "0x15000937200700723b0091db00944b00700723b00900e00915500700723b", + "0x937500700723b00904700937400700723b00904900937300700723b009", + "0x37100700723b00914500937700700723b00904300937600700723b00904c", + "0x15400923b00916000944c00700723b00914100937000700723b009041009", + "0x15e00922100705d00923b00905d00900e00715d00923b00915d009125007", + "0x12e00715415e05d15d00e00915400923b00915400944d00715e00923b009", + "0x37000700723b00904100937100700723b00914500937700700723b009007", + "0x700723b00915000937200700723b0091db00944b00700723b009141009", + "0x723b00904c00937500700723b00904700937400700723b009049009373", + "0x23b00915900944c00700723b0091fd00907f00700723b009043009376007", + "0x22100715500923b00915500900e00715300923b009153009125007158009", + "0x15815715515300e00915800923b00915800944d00715700923b009157009", + "0x723b0091fd00907f00700723b00903e00911100700723b00900712e007", + "0x923b00900722900700723b00912500915200700723b0091db00944b007", + "0xfd12e03000715100923b00915100902e00715100923b0090073c80070fd", + "0x923b00910710112e03100710100923b00900722500710700923b009151", + "0x900e00700700923b00900700912500710400923b00910200944c007102", + "0x923b00910400944d00702500923b00902500922100702000923b009020", + "0x723b0091fd00907f00700723b00900712e00710402502000700e009104", + "0x23b00901f0093c900700723b00912500915200700723b0091db00944b007", + "0x900e00700700923b00900700912500714c00923b00922c00944c007007", + "0x923b00914c00944d00702500923b00902500922100702000923b009020", + "0x723b00912500915200700723b00900712e00714c02502000700e00914c", + "0x23b00901500944c00700723b0091db00944b00700723b0091fd00907f007", + "0x22100722300923b00922300900e00700700923b00900700912500714f009", + "0x14f01822300700e00914f00923b00914f00944d00701800923b009018009", + "0x23b00912e00922100700900923b00900900900e00700723b0090070ea007", + "0x923b12e0110090fd0070111fd00e12523b00912e00912e38700712e009", + "0x22100700e00923b00900e00900e00700723b00900712e0072230094dd1db", + "0x90fd00701f01b01812523b0091fd00e12e1580071fd00923b0091fd009", + "0x23b0091db00915100700723b00900712e0070200094de01500923b12e01f", + "0x10200700723b00902300910100702602312e23b009025009107007025009", + "0x23b00901500915100723c00923b00922c00910400722c00923b009026009", + "0x10200700723b00902c00910100702e02c12e23b009229009107007229009", + "0x23b00923c00915300722500923b00903000910400703000923b00902e009", + "0x722103312e23b00922500915300700723b00903100915500704503112e", + "0x23b00922100916300703600923b00904500916300700723b009033009155", + "0x703800923b00903800902e00703800923b00921903612e14f007219009", + "0x912500936900700723b00900712e00703a0094df00723b12e038009106", + "0x704714812e23b00914100943100704314504114103e03c12603b22323b", + "0x901b00922100701800923b00901800900e00700700923b009007009125", + "0x90cf00715204c15004900e23b00904701b01800700e43200701b00923b", + "0x23b0091530091a800700723b00900712e0071550094e015300923b12e152", + "0x700723b00905400915500715905405212523b009157009246007157009", + "0x904c00922100715000923b00915000900e00704900923b009049009125", + "0x23b00905204c15004900e43500705200923b00905200943400704c00923b", + "0x900712e00715e0094e105d00923b12e15d00943600715d05a05805700e", + "0x716015f12e23b00906000943900706000923b00905d00943800700723b", + "0x923b0090640094cf00706400923b00900716c00700723b00915f00943b", + "0x943c00700723b00916200943b00706716212e23b009161009439007161", + "0x23b00906716012e43d00706700923b00906700943c00716000923b009160", + "0x700723b00900712e0071680094e216600923b12e164009140007164009", + "0x723b00904300937200700723b00915900915500700723b009166009054", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x912600937100700723b00903c00937700700723b00903e009376007007", + "0x90074d100716b00923b00900722900700723b00903b00937000700723b", + "0x6e00923b00906d16b12e03000706d00923b00906d00902e00706d00923b", + "0x7100944c00707100923b00906e06f12e03100706f00923b009007225007", + "0x5800923b00905800900e00705700923b00905700912500716e00923b009", + "0x5805700e00916e00923b00916e00944d00705a00923b00905a009221007", + "0x12603b22314800700723b00916800905400700723b00900712e00716e05a", + "0x7617407422323b00907200936900707200923b00904314504114803e03c", + "0x5800923b00905800900e00718700923b00900702500707b186078077180", + "0x5800e45200718700923b00918700902600705a00923b00905a009221007", + "0x900094e308f00923b12e08e00924400708e07f08d12523b00918707b05a", + "0x923b00908d00900e00709100923b00900702500700723b00900712e007", + "0xe45400709100923b00909100902600707f00923b00907f00922100708d", + "0x94e409500923b12e09400945500709409309212523b00909118607f08d", + "0x9800905400709809712e23b00908f00945700700723b00900712e007096", + "0x700723b0091a50090540071a509912e23b00909500945800700723b009", + "0x23b00909c00936900709c00923b009097099078077180076174074223148", + "0x922100709200923b00909200900e0070a31b21b01ac09f05b0371a7223", + "0x23b00904a00902e00704a15912e23b00915900936b00709300923b009093", + "0x12e0a700947d0070a71b50a512523b00904a05b09309200e47c00704a009", + "0xac12e23b0090a900947f00700723b00900712e0071b80094e50a900923b", + "0x1a72231480071bc00923b0091590094e600700723b0090ae0090540070ae", + "0x705700923b0090570091250070b000923b0090a31b21b01ac09f0ac037", + "0x91bc0094e70071b500923b0091b50092210070a500923b0090a500900e", + "0xc00070b60b41bd0b200e23b0091bc0b01b50a50571fd4e80071bc00923b", + "0x91bb0092f300700723b00900712e0070b80094e91bb00923b12e0b6009", + "0xbe0bc22323b0090ba00936900700723b0091ba0090540071ba0ba12e23b", + "0xc700923b00900714c0071b300923b00900743f0070c60c41b60c20c01b9", + "0x91250070c900923b0091b70c71b31254400071b700923b00900714c007", + "0x923b0090b40092210071bd00923b0091bd00900e0070b200923b0090b2", + "0xe23b0090c90c20b41bd0b21fd4410070c900923b0090c90091a10070b4", + "0x23b00900712e0071a80094ea0cf00923b12e1aa0094420071aa0cd0cb1ad", + "0x716c00700723b0090d10090540070d11a312e23b0090cf009446007007", + "0x71a000923b0090c60c41b61a30c01b90be0bc2231480071a100923b009", + "0x1ad00912500719f00923b0090d50094690070d500923b0091a11a012e468", + "0xcd00923b0090cd0092210070cb00923b0090cb00900e0071ad00923b009", + "0x723b00900712e00719f0cd0cb1ad00e00919f00923b00919f00944d007", + "0x23b0090c400937300700723b0090c600937200700723b0090bc009370007", + "0x90c000937600700723b0090be00937100700723b0091b6009374007007", + "0x912500719b00923b0091a800944c00700723b0091b900937700700723b", + "0x923b0090cd0092210070cb00923b0090cb00900e0071ad00923b0091ad", + "0x23b00900712e00719b0cd0cb1ad00e00919b00923b00919b00944d0070cd", + "0x900e0070b200923b0090b20091250070d800923b0090b800944c007007", + "0x923b0090d800944d0070b400923b0090b40092210071bd00923b0091bd", + "0x723b0091a700937000700723b00900712e0070d80b41bd0b200e0090d8", + "0x23b0091b000937400700723b0091b200937300700723b0090a3009372007", + "0x915900915500700723b00909f00937600700723b0091ac009375007007", + "0x91250070da00923b0091b800944c00700723b00903700937100700723b", + "0x923b0091b50092210070a500923b0090a500900e00705700923b009057", + "0x23b00900712e0070da1b50a505700e0090da00923b0090da00944d0071b5", + "0x907400937000700723b00908f00946a00700723b009159009155007007", + "0x18000937600700723b00907700937500700723b00907800937400700723b", + "0x944c00700723b00917400937100700723b00907600937700700723b009", + "0x923b00909200900e00705700923b00905700912500719800923b009096", + "0x5700e00919800923b00919800944d00709300923b009093009221007092", + "0x17400937100700723b00907600937700700723b00900712e007198093092", + "0x937400700723b00907400937000700723b00915900915500700723b009", + "0x37300700723b00918000937600700723b00907700937500700723b009078", + "0x923b00905700912500719700923b00909000944c00700723b009186009", + "0x944d00707f00923b00907f00922100708d00923b00908d00900e007057", + "0x915500700723b00900712e00719707f08d05700e00919700923b009197", + "0x37400700723b00914500937300700723b00904300937200700723b009159", + "0x700723b00903e00937600700723b00914800937500700723b009041009", + "0x723b00903b00937000700723b00912600937100700723b00903c009377", + "0x5800900e00705700923b0090570091250070dd00923b00915e00944c007", + "0xdd00923b0090dd00944d00705a00923b00905a00922100705800923b009", + "0x700723b00903c00937700700723b00900712e0070dd05a05805700e009", + "0x723b00904300937200700723b00903b00937000700723b009126009371", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x4900912500718e00923b00915500944c00700723b00903e009376007007", + "0x4c00923b00904c00922100715000923b00915000900e00704900923b009", + "0x723b00900712e00718e04c15004900e00918e00923b00918e00944d007", + "0x923b00900722900700723b00912500915200700723b00903a009111007", + "0xdf12e0300070e100923b0090e100902e0070e100923b0090073c80070df", + "0x923b00918a18912e03100718900923b00900722500718a00923b0090e1", + "0x900e00700700923b00900700912500718c00923b00918800944c007188", + "0x923b00918c00944d00701b00923b00901b00922100701800923b009018", + "0x723b00912500915200700723b00900712e00718c01b01800700e00918c", + "0x900700912500718b00923b00902000944c00700723b0091db0093c9007", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b00900712e00718b01b01800700e00918b00923b00918b00944d", + "0x23b0090070091250070e500923b00922300944c00700723b009125009152", + "0x44d0071fd00923b0091fd00922100700e00923b00900e00900e007007009", + "0xe00700723b0090070ea0070e51fd00e00700e0090e500923b0090e5009", + "0x912e00912e38700712e00923b00912e00922100700900923b009009009", + "0x900712e0072230094eb1db00923b12e0110090fd0070111fd00e12523b", + "0x1580071fd00923b0091fd00922100700e00923b00900e00900e00700723b", + "0x200094ec01500923b12e01f0090fd00701f01b01812523b0091fd00e12e", + "0x23b00902500910700702500923b0091db00915100700723b00900712e007", + "0x10400722c00923b00902600910200700723b00902300910100702602312e", + "0x23b00922900910700722900923b00901500915100723c00923b00922c009", + "0x10400703000923b00902e00910200700723b00902c00910100702e02c12e", + "0x903100915500704503112e23b00923c00915300722500923b009030009", + "0x16300700723b00903300915500722103312e23b00922500915300700723b", + "0x921903612e14f00721900923b00922100916300703600923b009045009", + "0x94ed00723b12e03800910600703800923b00903800902e00703800923b", + "0x4114103e03c12603b22323b00912500936900700723b00900712e00703a", + "0x700700923b00900700912500704714812e23b009141009431007043145", + "0x1800700e43200701b00923b00901b00922100701800923b00901800900e", + "0x1550094ee15300923b12e1520090cf00715204c15004900e23b00904701b", + "0x23b00915700924600715700923b0091530091a800700723b00900712e007", + "0x12500700723b00915900915500700723b009054009155007159054052125", + "0x23b00904c00922100715000923b00915000900e00704900923b009049009", + "0xe23b00905204c15004900e43500705200923b00905200943400704c009", + "0x23b00900712e00715e0094ef05d00923b12e15d00943600715d05a058057", + "0x43b00716015f12e23b00906000943900706000923b00905d009438007007", + "0x16100923b00906400943a00706400923b00900716c00700723b00915f009", + "0x16000943900700723b00916200943b00706716212e23b009161009439007", + "0x16812e23b00906700943900700723b00916400943b00716616412e23b009", + "0x16b00943c00716600923b00916600943c00700723b00916800943b00716b", + "0x923b00906d00936e00706d00923b00916b16612e44500716b00923b009", + "0x710094f006f00923b12e06e00914000706e00923b00906e0090a500706e", + "0x723b00904300937200700723b00906f00905400700723b00900712e007", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x912600937100700723b00903c00937700700723b00903e009376007007", + "0x90074d100716e00923b00900722900700723b00903b00937000700723b", + "0x7400923b00907216e12e03000707200923b00907200902e00707200923b", + "0x7600944c00707600923b00907417412e03100717400923b009007225007", + "0x5800923b00905800900e00705700923b00905700912500718000923b009", + "0x5805700e00918000923b00918000944d00705a00923b00905a009221007", + "0x12603b22314800700723b00907100905400700723b00900712e00718005a", + "0x7b18607822323b00907700936900707700923b00904314504114803e03c", + "0x23b00905700912500709109012e23b00908d00943100708f08e07f08d187", + "0x43200705a00923b00905a00922100705800923b00905800900e007057009", + "0x9600923b12e0950090cf00709509409309200e23b00909105a05805700e", + "0x924600709800923b0090960091a800700723b00900712e0070970094f1", + "0x23b00909c00915500700723b0091a500915500709c1a509912523b009098", + "0x922100709300923b00909300900e00709200923b009092009125007007", + "0x9909409309200e43500709900923b00909900943400709400923b009094", + "0x12e0071b00094f21ac00923b12e09f00943600709f05b0371a700e23b009", + "0xa312e23b0091b20094390071b200923b0091ac00943800700723b009007", + "0x1b50094390071b500923b0090a500943a0070a500923b00900716c00704a", + "0x4a00923b00904a00943c00700723b0090a700943b0070a90a712e23b009", + "0x91400071b800923b0090a904a12e43d0070a900923b0090a900943c007", + "0x23b0090ac00905400700723b00900712e0070ae0094f30ac00923b12e1b8", + "0x23b00900714c0070b000923b00900714c0071bc00923b00900743f007007", + "0x1a700923b0091a70091250071bd00923b0090b20b01bc1254400070b2009", + "0x1bd0091a100705b00923b00905b00922100703700923b00903700900e007", + "0x70b81bb0b60b400e23b0091bd09005b0371a71fd4410071bd00923b009", + "0xa300943900700723b00900712e0071ba0094f40ba00923b12e0b8009442", + "0x71b900923b00900716c00700723b0090bc00943b0070be0bc12e23b009", + "0xc200943b0071b60c212e23b0090c00094390070c000923b0091b9009444", + "0x700723b0090c400943b0070c60c412e23b0090be00943900700723b009", + "0x90c600943c00700723b0091b300943b0070c71b312e23b0091b6009439", + "0x1b700923b0090c70c612e4450070c700923b0090c700943c0070c600923b", + "0x1b700914000700723b0091ad0090540071ad0c912e23b0090ba009446007", + "0x723b0090cb00905400700723b00900712e0070cd0094f50cb00923b12e", + "0x23b00908f08e07f0c918707b1860782231480071aa00923b009007245007", + "0x2210070b600923b0090b600900e0070b400923b0090b40091250070cf009", + "0xd11a31a800e23b0091aa0cf1bb0b60b41fd4480071bb00923b0091bb009", + "0x2f300700723b00900712e0070d50094f61a000923b12e1a10090c00071a1", + "0x23b0091a800912500700723b00919b00905400719b19f12e23b0091a0009", + "0x3f800719800923b0090d10092210070da00923b0091a300900e0070d8009", + "0x44c00700723b00900712e0070074f70090070ee00719700923b00919f009", + "0x23b0091a300900e0071a800923b0091a80091250070dd00923b0090d5009", + "0xe0090dd00923b0090dd00944d0070d100923b0090d10092210071a3009", + "0x22314800700723b0090cd00905400700723b00900712e0070dd0d11a31a8", + "0xd800923b0090b400912500718e00923b00908f08e07f0c918707b186078", + "0x18e0093f800719800923b0091bb0092210070da00923b0090b600900e007", + "0xe100923b0090da00944f0070df00923b0090d800944e00719700923b009", + "0x90070ee00718900923b0091970093f800718a00923b009198009450007", + "0x908f00937200700723b00907800937000700723b00900712e0070074f8", + "0xa300943b00700723b00907f00937400700723b00908e00937300700723b", + "0x937100700723b00907b00937700700723b00918700937600700723b009", + "0xb400923b0090b400912500718800923b0091ba00944c00700723b009186", + "0x18800944d0071bb00923b0091bb0092210070b600923b0090b600900e007", + "0xae00905400700723b00900712e0071881bb0b60b400e00918800923b009", + "0x8e07f09018707b18607822314800700723b0090a300943b00700723b009", + "0x923b00903700900e0070df00923b0091a700912500718c00923b00908f", + "0x936900718900923b00918c0093f800718a00923b00905b0092210070e1", + "0x70ea00923b00900702500717b1790e80a01831840e518b22323b009189", + "0xec17117512523b0090ea17b18a0e100e4520070ea00923b0090ea009026", + "0x702500700723b00900712e00716c0094f90ee00923b12e0ec009244007", + "0x17100923b00917100922100717500923b00917500900e0070f000923b009", + "0x16516912523b0090f017917117500e4540070f000923b0090f0009026007", + "0x45700700723b00900712e0070f60094fa16300923b12e0f30094550070f3", + "0x23b00916300945800700723b00915c00905400715c0f812e23b0090ee009", + "0xfa0e80a01831840e518b22314800700723b0091560090540071560fa12e", + "0x923b00915815412e46800715800923b00900716c00715400923b0090f8", + "0x900e0070df00923b0090df00912500715100923b0090fd0094690070fd", + "0x923b00915100944d00716500923b00916500922100716900923b009169", + "0x723b0090ee00946a00700723b00900712e0071511651690df00e009151", + "0x23b0090a000937500700723b0090e800937400700723b00918b009370007", + "0x90e500937100700723b00918400937700700723b009183009376007007", + "0xe0070df00923b0090df00912500710700923b0090f600944c00700723b", + "0x23b00910700944d00716500923b00916500922100716900923b009169009", + "0x23b0090e500937100700723b00900712e0071071651690df00e009107009", + "0x90e800937400700723b00918b00937000700723b009184009377007007", + "0x17900937300700723b00918300937600700723b0090a000937500700723b", + "0x70df00923b0090df00912500710100923b00916c00944c00700723b009", + "0x910100944d00717100923b00917100922100717500923b00917500900e", + "0x907800937000700723b00900712e0071011711750df00e00910100923b", + "0x18600937100700723b00907b00937700700723b00918700937600700723b", + "0x937400700723b00908e00937300700723b00908f00937200700723b009", + "0x710200923b0091b000944c00700723b00909000937500700723b00907f", + "0x905b00922100703700923b00903700900e0071a700923b0091a7009125", + "0x712e00710205b0371a700e00910200923b00910200944d00705b00923b", + "0x937700700723b00918700937600700723b00907800937000700723b009", + "0x37300700723b00908f00937200700723b00918600937100700723b00907b", + "0x700723b00909000937500700723b00907f00937400700723b00908e009", + "0x909300900e00709200923b00909200912500710400923b00909700944c", + "0x910400923b00910400944d00709400923b00909400922100709300923b", + "0x37300700723b00904300937200700723b00900712e00710409409309200e", + "0x700723b00914800937500700723b00904100937400700723b009145009", + "0x723b00912600937100700723b00903c00937700700723b00903e009376", + "0x905700912500714c00923b00915e00944c00700723b00903b009370007", + "0x705a00923b00905a00922100705800923b00905800900e00705700923b", + "0x700723b00900712e00714c05a05805700e00914c00923b00914c00944d", + "0x723b00903b00937000700723b00912600937100700723b00903c009377", + "0x23b00904100937400700723b00914500937300700723b009043009372007", + "0x915500944c00700723b00903e00937600700723b009148009375007007", + "0x715000923b00915000900e00704900923b00904900912500714f00923b", + "0x4c15004900e00914f00923b00914f00944d00704c00923b00904c009221", + "0x23b00912500915200700723b00903a00911100700723b00900712e00714f", + "0x914d00902e00714d00923b0090073c800710600923b009007229007007", + "0x714900923b00900722500714e00923b00914d10612e03000714d00923b", + "0x700912500710c00923b00910a00944c00710a00923b00914e14912e031", + "0x1b00923b00901b00922100701800923b00901800900e00700700923b009", + "0x723b00900712e00710c01b01800700e00910c00923b00910c00944d007", + "0x23b00902000944c00700723b0091db0093c900700723b009125009152007", + "0x22100701800923b00901800900e00700700923b009007009125007147009", + "0x14701b01800700e00914700923b00914700944d00701b00923b00901b009", + "0x923b00922300944c00700723b00912500915200700723b00900712e007", + "0x922100700e00923b00900e00900e00700700923b009007009125007146", + "0x71461fd00e00700e00914600923b00914600944d0071fd00923b0091fd", + "0x23b00912500937000701b0182231db0111fd00e12522323b00912e009369", + "0x91db00937500700723b00901100937600700723b0091fd009377007007", + "0x1b00937200700723b00901800937300700723b00922300937400700723b", + "0x700900923b00900900922100700700923b00900700900e00700723b009", + "0x4fb02500923b12e02000907b00702001501f12523b00900e0090071253d2", + "0x2600932f00702600923b00902500918700700723b00900712e007023009", + "0x1f00923b00901f00900e00723c00923b00922c00933000722c00923b009", + "0x1501f12500923c00923b00923c00933100701500923b009015009221007", + "0x901f00900e00722900923b00902300933200700723b00900712e00723c", + "0x922900923b00922900933100701500923b00901500922100701f00923b", + "0x701b0182231db0111fd00e12522323b00912e00936900722901501f125", + "0x723b00901100937600700723b00900e00937100700723b009125009370", + "0x23b00901800937300700723b00922300937400700723b0091db009375007", + "0x900922100700700923b00900700900e00700723b00901b009372007007", + "0x2000907b00702001501f12523b0091fd0090071253da00700900923b009", + "0x923b00902500918700700723b00900712e0070230094fc02500923b12e", + "0x900e00723c00923b00922c00933000722c00923b00902600932f007026", + "0x923b00923c00933100701500923b00901500922100701f00923b00901f", + "0x22900923b00902300933200700723b00900712e00723c01501f12500923c", + "0x22900933100701500923b00901500922100701f00923b00901f00900e007", + "0x111fd00e12522323b00912e00936900722901501f12500922900923b009", + "0x37700700723b00900e00937100700723b00912500937000701b0182231db", + "0x700723b00922300937400700723b0091db00937500700723b0091fd009", + "0x923b00900700900e00700723b00901b00937200700723b009018009373", + "0x1501f12523b0090110090071253de00700900923b009009009221007007", + "0x18700700723b00900712e0070230094fd02500923b12e02000907b007020", + "0x23b00922c00933000722c00923b00902600932f00702600923b009025009", + "0x33100701500923b00901500922100701f00923b00901f00900e00723c009", + "0x933200700723b00900712e00723c01501f12500923c00923b00923c009", + "0x923b00901500922100701f00923b00901f00900e00722900923b009023", + "0x23b00912500936900722901501f12500922900923b009229009331007015", + "0x1fd00937100700723b00900e00937000701f01b0182231db0111fd00e223", + "0x937400700723b0091db00937600700723b00901100937700700723b009", + "0x12500700723b00901f00937200700723b00901b00937300700723b009018", + "0x23b00912e00922100700900923b00900900900e00700700923b009007009", + "0x230090cf00702302502001500e23b00922312e00900700e43200712e009", + "0x923b0090260091a800700723b00900712e00722c0094fe02600923b12e", + "0x912500702c00923b00922900950000722900923b00923c0094ff00723c", + "0x923b00902500922100702000923b00902000900e00701500923b009015", + "0x23b00900712e00702c02502001500e00902c00923b00902c009501007025", + "0x900e00701500923b00901500912500702e00923b00922c009502007007", + "0x923b00902e00950100702500923b00902500922100702000923b009020", + "0x12e00924600712e00712e23b00900700950300702e02502001500e00902e", + "0x723b0091fd00915500700723b00900e0091550071fd00e12512523b009", + "0x912e0300071db00923b00901100950500701100923b009125009504007", + "0x23b00901800924600701800712e23b00900700950300722300923b0091db", + "0x2e00700723b00901500915500700723b00901b00934f00701501f01b125", + "0x922301f12e05200722300923b00922300915700701f00923b00901f009", + "0x2602312523b00900700924600700723b00902500905400702502012e23b", + "0x922c00902e00700723b00902600915500700723b00902300934f00722c", + "0x23c12e23b00902022c12e05200702000923b00902000915700722c00923b", + "0x700900923b00900750600700723b00900700915200722923c12e009229", + "0x912512e00912550900712500923b00900750800712e00923b009007507", + "0x23b00900700950a00700e00900900e00923b00900e0090d800700e00923b", + "0x723b00900e00950c0071fd00e12512523b00912e00950b00712e00712e", + "0x901100950e00701100923b00912500950d00700723b0091fd00950c007", + "0x712e23b00900700950a00722300923b0091db00912e0300071db00923b", + "0x50c00700723b00901b00950c00701501f01b12523b00901800950b007018", + "0x923b00902000950e00702000923b00901f00950d00700723b009015009", + "0x23c22c02612523b00900700950b00702300923b00902522312e030007025", + "0x23b00923c00950d00700723b00922c00950c00700723b00902600950c007", + "0x702e00923b00902c02312e03000702c00923b00922900950e007229009", + "0x36900703002e12e00902e00923b00902e00915700703000923b00900716c", + "0x723b00900e00937000701f01b0182231db0111fd00e22323b009125009", + "0x23b0091db00937600700723b00901100937700700723b0091fd009371007", + "0x901f00937200700723b00901800937400700723b009223009375007007", + "0x22100700900923b00900900900e00700700923b00900700912500700723b", + "0x2302502001500e23b00901b12e00900700e50f00712e00923b00912e009", + "0x918e00700723b00900712e00722c00951002600923b12e0230090dd007", + "0x923b00922900951200722900923b00923c00951100723c00923b009026", + "0x922100702000923b00902000900e00701500923b00901500912500702c", + "0x702c02502001500e00902c00923b00902c00951300702500923b009025", + "0x923b00901500912500702e00923b00922c00951400700723b00900712e", + "0x951300702500923b00902500922100702000923b00902000900e007015", + "0x1fd00e22323b00912500936900702e02502001500e00902e00923b00902e", + "0x723b0091fd00937100700723b00900e00937000701f01b0182231db011", + "0x23b00922300937500700723b0091db00937600700723b009011009377007", + "0x900700912500700723b00901b00937300700723b009018009374007007", + "0x712e00923b00912e00922100700900923b00900900900e00700700923b", + "0x923b12e0230090dd00702302502001500e23b00901f12e00900700e515", + "0x51100723c00923b00902600918e00700723b00900712e00722c009516026", + "0x23b00901500912500702c00923b00922900951200722900923b00923c009", + "0x51300702500923b00902500922100702000923b00902000900e007015009", + "0x51400700723b00900712e00702c02502001500e00902c00923b00902c009", + "0x23b00902000900e00701500923b00901500912500702e00923b00922c009", + "0xe00902e00923b00902e00951300702500923b009025009221007020009", + "0x701f01b0182231db0111fd00e22323b00912500936900702e025020015", + "0x723b00901100937700700723b0091fd00937100700723b00900e009370", + "0x23b00901b00937300700723b00901800937400700723b0091db009376007", + "0x900900e00700700923b00900700912500700723b00901f009372007007", + "0x922312e00900700e43200712e00923b00912e00922100700900923b009", + "0x712e00722c00951702600923b12e0230090cf00702302502001500e23b", + "0x2c22912523b00923c00924600723c00923b0090260091a800700723b009", + "0x922100702000923b00902000900e00701500923b00901500912500702e", + "0x23b00903000943400703022912e23b00922900936200702500923b009025", + "0x3300943600703304503122500e23b00903002502001500e435007030009", + "0x923b00922100943800700723b00900712e00703600951822100923b12e", + "0x3a00923b00921903812e51900703800923b00902e02c229125440007219", + "0x22500912500712600923b00903b00951b00703b00923b00903a00951a007", + "0x4500923b00904500922100703100923b00903100900e00722500923b009", + "0x723b00900712e00712604503122500e00912600923b00912600951c007", + "0x23b00902c00915500700723b00902e00915500700723b00922900934f007", + "0x900e00722500923b00922500912500703c00923b00903600951d007007", + "0x923b00903c00951c00704500923b00904500922100703100923b009031", + "0x923b00922c00951d00700723b00900712e00703c04503122500e00903c", + "0x922100702000923b00902000900e00701500923b00901500912500703e", + "0x703e02502001500e00903e00923b00903e00951c00702500923b009025", + "0x900915700712e00923b00912e0091a100712512e12e23b00900700951e", + "0x23b0091fd0090540071fd00e12e23b00900912e12e1a000700900923b009", + "0x12e51f00700e00923b00900e00915700712500923b00912500943c007007", + "0x52000700723b0090070091520071db01112e0091db01112e23b00900e125", + "0x912e12512e14f00712500912e23b00900900936b00712e00923b009007", + "0x952100723b12e00e00910600700e00923b00900e00902e00700e00923b", + "0x923b00900716c00700723b00900900915500700723b00900712e0071fd", + "0x70ee00722300923b0091db0090a50071db00923b009011009144007011", + "0x900724700700723b0091fd00911100700723b00900712e007007522009", + "0x923b00901801b12e14f00701b00912e23b00900900936b00701800923b", + "0x701500952300723b12e01f00910600701f00923b00901f00902e00701f", + "0x702000923b00900716c00700723b00900900915500700723b00900712e", + "0x5240090070ee00702300923b0090250090a500702500923b009020009144", + "0x923b00900752500700723b00901500911100700723b00900712e007007", + "0x723c00923b00902622c12e14f00722c00912e23b00900900936b007026", + "0x712e00722900952600723b12e23c00910600723c00923b00923c00902e", + "0x914400702c00923b00900716c00700723b00900900915500700723b009", + "0x70075270090070ee00703000923b00902e0090a500702e00923b00902c", + "0x722500923b00900752800700723b00922900911100700723b00900712e", + "0x902e00704500923b00922503112e14f00703100912e23b00900900936b", + "0x23b00900712e00703300952900723b12e04500910600704500923b009045", + "0x922100914400722100923b00900716c00700723b009009009155007007", + "0x712e00700752a0090070ee00721900923b0090360090a500703600923b", + "0x936b00703800923b00900752b00700723b00903300911100700723b009", + "0x903b00902e00703b00923b00903803a12e14f00703a00912e23b009009", + "0x700723b00900712e00712600952c00723b12e03b00910600703b00923b", + "0x923b00903c00914400703c00923b00900716c00700723b009009009155", + "0x23b00900712e00700752d0090070ee00714100923b00903e0090a500703e", + "0x4100912e14f00704100923b00900752e00700723b009126009111007007", + "0x52f00723b12e14500910600714500923b00914500902e00714500923b009", + "0x914800914400714800923b00900716c00700723b00900712e007043009", + "0x712e0070075300090070ee00704900923b0090470090a500704700923b", + "0x911300715000923b00900716c00700723b00904300911100700723b009", + "0x923b00904900939d00704900923b00904c0090a500704c00923b009150", + "0x939d00703000923b00921900939d00721900923b00914100939d007141", + "0x900902e00722300900922300923b00902300939d00702300923b009030", + "0x923b12e12e00914000712e00923b00900900712e18300700900923b009", + "0x714c00700723b00912500905400700723b00900712e00700e009531125", + "0x12e0070075320090070ee00701100923b0091fd00902e0071fd00923b009", + "0x2e0071db00923b00900714300700723b00900e00905400700723b009007", + "0x903300700700923b00900700912500701100900901100923b0091db009", + "0x923b00912500922100712e00923b00912e00900e00700900923b009009", + "0x1db18600701100923b0090110091570071fd00923b0091fd00902e007125", + "0x12e01f00907b00701f01b0182231db1fd23b0090111fd00e12512e009007", + "0x2500923b00901500918700700723b00900712e00702000953301500923b", + "0x90072f400700723b00902300915500702602312e23b009025009153007", + "0x700723b00923c00915500722923c12e23b00922c00915300722c00923b", + "0x2e02c12e14f00702e00923b00922900916300702c00923b009026009163", + "0x53400723b12e03000910600703000923b00903000902e00703000923b009", + "0x903100932f00703100923b00900714300700723b00900712e007225009", + "0x71db00923b0091db00912500703300923b00904500933000704500923b", + "0x901b00922100701800923b00901800900e00722300923b009223009033", + "0x12e00703301b0182231db1fd00903300923b00903300933100701b00923b", + "0x53500722100923b00900722900700723b00922500911100700723b009007", + "0x23b00903622112e03000703600923b00903600902e00703600923b009007", + "0x33200703a00923b00921903812e03100703800923b009007225007219009", + "0x23b0092230090330071db00923b0091db00912500703b00923b00903a009", + "0x33100701b00923b00901b00922100701800923b00901800900e007223009", + "0x700723b00900712e00703b01b0182231db1fd00903b00923b00903b009", + "0x92230090330071db00923b0091db00912500712600923b009020009332", + "0x701b00923b00901b00922100701800923b00901800900e00722300923b", + "0x723b0090070ea00712601b0182231db1fd00912600923b009126009331", + "0x22300915300722300923b00900714c0071db01112e23b00900e009153007", + "0x1f00923b0091db00916300700723b00901800915500701b01812e23b009", + "0x1b00916300700723b00901500915500702001512e23b00901f009153007", + "0x723b00902300915500702602312e23b00902500915300702500923b009", + "0x22c12e14f00723c00923b00902600916300722c00923b009020009163007", + "0x723b12e22900910600722900923b00922900902e00722900923b00923c", + "0x2e00914400702e00923b00900716c00700723b00900712e00702c009536", + "0x12e0070075370090070ee00722500923b0090300090a500703000923b009", + "0x11300703100923b00900716c00700723b00902c00911100700723b009007", + "0x23b00922500936e00722500923b0090450090a500704500923b009031009", + "0x953822100923b12e03300914000703300923b0090330090a5007033009", + "0x23b00901100915500700723b00922100905400700723b00900712e007036", + "0x23b00900722900700723b00912500915200700723b0091fd009155007007", + "0x12e03000703800923b00903800902e00703800923b0090073d8007219009", + "0x23b00903a03b12e03100703b00923b00900722500703a00923b009038219", + "0xe00700700923b00900700912500703c00923b00912600944c007126009", + "0x23b00903c00944d00712e00923b00912e00922100700900923b009009009", + "0x23b00903600905400700723b00900712e00703c12e00900700e00903c009", + "0x900900e00704904714804314504114103e22323b009125009369007007", + "0x1112e23b00901100936b00712e00923b00912e00922100700900923b009", + "0x4c12523b00915014112e00900e45a00715000923b00915000902e007150", + "0x700723b00900712e00715700953915500923b12e15300945c007153152", + "0x91fd00936b00715200923b00915200922100704c00923b00904c00900e", + "0x905204115204c00e47c00705200923b00905200902e0070521fd12e23b", + "0x900712e00705a00953a05800923b12e05700947d00705715905412523b", + "0x922100705400923b00905400900e00715d00923b00900714c00700723b", + "0x15d14515905400e49600715d00923b00915d00902e00715900923b009159", + "0x712e00716000953b15f00923b12e06000949700706015e05d12523b009", + "0x700723b00916100905400716106412e23b00915500945e00700723b009", + "0x915f00949900700723b00906700905400706716212e23b00905800947f", + "0x16801112e23b00901100936b00700723b00916600905400716616412e23b", + "0x4904714804316416206403e22314800716b00923b0091fd16812e53c007", + "0x5d00923b00905d00900e00700700923b00900700912500706d00923b009", + "0x71fd53e00716b00923b00916b00953d00715e00923b00915e009221007", + "0x53f07200923b12e16e0090c000716e07106f06e00e23b00916b06d15e05d", + "0x905400707617412e23b0090720092f300700723b00900712e007074009", + "0x6e00923b00906e00912500718000923b0090110093f400700723b009076", + "0x1800093f500707100923b00907100922100706f00923b00906f00900e007", + "0x707b18607807700e23b00918017407106f06e1fd3f600718000923b009", + "0x1870092f300700723b00900712e00708d00954018700923b12e07b0090c0", + "0x708f00923b00900716c00700723b00908e00905400708e07f12e23b009", + "0x7700912500709100923b00909000946900709000923b00908f07f12e468", + "0x18600923b00918600922100707800923b00907800900e00707700923b009", + "0x723b00900712e00709118607807700e00909100923b00909100944d007", + "0x7800900e00707700923b00907700912500709200923b00908d00944c007", + "0x9200923b00909200944d00718600923b00918600922100707800923b009", + "0x700723b00901100915500700723b00900712e00709218607807700e009", + "0x906f00900e00706e00923b00906e00912500709300923b00907400944c", + "0x909300923b00909300944d00707100923b00907100922100706f00923b", + "0x37000700723b00901100915500700723b00900712e00709307106f06e00e", + "0x700723b00904700937300700723b00904900937200700723b00903e009", + "0x723b0091fd00915500700723b00904300937500700723b009148009374", + "0x23b00916000944c00700723b00905800954200700723b009155009541007", + "0x22100705d00923b00905d00900e00700700923b009007009125007094009", + "0x9415e05d00700e00909400923b00909400944d00715e00923b00915e009", + "0x723b00903e00937000700723b00901100915500700723b00900712e007", + "0x23b00904700937300700723b00904900937200700723b009155009541007", + "0x91fd00915500700723b00904300937500700723b009148009374007007", + "0x912500709500923b00905a00944c00700723b00914500937600700723b", + "0x923b00915900922100705400923b00905400900e00700700923b009007", + "0x23b00900712e00709515905400700e00909500923b00909500944d007159", + "0x914500937600700723b00903e00937000700723b009011009155007007", + "0x14800937400700723b00904700937300700723b00904900937200700723b", + "0x937700700723b0091fd00915500700723b00904300937500700723b009", + "0x700923b00900700912500709600923b00915700944c00700723b009041", + "0x9600944d00715200923b00915200922100704c00923b00904c00900e007", + "0x900721900700723b0090070ea00709615204c00700e00909600923b009", + "0x12e23b12e1fd00900712503a0071fd00923b0091fd0090380071fd00923b", + "0xe12e23b00900e00936b00700723b00900712e00701822312e5431db011", + "0x701f00954400723b12e01b00910600701100923b00901100912500701b", + "0x1500923b00912500954500700723b00900e00915500700723b00900712e", + "0x912500702500923b00902000915c00702000923b00901512e12e0f8007", + "0x923b0090250090fa0071db00923b0091db00900e00701100923b009011", + "0x700723b00901f00911100700723b00900712e0070251db011125009025", + "0x912e0091fd0071db00923b0091db00900e00701100923b009011009125", + "0x12e22c00924f00722c02602312523b00912e1db01112554600712e00923b", + "0x2c12e23b00923c00954800700723b00900712e00722900954723c00923b", + "0x54b00700723b00900712e00722500954a03000923b12e02e00954900702e", + "0x904500e12e14f00704500923b00900714300703100923b00903012512e", + "0x702600923b00902600900e00702300923b00902300912500703300923b", + "0x903300902e00703100923b00903100904700702c00923b00902c0091fd", + "0x91db00721903622112523b00903303102c0260231fd0f600703300923b", + "0x23b00903800922300700723b00900712e00703a00954c03800923b12e219", + "0x3e00923b00903c00915c00703c00923b00912603b12e0f800712603b12e", + "0x3e0090fa00703600923b00903600900e00722100923b009221009125007", + "0x903a00915600700723b00900712e00703e03622112500903e00923b009", + "0x703600923b00903600900e00722100923b00922100912500714100923b", + "0x15500700723b00900712e00714103622112500914100923b0091410090fa", + "0x4100923b00922500915400700723b00912500923c00700723b00900e009", + "0x912500704300923b00914500915c00714500923b00904102c12e0f8007", + "0x923b0090430090fa00702600923b00902600900e00702300923b009023", + "0x700723b00900e00915500700723b00900712e007043026023125009043", + "0x23b00902300912500714800923b00922900915600700723b00912500923c", + "0x12500914800923b0091480090fa00702600923b00902600900e007023009", + "0x12500923c00700723b00900e00915500700723b00900712e007148026023", + "0x705d00704700923b00900722900700723b00912e00915e00700723b009", + "0x923b00904904712e03000704900923b00904900902e00704900923b009", + "0x915600715200923b00915004c12e03100704c00923b009007225007150", + "0x923b00901800900e00722300923b00922300912500715300923b009152", + "0x23b00900700900e00715301822312500915300923b0091530090fa007018", + "0x12512e12523b00900900712e54d00700900923b009009009221007007009", + "0x55000700723b00900712e00701100954f1fd00923b12e00e00954e00700e", + "0x23b00922300955200722300923b0091db0095510071db00923b0091fd009", + "0x723b00901b00955400700723b00901800955300702001501f01b0181fd", + "0x23b00901f00955500700723b00902000915500700723b009015009101007", + "0x22100712e00923b00912e00900e00702300923b009025009556007025009", + "0x702312512e12500902300923b00902300955700712500923b009125009", + "0x923b00912e00900e00702600923b00901100955800700723b00900712e", + "0x12e12500902600923b00902600955700712500923b00912500922100712e", + "0x54d00700900923b00900900922100700700923b00900700900e007026125", + "0x110095591fd00923b12e00e00954e00700e12512e12523b00900900712e", + "0x23b0091db0095510071db00923b0091fd00955000700723b00900712e007", + "0x23b00901800955300702001501f01b0181fd23b009223009552007223009", + "0x902000915500700723b00901500910100700723b00901f009101007007", + "0xe00702300923b00902500955b00702500923b00901b00955a00700723b", + "0x23b00902300955c00712500923b00912500922100712e00923b00912e009", + "0x923b00901100955d00700723b00900712e00702312512e125009023009", + "0x955c00712500923b00912500922100712e00923b00912e00900e007026", + "0x755f00701b00923b00900755e00702612512e12500902600923b009026", + "0x55f00702600923b00900755f00702500923b00900755f00701500923b009", + "0xea00700723b00900716000702c00923b00900715f00723c00923b009007", + "0x12500923b00912500922100712e00923b00912e00900e00700723b009007", + "0x22900923b00922902c12e16200703022902e12523b00912512e12e54d007", + "0x955000700723b00900712e00703100956022500923b12e03000954e007", + "0x12e23b0091fd00938b00703300923b00904500955100704500923b009225", + "0x55200721900923b00903600956200703600923b0092210095610072211fd", + "0x955400700723b00903800955300703c12603b03a0381fd23b009033009", + "0x1500700723b00903c00915500700723b00903b00910100700723b00903a", + "0x923b00900756300700723b00903e00902000714103e12e23b009219009", + "0x902300700723b00914500902000704314512e23b009041009015007041", + "0x923b00914800902600704700923b00904300902300714800923b009141", + "0x700756400723b12e04714812e22c00712600923b00912600935a007148", + "0x700723b00923c00956600700723b00901b00956500700723b00900712e", + "0x723b00902500956600700723b00902600956600700723b00922300904a", + "0x902e00900e00700700923b00900700912500700723b009015009566007", + "0x712600923b00912600935a0071fd00923b0091fd00912300702e00923b", + "0x15200923b12e04c00940200704c15004912523b0091261fd02e00700e401", + "0x4900912500700723b00915200940400700723b00900712e007153009567", + "0x12e0070075680090070ee00715700923b00915000900e00715500923b009", + "0x15200700723b00901100915500700723b0091db00915e00700723b009007", + "0x923b00904900912500705200923b00915300944c00700723b00900e009", + "0x922100715000923b00915000900e00700900923b009009009033007049", + "0x522291500090491fd00905200923b00905200944d00722900923b009229", + "0x923b0091fd00956100705400923b00900702500700723b00900712e007", + "0x902600715900923b00915900956900700700923b009007009125007159", + "0x5800956b00705805712e23b00905415900712556a00705400923b009054", + "0x923b00905a00956d00700723b00900712e00715d00956c05a00923b12e", + "0x57000701800923b00901801b12e56f00701800923b00905d00956e00705d", + "0x915500716015f06012523b00915e00957100715e01812e23b009018009", + "0x706400923b00906000910200700723b00916000957200700723b00915f", + "0x916200910200700723b00916100910100716216112e23b009064009107", + "0x16816612e23b00912600910700716400923b00906700910400706700923b", + "0x916b00910400716b00923b00916800910200700723b009166009101007", + "0x700723b00906e00915500706f06e12e23b00916400915300706d00923b", + "0x906f00916300700723b00907100915500716e07112e23b00906d009153", + "0x17400923b00907407212e14f00707400923b00916e00916300707200923b", + "0x23b12e17400910600717400923b00917400902e00700723b00900710f007", + "0x718001812e23b00901800957000700723b00900712e007076009573007", + "0x18600957200700723b00907700910100718607807712523b009180009571", + "0x36b00718700923b00900757400707b00923b00907800916300700723b009", + "0x7f00902e00707f00923b00918708d12e14f00708d07b12e23b00907b009", + "0x723b00900712e00708e00957500723b12e07f00910600707f00923b009", + "0x23b00901500956600700723b00902500956600700723b009026009566007", + "0x709000957608f00923b12e22300914000700723b00907b009155007007", + "0x36900700723b00908f00905400700723b0090070ea00700723b00900712e", + "0x12e23b00909700957700709809709609509409309209122323b00900e009", + "0x22100702e00923b00902e00900e00705700923b0090570091250071a5099", + "0x5b0371a709c00e23b0091a522902e05700e50f00722900923b009229009", + "0x918e00700723b00900712e0071ac00957809f00923b12e05b0090dd007", + "0x923b0091a700900e00709c00923b00909c00912500722c00923b00909f", + "0x260071b022c12e23b00922c00957900703700923b0090370092210071a7", + "0x1a709c00e57b00722c00923b00922c23c12e57a0071b000923b0091b0009", + "0xa700957c1b500923b12e0a50093b90070a504a0a31b200e23b0091b0037", + "0xa900923b00900756300700723b0091b50093bb00700723b00900712e007", + "0xa900902600722c00923b00922c0090260071b200923b0091b2009125007", + "0x12e0ac0090dd0070ac1b812e23b0090a922c1b212557d0070a900923b009", + "0xb000923b0090ae00918e00700723b00900712e0071bc00957e0ae00923b", + "0xb000902600704a00923b00904a0092210070a300923b0090a300900e007", + "0x94550070b41bd0b212523b0090b009904a0a300e4540070b000923b009", + "0x23b0090b600945800700723b00900712e0071bb00957f0b600923b12e0b4", + "0xb809609509409309209122314800700723b0090ba0090540070ba0b812e", + "0x923b0090b200900e0070bc00923b0091b80091250071ba00923b009098", + "0x70ee0070c000923b0091ba0093f80071b900923b0091bd0092210070be", + "0x1db00915e00700723b00901100915500700723b00900712e007007580009", + "0x937000700723b00909800937200700723b00901800958100700723b009", + "0x37600700723b00909500937500700723b00909600937400700723b009091", + "0x700723b00909200937100700723b00909300937700700723b009094009", + "0x90090090330071b800923b0091b80091250070c200923b0091bb00944c", + "0x71bd00923b0091bd0092210070b200923b0090b200900e00700900923b", + "0x723b00900712e0070c21bd0b20091b81fd0090c200923b0090c200944d", + "0x23b00901100915500700723b00909200937100700723b009093009377007", + "0x909800937200700723b00901800958100700723b0091db00915e007007", + "0x9500937500700723b00909600937400700723b00909100937000700723b", + "0x944c00700723b00909900937300700723b00909400937600700723b009", + "0x923b0090090090330071b800923b0091b80091250071b600923b0091bc", + "0x944d00704a00923b00904a0092210070a300923b0090a300900e007009", + "0x37700700723b00900712e0071b604a0a30091b81fd0091b600923b0091b6", + "0x700723b00901100915500700723b00909200937100700723b009093009", + "0x723b00909800937200700723b00901800958100700723b0091db00915e", + "0x23b00909500937500700723b00909600937400700723b009091009370007", + "0x922c00902000700723b00909900937300700723b009094009376007007", + "0x330071b200923b0091b20091250070c400923b0090a700944c00700723b", + "0x23b00904a0092210070a300923b0090a300900e00700900923b009009009", + "0x712e0070c404a0a30091b21fd0090c400923b0090c400944d00704a009", + "0x937100700723b00909900937300700723b00909300937700700723b009", + "0x58100700723b0091db00915e00700723b00901100915500700723b009092", + "0x700723b00909100937000700723b00909800937200700723b009018009", + "0x723b00909400937600700723b00909500937500700723b009096009374", + "0x909c0091250070c600923b0091ac00944c00700723b00923c009566007", + "0x71a700923b0091a700900e00700900923b00900900903300709c00923b", + "0x1a700909c1fd0090c600923b0090c600944d00703700923b009037009221", + "0x23b00909000905400700723b0090070ea00700723b00900712e0070c6037", + "0x2e00900e0070bc00923b00905700912500700723b00923c009566007007", + "0xc000923b00900e0093f80071b900923b0092290092210070be00923b009", + "0x915500700723b0091b30091010071b70c71b312523b009018009571007", + "0xc900923b0090c90091fd0070c900923b0091b700905800700723b0090c7", + "0x1aa0095820cd00923b12e0cb0090720070cb1ad12e23b0090c900916e007", + "0x23b0090cf00901f0070cf00923b0091ad00901b00700723b00900712e007", + "0x2500700723b0091a30090200070d11a312e23b0091a80090150071a8009", + "0x23b0091a00090200070d51a012e23b0091a10090150071a100923b009007", + "0x902600719b00923b0090d500902300719f00923b0090d1009023007007", + "0x23b00900712e00700758300723b12e19b19f12e22c00719f00923b00919f", + "0x90c000915200700723b0091db00915e00700723b009011009155007007", + "0x90075840070d800923b00900722900700723b0090cd00915500700723b", + "0x19800923b0090da0d812e0300070da00923b0090da00902e0070da00923b", + "0xdd00944c0070dd00923b00919819712e03100719700923b009007225007", + "0x900923b0090090090330070bc00923b0090bc00912500718e00923b009", + "0x18e00944d0071b900923b0091b90092210070be00923b0090be00900e007", + "0x915300700723b00900712e00718e1b90be0090bc1fd00918e00923b009", + "0x18a00923b00900714c00700723b0090df0091550070e10df12e23b0090cd", + "0xe100916300700723b00918900915500718818912e23b00918a009153007", + "0x723b00918b0091550070e518b12e23b00918c00915300718c00923b009", + "0x91550070a018312e23b00918400915300718400923b009188009163007", + "0x17900923b0090a00091630070e800923b0090e500916300700723b009183", + "0x917b00902e00700723b00900710f00717b00923b0091790e812e14f007", + "0x700723b00900712e0070ea00958500723b12e17b00910600717b00923b", + "0x23b0091710090a500717100923b00917500914400717500923b00900716c", + "0x23b0090ea00911100700723b00900712e0070075860090070ee0070ec009", + "0x16c0090a500716c00923b0090ee0091130070ee00923b00900716c007007", + "0xf000923b0090f00090a50070f000923b0090ec00936e0070ec00923b009", + "0x70ea00700723b00900712e00716500958716900923b12e0f0009140007", + "0x915e00700723b00901100915500700723b00916900905400700723b009", + "0x3d80070f300923b00900722900700723b0090c000915200700723b0091db", + "0x23b0091630f312e03000716300923b00916300902e00716300923b009007", + "0x44c00715c00923b0090f60f812e0310070f800923b0090072250070f6009", + "0x23b0090090090330070bc00923b0090bc0091250070fa00923b00915c009", + "0x44d0071b900923b0091b90092210070be00923b0090be00900e007009009", + "0x700723b00900712e0070fa1b90be0090bc1fd0090fa00923b0090fa009", + "0x915400936900715415612e23b0090c000907800700723b009165009054", + "0x937100700723b00915800937000714c1041021011071510fd15822323b", + "0x37400700723b00910100937500700723b00910700937600700723b0090fd", + "0x700723b00914c00937200700723b00910400937300700723b009102009", + "0x1b90be1253da0071b900923b0091b90092210070be00923b0090be00900e", + "0x12e00714900958814e00923b12e14d00907b00714d10614f12523b009151", + "0x10c12e23b00910a00915300710a00923b00914e00918700700723b009007", + "0x914600915300714600923b00900714c00700723b00910c009155007147", + "0x714400923b00914700916300700723b00914b00915500710f14b12e23b", + "0x910f00916300700723b00911100915500714311112e23b009144009153", + "0x700723b00914000915500711814012e23b00911300915300711300923b", + "0x13b11512e14f00713b00923b00911800916300711500923b009143009163", + "0x58900723b12e13900910600713900923b00913900902e00713900923b009", + "0x911a00914400711a00923b00900716c00700723b00900712e007137009", + "0x712e00700758a0090070ee00712800923b00911c0090a500711c00923b", + "0x911300712300923b00900716c00700723b00913700911100700723b009", + "0x923b00912800936e00712800923b0090000090a500700000923b009123", + "0x2f500958b2f400923b12e2f30091400072f300923b0092f30090a50072f3", + "0x700723b0092f400905400700723b0090070ea00700723b00900712e007", + "0x723b00915600915200700723b00901100915500700723b0091db00915e", + "0x23b0092f700902e0072f700923b00900748b0072f600923b009007229007", + "0x3100724200923b0090072250072f800923b0092f72f612e0300072f7009", + "0x90bc00912500730800923b00930700944c00730700923b0092f824212e", + "0x714f00923b00914f00900e00700900923b0090090090330070bc00923b", + "0x14f0090bc1fd00930800923b00930800944d00710600923b009106009221", + "0x23b0092f500905400700723b0090070ea00700723b00900712e007308106", + "0x330070bc00923b0090bc00912500730a30912e23b009156009078007007", + "0x23b00910600922100714f00923b00914f00900e00700900923b009009009", + "0x58c0071db00923b0091db0091fd00701100923b00901100902e007106009", + "0x30f0091b000730f30e24130d30c1fd23b0091db01130a10614f0090bc1db", + "0x923b0093100091b200700723b00900712e00731200958d31000923b12e", + "0x5400700723b00900712e00724000958e31400923b12e313009140007313", + "0x731500923b00900722900700723b00930900915200700723b009314009", + "0x931631512e03000731600923b00931600902e00731600923b00900758f", + "0x731a00923b00931831912e03100731900923b00900722500731800923b", + "0x930d00903300730c00923b00930c00912500731b00923b00931a00944c", + "0x730e00923b00930e00922100724100923b00924100900e00730d00923b", + "0x723b00900712e00731b30e24130d30c1fd00931b00923b00931b00944d", + "0x931f30912e46800731f00923b00900716c00700723b009240009054007", + "0x730c00923b00930c00912500732100923b00932000946900732000923b", + "0x930e00922100724100923b00924100900e00730d00923b00930d009033", + "0x12e00732130e24130d30c1fd00932100923b00932100944d00730e00923b", + "0x732500923b00931200944c00700723b00930900915200700723b009007", + "0x924100900e00730d00923b00930d00903300730c00923b00930c009125", + "0x932500923b00932500944d00730e00923b00930e00922100724100923b", + "0x15e00700723b0090070ea00700723b00900712e00732530e24130d30c1fd", + "0x700723b00915600915200700723b00901100915500700723b0091db009", + "0x90090090330070bc00923b0090bc00912500732700923b00914900944c", + "0x710600923b00910600922100714f00923b00914f00900e00700900923b", + "0x723b00900712e00732710614f0090bc1fd00932700923b00932700944d", + "0x23b0091db00915e00700723b00901100915500700723b0091aa009054007", + "0x23b00900722900700723b0091ad00915e00700723b0090c0009152007007", + "0x12e03000732900923b00932900902e00732900923b009007584007328009", + "0x23b00932a23f12e03100723f00923b00900722500732a00923b009329328", + "0x330070bc00923b0090bc00912500732f00923b00932b00944c00732b009", + "0x23b0091b90092210070be00923b0090be00900e00700900923b009009009", + "0x712e00732f1b90be0090bc1fd00932f00923b00932f00944d0071b9009", + "0x759000700723b00923c00956600700723b00908e00911100700723b009", + "0x23b00933033112e14f00733107b12e23b00907b00936b00733000923b009", + "0x33300959100723b12e33200910600733200923b00933200902e007332009", + "0x723b00901500956600700723b00902500956600700723b00900712e007", + "0x12e00733500959233400923b12e22300914000700723b00907b009155007", + "0x936900700723b00933400905400700723b0090070ea00700723b009007", + "0x34812e23b00934600957700723e34634534033e33d33833622323b00900e", + "0x922100702e00923b00902e00900e00705700923b00905700912500734a", + "0x734e34d34c34b00e23b00934a22902e05700e50f00722900923b009229", + "0x34f00918e00700723b00900712e00723d00959334f00923b12e34e0090dd", + "0x34c00923b00934c00900e00734b00923b00934b00912500702300923b009", + "0x902600735002312e23b00902300957900734d00923b00934d009221007", + "0x34d34c34b00e57b00702300923b00902302612e57a00735000923b009350", + "0x735800959435700923b12e3560093b900735635535235100e23b009350", + "0x735a00923b00900756300700723b0093570093bb00700723b00900712e", + "0x935a00902600702300923b00902300902600735100923b009351009125", + "0x23b12e35f0090dd00735f35e12e23b00935a02335112557d00735a00923b", + "0x736300923b00936100918e00700723b00900712e007362009595361009", + "0x936300902600735500923b00935500922100735200923b00935200900e", + "0x36900945500736936836512523b00936334835535200e45400736300923b", + "0x12e23b00936a00945800700723b00900712e00736b00959636a00923b12e", + "0x23e36c34534033e33d33833622314800700723b00936e00905400736e36c", + "0x37200923b00936500900e00737100923b00935e00912500737000923b009", + "0x90070ee00737400923b0093700093f800737300923b009368009221007", + "0x91db00915e00700723b00901100915500700723b00900712e007007597", + "0x33600937000700723b00923e00937200700723b00901800958100700723b", + "0x937600700723b00934000937500700723b00934500937400700723b009", + "0x44c00700723b00933800937100700723b00933d00937700700723b00933e", + "0x23b00900900903300735e00923b00935e00912500737500923b00936b009", + "0x44d00736800923b00936800922100736500923b00936500900e007009009", + "0x700723b00900712e00737536836500935e1fd00937500923b009375009", + "0x723b00901100915500700723b00933800937100700723b00933d009377", + "0x23b00923e00937200700723b00901800958100700723b0091db00915e007", + "0x934000937500700723b00934500937400700723b009336009370007007", + "0x36200944c00700723b00934800937300700723b00933e00937600700723b", + "0x900923b00900900903300735e00923b00935e00912500737600923b009", + "0x37600944d00735500923b00935500922100735200923b00935200900e007", + "0x937700700723b00900712e00737635535200935e1fd00937600923b009", + "0x15e00700723b00901100915500700723b00933800937100700723b00933d", + "0x700723b00923e00937200700723b00901800958100700723b0091db009", + "0x723b00934000937500700723b00934500937400700723b009336009370", + "0x23b00902300902000700723b00934800937300700723b00933e009376007", + "0x903300735100923b00935100912500737700923b00935800944c007007", + "0x923b00935500922100735200923b00935200900e00700900923b009009", + "0x900712e0073773553520093511fd00937700923b00937700944d007355", + "0x33800937100700723b00934800937300700723b00933d00937700700723b", + "0x958100700723b0091db00915e00700723b00901100915500700723b009", + "0x37400700723b00933600937000700723b00923e00937200700723b009018", + "0x700723b00933e00937600700723b00934000937500700723b009345009", + "0x23b00934b00912500737800923b00923d00944c00700723b009026009566", + "0x22100734c00923b00934c00900e00700900923b00900900903300734b009", + "0x34d34c00934b1fd00937800923b00937800944d00734d00923b00934d009", + "0x723b00933500905400700723b0090070ea00700723b00900712e007378", + "0x902e00900e00737100923b00905700912500700723b009026009566007", + "0x737400923b00900e0093f800737300923b00922900922100737200923b", + "0x37b00915500700723b00937900910100737c37b37912523b009018009571", + "0x37f37e12e23b00937d00901500737d00923b00937c00901f00700723b009", + "0x23b00938000901500738000923b00900702500700723b00937e009020007", + "0x2300738300923b00937f00902300700723b00938100902000738238112e", + "0x12e38438312e22c00738300923b00938300902600738400923b009382009", + "0x915e00700723b00901100915500700723b00900712e00700759800723b", + "0x58400738500923b00900722900700723b00937400915200700723b0091db", + "0x23b00938638512e03000738600923b00938600902e00738600923b009007", + "0x44c00738b00923b00938738912e03100738900923b009007225007387009", + "0x23b00900900903300737100923b00937100912500738d00923b00938b009", + "0x44d00737300923b00937300922100737200923b00937200900e007009009", + "0x700723b00900712e00738d3733720093711fd00938d00923b00938d009", + "0x39b39a39939439322323b00939100936900739138e12e23b009374009078", + "0x937600700723b00939400937100700723b0093930093700073a139d39c", + "0x37300700723b00939c00937400700723b00939b00937500700723b00939a", + "0x37200923b00937200900e00700723b0093a100937200700723b00939d009", + "0x3a53a43a312523b0093993733721253da00737300923b009373009221007", + "0x918700700723b00900712e0073aa0095993a900923b12e3a500907b007", + "0x23b0093ab0091550073ac3ab12e23b00924700915300724700923b0093a9", + "0x91550073b13b012e23b0093af0091530073af00923b00900714c007007", + "0x3b412e23b0093b20091530073b200923b0093ac00916300700723b0093b0", + "0x3b70091530073b700923b0093b100916300700723b0093b40091550073b5", + "0x3bb00923b0093b500916300700723b0093b80091550073b93b812e23b009", + "0x710f0073bd00923b0093bc3bb12e14f0073bc00923b0093b9009163007", + "0x959a00723b12e3bd0091060073bd00923b0093bd00902e00700723b009", + "0x23b0093c00091440073c000923b00900716c00700723b00900712e0073be", + "0x900712e00700759b0090070ee0073c200923b0093c10090a50073c1009", + "0x3c30091130073c300923b00900716c00700723b0093be00911100700723b", + "0x3c600923b0093c200936e0073c200923b0093c50090a50073c500923b009", + "0x73c800959c3c700923b12e3c60091400073c600923b0093c60090a5007", + "0x15e00700723b0093c700905400700723b0090070ea00700723b00900712e", + "0x700723b00938e00915200700723b00901100915500700723b0091db009", + "0x923b0093ca00902e0073ca00923b00900748b0073c900923b009007229", + "0x12e0310073cd00923b0090072250073cb00923b0093ca3c912e0300073ca", + "0x23b0093710091250073d200923b0093d100944c0073d100923b0093cb3cd", + "0x2210073a300923b0093a300900e00700900923b009009009033007371009", + "0x3a43a30093711fd0093d200923b0093d200944d0073a400923b0093a4009", + "0x23b00938e00936900700723b0093c800905400700723b00900712e0073d2", + "0x1250073e53e412e23b0093dd0094310073e33e13de3dd3da3d93d83d7223", + "0x23b0093a40092210073a300923b0093a300900e00737100923b009371009", + "0x3ea0090cf0073ea3e93e83e600e23b0093e53a43a337100e4320073a4009", + "0x923b0092490091a800700723b00900712e0073ef00959d24900923b12e", + "0x15300700723b0093f300934f0073f53f43f312523b0093f00092460073f0", + "0x923b00900740b00700723b0093f60091550073f83f612e23b0093f4009", + "0x916300700723b0093fd0091550073ff3fd12e23b009248009153007248", + "0x23b00940240112e14f00740200923b0093ff00916300740100923b0093f8", + "0x40700959e00723b12e40400910600740400923b00940400902e007404009", + "0x940b00915500741340b12e23b0093f500915300700723b00900712e007", + "0x15500742741912e23b00941600915300741600923b00900714c00700723b", + "0x12e23b00942b00915300742b00923b00941300916300700723b009419009", + "0x915300743200923b00942700916300700723b00942f00915500743142f", + "0x923b00943100916300700723b00924600915500743424612e23b009432", + "0x2e00743800923b00943643512e14f00743600923b009434009163007435", + "0x900712e00743900959f00723b12e43800910600743800923b009438009", + "0x90a500743b00923b00943a00914400743a00923b00900716c00700723b", + "0x911100700723b00900712e0070075a00090070ee00743c00923b00943b", + "0x743f00923b00943d00911300743d00923b00900716c00700723b009439", + "0x94400090a500744000923b00943c00936e00743c00923b00943f0090a5", + "0x723b00900712e0074420095a144100923b12e44000914000744000923b", + "0x723b0091db00915e00700723b00944100905400700723b0090070ea007", + "0x23b0093e100937300700723b0093e300937200700723b009011009155007", + "0x93da00937600700723b0093e400937500700723b0093de009374007007", + "0x3d700937000700723b0093d800937100700723b0093d900937700700723b", + "0x902e00744500923b0090073d800744400923b00900722900700723b009", + "0x923b00900722500744600923b00944544412e03000744500923b009445", + "0x12500744b00923b00944800944c00744800923b00944624512e031007245", + "0x23b0093e800900e00700900923b0090090090330073e600923b0093e6009", + "0x1fd00944b00923b00944b00944d0073e900923b0093e90092210073e8009", + "0x905400700723b0090070ea00700723b00900712e00744b3e93e80093e6", + "0x744c00923b0093e33e13de3e43da3d93d83d722314800700723b009442", + "0x90090330073e600923b0093e600912500744e44d12e23b00944c009078", + "0x3e900923b0093e90092210073e800923b0093e800900e00700900923b009", + "0x3e61db58c0071db00923b0091db0091fd00701100923b00901100902e007", + "0x23b12e4540091b000745424445245044f1fd23b0091db01144e3e93e8009", + "0x745800923b0094550091b200700723b00900712e0074570095a2455009", + "0x45a00905400700723b00900712e00745b0095a345a00923b12e458009140", + "0x758f00745c00923b00900722900700723b00944d00915200700723b009", + "0x923b00945e45c12e03000745e00923b00945e00902e00745e00923b009", + "0x944c00746100923b00945f46012e03100746000923b00900722500745f", + "0x923b00945000903300744f00923b00944f00912500746300923b009461", + "0x944d00724400923b00924400922100745200923b00945200900e007450", + "0x5400700723b00900712e00746324445245044f1fd00946300923b009463", + "0x923b00946444d12e46800746400923b00900716c00700723b00945b009", + "0x903300744f00923b00944f00912500746800923b009465009469007465", + "0x923b00924400922100745200923b00945200900e00745000923b009450", + "0x900712e00746824445245044f1fd00946800923b00946800944d007244", + "0x912500746900923b00945700944c00700723b00944d00915200700723b", + "0x923b00945200900e00745000923b00945000903300744f00923b00944f", + "0x44f1fd00946900923b00946900944d00724400923b009244009221007452", + "0x40700911100700723b0090070ea00700723b00900712e007469244452450", + "0x937200700723b00901100915500700723b0091db00915e00700723b009", + "0x37500700723b0093de00937400700723b0093e100937300700723b0093e3", + "0x700723b0093d900937700700723b0093da00937600700723b0093e4009", + "0x723b0093f500915500700723b0093d700937000700723b0093d8009371", + "0x23b00946a00902e00746a00923b0090074d100724300923b009007229007", + "0x3100747d00923b00900722500747c00923b00946a24312e03000746a009", + "0x93e600912500748000923b00947f00944c00747f00923b00947c47d12e", + "0x73e800923b0093e800900e00700900923b0090090090330073e600923b", + "0x3e80093e61fd00948000923b00948000944d0073e900923b0093e9009221", + "0x23b0091db00915e00700723b0090070ea00700723b00900712e0074803e9", + "0x93e100937300700723b0093e300937200700723b009011009155007007", + "0x3da00937600700723b0093e400937500700723b0093de00937400700723b", + "0x937000700723b0093d800937100700723b0093d900937700700723b009", + "0x3e600923b0093e600912500748100923b0093ef00944c00700723b0093d7", + "0x3e90092210073e800923b0093e800900e00700900923b009009009033007", + "0x74813e93e80093e61fd00948100923b00948100944d0073e900923b009", + "0x700723b00901100915500700723b0091db00915e00700723b00900712e", + "0x23b00937100912500748200923b0093aa00944c00700723b00938e009152", + "0x2210073a300923b0093a300900e00700900923b009009009033007371009", + "0x3a43a30093711fd00948200923b00948200944d0073a400923b0093a4009", + "0x23b00902600956600700723b00933300911100700723b00900712e007482", + "0x12e14f00749607b12e23b00907b00936b00748b00923b0090075a4007007", + "0x23b12e49700910600749700923b00949700902e00749700923b00948b496", + "0x915500700723b00901500956600700723b00900712e0074990095a5007", + "0x23b00900712e00749b0095a649a00923b12e22300914000700723b00907b", + "0x23b00900e00936900700723b00949a00905400700723b0090070ea007007", + "0x1250074c84c712e23b0094c60095a70074c64b64b54b44b14b04a549c223", + "0x23b00922900922100702e00923b00902e00900e00705700923b009057009", + "0x4d70090dd0074d74d64d14cf00e23b0094c822902e05700e515007229009", + "0x923b0094d800918e00700723b00900712e0074e60095a84d800923b12e", + "0x92210074d100923b0094d100900e0074cf00923b0094cf009125007020", + "0x23b0094e70090260074e702012e23b0090200095790074d600923b0094d6", + "0x23b0094e74d64d14cf00e57b00702000923b00902002512e57a0074e7009", + "0x900712e0075030095a950200923b12e5010093b90075015004ff4e800e", + "0x4e800912500750400923b00900756300700723b0095020093bb00700723b", + "0x50400923b00950400902600702000923b0090200090260074e800923b009", + "0x5aa50700923b12e5060090dd00750650512e23b0095040204e812557d007", + "0x4ff00900e00750900923b00950700918e00700723b00900712e007508009", + "0x50900923b00950900902600750000923b0095000092210074ff00923b009", + "0x923b12e50c00924400750c50b50a12523b0095094c75004ff00e452007", + "0x751150f12e23b00950d00945700700723b00900712e00750e0095ab50d", + "0x923b00950f4b64b54b44b14b04a549c22314800700723b009511009054", + "0x922100751400923b00950a00900e00751300923b009505009125007512", + "0x70075ac0090070ee00751900923b0095120093f800751500923b00950b", + "0x700723b0091db00915e00700723b00901100915500700723b00900712e", + "0x723b0094b600937300700723b00949c00937000700723b009018009581", + "0x23b0094b100937600700723b0094b400937500700723b0094b5009374007", + "0x950e00944c00700723b0094a500937100700723b0094b0009377007007", + "0x700900923b00900900903300750500923b00950500912500751a00923b", + "0x951a00944d00750b00923b00950b00922100750a00923b00950a00900e", + "0x4b000937700700723b00900712e00751a50b50a0095051fd00951a00923b", + "0x915e00700723b00901100915500700723b0094a500937100700723b009", + "0x37300700723b00949c00937000700723b00901800958100700723b0091db", + "0x700723b0094b400937500700723b0094b500937400700723b0094b6009", + "0x923b00950800944c00700723b0094c700937200700723b0094b1009376", + "0x900e00700900923b00900900903300750500923b00950500912500751b", + "0x923b00951b00944d00750000923b0095000092210074ff00923b0094ff", + "0x23b0094b000937700700723b00900712e00751b5004ff0095051fd00951b", + "0x91db00915e00700723b00901100915500700723b0094a5009371007007", + "0x4b600937300700723b00949c00937000700723b00901800958100700723b", + "0x937600700723b0094b400937500700723b0094b500937400700723b009", + "0x44c00700723b00902000902000700723b0094c700937200700723b0094b1", + "0x23b0090090090330074e800923b0094e800912500751c00923b009503009", + "0x44d00750000923b0095000092210074ff00923b0094ff00900e007009009", + "0x700723b00900712e00751c5004ff0094e81fd00951c00923b00951c009", + "0x723b0094a500937100700723b0094c700937200700723b0094b0009377", + "0x23b00901800958100700723b0091db00915e00700723b009011009155007", + "0x94b500937400700723b0094b600937300700723b00949c009370007007", + "0x2500956600700723b0094b100937600700723b0094b400937500700723b", + "0x74cf00923b0094cf00912500751d00923b0094e600944c00700723b009", + "0x94d60092210074d100923b0094d100900e00700900923b009009009033", + "0x12e00751d4d64d10094cf1fd00951d00923b00951d00944d0074d600923b", + "0x956600700723b00949b00905400700723b0090070ea00700723b009007", + "0x51400923b00902e00900e00751300923b00905700912500700723b009025", + "0x1800957100751900923b00900e0093f800751500923b009229009221007", + "0x723b00951f00915500700723b00951e00910100752051f51e12523b009", + "0x52500916e00752500923b0095250091fd00752500923b009520009058007", + "0x900712e0075350095ad52e00923b12e52b00907200752b52812e23b009", + "0x1500753d00923b00953c00901f00753c00923b00952800901b00700723b", + "0x923b00900702500700723b00953e00902000754153e12e23b00953d009", + "0x902300700723b00954500902000754654512e23b009542009015007542", + "0x923b00924f00902600754800923b00954600902300724f00923b009541", + "0x915500700723b00900712e0070075ae00723b12e54824f12e22c00724f", + "0x15500700723b00951900915200700723b0091db00915e00700723b009011", + "0x754b00923b00900758400754900923b00900722900700723b00952e009", + "0x900722500754d00923b00954b54912e03000754b00923b00954b00902e", + "0x55100923b00955000944c00755000923b00954d54e12e03100754e00923b", + "0x51400900e00700900923b00900900903300751300923b009513009125007", + "0x55100923b00955100944d00751500923b00951500922100751400923b009", + "0x700723b00900710f00700723b00900712e0075515155140095131fd009", + "0x951900936900700723b00900712e0075520095af00723b12e52e009106", + "0x755d55c12e23b0095560093dd00755b55a55855755655555455322323b", + "0x5155141253de00751500923b00951500922100751400923b00951400900e", + "0x12e0075630095b056200923b12e56100907b00756155f55e12523b00955d", + "0x56612e23b00956500915300756500923b00956200918700700723b009007", + "0x956a00915300756a00923b00900714c00700723b009566009155007569", + "0x756e00923b00956900916300700723b00956b00915500756d56b12e23b", + "0x57000902e00757000923b00956f56e12e14f00756f00923b00956d009163", + "0x723b00900712e0075710095b100723b12e57000910600757000923b009", + "0x955e00900e00757200923b00955b55a55855755c555554553223148007", + "0x757900923b0095720093f800757700923b00955f00922100757400923b", + "0x911100700723b0090070ea00700723b00900712e0070075b20090070ee", + "0x37200700723b0091db00915e00700723b00901100915500700723b009571", + "0x700723b00955800937400700723b00955a00937300700723b00955b009", + "0x723b00955500937700700723b00955c00937600700723b009557009375", + "0x923b00900722900700723b00955300937000700723b009554009371007", + "0x57a12e03000757b00923b00957b00902e00757b00923b0090073e300757a", + "0x923b00957d58112e03100758100923b00900722500757d00923b00957b", + "0x903300751300923b00951300912500758c00923b00958400944c007584", + "0x923b00955f00922100755e00923b00955e00900e00700900923b009009", + "0x900712e00758c55f55e0095131fd00958c00923b00958c00944d00755f", + "0x91db00915e00700723b00901100915500700723b0090070ea00700723b", + "0x55800937400700723b00955a00937300700723b00955b00937200700723b", + "0x937700700723b00955c00937600700723b00955700937500700723b009", + "0x44c00700723b00955300937000700723b00955400937100700723b009555", + "0x23b00900900903300751300923b00951300912500758f00923b009563009", + "0x44d00755f00923b00955f00922100755e00923b00955e00900e007009009", + "0x700723b00900712e00758f55f55e0095131fd00958f00923b00958f009", + "0x23b00951500922100757400923b00951400900e00700723b009552009111", + "0x75a459012e23b00957900907800757900923b0095190093f8007577009", + "0x23b0095a70093700075b82525b75b65b55b45b35a722323b0095a4009369", + "0x95b600937500700723b0095b500937600700723b0095b3009371007007", + "0x5b800937200700723b00925200937300700723b0095b700937400700723b", + "0x12e5bb00907b0075bb5ba5b912523b0095b45775741253da00700723b009", + "0x5bf00923b0095bc00918700700723b00900712e0075be0095bd5bc00923b", + "0x900714c00700723b0095c00091550072515c012e23b0095bf009153007", + "0x700723b0095c20091550075c35c212e23b0095c10091530075c100923b", + "0x5c50091550075c65c512e23b0095c40091530075c400923b009251009163", + "0x2505c812e23b0095c70091530075c700923b0095c300916300700723b009", + "0x92500091630075c900923b0095c600916300700723b0095c8009155007", + "0x5cb00923b0095cb00902e0075cb00923b0095ca5c912e14f0075ca00923b", + "0x900716c00700723b00900712e0075cd0095cc00723b12e5cb009106007", + "0x75d000923b0095cf0090a50075cf00923b0095ce0091440075ce00923b", + "0x16c00700723b0095cd00911100700723b00900712e0070075d10090070ee", + "0x923b0095d30090a50075d300923b0095d20091130075d200923b009007", + "0x91400075d400923b0095d40090a50075d400923b0095d000936e0075d0", + "0x723b0090070ea00700723b00900712e0075d70095d65d500923b12e5d4", + "0x23b00901100915500700723b0091db00915e00700723b0095d5009054007", + "0x23b00900748b0075d800923b00900722900700723b009590009152007007", + "0x75da00923b0095d95d812e0300075d900923b0095d900902e0075d9009", + "0x95dc00944c0075dc00923b0095da5db12e0310075db00923b009007225", + "0x700900923b00900900903300751300923b0095130091250075dd00923b", + "0x95dd00944d0075ba00923b0095ba0092210075b900923b0095b900900e", + "0x90070ea00700723b00900712e0075dd5ba5b90095131fd0095dd00923b", + "0x12500724e5de12e23b00959000907800700723b0095d700905400700723b", + "0x23b0095b900900e00700900923b00900900903300751300923b009513009", + "0x1fd00701100923b00901100902e0075ba00923b0095ba0092210075b9009", + "0x5df1fd23b0091db01124e5ba5b90095131db5b30071db00923b0091db009", + "0x23b00900712e0075e60095e55e400923b12e5e30091b00075e35e25e15e0", + "0x5ea0095e95e800923b12e5e70091400075e700923b0095e40091b2007007", + "0x723b0095de00915200700723b0095e800905400700723b00900712e007", + "0x23b0095ec00902e0075ec00923b0090075b40075eb00923b009007229007", + "0x310075ee00923b0090072250075ed00923b0095ec5eb12e0300075ec009", + "0x95df0091250075f000923b0095ef00944c0075ef00923b0095ed5ee12e", + "0x75e100923b0095e100900e0075e000923b0095e00090330075df00923b", + "0x5e15e05df1fd0095f000923b0095f000944d0075e200923b0095e2009221", + "0x23b00900716c00700723b0095ea00905400700723b00900712e0075f05e2", + "0x75f300923b0095f20094690075f200923b0095f15de12e4680075f1009", + "0x95e100900e0075e000923b0095e00090330075df00923b0095df009125", + "0x95f300923b0095f300944d0075e200923b0095e20092210075e100923b", + "0x700723b0095de00915200700723b00900712e0075f35e25e15e05df1fd", + "0x95e00090330075df00923b0095df0091250075f400923b0095e600944c", + "0x75e200923b0095e20092210075e100923b0095e100900e0075e000923b", + "0x723b00900712e0075f45e25e15e05df1fd0095f400923b0095f400944d", + "0x723b00901100915500700723b0091db00915e00700723b0090070ea007", + "0x951300912500724d00923b0095be00944c00700723b009590009152007", + "0x75b900923b0095b900900e00700900923b00900900903300751300923b", + "0x5b90095131fd00924d00923b00924d00944d0075ba00923b0095ba009221", + "0x901100915500700723b00953500905400700723b00900712e00724d5ba", + "0x52800915e00700723b00951900915200700723b0091db00915e00700723b", + "0x902e0075f600923b0090075840075f500923b00900722900700723b009", + "0x923b0090072250075f700923b0095f65f512e0300075f600923b0095f6", + "0x1250075fa00923b0095f900944c0075f900923b0095f75f812e0310075f8", + "0x23b00951400900e00700900923b00900900903300751300923b009513009", + "0x1fd0095fa00923b0095fa00944d00751500923b009515009221007514009", + "0x56600700723b00949900911100700723b00900712e0075fa515514009513", + "0x7b12e23b00907b00936b0075fb00923b0090075b500700723b009025009", + "0x1060075fd00923b0095fd00902e0075fd00923b0095fb5fc12e14f0075fc", + "0x23b00907b00915500700723b00900712e0075ff0095fe00723b12e5fd009", + "0xea00700723b00900712e00760200960160000923b12e223009140007007", + "0x60324c22323b00900e00936900700723b00960000905400700723b009007", + "0x905700912500760b60a12e23b0096090095a7007609608607606605604", + "0x722900923b00922900922100702e00923b00902e00900e00705700923b", + "0x923b12e60f0090dd00760f60e60d60c00e23b00960b22902e05700e515", + "0x12500701f00923b00961000918e00700723b00900712e007612009611610", + "0x23b00960e00922100760d00923b00960d00900e00760c00923b00960c009", + "0x761300923b00961300902600761301f12e23b00901f00957900760e009", + "0x61561400e23b00961360e60d60c00e57b00701f00923b00901f01512e57a", + "0x700723b00900712e00761900961824b00923b12e6170093b9007617616", + "0x923b00961400912500761a00923b00900756300700723b00924b0093bb", + "0x12557d00761a00923b00961a00902600701f00923b00901f009026007614", + "0x761f00961e61d00923b12e61c0090dd00761c61b12e23b00961a01f614", + "0x923b00961500900e00762000923b00961d00918e00700723b00900712e", + "0xe45200762000923b00962000902600761600923b009616009221007615", + "0x962562400923b12e62300924400762362262112523b00962060a616615", + "0x62700905400762724a12e23b00962400945700700723b00900712e007626", + "0x12500762800923b00924a60860760660560460324c22314800700723b009", + "0x23b00962200922100762a00923b00962100900e00762900923b00961b009", + "0x900712e00700762d0090070ee00762c00923b0096280093f800762b009", + "0x1800958100700723b0091db00915e00700723b00901100915500700723b", + "0x937400700723b00960800937300700723b00924c00937000700723b009", + "0x37700700723b00960500937600700723b00960600937500700723b009607", + "0x62e00923b00962600944c00700723b00960300937100700723b009604009", + "0x62100900e00700900923b00900900903300761b00923b00961b009125007", + "0x62e00923b00962e00944d00762200923b00962200922100762100923b009", + "0x723b00960400937700700723b00900712e00762e62262100961b1fd009", + "0x23b0091db00915e00700723b00901100915500700723b009603009371007", + "0x960800937300700723b00924c00937000700723b009018009581007007", + "0x60500937600700723b00960600937500700723b00960700937400700723b", + "0x12500762f00923b00961f00944c00700723b00960a00937200700723b009", + "0x23b00961500900e00700900923b00900900903300761b00923b00961b009", + "0x1fd00962f00923b00962f00944d00761600923b009616009221007615009", + "0x37100700723b00960400937700700723b00900712e00762f61661500961b", + "0x700723b0091db00915e00700723b00901100915500700723b009603009", + "0x723b00960800937300700723b00924c00937000700723b009018009581", + "0x23b00960500937600700723b00960600937500700723b009607009374007", + "0x961900944c00700723b00901f00902000700723b00960a009372007007", + "0x700900923b00900900903300761400923b00961400912500763000923b", + "0x963000944d00761600923b00961600922100761500923b00961500900e", + "0x60400937700700723b00900712e0076306166150096141fd00963000923b", + "0x915500700723b00960300937100700723b00960a00937200700723b009", + "0x37000700723b00901800958100700723b0091db00915e00700723b009011", + "0x700723b00960700937400700723b00960800937300700723b00924c009", + "0x723b00901500956600700723b00960500937600700723b009606009375", + "0x900903300760c00923b00960c00912500763100923b00961200944c007", + "0x60e00923b00960e00922100760d00923b00960d00900e00700900923b009", + "0x23b00900712e00763160e60d00960c1fd00963100923b00963100944d007", + "0x23b00901500956600700723b00960200905400700723b0090070ea007007", + "0x922100762a00923b00902e00900e00762900923b009057009125007007", + "0x12523b00901800957100762c00923b00900e0093f800762b00923b009229", + "0x901f00700723b00963300915500700723b009632009101007634633632", + "0x23b00963600902000763763612e23b00963500901500763500923b009634", + "0x902000763a63912e23b00963800901500763800923b009007025007007", + "0x63c00923b00963a00902300763b00923b00963700902300700723b009639", + "0x12e00700763d00723b12e63c63b12e22c00763b00923b00963b009026007", + "0x15200700723b0091db00915e00700723b00901100915500700723b009007", + "0x763f00923b00900758400763e00923b00900722900700723b00962c009", + "0x900722500764000923b00963f63e12e03000763f00923b00963f00902e", + "0x64300923b00964200944c00764200923b00964064112e03100764100923b", + "0x62a00900e00700900923b00900900903300762900923b009629009125007", + "0x64300923b00964300944d00762b00923b00962b00922100762a00923b009", + "0x12e23b00962c00907800700723b00900712e00764362b62a0096291fd009", + "0x937000764d64c64b64a64964864764622323b009645009369007645644", + "0x37500700723b00964900937600700723b00964700937100700723b009646", + "0x700723b00964c00937300700723b00964b00937400700723b00964a009", + "0x23b00962b00922100762a00923b00962a00900e00700723b00964d009372", + "0x23b12e65000907b00765064f64e12523b00964862b62a1253da00762b009", + "0x765400923b00965100918700700723b00900712e007653009652651009", + "0x23b00900714c00700723b00965500915500765665512e23b009654009153", + "0x16300700723b00965800915500765965812e23b009657009153007657009", + "0x965b00915500765c65b12e23b00965a00915300765a00923b009656009", + "0x765f65e12e23b00965d00915300765d00923b00965900916300700723b", + "0x23b00965f00916300766000923b00965c00916300700723b00965e009155", + "0x902e00700723b00900710f00766200923b00966166012e14f007661009", + "0x23b00900712e00725600966300723b12e66200910600766200923b009662", + "0x6650090a500766500923b00966400914400766400923b00900716c007007", + "0x25600911100700723b00900712e0070076670090070ee00766600923b009", + "0xa500766900923b00966800911300766800923b00900716c00700723b009", + "0x23b00966a0090a500766a00923b00966600936e00766600923b009669009", + "0x700723b00900712e00766d00966c66b00923b12e66a00914000766a009", + "0x700723b0091db00915e00700723b00966b00905400700723b0090070ea", + "0x66e00923b00900722900700723b00964400915200700723b009011009155", + "0x66f66e12e03000766f00923b00966f00902e00766f00923b00900748b007", + "0x67200923b00967067112e03100767100923b00900722500767000923b009", + "0x900903300762900923b00962900912500767300923b00967200944c007", + "0x64f00923b00964f00922100764e00923b00964e00900e00700900923b009", + "0x23b00900712e00767364f64e0096291fd00967300923b00967300944d007", + "0x67867767667567422323b00964400936900700723b00966d009054007007", + "0x62900923b00962900912500767d67c12e23b00967800943100767b67a679", + "0x62900e43200764f00923b00964f00922100764e00923b00964e00900e007", + "0x968368200923b12e6810090cf00768168067f67e00e23b00967d64f64e", + "0x968500924600768500923b0096820091a800700723b00900712e007684", + "0x68912e23b00968700915300700723b00968600934f00768868768612523b", + "0x968b00915300768b00923b00900714300700723b00968900915500768a", + "0x768e00923b00968a00916300700723b00968c00915500768d68c12e23b", + "0x69000902e00769000923b00968f68e12e14f00768f00923b00968d009163", + "0x723b00900712e00725800969100723b12e69000910600769000923b009", + "0x6770093dd00700723b00900712e00769300969200723b12e688009106007", + "0x923b00968000922100767f00923b00967f00900e00769569412e23b009", + "0x923b12e69800907b00769869769612523b00969568067f1253de007680", + "0x15300769b00923b00969900918700700723b00900712e00725700969a699", + "0x923b00900714c00700723b00969c00915500769d69c12e23b00969b009", + "0x916300700723b00969f0091550076a069f12e23b00969e00915300769e", + "0x23b0096a26a112e14f0076a200923b0096a00091630076a100923b00969d", + "0x6a50096a400723b12e6a30091060076a300923b0096a300902e0076a3009", + "0x23b0096970092210076a600923b00969600900e00700723b00900712e007", + "0x900712e0070076a90090070ee0076a800923b0096940093e10076a7009", + "0x91db00915e00700723b0096a500911100700723b0090070ea00700723b", + "0x67b00937200700723b00969400937600700723b00901100915500700723b", + "0x937500700723b00967900937400700723b00967a00937300700723b009", + "0x37100700723b00967600937700700723b00967400937000700723b00967c", + "0x725500923b0090073e30076aa00923b00900722900700723b009675009", + "0x90072250076ab00923b0092556aa12e03000725500923b00925500902e", + "0x6ae00923b0096ad00944c0076ad00923b0096ab6ac12e0310076ac00923b", + "0x69600900e00700900923b00900900903300767e00923b00967e009125007", + "0x6ae00923b0096ae00944d00769700923b00969700922100769600923b009", + "0x700723b0090070ea00700723b00900712e0076ae69769600967e1fd009", + "0x723b00969400937600700723b00901100915500700723b0091db00915e", + "0x23b00967900937400700723b00967a00937300700723b00967b009372007", + "0x967600937700700723b00967400937000700723b00967c009375007007", + "0x91250076af00923b00925700944c00700723b00967500937100700723b", + "0x923b00969600900e00700900923b00900900903300767e00923b00967e", + "0x67e1fd0096af00923b0096af00944d00769700923b009697009221007696", + "0x900e00700723b00969300911100700723b00900712e0076af697696009", + "0x923b0096770093e10076a700923b0096800092210076a600923b00967f", + "0x23b00967b67a67967c6a867667567422314800700723b0090070ea0076a8", + "0x767e00923b00967e0091250076b26b112e23b0096b00090780076b0009", + "0x96a70092210076a600923b0096a600900e00700900923b009009009033", + "0x71db00923b0091db0091fd00701100923b00901100902e0076a700923b", + "0x91b00076b76b66b56b46b31fd23b0091db0116b26a76a600967e1db5b3", + "0x23b0096b80091b200700723b00900712e0076ba0096b96b800923b12e6b7", + "0x700723b00900712e0076bd0096bc6bb00923b12e254009140007254009", + "0x6be00923b00900722900700723b0096b100915200700723b0096bb009054", + "0x6bf6be12e0300076bf00923b0096bf00902e0076bf00923b0090075b4007", + "0x6c200923b0096c06c112e0310076c100923b0090072250076c000923b009", + "0x6b40090330076b300923b0096b300912500725300923b0096c200944c007", + "0x6b600923b0096b60092210076b500923b0096b500900e0076b400923b009", + "0x23b00900712e0072536b66b56b46b31fd00925300923b00925300944d007", + "0x6c36b112e4680076c300923b00900716c00700723b0096bd009054007007", + "0x6b300923b0096b30091250076c500923b0096c40094690076c400923b009", + "0x6b60092210076b500923b0096b500900e0076b400923b0096b4009033007", + "0x76c56b66b56b46b31fd0096c500923b0096c500944d0076b600923b009", + "0x6c600923b0096ba00944c00700723b0096b100915200700723b00900712e", + "0x6b500900e0076b400923b0096b40090330076b300923b0096b3009125007", + "0x6c600923b0096c600944d0076b600923b0096b60092210076b500923b009", + "0x700723b0090070ea00700723b00900712e0076c66b66b56b46b31fd009", + "0x723b00901100915500700723b0091db00915e00700723b009258009111", + "0x23b00967a00937300700723b00967b00937200700723b009675009371007", + "0x967400937000700723b00967c00937500700723b009679009374007007", + "0x68800915500700723b00967700937600700723b00967600937700700723b", + "0x902e0076c800923b0090074d10076c700923b00900722900700723b009", + "0x923b0090072250076c900923b0096c86c712e0300076c800923b0096c8", + "0x1250076cc00923b0096cb00944c0076cb00923b0096c96ca12e0310076ca", + "0x23b00967f00900e00700900923b00900900903300767e00923b00967e009", + "0x1fd0096cc00923b0096cc00944d00768000923b00968000922100767f009", + "0x915e00700723b0090070ea00700723b00900712e0076cc68067f00967e", + "0x37200700723b00967500937100700723b00901100915500700723b0091db", + "0x700723b00967900937400700723b00967a00937300700723b00967b009", + "0x723b00967600937700700723b00967400937000700723b00967c009375", + "0x967e0091250076cd00923b00968400944c00700723b009677009376007", + "0x767f00923b00967f00900e00700900923b00900900903300767e00923b", + "0x67f00967e1fd0096cd00923b0096cd00944d00768000923b009680009221", + "0x901100915500700723b0091db00915e00700723b00900712e0076cd680", + "0x91250076ce00923b00965300944c00700723b00964400915200700723b", + "0x923b00964e00900e00700900923b00900900903300762900923b009629", + "0x6291fd0096ce00923b0096ce00944d00764f00923b00964f00922100764e", + "0x958100700723b0095ff00911100700723b00900712e0076ce64f64e009", + "0x15300700723b00922300904a00700723b00901500956600700723b009018", + "0x923b0090075b600700723b0096cf0091550076d06cf12e23b00907b009", + "0x916300700723b0096d20091550076d36d212e23b0096d10091530076d1", + "0x23b0096d50091550076d66d512e23b0096d40091530076d400923b0096d0", + "0x1550076d96d812e23b0096d70091530076d700923b0096d3009163007007", + "0x923b0096d90091630076da00923b0096d600916300700723b0096d8009", + "0x1060076dc00923b0096dc00902e0076dc00923b0096db6da12e14f0076db", + "0x923b00900716c00700723b00900712e0076de0096dd00723b12e6dc009", + "0x70ee0076e100923b0096e00090a50076e000923b0096df0091440076df", + "0x900716c00700723b0096de00911100700723b00900712e0070076e2009", + "0x76e100923b0096e40090a50076e400923b0096e30091130076e300923b", + "0x12e6e50091400076e500923b0096e50090a50076e500923b0096e100936e", + "0x5400700723b0090070ea00700723b00900712e0076e80096e76e600923b", + "0x700723b00901100915500700723b0091db00915e00700723b0096e6009", + "0x6ea00923b0090075b70076e900923b00900722900700723b00900e009152", + "0x72250076eb00923b0096ea6e912e0300076ea00923b0096ea00902e007", + "0x923b0096ed00944c0076ed00923b0096eb6ec12e0310076ec00923b009", + "0x900e00700900923b00900900903300705700923b0090570091250076ee", + "0x923b0096ee00944d00722900923b00922900922100702e00923b00902e", + "0x23b0096e800905400700723b00900712e0076ee22902e0090571fd0096ee", + "0x723b00907600911100700723b00900712e0070076ef0090070ee007007", + "0x23b00922300904a00700723b00923c00956600700723b009018009581007", + "0x901500956600700723b00902500956600700723b009026009566007007", + "0x2e00900e00715500923b00905700912500700723b0090070ea00700723b", + "0x923b0091550091250076f16f012e23b00900e00907800715700923b009", + "0x922100715700923b00915700900e00700900923b009009009033007155", + "0x923b0091db0091fd00701100923b00901100902e00722900923b009229", + "0x76f66f56f46f36f21fd23b0091db0116f12291570091551db4190071db", + "0x25b0093bb00700723b00900712e0076f80096f725b00923b12e6f60093b9", + "0x76fa00923b0096f96f012e4680076f900923b00900716c00700723b009", + "0x96f30090330076f200923b0096f20091250076fb00923b0096fa009469", + "0x76f500923b0096f50092210076f400923b0096f400900e0076f300923b", + "0x723b00900712e0076fb6f56f46f36f21fd0096fb00923b0096fb00944d", + "0x96f20091250076fc00923b0096f800944c00700723b0096f0009152007", + "0x76f400923b0096f400900e0076f300923b0096f30090330076f200923b", + "0x6f46f36f21fd0096fc00923b0096fc00944d0076f500923b0096f5009221", + "0x91db00915e00700723b00901100915500700723b00900712e0076fc6f5", + "0xe00915200700723b00923c00956600700723b00912600910100700723b", + "0x956600700723b00902600956600700723b00922300904a00700723b009", + "0x44c00700723b00901b00956500700723b00901500956600700723b009025", + "0x23b00900900903300705700923b0090570091250076fd00923b00915d009", + "0x44d00722900923b00922900922100702e00923b00902e00900e007009009", + "0x700723b00900712e0076fd22902e0090571fd0096fd00923b0096fd009", + "0x723b00901100915500700723b0091db00915e00700723b00900e009152", + "0x23b00901b00956500700723b0091fd00936500700723b009015009566007", + "0x902600956600700723b00922300904a00700723b00923c009566007007", + "0x91250076fe00923b00903100944c00700723b00902500956600700723b", + "0x923b00902e00900e00700900923b00900900903300700700923b009007", + "0x71fd0096fe00923b0096fe00944d00722900923b00922900922100702e", + "0x714c00700e00923b00900725200700723b0090070ea0076fe22902e009", + "0x900923b00900900900e00700700923b0090070091250071fd00923b009", + "0x1fd00902e00712500923b00912500912300712e00923b00912e009221007", + "0x1fd12512e0090070115b900700e00923b00900e0095b80071fd00923b009", + "0x701f0096ff01b00923b12e0180095ba0070182231db01100e23b00900e", + "0x1500936500702302502001500e23b00901b0095bb00700723b00900712e", + "0x95bc00700723b00902300905400700723b00902500915500700723b009", + "0x923b00901100912500722c00923b0090260095be00702600923b009020", + "0x95bf00722300923b0092230092210071db00923b0091db00900e007011", + "0x95c000700723b00900712e00722c2231db01100e00922c00923b00922c", + "0x923b0091db00900e00701100923b00901100912500723c00923b00901f", + "0x1100e00923c00923b00923c0095bf00722300923b0092230092210071db", + "0x925100700e00923b00900e00930f00700723b0090070ea00723c2231db", + "0x71db00923b00900722900701100923b0090072290071fd00923b00900e", + "0x900700912500700723b0092230095c200701822312e23b0091fd0095c1", + "0x701800923b0090180095c300700900923b00900900900e00700700923b", + "0x90071fd5c40071db00923b0091db00915700701100923b009011009157", + "0x2500970002000923b12e0150095c500701501f01b12523b0091db011018", + "0x22c00905400722c02602312523b0090200095c600700723b00900712e007", + "0x700723b00923c00905700722923c12e23b00902300915900700723b009", + "0x2e00905700703002e12e23b00902600915900702c00923b009229009058", + "0x91fd00700723b00900710f00722500923b00903000905800700723b009", + "0x22502c12e01f00e5c700722500923b0092250091fd00702c00923b00902c", + "0x900716c00700723b00900712e00703622103312570104503112e23b12e", + "0x703a00923b00903100900e00703800923b0092190093b400721900923b", + "0x7020090070ee00712600923b0090380093b500703b00923b009045009221", + "0x903300900e00703c00923b0090360093b700700723b00900712e007007", + "0x712600923b00903c0093b500703b00923b00922100922100703a00923b", + "0x12e00704100970314100923b12e03e0093b900703e00923b0091260095c8", + "0x46800714500923b00914100925000700723b0090070ea00700723b009007", + "0x901b00912500714800923b00904300946900704300923b00914512512e", + "0x703b00923b00903b00922100703a00923b00903a00900e00701b00923b", + "0x700723b00900712e00714803b03a01b00e00914800923b00914800944d", + "0x4700923b00904100944c00700723b00912500915200700723b0090070ea", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00704703b03a01b00e00904700923b00904700944d00703b00923b009", + "0x704900923b00902500944c00700723b00912500915200700723b009007", + "0x912e00922100701f00923b00901f00900e00701b00923b00901b009125", + "0x75c900704912e01f01b00e00904900923b00904900944d00712e00923b", + "0x900721900700723b0090070ea00700723b0090071600071fd00923b009", + "0x12e23b12e01100900712503a00701100923b00901100903800701100923b", + "0x1f00923b00912e0095ca00700723b00900712e00701b01812e7042231db", + "0x23b12e01f0095cb0071db00923b0091db00912500700723b00900710f007", + "0x2300923b0090200095cd00700723b00900712e00702500970502001512e", + "0x90070ee00702600923b0090230095ce00700e00923b00901500916b007", + "0x922c0095cf00722c00923b00900716c00700723b00900712e007007706", + "0x702600923b00923c0095ce00700e00923b00902500916b00723c00923b", + "0x702c00970722900923b12e0260095d200700e00923b00900e1fd12e5d0", + "0x702e00923b0092290095d300700723b0090070ea00700723b00900712e", + "0x902e0091fd00722300923b00922300900e0071db00923b0091db009125", + "0x23b00912502e2231db00e5d400712500923b00912500915700702e00923b", + "0x23b00900712e00703300970804500923b12e03100906e007031225030125", + "0x5400721903612e23b00904500906f00722100923b00900e009241007007", + "0x923b00922500900e00703000923b00903000912500700723b009219009", + "0xe31600703600923b00903600915700722100923b009221009315007225", + "0x970912600923b12e03b00906e00703b03a03812523b009036221225030", + "0x14100905400714103e12e23b00912600906f00700723b00900712e00703c", + "0x714500923b00903a00900e00704100923b00903800912500700723b009", + "0x700723b00900712e00700770a0090070ee00704300923b00903e009157", + "0x903a00900e00703800923b00903800912500714800923b00903c00931b", + "0x900712e00714803a03812500914800923b00914800931a00703a00923b", + "0x912500704700923b00903300931b00700723b00900e0095d500700723b", + "0x923b00904700931a00722500923b00922500900e00703000923b009030", + "0x5400700723b0090070ea00700723b00900712e007047225030125009047", + "0x4100923b0091db00912500700723b00900e0095d500700723b00902c009", + "0x900716c00704300923b00912500915700714500923b00922300900e007", + "0x4c00923b00915000931900715000923b00904904312e31800704900923b", + "0x4c00931a00714500923b00914500900e00704100923b009041009125007", + "0x91fd0095d700700723b00900712e00704c14504112500904c00923b009", + "0x900722900700723b00912e0095d800700723b00912500905700700723b", + "0x3000715300923b00915300902e00715300923b00900705d00715200923b", + "0x915515712e03100715700923b00900722500715500923b00915315212e", + "0x701800923b00901800912500705400923b00905200931b00705200923b", + "0x5401b01812500905400923b00905400931a00701b00923b00901b00900e", + "0x923b0091fd0090380071fd00923b00900721900700723b0090070ea007", + "0x900712e00701822312e70b1db01112e23b12e1fd00900712503a0071fd", + "0x701100923b00901100912500701b00e12e23b00900e00936b00700723b", + "0x900e00915500700723b00900712e00701f00970c00723b12e01b009106", + "0x702000923b00901512e12e32700701500923b0091250095d900700723b", + "0x91db00900e00701100923b00901100912500702500923b009020009328", + "0x900712e0070251db01112500902500923b0090250093290071db00923b", + "0x916e00712e00923b00912e0091fd00700723b00901f00911100700723b", + "0x712e00723c00970d22c00923b12e02600907200702602312e23b00912e", + "0x702c00923b00900714300722900923b00922c12512e03000700723b009", + "0x1db00900e00701100923b00901100912500702e00923b00902c00e12e14f", + "0x22900923b00922900915700702300923b0090230091fd0071db00923b009", + "0x3012523b00902e2290231db0111fd32500702e00923b00902e00902e007", + "0x700723b00900712e00703300970e04500923b12e031009076007031225", + "0x932800721900923b00903622112e32700703622112e23b009045009180", + "0x923b00922500900e00703000923b00903000912500703800923b009219", + "0x723b00900712e00703822503012500903800923b009038009329007225", + "0x22500900e00703000923b00903000912500703a00923b00903300932a007", + "0x712e00703a22503012500903a00923b00903a00932900722500923b009", + "0x923f00700723b00912500905700700723b00900e00915500700723b009", + "0x23b00912600932800712600923b00903b02312e32700703b00923b00923c", + "0x3290071db00923b0091db00900e00701100923b00901100912500703c009", + "0x915500700723b00900712e00703c1db01112500903c00923b00903c009", + "0x22900700723b00912e00915e00700723b00912500905700700723b00900e", + "0x14100923b00914100902e00714100923b00900705d00703e00923b009007", + "0x14512e03100714500923b00900722500704100923b00914103e12e030007", + "0x923b00922300912500714800923b00904300932a00704300923b009041", + "0x22312500914800923b00914800932900701800923b00901800900e007223", + "0x5da00701100923b0090110091fd00700700923b009007009125007148018", + "0x701b00970f01800923b12e2230095db0072231db12e23b00901100712e", + "0x12e23b00901f0095dd00701f00923b0090180095dc00700723b00900712e", + "0xe00700900923b0090090090330071db00923b0091db009125007020015", + "0x23b00900e0095de00712500923b00912500922100712e00923b00912e009", + "0x2300923b00902300902e0070231fd12e23b0091fd00936b00702500e12e", + "0x23b00901502302512512e0091db1db5b300701500923b0090150091fd007", + "0x712e00703000971002e00923b12e02c0091b000702c22923c22c0261fd", + "0x71103100923b12e22500914000722500923b00902e0091b200700723b009", + "0x900e00915200700723b00903100905400700723b00900712e007045009", + "0x900716c00700723b00902000915e00700723b0091fd00915500700723b", + "0x703600923b00922100939900722100923b00903300911300703300923b", + "0x922c00903300702600923b00902600912500721900923b00903600939a", + "0x722900923b00922900922100723c00923b00923c00900e00722c00923b", + "0x723b00900712e00721922923c22c0261fd00921900923b00921900939b", + "0x3800936900703800e12e23b00900e0095de00700723b009045009054007", + "0x37100700723b00903a00937000714504114103e03c12603b03a22323b009", + "0x700723b00903e00937500700723b00903c00937600700723b00903b009", + "0x723b00914500937200700723b00904100937300700723b009141009374", + "0x23c1253da00722900923b00922900922100723c00923b00923c00900e007", + "0x715000971204900923b12e04700907b00704714804312523b009126229", + "0x723b12e04c00910600704c00923b00904900918700700723b00900712e", + "0xe00915200700723b0091fd00915500700723b00900712e007152009713", + "0x715500923b00915300901f00715300923b00902000901b00700723b009", + "0x23b00900702500700723b00915700902000705215712e23b009155009015", + "0x2300700723b00915900902000705715912e23b009054009015007054009", + "0x23b00905800902600705a00923b00905700902300705800923b009052009", + "0x16c00700723b00900712e00700771400723b12e05a05812e22c007058009", + "0x923b00905d0090a500705d00923b00915d00911300715d00923b009007", + "0x6000923b00900716c00700723b00900712e0070077150090070ee00715e", + "0x2600912500715e00923b00915f0090a500715f00923b009060009144007", + "0x16100923b00904300900e00706400923b00922c00903300716000923b009", + "0x90070ee00706700923b00915e0090a500716200923b009148009221007", + "0x902600912500700723b00915200911100700723b00900712e007007716", + "0x704300923b00904300900e00722c00923b00922c00903300702600923b", + "0x90200091fd0071fd00923b0091fd00902e00714800923b009148009221", + "0x16b1681661641fd23b0090201fd00e14804322c0261db58c00702000923b", + "0x1b200700723b00900712e00706f00971706e00923b12e06d0091b000706d", + "0x23b00916600903300716000923b00916400912500707100923b00906e009", + "0xa500716200923b00916b00922100716100923b00916800900e007064009", + "0x23b00916e00939a00716e00923b00906700939900706700923b009071009", + "0xe00706400923b00906400903300716000923b009160009125007072009", + "0x23b00907200939b00716200923b00916200922100716100923b009161009", + "0x906f00939c00700723b00900712e0070721621610641601fd009072009", + "0x716600923b00916600903300716400923b00916400912500707400923b", + "0x907400939b00716b00923b00916b00922100716800923b00916800900e", + "0x2000915e00700723b00900712e00707416b1681661641fd00907400923b", + "0x939c00700723b00900e00915200700723b0091fd00915500700723b009", + "0x923b00922c00903300702600923b00902600912500717400923b009150", + "0x939b00714800923b00914800922100704300923b00904300900e00722c", + "0x15200700723b00900712e00717414804322c0261fd00917400923b009174", + "0x700723b00902000915e00700723b0091fd00915500700723b00900e009", + "0x922c00903300702600923b00902600912500707600923b00903000939c", + "0x722900923b00922900922100723c00923b00923c00900e00722c00923b", + "0x723b00900712e00707622923c22c0261fd00907600923b00907600939b", + "0x23b00901b00939c00700723b0091fd00915500700723b00900e009152007", + "0xe00700900923b0090090090330071db00923b0091db009125007180009", + "0x23b00918000939b00712500923b00912500922100712e00923b00912e009", + "0x916e00700900923b0090090091fd00718012512e0091db1fd009180009", + "0x712e0071fd00971800e00923b12e12500907200712512e12e23b009009", + "0x900712e0072230097191db01112e23b12e00e00712e24e00700723b009", + "0x1fd00701100923b00901100912500701800923b0091db0095df00700723b", + "0x701812e01112500901800923b0090180095e000712e00923b00912e009", + "0x1f00923b00901b0095e100701b00923b00900716c00700723b00900712e", + "0x1f0095e000712e00923b00912e0091fd00722300923b009223009125007", + "0x91fd0095e100700723b00900712e00701f12e22312500901f00923b009", + "0x712e00923b00912e0091fd00700700923b00900700912500701500923b", + "0x12e23b12e00900712e5e200701512e00712500901500923b0090150095e0", + "0x71fd00923b0091250095e300700723b00900712e00700e00971a12512e", + "0x71b0090070ee0071db00923b0091fd0095e400701100923b00912e009125", + "0x23b0092230095e600722300923b00900716c00700723b00900712e007007", + "0x12e0091db00923b0090180095e400701100923b00900e009125007018009", + "0x12500917500712500923b00912e00901b00700723b0090070ea0071db011", + "0x23b0091fd00917100700723b00900712e00701100971c1fd00e12e23b12e", + "0xee00701800923b0091db0090ec00722300923b00900e0090b40071db009", + "0x90f000701b00923b00900716c00700723b00900712e00700771d009007", + "0x923b00901f0090ec00722300923b0090110090b400701f00923b00901b", + "0x916900701500923b0090150091fd00701500923b009223009058007018", + "0x23b00902000916500700723b00900712e00702500971e02000923b12e018", + "0x912500722c00923b00902300916300702600923b0090070f3007023009", + "0x923b0090150091fd00700900923b00900900900e00700700923b009007", + "0x1fd0f600722c00923b00922c00902e00702600923b009026009047007015", + "0x71f02e00923b12e02c0091db00702c22923c12523b00922c026015009007", + "0x901800703122512e23b00902e00922300700723b00900712e007030009", + "0x23b00904500911c00700723b00900712e00703300972004500923b12e031", + "0x5e700721900923b00903600912800700723b00922100923c00703622112e", + "0x903a0095ea00703a00923b00903822512e5e800703800923b009219009", + "0x722900923b00922900900e00723c00923b00923c00912500703b00923b", + "0x5ec00700723b00900712e00703b22923c12500903b00923b00903b0095eb", + "0x903c0095ea00703c00923b00912622512e5e800712600923b009033009", + "0x722900923b00922900900e00723c00923b00923c00912500703e00923b", + "0x5ed00700723b00900712e00703e22923c12500903e00923b00903e0095eb", + "0x23b00922900900e00723c00923b00923c00912500714100923b009030009", + "0x23b00900712e00714122923c12500914100923b0091410095eb007229009", + "0x90410095ec00704100923b00900716c00700723b009025009054007007", + "0x14800923b0090430095ea00704300923b00914501512e5e800714500923b", + "0x1480095eb00700900923b00900900900e00700700923b009007009125007", + "0x922100700700923b00900700900e00714800900712500914800923b009", + "0xe0095ef00700e12512e12523b00900900712e5ee00700900923b009009", + "0x923b0091fd0095f000700723b00900712e0070110097211fd00923b12e", + "0x701f01b01812523b0092230095f200722300923b0091db0095f10071db", + "0x923b00901b0095f300700723b00901f00910100700723b00901800934f", + "0x922100712e00923b00912e00900e00702000923b0090150095f4007015", + "0x12e00702012512e12500902000923b00902000924d00712500923b009125", + "0x12e00923b00912e00900e00702500923b0090110095f500700723b009007", + "0x12512e12500902500923b00902500924d00712500923b009125009221007", + "0x902e00712e00923b00912e00909900700700923b009007009125007025", + "0x5f70072231db01112523b0091fd00e12e00700e5f60071fd00923b0091fd", + "0x923b00901b00902600701b00923b00900702500701800923b009223009", + "0x702602302512572202001501f12523b12e01801b12500900e5f800701b", + "0x23b00922c00915500723c22c12e23b00902000915300700723b00900712e", + "0x915500702e02c12e23b00922900915300722900923b00900714c007007", + "0x22512e23b00903000915300703000923b00923c00916300700723b00902c", + "0x4500915300704500923b00902e00916300700723b009225009155007031", + "0x3600923b00903100916300700723b00903300915500722103312e23b009", + "0x3612e14f00703600923b00903600902e00721900923b009221009163007", + "0x923b00901f00900e00703800923b00903800902e00703800923b009219", + "0x703a00972300723b12e03800910600701500923b00901500922100701f", + "0x12600923b00903b00914400703b00923b00900716c00700723b00900712e", + "0x723b00900712e0070077240090070ee00703c00923b0091260090a5007", + "0x23b00903e00911300703e00923b00900716c00700723b00903a009111007", + "0x5f900704100923b00903c00936e00703c00923b0091410090a5007141009", + "0x23b00901500922100704300923b00901f00900e00714500923b009041009", + "0x900712e0070077250090070ee00704700923b0091450095fa007148009", + "0x22100704300923b00902500900e00704900923b0090260095fb00700723b", + "0x23b0090470095fc00704700923b0090490095fa00714800923b009023009", + "0x700723b00900712e00715200972604c00923b12e1500091b0007150009", + "0x915500939a00715500923b00915300939900715300923b00904c0091b2", + "0x704300923b00904300900e00701100923b00901100912500715700923b", + "0x915700939b00714800923b0091480092210071db00923b0091db009099", + "0x15200939c00700723b00900712e0071571481db0430111fd00915700923b", + "0x4300923b00904300900e00701100923b00901100912500705200923b009", + "0x5200939b00714800923b0091480092210071db00923b0091db009099007", + "0x700700923b00900700900e0070521481db0430111fd00905200923b009", + "0x54e00700e12512e12523b00900900712e54d00700900923b009009009221", + "0x91fd00955000700723b00900712e0070110097271fd00923b12e00e009", + "0x1b0181fd23b00922300955200722300923b0091db0095510071db00923b", + "0x910100700723b00901b00955400700723b00901800955300702001501f", + "0x702500923b00901500955500700723b00902000915500700723b00901f", + "0x912500922100712e00923b00912e00900e00702300923b009025009556", + "0x900712e00702312512e12500902300923b00902300955700712500923b", + "0x22100712e00923b00912e00900e00702600923b00901100955800700723b", + "0x702612512e12500902600923b00902600955700712500923b009125009", + "0x5fd00700723b0090070ea00700723b0090071600071fd00923b00900755f", + "0x701f01b0182231db1fd23b00901100935600701112512e23b009125009", + "0x723b00901800934f00700723b00922300915500700723b0091db009101", + "0x901500956100701500923b00901f0095ff00700723b00901b00934f007", + "0xe00923b00900e1fd12e57a00700e00923b00902000956200702000923b", + "0x902300937b00702300923b00900714c00702500923b00900e0090df007", + "0x23c1fd23b00922c00935600722c12512e23b0091250095fd00702600923b", + "0x34f00700723b00922900915500700723b00923c00910100703002e02c229", + "0x22500923b0090300095ff00700723b00902e00934f00700723b00902c009", + "0x12e00909900700900923b00900900900e00700700923b009007009125007", + "0x2600923b00902600960000722500923b00922500912300712e00923b009", + "0x1160200703100923b00903100902e00703102512e23b00902500936b007", + "0x923b12e03600924c00703622103304500e23b00903102622512e009007", + "0x937b00703a00923b00900714c00700723b00900712e007038009728219", + "0x3c00923b00903b00937d00712600923b00900760300703b00923b00903a", + "0x22112537e00712600923b00912600902e00703c00923b00903c00902e007", + "0x4100935600704112512e23b0091250095fd00714103e12e23b00912603c", + "0x914800934f00700723b0090430091550070490471480431451fd23b009", + "0x14500910200700723b00904900936500700723b00904700934f00700723b", + "0x15200923b00914100937b00704c00923b00915000910400715000923b009", + "0x3e12537e00715300923b00915300902e00715300923b00915200937d007", + "0x91250095fd00705200923b00915700937b00715715512e23b00904c153", + "0x15900910100715d05a0580571591fd23b00905400935600705412512e23b", + "0x936500700723b00905a00934f00700723b00905800934f00700723b009", + "0x15e00923b00905200937d00705d00923b00905700916300700723b00915d", + "0x715f06012e23b00905d15e15512537e00715e00923b00915e00902e007", + "0x1640671621610641fd23b00916000935600716012512e23b0091250095fd", + "0x23b00906700934f00700723b00916100915500700723b009064009101007", + "0x16600950500716600923b00916200950400700723b009164009365007007", + "0x6d00923b00916b00937d00716b00923b00915f00937b00716800923b009", + "0x706f06e12e23b00916806d06012537e00706d00923b00906d00902e007", + "0x15500700723b00907100910100717407407216e0711fd23b009125009356", + "0x700723b00917400936500700723b00907200934f00700723b00916e009", + "0x906f00937b00718000923b00907600950500707600923b009074009504", + "0x707800923b00907800902e00707800923b00907700937d00707700923b", + "0x37d00718700923b00907b00937b00707b18612e23b00918007806e12537e", + "0x2508d18612537e00708d00923b00908d00902e00708d00923b009187009", + "0x908f00936500709109008f12523b00921900960400708e07f12e23b009", + "0x937d00709200923b00908e00937b00700723b00909000960500700723b", + "0x909109307f12537e00709300923b00909300902e00709300923b009092", + "0x709700923b00900760600709600923b00909500937b00709509412e23b", + "0x909700902e00709800923b00909800902e00709800923b00909600937d", + "0x23b0091a500937b0071a509912e23b00909709809412537e00709700923b", + "0x33000703700923b0091a700932f0071a700923b00909c00937d00709c009", + "0x23b00903300900e00704500923b00904500912500705b00923b009037009", + "0xe00905b00923b00905b00933100709900923b009099009099007033009", + "0x909800700723b00902500915500700723b00900712e00705b099033045", + "0x4500923b00904500912500709f00923b00903800933200700723b009125", + "0x9f00933100722100923b00922100909900703300923b00903300900e007", + "0x72231db12e23b00900e00936a00709f22103304500e00909f00923b009", + "0x91fd00902e00712e00923b00912e00909900700700923b009007009125", + "0x1100960700701f01b01812523b0091fd22312e00700e5f60071fd00923b", + "0x702500923b00900702500702000923b00901f0095f700701500923b009", + "0x2602312e23b12e0150200251250091fd60800702500923b009025009026", + "0x3b400702c00923b00900716c00700723b00900712e00722923c22c125729", + "0x23b00902600922100703000923b00902300900e00702e00923b00902c009", + "0x900712e00700772a0090070ee00703100923b00902e0093b5007225009", + "0x22100703000923b00922c00900e00704500923b0092290093b700700723b", + "0x23b0090310095c800703100923b0090450093b500722500923b00923c009", + "0x700723b00900712e00703600972b22100923b12e0330093b9007033009", + "0x3800960a00703800923b0092191db12e60900721900923b009221009250", + "0x3000923b00903000900e00701800923b00901800912500703a00923b009", + "0x3a00960b00722500923b00922500922100701b00923b00901b009099007", + "0x937400700723b00900712e00703a22501b0300181fd00903a00923b009", + "0x1800923b00901800912500703b00923b00903600960c00700723b0091db", + "0x22500922100701b00923b00901b00909900703000923b00903000900e007", + "0x703b22501b0300181fd00903b00923b00903b00960b00722500923b009", + "0x91fd0091550070111fd12e23b00912500915300700e00923b009007229", + "0x5200700e00923b00900e00915700701100923b00901100902e00700723b", + "0x912e00960d00700723b0092230090540072231db12e23b00900e01112e", + "0x701501f12e23b0091db00915900701b00923b00900760e00701800923b", + "0x23b00901b00902e00702000923b00901500905800700723b00901f009057", + "0x23b12e02001b0180090071fd60f00702000923b0090200091fd00701b009", + "0x902600961000700723b00900712e00722923c22c12572c026023025125", + "0x703000923b00902300922100702e00923b00902500900e00702c00923b", + "0x700723b00900712e00700772d0090070ee00722500923b00902c009612", + "0x923c00922100702e00923b00922c00900e00703100923b009229009613", + "0x704500923b00922500961400722500923b00903100961200703000923b", + "0x3300961600700723b00900712e00722100972e03300923b12e045009615", + "0x21912e23b00903600961700703600923b0090360091fd00703600923b009", + "0x703b00972f03a00923b12e03800924b00700723b00921900915e007038", + "0x923b00912600939a00712600923b00903a00939900700723b00900712e", + "0x939b00703000923b00903000922100702e00923b00902e00900e00703c", + "0x3b00905400700723b00900712e00703c03002e12500903c00923b00903c", + "0x902e00714100923b00900761900703e00923b00900722900700723b009", + "0x923b00900722500704100923b00914103e12e03000714100923b009141", + "0xe00714800923b00904300939c00704300923b00904114512e031007145", + "0x23b00914800939b00703000923b00903000922100702e00923b00902e009", + "0x923b00922100939c00700723b00900712e00714803002e125009148009", + "0x939b00703000923b00903000922100702e00923b00902e00900e007047", + "0x93b500700900923b00900761a00704703002e12500904700923b009047", + "0x23b00900900712e61b00700900923b00900900902e00700700923b009007", + "0x700723b00900712e00700e00973012500923b12e12e0093b900712e009", + "0x901100961d00701100923b0091fd00961c0071fd00923b009125009250", + "0x723b00900712e0071db0090091db00923b0091db00961f0071db00923b", + "0x722300900922300923b00922300961f00722300923b00900e009620007", + "0x923b00900e00962100700e00923b00900e0093bd00700723b0090070ea", + "0x91fd0095c10071db00923b00900722900701100923b0090072290071fd", + "0x700700923b00900700912500700723b0092230095c200701822312e23b", + "0x901100915700701800923b0090180095c300700900923b00900900900e", + "0x91db0110180090071fd5c40071db00923b0091db00915700701100923b", + "0x900712e00702500973102000923b12e0150095c500701501f01b12523b", + "0x700723b00922c00905400722c02602312523b0090200095c600700723b", + "0x922900905800700723b00923c00905700722923c12e23b009023009159", + "0x700723b00902e00905700703002e12e23b00902600915900702c00923b", + "0x923b00902c0091fd00700723b00900710f00722500923b009030009058", + "0x3112e23b12e22502c12e01f00e5c700722500923b0092250091fd00702c", + "0x721900923b00900716c00700723b00900712e007036221033125732045", + "0x904500922100703a00923b00903100900e00703800923b0092190093b4", + "0x712e0070077330090070ee00712600923b0090380093b500703b00923b", + "0x703a00923b00903300900e00703c00923b0090360093b700700723b009", + "0x91260095c800712600923b00903c0093b500703b00923b009221009221", + "0x723b00900712e00704100973414100923b12e03e0093b900703e00923b", + "0x914512512e46800714500923b00914100925000700723b0090070ea007", + "0x701b00923b00901b00912500714800923b00904300946900704300923b", + "0x914800944d00703b00923b00903b00922100703a00923b00903a00900e", + "0x23b0090070ea00700723b00900712e00714803b03a01b00e00914800923b", + "0x1b00912500704700923b00904100944c00700723b009125009152007007", + "0x3b00923b00903b00922100703a00923b00903a00900e00701b00923b009", + "0x723b00900712e00704703b03a01b00e00904700923b00904700944d007", + "0x901b00912500704900923b00902500944c00700723b009125009152007", + "0x712e00923b00912e00922100701f00923b00901f00900e00701b00923b", + "0x1100923b00900715f00704912e01f01b00e00904900923b00904900944d", + "0x71db00923b00900722900700723b0090070ea00700723b009007160007", + "0x900700912500700723b00922300905700701822312e23b00900e009159", + "0x701800923b0090180090b400700900923b00900900900e00700700923b", + "0x1501f01b12523b0091db01800900700e0b60071db00923b0091db009157", + "0x906f00700723b00900712e00702500973502000923b12e01500906e007", + "0x923b00912500962200700723b00902600905400702602312e23b009020", + "0x905700702c22912e23b00902300915900723c00923b0090075b600722c", + "0x2e00700723b00900710f00702e00923b00902c00905800700723b009229", + "0x22c12e01f1fd60f00702e00923b00902e0091fd00723c00923b00923c009", + "0x700723b00900712e00722103304512573603122503012523b12e02e23c", + "0x922500922100721900923b00903000900e00703600923b009031009610", + "0x712e0070077370090070ee00703800923b0090360096120071fd00923b", + "0x721900923b00904500900e00703a00923b00922100961300700723b009", + "0x903800961400703800923b00903a0096120071fd00923b009033009221", + "0x12600923b12e03b0096150071fd00923b0091fd01112e16200703b00923b", + "0x912600961600700723b0090070ea00700723b00900712e00703c009738", + "0x721900923b00921900900e00701b00923b00901b00912500703e00923b", + "0x714504114112523b00903e21901b12517400703e00923b00903e0091fd", + "0x4300918000700723b00900712e00714800973904300923b12e145009076", + "0x15000923b12e04900907700700723b00904700915e00704904712e23b009", + "0x962400715200923b00915000962300700723b00900712e00704c00973a", + "0x923b00904100900e00714100923b00914100912500715300923b009152", + "0x14100e00915300923b0091530096260071fd00923b0091fd009221007041", + "0x900722900700723b00904c00905400700723b00900712e0071531fd041", + "0x3000715700923b00915700902e00715700923b00900761900715500923b", + "0x905205412e03100705400923b00900722500705200923b00915715512e", + "0x714100923b00914100912500705700923b00915900924a00715900923b", + "0x90570096260071fd00923b0091fd00922100704100923b00904100900e", + "0x914800924a00700723b00900712e0070571fd04114100e00905700923b", + "0x704100923b00904100900e00714100923b00914100912500705800923b", + "0x1fd04114100e00905800923b0090580096260071fd00923b0091fd009221", + "0x923b00903c00924a00700723b0090070ea00700723b00900712e007058", + "0x922100721900923b00921900900e00701b00923b00901b00912500705a", + "0x705a1fd21901b00e00905a00923b00905a0096260071fd00923b0091fd", + "0x700723b00912500962700700723b00901100906400700723b00900712e", + "0x901f00900e00701b00923b00901b00912500715d00923b00902500924a", + "0x915d00923b00915d00962600712e00923b00912e00922100701f00923b", + "0x3800700e00923b00900721900700723b0090070ea00715d12e01f01b00e", + "0x1db12e73b0111fd12e23b12e00e00900712503a00700e00923b00900e009", + "0x23b00900710f00701800923b00912e00901b00700723b00900712e007223", + "0x973c01f01b12e23b12e0180091750071fd00923b0091fd009125007007", + "0x901b0090b400702000923b00901f00917100700723b00900712e007015", + "0x712e00700773d0090070ee00702300923b0090200090ec00702500923b", + "0xb400722c00923b0090260090f000702600923b00900716c00700723b009", + "0x23b12e02300916900702300923b00922c0090ec00702500923b009015009", + "0x916500700723b0090070ea00700723b00900712e00722900973e23c009", + "0x923b00912500915700702c00923b00902c00902e00702c00923b00923c", + "0x5800700723b00903000905400703002e12e23b00912502c12e052007125", + "0x23b00901100900e0071fd00923b0091fd00912500722500923b009025009", + "0x3cb00702e00923b00902e00915700722500923b0092250091fd007011009", + "0x73f22100923b12e03300906e00703304503112523b00902e2250111fd00e", + "0x905400703821912e23b00922100906f00700723b00900712e007036009", + "0x3b00923b00904500900e00703a00923b00903100912500700723b009038", + "0x723b00900712e0070077400090070ee00712600923b009219009157007", + "0x4500900e00703100923b00903100912500703c00923b00903600931b007", + "0x712e00703c04503112500903c00923b00903c00931a00704500923b009", + "0x2500957200700723b00922900905400700723b0090070ea00700723b009", + "0x703b00923b00901100900e00703a00923b0091fd00912500700723b009", + "0x903e12612e31800703e00923b00900716c00712600923b009125009157", + "0x703a00923b00903a00912500704100923b00914100931900714100923b", + "0x4103b03a12500904100923b00904100931a00703b00923b00903b00900e", + "0x723b00912e00915e00700723b00912500905700700723b00900712e007", + "0x23b00904300902e00704300923b00900705d00714500923b009007229007", + "0x3100704700923b00900722500714800923b00904314512e030007043009", + "0x91db00912500715000923b00904900931b00704900923b00914804712e", + "0x915000923b00915000931a00722300923b00922300900e0071db00923b", + "0x5f700712500923b00900762800700723b00912e0093710071502231db125", + "0x923b0091fd0090260071fd00923b00900702500700e00923b009125009", + "0x1112523b12e00e1fd00900700e5f800700e00923b00900e0096290071fd", + "0x923b00922300962a00700723b00900712e00701f01b0181257412231db", + "0x962b00702500923b0091db00922100702000923b00901100900e007015", + "0x962c00700723b00900712e0070077420090070ee00702300923b009015", + "0x923b00901b00922100702000923b00901800900e00702600923b00901f", + "0x907b00722c00923b00902300962e00702300923b00902600962b007025", + "0x23b00923c00918700700723b00900712e00722900974323c00923b12e22c", + "0xe00703000923b00902e00933000702e00923b00902c00932f00702c009", + "0x23b00903000933100702500923b00902500922100702000923b009020009", + "0x923b00922900933200700723b00900712e007030025020125009030009", + "0x933100702500923b00902500922100702000923b00902000900e007225", + "0x762f00700723b00912e00937700722502502012500922500923b009225", + "0x71fd00923b00900702500700e00923b0091250095f700712500923b009", + "0x900700e5f800700e00923b00900e0096290071fd00923b0091fd009026", + "0x700723b00900712e00701f01b0181257442231db01112523b12e00e1fd", + "0x91db00922100702000923b00901100900e00701500923b00922300962a", + "0x712e0070077450090070ee00702300923b00901500962b00702500923b", + "0x702000923b00901800900e00702600923b00901f00962c00700723b009", + "0x902300962e00702300923b00902600962b00702500923b00901b009221", + "0x723b00900712e00722900974623c00923b12e22c00907b00722c00923b", + "0x2e00933000702e00923b00902c00932f00702c00923b00923c009187007", + "0x2500923b00902500922100702000923b00902000900e00703000923b009", + "0x700723b00900712e00703002502012500903000923b009030009331007", + "0x902500922100702000923b00902000900e00722500923b009229009332", + "0x12e00937600722502502012500922500923b00922500933100702500923b", + "0x2500700e00923b0091250095f700712500923b00900763000700723b009", + "0x923b00900e0096290071fd00923b0091fd0090260071fd00923b009007", + "0x701f01b0181257472231db01112523b12e00e1fd00900700e5f800700e", + "0x923b00901100900e00701500923b00922300962a00700723b00900712e", + "0x70ee00702300923b00901500962b00702500923b0091db009221007020", + "0x900e00702600923b00901f00962c00700723b00900712e007007748009", + "0x923b00902600962b00702500923b00901b00922100702000923b009018", + "0x22900974923c00923b12e22c00907b00722c00923b00902300962e007023", + "0x23b00902c00932f00702c00923b00923c00918700700723b00900712e007", + "0x22100702000923b00902000900e00703000923b00902e00933000702e009", + "0x703002502012500903000923b00903000933100702500923b009025009", + "0x923b00902000900e00722500923b00922900933200700723b00900712e", + "0x2012500922500923b00922500933100702500923b009025009221007020", + "0xe0095f700700e00923b00900763100700723b009125009370007225025", + "0x701100923b00901100902600701100923b0090070250071fd00923b009", + "0x182231db12523b12e1fd01112e00900e5f80071fd00923b0091fd009629", + "0x700700923b00900700912500700723b00900712e00701501f01b12574a", + "0x900e00702502012e23b00901800712e63200701800923b00901800902e", + "0x923b12e0250091b800722300923b0092230092210071db00923b0091db", + "0x12500722c00923b00902300963300700723b00900712e00702600974b023", + "0x23b00922300922100722900923b0091db00900e00723c00923b009020009", + "0x900712e00700774c0090070ee00702e00923b00922c00963400702c009", + "0x900763500703000923b00900722900700723b00902600905400700723b", + "0x3100923b00922503012e03000722500923b00922500902e00722500923b", + "0x3300963600703300923b00903104512e03100704500923b009007225007", + "0x1db00923b0091db00900e00702000923b00902000912500722100923b009", + "0x1db02000e00922100923b00922100963700722300923b009223009221007", + "0x700912500703600923b00901500963800700723b00900712e007221223", + "0x2c00923b00901f00922100722900923b00901b00900e00723c00923b009", + "0x2190093e600721900923b00902e00963900702e00923b009036009634007", + "0x923b0090380093e800700723b00900712e00703a00974d03800923b12e", + "0x912500703c00923b00912600963b00712600923b00903b00963a00703b", + "0x923b00902c00922100722900923b00922900900e00723c00923b00923c", + "0x23b00900712e00703c02c22923c00e00903c00923b00903c00963700702c", + "0x900e00723c00923b00923c00912500703e00923b00903a009636007007", + "0x923b00903e00963700702c00923b00902c00922100722900923b009229", + "0x912e00963c00712e00923b00900700963c00703e02c22923c00e00903e", + "0x71fd00923b00900900963c00700e00923b00912500963e00712500923b", + "0x900e0091530071db00923b00901100963e00701100923b0091fd00963c", + "0x1f01b12e23b0091db00915300700723b00922300915500701822312e23b", + "0x901f00916300701500923b00901800916300700723b00901b009155007", + "0x2500923b00902500902e00702500923b00902001512e14f00702000923b", + "0x900716c00700723b00900712e00702300974e00723b12e025009106007", + "0x723c00923b00922c0090a500722c00923b00902600914400702600923b", + "0x16c00700723b00902300911100700723b00900712e00700774f0090070ee", + "0x923b00902c0090a500702c00923b00922900911300722900923b009007", + "0x71fd00923b00912500963e00700e00923b00900763100723c00900923c", + "0x23b00912e0093e40071db00923b00900702500701100923b00900e0095f7", + "0x6290071db00923b0091db00902600700723b00901800937000701822312e", + "0x75001f01b12e23b12e1fd0111db0090071fd60800701100923b009011009", + "0x93b400702300923b00900716c00700723b00900712e007025020015125", + "0x923b00901f00922100722c00923b00901b00900e00702600923b009023", + "0x23b00900712e0070077510090070ee00722900923b0090260093b500723c", + "0x922100722c00923b00901500900e00702c00923b0090250093b7007007", + "0x923b0092290095c800722900923b00902c0093b500723c00923b009020", + "0x25000700723b00900712e00722500975203000923b12e02e0093b900702e", + "0x904500964000704500923b00903122312e63f00703100923b009030009", + "0x723c00923b00923c00922100722c00923b00922c00900e00703300923b", + "0x37000700723b00900712e00703323c22c12500903300923b009033009641", + "0x923b00922c00900e00722100923b00922500964200700723b009223009", + "0x22c12500922100923b00922100964100723c00923b00923c00922100722c", + "0xe00964300700e00923b00900e0093f500700723b0090070ea00722123c", + "0x5c10071db00923b00900722900701100923b0090072290071fd00923b009", + "0x23b00900700912500700723b0092230095c200701822312e23b0091fd009", + "0x15700701800923b0090180095c300700900923b00900900900e007007009", + "0x180090071fd5c40071db00923b0091db00915700701100923b009011009", + "0x702500975302000923b12e0150095c500701501f01b12523b0091db011", + "0x922c00905400722c02602312523b0090200095c600700723b00900712e", + "0x5800700723b00923c00905700722923c12e23b00902300915900700723b", + "0x902e00905700703002e12e23b00902600915900702c00923b009229009", + "0x2c0091fd00700723b00900710f00722500923b00903000905800700723b", + "0x12e22502c12e01f00e5c700722500923b0092250091fd00702c00923b009", + "0x23b00900716c00700723b00900712e00703622103312575404503112e23b", + "0x22100703a00923b00903100900e00703800923b0092190093b4007219009", + "0x77550090070ee00712600923b0090380093b500703b00923b009045009", + "0x23b00903300900e00703c00923b0090360093b700700723b00900712e007", + "0x5c800712600923b00903c0093b500703b00923b00922100922100703a009", + "0x712e00704100975614100923b12e03e0093b900703e00923b009126009", + "0x12e46800714500923b00914100925000700723b0090070ea00700723b009", + "0x23b00901b00912500714800923b00904300946900704300923b009145125", + "0x44d00703b00923b00903b00922100703a00923b00903a00900e00701b009", + "0xea00700723b00900712e00714803b03a01b00e00914800923b009148009", + "0x704700923b00904100944c00700723b00912500915200700723b009007", + "0x903b00922100703a00923b00903a00900e00701b00923b00901b009125", + "0x712e00704703b03a01b00e00904700923b00904700944d00703b00923b", + "0x12500704900923b00902500944c00700723b00912500915200700723b009", + "0x23b00912e00922100701f00923b00901f00900e00701b00923b00901b009", + "0x90070ea00704912e01f01b00e00904900923b00904900944d00712e009", + "0x12503a00700e00923b00900e00903800700e00923b00900721900700723b", + "0x56100700723b00900712e0072231db12e7570111fd12e23b12e00e009007", + "0x1fd00923b0091fd00912500700723b00900710f00701800923b00912e009", + "0x64500700723b00900712e00701500975801f01b12e23b12e018009644007", + "0x23b00902000964600702500923b00901b00956900702000923b00901f009", + "0x923b00900716c00700723b00900712e0070077590090070ee007023009", + "0x964600702500923b00901500956900722c00923b009026009647007026", + "0x923b00923c00912300723c00923b00902500912800702300923b00922c", + "0x56e00700723b00900712e00702c00975a22900923b12e02300964800723c", + "0x902e00964900722503012e23b00912500910700702e00923b009229009", + "0x723b00904500915500703304503112523b00902e00957100702e00923b", + "0x922100910700722100923b00903100910200700723b009033009572007", + "0x3a03812e23b00921900910700700723b00903600910100721903612e23b", + "0x3b00910100712603b12e23b00922500910700700723b009038009101007", + "0x712600923b00912600935a00703a00923b00903a00935a00700723b009", + "0x3e0090a500703e00923b00903c00936e00703c00923b00912603a12e64a", + "0x23b00900712e00704100975b14100923b12e03e00914000703e00923b009", + "0x23b00903000910100700723b00914100905400700723b0090070ea007007", + "0x23b00900764b00714500923b00900722900700723b00923c009365007007", + "0x714800923b00904314512e03000704300923b00904300902e007043009", + "0x904900964c00704900923b00914804712e03100704700923b009007225", + "0x701100923b00901100900e0071fd00923b0091fd00912500715000923b", + "0xea00700723b00900712e0071500111fd12500915000923b00915000964d", + "0x71fd00923b0091fd00912500700723b00904100905400700723b009007", + "0x903000935a00723c00923b00923c00912300701100923b00901100900e", + "0x15300940200715315204c12523b00903023c0111fd00e40100703000923b", + "0x12e23b00915500964e00700723b00900712e00715700975c15500923b12e", + "0x705700923b00915900965000715900923b00905405212e64f007054052", + "0x905700964d00715200923b00915200900e00704c00923b00904c009125", + "0x23b00915700964c00700723b00900712e00705715204c12500905700923b", + "0x64d00715200923b00915200900e00704c00923b00904c009125007058009", + "0x70ea00700723b00900712e00705815204c12500905800923b009058009", + "0x716c00700723b00912500910100700723b00902c00905400700723b009", + "0x923b00915d00965000715d00923b00905a23c12e64f00705a00923b009", + "0x964d00701100923b00901100900e0071fd00923b0091fd00912500705d", + "0x12e00936500700723b00900712e00705d0111fd12500905d00923b00905d", + "0x705d00715e00923b00900722900700723b00912500910100700723b009", + "0x923b00906015e12e03000706000923b00906000902e00706000923b009", + "0x964c00706400923b00915f16012e03100716000923b00900722500715f", + "0x923b00922300900e0071db00923b0091db00912500716100923b009064", + "0x23b0090070091250071612231db12500916100923b00916100964d007223", + "0x2231db12e23b00901100712e5da00701100923b0090110091fd007007009", + "0x95dc00700723b00900712e00701b00975d01800923b12e2230095db007", + "0x23b0091db00912500702001512e23b00901f0095dd00701f00923b009018", + "0x22100712e00923b00912e00900e00700900923b0090090090330071db009", + "0x91fd00936b00702500e12e23b00900e0095de00712500923b009125009", + "0x1500923b0090150091fd00702300923b00902300902e0070231fd12e23b", + "0x1b000702c22923c22c0261fd23b00901502302512512e0091db1db5b3007", + "0x902e0091b200700723b00900712e00703000975e02e00923b12e02c009", + "0x723b00900712e00704500975f03100923b12e22500914000722500923b", + "0x23b0091fd00915500700723b00900e00915200700723b009031009054007", + "0x23b0090075b400703300923b00900722900700723b00902000915e007007", + "0x703600923b00922103312e03000722100923b00922100902e007221009", + "0x903800962000703800923b00903621912e03100721900923b009007225", + "0x722c00923b00922c00903300702600923b00902600912500703a00923b", + "0x903a00961f00722900923b00922900922100723c00923b00923c00900e", + "0x4500905400700723b00900712e00703a22923c22c0261fd00903a00923b", + "0x12622323b00903b00936900703b00e12e23b00900e0095de00700723b009", + "0x23b00903c00937100700723b00912600937000714804314504114103e03c", + "0x914500937400700723b00904100937500700723b009141009376007007", + "0x23c00900e00700723b00914800937200700723b00904300937300700723b", + "0x23b00903e22923c1253da00722900923b00922900922100723c00923b009", + "0x23b00900712e00715200976004c00923b12e15000907b007150049047125", + "0x715500976100723b12e15300910600715300923b00904c009187007007", + "0x700723b00900e00915200700723b0091fd00915500700723b00900712e", + "0x905200901500705200923b00915700901f00715700923b00902000901b", + "0x1500705700923b00900702500700723b00905400902000715905412e23b", + "0x23b00915900902300700723b00905800902000705a05812e23b009057009", + "0x22c00715d00923b00915d00902600705d00923b00905a00902300715d009", + "0x923b00900722900700723b00900712e00700776200723b12e05d15d12e", + "0x15e12e03000706000923b00906000902e00706000923b00900758f00715e", + "0x923b00915f16012e03100716000923b00900722500715f00923b009060", + "0x903300702600923b00902600912500716100923b009064009620007064", + "0x923b00904900922100704700923b00904700900e00722c00923b00922c", + "0x900712e00716104904722c0261fd00916100923b00916100961f007049", + "0xe00706700923b00922c00903300716200923b00902600912500700723b", + "0x77630090070ee00716600923b00904900922100716400923b009047009", + "0x923b00902600912500700723b00915500911100700723b00900712e007", + "0x922100704700923b00904700900e00722c00923b00922c009033007026", + "0x923b0090200091fd0071fd00923b0091fd00902e00704900923b009049", + "0x706f06e06d16b1681fd23b0090201fd00e04904722c0261db58c007020", + "0x710091b200700723b00900712e00716e00976407100923b12e06f0091b0", + "0x23b00900712e00717400976507400923b12e07200914000707200923b009", + "0x23b00900758f00707600923b00900722900700723b009074009054007007", + "0x707700923b00918007612e03000718000923b00918000902e007180009", + "0x918600962000718600923b00907707812e03100707800923b009007225", + "0x716b00923b00916b00903300716800923b00916800912500707b00923b", + "0x907b00961f00706e00923b00906e00922100706d00923b00906d00900e", + "0x17400905400700723b00900712e00707b06e06d16b1681fd00907b00923b", + "0x706700923b00916b00903300716200923b00916800912500700723b009", + "0x23b00900716c00716600923b00906e00922100716400923b00906d00900e", + "0x61f00707f00923b00908d00961d00708d00923b00918700961c007187009", + "0x700723b00900712e00707f1661640671621fd00907f00923b00907f009", + "0x916b00903300716800923b00916800912500708e00923b00916e009620", + "0x706e00923b00906e00922100706d00923b00906d00900e00716b00923b", + "0x723b00900712e00708e06e06d16b1681fd00908e00923b00908e00961f", + "0x23b00900e00915200700723b0091fd00915500700723b00902000915e007", + "0x903300702600923b00902600912500708f00923b009152009620007007", + "0x923b00904900922100704700923b00904700900e00722c00923b00922c", + "0x900712e00708f04904722c0261fd00908f00923b00908f00961f007049", + "0x2000915e00700723b0091fd00915500700723b00900e00915200700723b", + "0x702600923b00902600912500709000923b00903000962000700723b009", + "0x922900922100723c00923b00923c00900e00722c00923b00922c009033", + "0x12e00709022923c22c0261fd00909000923b00909000961f00722900923b", + "0x62000700723b0091fd00915500700723b00900e00915200700723b009007", + "0x23b0090090090330071db00923b0091db00912500709100923b00901b009", + "0x61f00712500923b00912500922100712e00923b00912e00900e007009009", + "0x12e23b00901100915300709112512e0091db1fd00909100923b009091009", + "0x15500702001512e23b00901f00915300701f00923b00900714c00701b018", + "0x12e23b00902500915300702500923b00901b00916300700723b009015009", + "0x915300722c00923b00902000916300700723b009023009155007026023", + "0x923b00902600916300700723b00923c00915500722923c12e23b00922c", + "0x2e00703000923b00902e02c12e14f00702e00923b00922900916300702c", + "0x900712e00722500976600723b12e03000910600703000923b009030009", + "0x90a500704500923b00903100914400703100923b00900716c00700723b", + "0x911100700723b00900712e0070077670090070ee00703300923b009045", + "0x703600923b00922100911300722100923b00900716c00700723b009225", + "0x92190090a500721900923b00903300936e00703300923b0090360090a5", + "0x723b00900712e00703a00976803800923b12e21900914000721900923b", + "0x23b00922300915500700723b0091fd00915200700723b009038009054007", + "0x23b00900722900700723b00901800915500700723b0091db009155007007", + "0x12e03000712600923b00912600902e00712600923b0090073d800703b009", + "0x23b00903c03e12e03100703e00923b00900722500703c00923b00912603b", + "0x3300700700923b00900700912500704100923b009141009620007141009", + "0x23b00912500909900712e00923b00912e00900e00700900923b009009009", + "0x1100904100923b00904100961f00700e00923b00900e009221007125009", + "0x700723b00903a00905400700723b00900712e00704100e12512e009007", + "0xe12e12e14d00700e00923b00900e00922100712e00923b00912e00900e", + "0x712e00704900976904700923b12e14800914e00714804314512523b009", + "0x704c00923b00915000910a00715000923b00904700914900700723b009", + "0x923b00900765100715300923b00915200937b00715200923b00900714c", + "0x902e00715700923b00915700902e00715700923b00915300937d007155", + "0x4c00910c00705405212e23b00915515712512537e00715500923b009155", + "0x15900915500716216106416015f06015e05d15d05a05805715902023b009", + "0x915e00700723b00905800914700700723b00905700910100700723b009", + "0x14600700723b00915e00915500700723b00915d00915500700723b00905a", + "0x700723b00916000915e00700723b00915f00914700700723b009060009", + "0x723b00916200915e00700723b00916100902000700723b009064009020", + "0x16400902e00716400923b00906700937d00706700923b00905400937b007", + "0x23b00905d16405212537e00705d00923b00905d00902e00716400923b009", + "0x704300923b00904300922100714500923b00914500900e00716816612e", + "0x2e00716600923b00916600909900706e06d16b12523b00904314512e387", + "0x712e00707100976a06f00923b12e06e0090fd00716800923b009168009", + "0x707200923b00916e00910400716e00923b00906f00915100700723b009", + "0x917400902e00717400923b00907400937d00707400923b00916800937b", + "0x23b0091fd00936900718007612e23b00907217416612537e00717400923b", + "0x18600937700700723b00907700937000708e07f08d18707b186078077223", + "0x937400700723b00918700937500700723b00907b00937600700723b009", + "0xe00700723b00908e00937200700723b00907f00937300700723b00908d", + "0x7806d16b1253d200706d00923b00906d00922100716b00923b00916b009", + "0x23b00918000902e00707600923b00907600909900709109008f12523b009", + "0x700723b00900712e00709300976b09200923b12e09100907b007180009", + "0x909400937d00709500923b00909200918700709400923b00918000937b", + "0x12e23b00909509607612537e00709600923b00909600902e00709600923b", + "0x937d0071a500923b00900738600709900923b00909800937b007098097", + "0x923b0091a500902e00709c00923b00909c00902e00709c00923b009099", + "0x5b00923b00903700937b0070371a712e23b0091a509c09712537e0071a5", + "0x900903300700700923b00900700912500709f00923b00905b00937d007", + "0x1800923b00901800902e00709f00923b00909f00902e00700900923b009", + "0x701165300722300923b00922300902e0071db00923b0091db00902e007", + "0x71a700923b0091a70090990071b21b01ac12523b0092231db01809f009", + "0xa300905400700723b00900712e00704a00976c0a300923b12e1b2009140", + "0x902e0071b500923b0090075b40070a500923b00900722900700723b009", + "0x923b0090072250070a700923b0091b50a512e0300071b500923b0091b5", + "0x1250070ac00923b0091b80096200071b800923b0090a70a912e0310070a9", + "0x23b00908f00900e0071b000923b0091b00090330071ac00923b0091ac009", + "0x61f00709000923b0090900092210071a700923b0091a700909900708f009", + "0x723b00900712e0070ac0901a708f1b01ac0110090ac00923b0090ac009", + "0x23b0090ae00961c0070ae00923b00900716c00700723b00904a009054007", + "0x330071ac00923b0091ac0091250070b000923b0091bc00961d0071bc009", + "0x23b0091a700909900708f00923b00908f00900e0071b000923b0091b0009", + "0x110090b000923b0090b000961f00709000923b0090900092210071a7009", + "0x700723b00922300915500700723b00900712e0070b00901a708f1b01ac", + "0x723b00918000915500700723b00901800915500700723b0091db009155", + "0x900903300700700923b0090070091250070b200923b009093009620007", + "0x7600923b00907600909900708f00923b00908f00900e00700900923b009", + "0x90070110090b200923b0090b200961f00709000923b009090009221007", + "0x915500700723b0091fd00915200700723b00900712e0070b209007608f", + "0x15500700723b00901800915500700723b0091db00915500700723b009223", + "0x923b0090070091250071bd00923b00907100962000700723b009168009", + "0x909900716b00923b00916b00900e00700900923b009009009033007007", + "0x923b0091bd00961f00706d00923b00906d00922100716600923b009166", + "0x91fd00915200700723b00900712e0071bd06d16616b0090070110091bd", + "0x1800915500700723b0091db00915500700723b00922300915500700723b", + "0x700700923b0090070091250070b400923b00904900962000700723b009", + "0x912500909900714500923b00914500900e00700900923b009009009033", + "0x90b400923b0090b400961f00704300923b00904300922100712500923b", + "0x923b00900765400700723b0091250093750070b4043125145009007011", + "0x900900e00700700923b0090070091250071fd00923b00900702500700e", + "0x1fd00923b0091fd00902600712e00923b00912e00922100700900923b009", + "0x1100e23b00900e1fd12e0090071fd65600700e00923b00900e009655007", + "0x723b00900712e00701f00976d01b00923b12e0180096570070182231db", + "0x1500965a00701500923b00901500965900701500923b00901b009658007", + "0x23b00900712e00702300976e02500923b12e0200090cf00702000923b009", + "0x950000722c00923b0090260094ff00702600923b0090250091a8007007", + "0x923b0091db00900e00701100923b00901100912500723c00923b00922c", + "0x1100e00923c00923b00923c00950100722300923b0092230092210071db", + "0x912500722900923b00902300950200700723b00900712e00723c2231db", + "0x923b0092230092210071db00923b0091db00900e00701100923b009011", + "0x23b00900712e0072292231db01100e00922900923b009229009501007223", + "0x900e00701100923b00901100912500702c00923b00901f009502007007", + "0x923b00902c00950100722300923b0092230092210071db00923b0091db", + "0x900743f0071fd00e12e23b00912500965b00702c2231db01100e00902c", + "0x700723b0091db00934f0072231db12e23b00901100965b00701100923b", + "0x1b01812e65c00701b00923b00922300950400701800923b0091fd009504", + "0x700900923b00900900900e00700723b00900712e00700776f00723b12e", + "0x35f00702001501f12523b00912e00912e35e00712e00923b00912e009221", + "0x902500936100700723b00900712e00702300977002500923b12e020009", + "0xe12e23b00900e00936200722c02612e23b00902600936200702600923b", + "0x900712e00703002e12e77102c22912e23b12e23c22c00712536300723c", + "0x22900912500722500923b0090074b000700723b00902c00934f00700723b", + "0x22500923b00922500943400700e00923b00900e00943400722900923b009", + "0x77203300923b12e04500935f00704503112e23b00922500e2291254b1007", + "0x3112536300703600923b00903300936100700723b00900712e007221009", + "0x934f00700723b00900712e00703b03a12e77303821912e23b12e036026", + "0x703c00923b00912600944400712600923b00900716c00700723b009038", + "0x921900912500714100923b00903e00965e00703e00923b00903c00965d", + "0x701500923b00901500922100701f00923b00901f00900e00721900923b", + "0x700723b00900712e00714101501f21900e00914100923b00914100965f", + "0x923b0090410094cf00704100923b00900716c00700723b00903b00934f", + "0x912500714800923b00904300965e00704300923b00914500965d007145", + "0x923b00901500922100701f00923b00901f00900e00703a00923b00903a", + "0x23b00900712e00714801501f03a00e00914800923b00914800965f007015", + "0x3100912500704700923b00922100966000700723b00902600934f007007", + "0x1500923b00901500922100701f00923b00901f00900e00703100923b009", + "0x723b00900712e00704701501f03100e00904700923b00904700965f007", + "0x23b00900e00934f00700723b00902600934f00700723b00903000934f007", + "0x15000965d00715000923b00904900966100704900923b00900716c007007", + "0x2e00923b00902e00912500715200923b00904c00965e00704c00923b009", + "0x15200965f00701500923b00901500922100701f00923b00901f00900e007", + "0xe00934f00700723b00900712e00715201501f02e00e00915200923b009", + "0x700700923b00900700912500715300923b00902300966000700723b009", + "0x915300965f00701500923b00901500922100701f00923b00901f00900e", + "0x900e00934f00700723b00900712e00715301501f00700e00915300923b", + "0x965d00715700923b00915500943a00715500923b00900716c00700723b", + "0x923b00900700912500705400923b00905200965e00705200923b009157", + "0x965f00712e00923b00912e00922100700900923b00900900900e007007", + "0x77412e00923b00e00700966200705412e00900700e00905400923b009054", + "0x23b00e00900966200700723b00900712e0071fd00977600e009775125009", + "0x925600700723b00900712e0070180097792230097781db009777011009", + "0x12e23b00901100925600700723b00901b00905400701f01b12e23b00912e", + "0x39d00702500923b00902001f12e66400700723b009015009054007020015", + "0x5400700723b00900712e00700777a0090070ee00702300923b009025009", + "0x702600923b00900716c00700723b00912e00905400700723b0091db009", + "0x77a0090070ee00702300923b00922c0090a500722c00923b009026009113", + "0x23b00912e00905400700723b00922300905400700723b00900712e007007", + "0x2290090a500722900923b00923c00911300723c00923b00900716c007007", + "0x1800905400700723b00900712e00700777a0090070ee00702300923b009", + "0x911300702c00923b00900716c00700723b00912e00905400700723b009", + "0x923b00902300939d00702300923b00902e0090a500702e00923b00902c", + "0x923b00e00900966200700723b00900712e00700777b0090070ee007030", + "0x22500905400700723b00900712e00703300977e04500977d03100977c225", + "0x911300722100923b00900716c00700723b00912500905400700723b009", + "0x700777f0090070ee00721900923b0090360090a500703600923b009221", + "0x23b00903800905400703a03812e23b00912500925600700723b00900712e", + "0x12e66400700723b00903b00905400712603b12e23b009031009256007007", + "0x777f0090070ee00721900923b00903c00939d00703c00923b00912603a", + "0x723b00912500905400700723b00904500905400700723b00900712e007", + "0x91410090a500714100923b00903e00911300703e00923b00900716c007", + "0x903300905400700723b00900712e00700777f0090070ee00721900923b", + "0x4100911300704100923b00900716c00700723b00912500905400700723b", + "0x3000923b00921900939d00721900923b0091450090a500714500923b009", + "0x4300923b00e00900966200700723b00900712e00700777b0090070ee007", + "0x904300905400700723b00900712e007049009782047009781148009780", + "0x15000911300715000923b00900716c00700723b00900e00905400700723b", + "0x12e0070077830090070ee00715200923b00904c0090a500704c00923b009", + "0x16c00700723b00900e00905400700723b00914800905400700723b009007", + "0x923b0091550090a500715500923b00915300911300715300923b009007", + "0x12e23b00900e00925600700723b00900712e0070077830090070ee007152", + "0x5400715905412e23b00904700925600700723b009157009054007052157", + "0x23b00905700939d00705700923b00915905212e66400700723b009054009", + "0x23b00904900905400700723b00900712e0070077830090070ee007152009", + "0x905800911300705800923b00900716c00700723b00900e009054007007", + "0x703000923b00915200939d00715200923b00905a0090a500705a00923b", + "0x78415d00923b00e00900966200700723b00900712e00700777b0090070ee", + "0x23b00915d00905400700723b00900712e00706000978615e00978505d009", + "0x915f00911300715f00923b00900716c00700723b0091fd009054007007", + "0x712e0070077870090070ee00706400923b0091600090a500716000923b", + "0x716c00700723b0091fd00905400700723b00905d00905400700723b009", + "0x6400923b0091620090a500716200923b00916100911300716100923b009", + "0x700723b00915e00905400700723b00900712e0070077870090070ee007", + "0x923b00906700911300706700923b00900716c00700723b0091fd009054", + "0x23b00900712e0070077870090070ee00706400923b0091640090a5007164", + "0x925600700723b00916600905400716816612e23b0091fd009256007007", + "0x23b00906d16812e66400700723b00916b00905400706d16b12e23b009060", + "0x900903000923b00906400939d00706400923b00906e00939d00706e009", + "0x900700912500701100923b0090070250071fd00923b009007654007030", + "0x712e00923b00912e00922100700900923b00900900900e00700700923b", + "0x900e0091a10071fd00923b0091fd00965500701100923b009011009026", + "0x701b0182231db00e23b00900e1fd01112e00900701166500700e00923b", + "0x1f00966800700723b00900712e00701500978801f00923b12e01b009666", + "0x2500923b0090200095c800702000923b0090200093b500702000923b009", + "0x943100700723b00900712e00702600978902300923b12e0250093b9007", + "0x923b00902300925000700723b00923c00937500723c22c12e23b009125", + "0x12500702e00923b00902c00966a00702c00923b00922922c12e669007229", + "0x23b00901800922100722300923b00922300900e0071db00923b0091db009", + "0x900712e00702e0182231db00e00902e00923b00902e00966b007018009", + "0x912500703000923b00902600966d00700723b00912500937500700723b", + "0x923b00901800922100722300923b00922300900e0071db00923b0091db", + "0x23b00900712e0070300182231db00e00903000923b00903000966b007018", + "0x1db00912500722500923b00901500966d00700723b009125009375007007", + "0x1800923b00901800922100722300923b00922300900e0071db00923b009", + "0x23b00900700966e0072250182231db00e00922500923b00922500966b007", + "0x43c00712e00923b00912e00943c00712500923b00900900966e00712e009", + "0xea00700e00900900e00923b00912512e12e43d00712500923b009125009", + "0x701100923b0090072290071fd00923b00900e00966f00700723b009007", + "0x92230095c200701822312e23b0091fd0095c10071db00923b009007229", + "0x5c300700900923b00900900900e00700700923b00900700912500700723b", + "0x23b0091db00915700701100923b00901100915700701800923b009018009", + "0x150095c500701501f01b12523b0091db0110180090071fd5c40071db009", + "0x12523b0090200095c600700723b00900712e00702500978a02000923b12e", + "0x722923c12e23b00902300915900700723b00922c00905400722c026023", + "0x23b00902600915900702c00923b00922900905800700723b00923c009057", + "0x10f00722500923b00903000905800700723b00902e00905700703002e12e", + "0x22500923b0092250091fd00702c00923b00902c0091fd00700723b009007", + "0x712e00703622103312578b04503112e23b12e22502c12e01f00e5c7007", + "0xe00703800923b0092190093b400721900923b00900716c00700723b009", + "0x23b0090380093b500703b00923b00904500922100703a00923b009031009", + "0x23b0090360093b700700723b00900712e00700778c0090070ee007126009", + "0x3b500703b00923b00922100922100703a00923b00903300900e00703c009", + "0x23b12e03e0093b900703e00923b0091260095c800712600923b00903c009", + "0x925000700723b0090070ea00700723b00900712e00704100978d141009", + "0x23b00904300946900704300923b00914512512e46800714500923b009141", + "0x22100703a00923b00903a00900e00701b00923b00901b009125007148009", + "0x14803b03a01b00e00914800923b00914800944d00703b00923b00903b009", + "0x700723b00912500915200700723b0090070ea00700723b00900712e007", + "0x903a00900e00701b00923b00901b00912500704700923b00904100944c", + "0x904700923b00904700944d00703b00923b00903b00922100703a00923b", + "0x44c00700723b00912500915200700723b00900712e00704703b03a01b00e", + "0x23b00901f00900e00701b00923b00901b00912500704900923b009025009", + "0xe00904900923b00904900944d00712e00923b00912e00922100701f009", + "0x71fd00923b0091250090df00700e00923b00900767000704912e01f01b", + "0x23b00912e0095a70071db00923b00900702500701100923b00900e0095f7", + "0x6290071db00923b0091db00902600700723b00901800937200701822312e", + "0x78e01f01b12e23b12e1fd0111db0090071fd60800701100923b009011009", + "0x93b400702300923b00900716c00700723b00900712e007025020015125", + "0x923b00901f00922100722c00923b00901b00900e00702600923b009023", + "0x23b00900712e00700778f0090070ee00722900923b0090260093b500723c", + "0x922100722c00923b00901500900e00702c00923b0090250093b7007007", + "0x923b0092290095c800722900923b00902c0093b500723c00923b009020", + "0x25000700723b00900712e00722500979003000923b12e02e0093b900702e", + "0x904500967200704500923b00903122312e67100703100923b009030009", + "0x723c00923b00923c00922100722c00923b00922c00900e00703300923b", + "0x37200700723b00900712e00703323c22c12500903300923b009033009673", + "0x923b00922c00900e00722100923b00922500967400700723b009223009", + "0x22c12500922100923b00922100967300723c00923b00923c00922100722c", + "0x95f70071fd00923b0091250090df00700e00923b00900767500722123c", + "0x22312e23b00912e0095770071db00923b00900702500701100923b00900e", + "0x110096290071db00923b0091db00902600700723b009018009373007018", + "0x1512579101f01b12e23b12e1fd0111db0090071fd60800701100923b009", + "0x90230093b400702300923b00900716c00700723b00900712e007025020", + "0x723c00923b00901f00922100722c00923b00901b00900e00702600923b", + "0x700723b00900712e0070077920090070ee00722900923b0090260093b5", + "0x902000922100722c00923b00901500900e00702c00923b0090250093b7", + "0x702e00923b0092290095c800722900923b00902c0093b500723c00923b", + "0x3000925000700723b00900712e00722500979303000923b12e02e0093b9", + "0x923b00904500967700704500923b00903122312e67600703100923b009", + "0x967800723c00923b00923c00922100722c00923b00922c00900e007033", + "0x22300937300700723b00900712e00703323c22c12500903300923b009033", + "0x722c00923b00922c00900e00722100923b00922500967900700723b009", + "0x22123c22c12500922100923b00922100967800723c00923b00923c009221", + "0x23b0090070250071fd00923b00900e0095f700700e00923b009007628007", + "0x2600700723b0092230093710072231db12e23b00912e0093d1007011009", + "0x110090071fd6080071fd00923b0091fd00962900701100923b009011009", + "0x16c00700723b00900712e00702001501f12579401b01812e23b12e1251fd", + "0x923b00901800900e00702300923b0090250093b400702500923b009007", + "0x70ee00723c00923b0090230093b500722c00923b00901b009221007026", + "0x900e00722900923b0090200093b700700723b00900712e007007795009", + "0x923b0092290093b500722c00923b00901500922100702600923b00901f", + "0x3000979602e00923b12e02c0093b900702c00923b00923c0095c800723c", + "0x92251db12e67a00722500923b00902e00925000700723b00900712e007", + "0x702600923b00902600900e00704500923b00903100967b00703100923b", + "0x4522c02612500904500923b00904500967c00722c00923b00922c009221", + "0x923b00903000967d00700723b0091db00937100700723b00900712e007", + "0x967c00722c00923b00922c00922100702600923b00902600900e007033", + "0xe00946000700723b0090070ea00703322c02612500903300923b009033", + "0x701100923b0090072290071fd00923b00900e00967e00700e00923b009", + "0x92230095c200701822312e23b0091fd0095c10071db00923b009007229", + "0x5c300700900923b00900900900e00700700923b00900700912500700723b", + "0x23b0091db00915700701100923b00901100915700701800923b009018009", + "0x150095c500701501f01b12523b0091db0110180090071fd5c40071db009", + "0x12523b0090200095c600700723b00900712e00702500979702000923b12e", + "0x722923c12e23b00902300915900700723b00922c00905400722c026023", + "0x23b00902600915900702c00923b00922900905800700723b00923c009057", + "0x10f00722500923b00903000905800700723b00902e00905700703002e12e", + "0x22500923b0092250091fd00702c00923b00902c0091fd00700723b009007", + "0x712e00703622103312579804503112e23b12e22502c12e01f00e5c7007", + "0xe00703800923b0092190093b400721900923b00900716c00700723b009", + "0x23b0090380093b500703b00923b00904500922100703a00923b009031009", + "0x23b0090360093b700700723b00900712e0070077990090070ee007126009", + "0x3b500703b00923b00922100922100703a00923b00903300900e00703c009", + "0x23b12e03e0093b900703e00923b0091260095c800712600923b00903c009", + "0x925000700723b0090070ea00700723b00900712e00704100979a141009", + "0x23b00904300946900704300923b00914512512e46800714500923b009141", + "0x22100703a00923b00903a00900e00701b00923b00901b009125007148009", + "0x14803b03a01b00e00914800923b00914800944d00703b00923b00903b009", + "0x700723b00912500915200700723b0090070ea00700723b00900712e007", + "0x903a00900e00701b00923b00901b00912500704700923b00904100944c", + "0x904700923b00904700944d00703b00923b00903b00922100703a00923b", + "0x44c00700723b00912500915200700723b00900712e00704703b03a01b00e", + "0x23b00901f00900e00701b00923b00901b00912500704900923b009025009", + "0xe00904900923b00904900944d00712e00923b00912e00922100701f009", + "0x67f00700e00923b00900e00946400700723b0090070ea00704912e01f01b", + "0x1db00923b00900722900701100923b0090072290071fd00923b00900e009", + "0x700912500700723b0092230095c200701822312e23b0091fd0095c1007", + "0x1800923b0090180095c300700900923b00900900900e00700700923b009", + "0x71fd5c40071db00923b0091db00915700701100923b009011009157007", + "0x979b02000923b12e0150095c500701501f01b12523b0091db011018009", + "0x905400722c02602312523b0090200095c600700723b00900712e007025", + "0x723b00923c00905700722923c12e23b00902300915900700723b00922c", + "0x905700703002e12e23b00902600915900702c00923b009229009058007", + "0x1fd00700723b00900710f00722500923b00903000905800700723b00902e", + "0x2c12e01f00e5c700722500923b0092250091fd00702c00923b00902c009", + "0x716c00700723b00900712e00703622103312579c04503112e23b12e225", + "0x3a00923b00903100900e00703800923b0092190093b400721900923b009", + "0x90070ee00712600923b0090380093b500703b00923b009045009221007", + "0x3300900e00703c00923b0090360093b700700723b00900712e00700779d", + "0x12600923b00903c0093b500703b00923b00922100922100703a00923b009", + "0x704100979e14100923b12e03e0093b900703e00923b0091260095c8007", + "0x714500923b00914100925000700723b0090070ea00700723b00900712e", + "0x1b00912500714800923b00904300946900704300923b00914512512e468", + "0x3b00923b00903b00922100703a00923b00903a00900e00701b00923b009", + "0x723b00900712e00714803b03a01b00e00914800923b00914800944d007", + "0x923b00904100944c00700723b00912500915200700723b0090070ea007", + "0x922100703a00923b00903a00900e00701b00923b00901b009125007047", + "0x704703b03a01b00e00904700923b00904700944d00703b00923b00903b", + "0x4900923b00902500944c00700723b00912500915200700723b00900712e", + "0x12e00922100701f00923b00901f00900e00701b00923b00901b009125007", + "0x62f00704912e01f01b00e00904900923b00904900944d00712e00923b009", + "0x1100923b0090070250071fd00923b00900e0095f700700e00923b009007", + "0x1100902600700723b0092230093770072231db12e23b00912e0093d9007", + "0x1251fd0110090071fd6080071fd00923b0091fd00962900701100923b009", + "0x900716c00700723b00900712e00702001501f12579f01b01812e23b12e", + "0x702600923b00901800900e00702300923b0090250093b400702500923b", + "0x7a00090070ee00723c00923b0090230093b500722c00923b00901b009221", + "0x901f00900e00722900923b0090200093b700700723b00900712e007007", + "0x723c00923b0092290093b500722c00923b00901500922100702600923b", + "0x12e0070300097a102e00923b12e02c0093b900702c00923b00923c0095c8", + "0x923b0092251db12e68000722500923b00902e00925000700723b009007", + "0x922100702600923b00902600900e00704500923b009031009681007031", + "0x12e00704522c02612500904500923b00904500968200722c00923b00922c", + "0x703300923b00903000968400700723b0091db00937700700723b009007", + "0x903300968200722c00923b00922c00922100702600923b00902600900e", + "0x23b00900e00948100700723b0090070ea00703322c02612500903300923b", + "0x722900701100923b0090072290071fd00923b00900e00968500700e009", + "0x723b0092230095c200701822312e23b0091fd0095c10071db00923b009", + "0x180095c300700900923b00900900900e00700700923b009007009125007", + "0x1db00923b0091db00915700701100923b00901100915700701800923b009", + "0x23b12e0150095c500701501f01b12523b0091db0110180090071fd5c4007", + "0x2602312523b0090200095c600700723b00900712e0070250097a2020009", + "0x905700722923c12e23b00902300915900700723b00922c00905400722c", + "0x2e12e23b00902600915900702c00923b00922900905800700723b00923c", + "0x900710f00722500923b00903000905800700723b00902e009057007030", + "0x5c700722500923b0092250091fd00702c00923b00902c0091fd00700723b", + "0x23b00900712e0070362210331257a304503112e23b12e22502c12e01f00e", + "0x3100900e00703800923b0092190093b400721900923b00900716c007007", + "0x12600923b0090380093b500703b00923b00904500922100703a00923b009", + "0x3c00923b0090360093b700700723b00900712e0070077a40090070ee007", + "0x3c0093b500703b00923b00922100922100703a00923b00903300900e007", + "0x14100923b12e03e0093b900703e00923b0091260095c800712600923b009", + "0x914100925000700723b0090070ea00700723b00900712e0070410097a5", + "0x14800923b00904300946900704300923b00914512512e46800714500923b", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00714803b03a01b00e00914800923b00914800944d00703b00923b009", + "0x944c00700723b00912500915200700723b0090070ea00700723b009007", + "0x923b00903a00900e00701b00923b00901b00912500704700923b009041", + "0x1b00e00904700923b00904700944d00703b00923b00903b00922100703a", + "0x2500944c00700723b00912500915200700723b00900712e00704703b03a", + "0x1f00923b00901f00900e00701b00923b00901b00912500704900923b009", + "0x1f01b00e00904900923b00904900944d00712e00923b00912e009221007", + "0x70250071fd00923b00900e0095f700700e00923b00900763000704912e", + "0x723b0092230093760072231db12e23b00912e0093dd00701100923b009", + "0x71fd6080071fd00923b0091fd00962900701100923b009011009026007", + "0x723b00900712e00702001501f1257a601b01812e23b12e1251fd011009", + "0x901800900e00702300923b0090250093b400702500923b00900716c007", + "0x723c00923b0090230093b500722c00923b00901b00922100702600923b", + "0x722900923b0090200093b700700723b00900712e0070077a70090070ee", + "0x92290093b500722c00923b00901500922100702600923b00901f00900e", + "0x7a802e00923b12e02c0093b900702c00923b00923c0095c800723c00923b", + "0x1db12e68600722500923b00902e00925000700723b00900712e007030009", + "0x923b00902600900e00704500923b00903100968700703100923b009225", + "0x2612500904500923b00904500968800722c00923b00922c009221007026", + "0x903000968900700723b0091db00937600700723b00900712e00704522c", + "0x722c00923b00922c00922100702600923b00902600900e00703300923b", + "0x49b00700723b0090070ea00703322c02612500903300923b009033009688", + "0x923b0090072290071fd00923b00900e00968a00700e00923b00900e009", + "0x95c200701822312e23b0091fd0095c10071db00923b009007229007011", + "0x900923b00900900900e00700700923b00900700912500700723b009223", + "0x1db00915700701100923b00901100915700701800923b0090180095c3007", + "0x5c500701501f01b12523b0091db0110180090071fd5c40071db00923b009", + "0x90200095c600700723b00900712e0070250097a902000923b12e015009", + "0x23c12e23b00902300915900700723b00922c00905400722c02602312523b", + "0x2600915900702c00923b00922900905800700723b00923c009057007229", + "0x22500923b00903000905800700723b00902e00905700703002e12e23b009", + "0x23b0092250091fd00702c00923b00902c0091fd00700723b00900710f007", + "0x70362210331257aa04503112e23b12e22502c12e01f00e5c7007225009", + "0x3800923b0092190093b400721900923b00900716c00700723b00900712e", + "0x380093b500703b00923b00904500922100703a00923b00903100900e007", + "0x360093b700700723b00900712e0070077ab0090070ee00712600923b009", + "0x3b00923b00922100922100703a00923b00903300900e00703c00923b009", + "0x3e0093b900703e00923b0091260095c800712600923b00903c0093b5007", + "0x700723b0090070ea00700723b00900712e0070410097ac14100923b12e", + "0x4300946900704300923b00914512512e46800714500923b009141009250", + "0x3a00923b00903a00900e00701b00923b00901b00912500714800923b009", + "0x3a01b00e00914800923b00914800944d00703b00923b00903b009221007", + "0x23b00912500915200700723b0090070ea00700723b00900712e00714803b", + "0x900e00701b00923b00901b00912500704700923b00904100944c007007", + "0x923b00904700944d00703b00923b00903b00922100703a00923b00903a", + "0x723b00912500915200700723b00900712e00704703b03a01b00e009047", + "0x1f00900e00701b00923b00901b00912500704900923b00902500944c007", + "0x4900923b00904900944d00712e00923b00912e00922100701f00923b009", + "0x1fd12e7ad00e12512e23b12e12e00900712568b00704912e01f01b00e009", + "0x91250091250071db00923b00900e00968c00700723b00900712e007011", + "0x712e0070077ae0090070ee00701800923b0091db00968d00722300923b", + "0x722300923b0091fd00912500701b00923b00901100968e00700723b009", + "0x23b00901f00902e00701f00923b00900768f00701800923b00901b00968d", + "0x7af02000923b12e01500935f00701500923b00901f01812e69000701f009", + "0x230095f300702300923b00902000936100700723b00900712e007025009", + "0x22300923b00922300912500722c00923b0090260095f400702600923b009", + "0x5f500700723b00900712e00722c22312e00922c00923b00922c00924d007", + "0x23b00923c00924d00722300923b00922300912500723c00923b009025009", + "0xe00923b00900e0094b500700723b0090070ea00723c22312e00923c009", + "0x23b00900722900701100923b0090072290071fd00923b00900e009258007", + "0x12500700723b0092230095c200701822312e23b0091fd0095c10071db009", + "0x23b0090180095c300700900923b00900900900e00700700923b009007009", + "0x5c40071db00923b0091db00915700701100923b009011009157007018009", + "0x2000923b12e0150095c500701501f01b12523b0091db0110180090071fd", + "0x722c02602312523b0090200095c600700723b00900712e0070250097b0", + "0x923c00905700722923c12e23b00902300915900700723b00922c009054", + "0x703002e12e23b00902600915900702c00923b00922900905800700723b", + "0x723b00900710f00722500923b00903000905800700723b00902e009057", + "0x1f00e5c700722500923b0092250091fd00702c00923b00902c0091fd007", + "0x700723b00900712e0070362210331257b104503112e23b12e22502c12e", + "0x23b00903100900e00703800923b0092190093b400721900923b00900716c", + "0xee00712600923b0090380093b500703b00923b00904500922100703a009", + "0xe00703c00923b0090360093b700700723b00900712e0070077b2009007", + "0x23b00903c0093b500703b00923b00922100922100703a00923b009033009", + "0x97b314100923b12e03e0093b900703e00923b0091260095c8007126009", + "0x923b00914100925000700723b0090070ea00700723b00900712e007041", + "0x12500714800923b00904300946900704300923b00914512512e468007145", + "0x23b00903b00922100703a00923b00903a00900e00701b00923b00901b009", + "0x900712e00714803b03a01b00e00914800923b00914800944d00703b009", + "0x904100944c00700723b00912500915200700723b0090070ea00700723b", + "0x703a00923b00903a00900e00701b00923b00901b00912500704700923b", + "0x3b03a01b00e00904700923b00904700944d00703b00923b00903b009221", + "0x23b00902500944c00700723b00912500915200700723b00900712e007047", + "0x22100701f00923b00901f00900e00701b00923b00901b009125007049009", + "0x4912e01f01b00e00904900923b00904900944d00712e00923b00912e009", + "0x23b00900e00969300700e00923b00900e0094c700700723b0090070ea007", + "0x1fd0095c10071db00923b00900722900701100923b0090072290071fd009", + "0x700923b00900700912500700723b0092230095c200701822312e23b009", + "0x1100915700701800923b0090180095c300700900923b00900900900e007", + "0x1db0110180090071fd5c40071db00923b0091db00915700701100923b009", + "0x712e0070250097b402000923b12e0150095c500701501f01b12523b009", + "0x723b00922c00905400722c02602312523b0090200095c600700723b009", + "0x22900905800700723b00923c00905700722923c12e23b009023009159007", + "0x723b00902e00905700703002e12e23b00902600915900702c00923b009", + "0x23b00902c0091fd00700723b00900710f00722500923b009030009058007", + "0x12e23b12e22502c12e01f00e5c700722500923b0092250091fd00702c009", + "0x21900923b00900716c00700723b00900712e0070362210331257b5045031", + "0x4500922100703a00923b00903100900e00703800923b0092190093b4007", + "0x12e0070077b60090070ee00712600923b0090380093b500703b00923b009", + "0x3a00923b00903300900e00703c00923b0090360093b700700723b009007", + "0x1260095c800712600923b00903c0093b500703b00923b009221009221007", + "0x23b00900712e0070410097b714100923b12e03e0093b900703e00923b009", + "0x14512512e46800714500923b00914100925000700723b0090070ea007007", + "0x1b00923b00901b00912500714800923b00904300946900704300923b009", + "0x14800944d00703b00923b00903b00922100703a00923b00903a00900e007", + "0x90070ea00700723b00900712e00714803b03a01b00e00914800923b009", + "0x912500704700923b00904100944c00700723b00912500915200700723b", + "0x923b00903b00922100703a00923b00903a00900e00701b00923b00901b", + "0x23b00900712e00704703b03a01b00e00904700923b00904700944d00703b", + "0x1b00912500704900923b00902500944c00700723b009125009152007007", + "0x12e00923b00912e00922100701f00923b00901f00900e00701b00923b009", + "0x723b0090070ea00704912e01f01b00e00904900923b00904900944d007", + "0x90072290071fd00923b00900e00969400700e00923b00900e0094d7007", + "0x701822312e23b0091fd0095c10071db00923b00900722900701100923b", + "0x23b00900900900e00700700923b00900700912500700723b0092230095c2", + "0x15700701100923b00901100915700701800923b0090180095c3007009009", + "0x1501f01b12523b0091db0110180090071fd5c40071db00923b0091db009", + "0x95c600700723b00900712e0070250097b802000923b12e0150095c5007", + "0x23b00902300915900700723b00922c00905400722c02602312523b009020", + "0x15900702c00923b00922900905800700723b00923c00905700722923c12e", + "0x23b00903000905800700723b00902e00905700703002e12e23b009026009", + "0x2250091fd00702c00923b00902c0091fd00700723b00900710f007225009", + "0x2210331257b904503112e23b12e22502c12e01f00e5c700722500923b009", + "0x23b0092190093b400721900923b00900716c00700723b00900712e007036", + "0x3b500703b00923b00904500922100703a00923b00903100900e007038009", + "0x3b700700723b00900712e0070077ba0090070ee00712600923b009038009", + "0x23b00922100922100703a00923b00903300900e00703c00923b009036009", + "0x3b900703e00923b0091260095c800712600923b00903c0093b500703b009", + "0x23b0090070ea00700723b00900712e0070410097bb14100923b12e03e009", + "0x46900704300923b00914512512e46800714500923b009141009250007007", + "0x23b00903a00900e00701b00923b00901b00912500714800923b009043009", + "0xe00914800923b00914800944d00703b00923b00903b00922100703a009", + "0x12500915200700723b0090070ea00700723b00900712e00714803b03a01b", + "0x701b00923b00901b00912500704700923b00904100944c00700723b009", + "0x904700944d00703b00923b00903b00922100703a00923b00903a00900e", + "0x912500915200700723b00900712e00704703b03a01b00e00904700923b", + "0xe00701b00923b00901b00912500704900923b00902500944c00700723b", + "0x23b00904900944d00712e00923b00912e00922100701f00923b00901f009", + "0x23b00900e0094e700700723b0090070ea00704912e01f01b00e009049009", + "0x722900701100923b0090072290071fd00923b00900e00969500700e009", + "0x723b0092230095c200701822312e23b0091fd0095c10071db00923b009", + "0x180095c300700900923b00900900900e00700700923b009007009125007", + "0x1db00923b0091db00915700701100923b00901100915700701800923b009", + "0x23b12e0150095c500701501f01b12523b0091db0110180090071fd5c4007", + "0x2602312523b0090200095c600700723b00900712e0070250097bc020009", + "0x905700722923c12e23b00902300915900700723b00922c00905400722c", + "0x2e12e23b00902600915900702c00923b00922900905800700723b00923c", + "0x900710f00722500923b00903000905800700723b00902e009057007030", + "0x5c700722500923b0092250091fd00702c00923b00902c0091fd00700723b", + "0x23b00900712e0070362210331257bd04503112e23b12e22502c12e01f00e", + "0x3100900e00703800923b0092190093b400721900923b00900716c007007", + "0x12600923b0090380093b500703b00923b00904500922100703a00923b009", + "0x3c00923b0090360093b700700723b00900712e0070077be0090070ee007", + "0x3c0093b500703b00923b00922100922100703a00923b00903300900e007", + "0x14100923b12e03e0093b900703e00923b0091260095c800712600923b009", + "0x914100925000700723b0090070ea00700723b00900712e0070410097bf", + "0x14800923b00904300946900704300923b00914512512e46800714500923b", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00714803b03a01b00e00914800923b00914800944d00703b00923b009", + "0x944c00700723b00912500915200700723b0090070ea00700723b009007", + "0x923b00903a00900e00701b00923b00901b00912500704700923b009041", + "0x1b00e00904700923b00904700944d00703b00923b00903b00922100703a", + "0x2500944c00700723b00912500915200700723b00900712e00704703b03a", + "0x1f00923b00901f00900e00701b00923b00901b00912500704900923b009", + "0x1f01b00e00904900923b00904900944d00712e00923b00912e009221007", + "0xe0095f700700e00923b00900767500700723b00912500937300704912e", + "0x701100923b00901100902600701100923b0090070250071fd00923b009", + "0x182231db12523b12e1fd01112e00900e5f80071fd00923b0091fd009629", + "0x700700923b00900700912500700723b00900712e00701501f01b1257c0", + "0x900e00702502012e23b00901800712e69600701800923b00901800902e", + "0x923b12e02500969700722300923b0092230092210071db00923b0091db", + "0x12500722c00923b00902300969800700723b00900712e0070260097c1023", + "0x23b00922300922100722900923b0091db00900e00723c00923b009020009", + "0x900712e0070077c20090070ee00702e00923b00922c00969900702c009", + "0x900725700703000923b00900722900700723b00902600905400700723b", + "0x3100923b00922503012e03000722500923b00922500902e00722500923b", + "0x3300951400703300923b00903104512e03100704500923b009007225007", + "0x1db00923b0091db00900e00702000923b00902000912500722100923b009", + "0x1db02000e00922100923b00922100951300722300923b009223009221007", + "0x700912500703600923b00901500969b00700723b00900712e007221223", + "0x2c00923b00901f00922100722900923b00901b00900e00723c00923b009", + "0x2190090dd00721900923b00902e00969c00702e00923b009036009699007", + "0x923b00903800918e00700723b00900712e00703a0097c303800923b12e", + "0x912500703c00923b00912600951200712600923b00903b00951100703b", + "0x923b00902c00922100722900923b00922900900e00723c00923b00923c", + "0x23b00900712e00703c02c22923c00e00903c00923b00903c00951300702c", + "0x900e00723c00923b00923c00912500703e00923b00903a009514007007", + "0x923b00903e00951300702c00923b00902c00922100722900923b009229", + "0x923b00900767000700723b00912500937200703e02c22923c00e00903e", + "0x1100902600701100923b0090070250071fd00923b00900e0095f700700e", + "0x12e1fd01112e00900e5f80071fd00923b0091fd00962900701100923b009", + "0x700912500700723b00900712e00701501f01b1257c40182231db12523b", + "0x12e23b00901800712e69600701800923b00901800902e00700700923b009", + "0x69700722300923b0092230092210071db00923b0091db00900e007025020", + "0x902300969800700723b00900712e0070260097c502300923b12e025009", + "0x722900923b0091db00900e00723c00923b00902000912500722c00923b", + "0x7c60090070ee00702e00923b00922c00969900702c00923b009223009221", + "0x923b00900722900700723b00902600905400700723b00900712e007007", + "0x3012e03000722500923b00922500902e00722500923b009007257007030", + "0x923b00903104512e03100704500923b00900722500703100923b009225", + "0x900e00702000923b00902000912500722100923b009033009514007033", + "0x923b00922100951300722300923b0092230092210071db00923b0091db", + "0x923b00901500969b00700723b00900712e0072212231db02000e009221", + "0x922100722900923b00901b00900e00723c00923b009007009125007036", + "0x923b00902e00969c00702e00923b00903600969900702c00923b00901f", + "0x18e00700723b00900712e00703a0097c703800923b12e2190090dd007219", + "0x23b00912600951200712600923b00903b00951100703b00923b009038009", + "0x22100722900923b00922900900e00723c00923b00923c00912500703c009", + "0x3c02c22923c00e00903c00923b00903c00951300702c00923b00902c009", + "0x23b00923c00912500703e00923b00903a00951400700723b00900712e007", + "0x51300702c00923b00902c00922100722900923b00922900900e00723c009", + "0x12e00923b00e00700966200703e02c22923c00e00903e00923b00903e009", + "0x23b00900714c00700723b00900712e0071fd0097ca00e0097c91250097c8", + "0x2e00700723b0091db0091550072231db12e23b009011009153007011009", + "0x900922312e05200700900923b00900900915700722300923b009223009", + "0x701800923b00901800915700700723b00901b00905400701b01812e23b", + "0x1f00969e00700723b00901500905400701501f12e23b00901812e12e69d", + "0x900714300700723b00900712e0070077cb0090070ee00702000923b009", + "0x700723b00902300915500702602312e23b00902500915300702500923b", + "0x902612e05200700900923b00900900915700702600923b00902600902e", + "0x22c00923b00922c00915700700723b00923c00905400723c22c12e23b009", + "0x969e00700723b00902c00905400702c22912e23b00922c12512e69d007", + "0x740b00700723b00900712e0070077cb0090070ee00702000923b009229", + "0x723b00903000915500722503012e23b00902e00915300702e00923b009", + "0x22512e05200700900923b00900900915700722500923b00922500902e007", + "0x923b00903100915700700723b00904500905400704503112e23b009009", + "0x69e00700723b00922100905400722103312e23b00903100e12e69d007031", + "0x14b00700723b00900712e0070077cb0090070ee00702000923b009033009", + "0x23b00921900915500703821912e23b00903600915300703600923b009007", + "0x12e05200700900923b00900900915700703800923b00903800902e007007", + "0x23b00903a00915700700723b00903b00905400703b03a12e23b009009038", + "0x700723b00903c00905400703c12612e23b00903a1fd12e69d00703a009", + "0xea00703e02012e00903e00923b00900716c00702000923b00912600969e", + "0x1fd00923b00900e00969f00700e00923b00900e00953d00700723b009007", + "0x23b0091fd0095c10071db00923b00900722900701100923b009007229007", + "0xe00700700923b00900700912500700723b0092230095c200701822312e", + "0x23b00901100915700701800923b0090180095c300700900923b009009009", + "0x23b0091db0110180090071fd5c40071db00923b0091db009157007011009", + "0x23b00900712e0070250097cc02000923b12e0150095c500701501f01b125", + "0x15900700723b00922c00905400722c02602312523b0090200095c6007007", + "0x23b00922900905800700723b00923c00905700722923c12e23b009023009", + "0x5800700723b00902e00905700703002e12e23b00902600915900702c009", + "0x2c00923b00902c0091fd00700723b00900710f00722500923b009030009", + "0x4503112e23b12e22502c12e01f00e5c700722500923b0092250091fd007", + "0x3b400721900923b00900716c00700723b00900712e0070362210331257cd", + "0x23b00904500922100703a00923b00903100900e00703800923b009219009", + "0x900712e0070077ce0090070ee00712600923b0090380093b500703b009", + "0x22100703a00923b00903300900e00703c00923b0090360093b700700723b", + "0x23b0091260095c800712600923b00903c0093b500703b00923b009221009", + "0x700723b00900712e0070410097cf14100923b12e03e0093b900703e009", + "0x23b00914512512e46800714500923b00914100925000700723b0090070ea", + "0xe00701b00923b00901b00912500714800923b009043009469007043009", + "0x23b00914800944d00703b00923b00903b00922100703a00923b00903a009", + "0x723b0090070ea00700723b00900712e00714803b03a01b00e009148009", + "0x901b00912500704700923b00904100944c00700723b009125009152007", + "0x703b00923b00903b00922100703a00923b00903a00900e00701b00923b", + "0x700723b00900712e00704703b03a01b00e00904700923b00904700944d", + "0x23b00901b00912500704900923b00902500944c00700723b009125009152", + "0x44d00712e00923b00912e00922100701f00923b00901f00900e00701b009", + "0x700e00923b00900707100704912e01f01b00e00904900923b009049009", + "0x12500700723b0090070ea00700723b00900716000701100923b009007334", + "0x912e00712e33500712e00923b00912e0091fd00700700923b009007009", + "0x900712e00701b0097d01fd00923b12e0180093360070182231db12523b", + "0x701501f12e23b00922300916e00722300923b0092230091fd00700723b", + "0x70200097d112500923b12e0150090720071fd00923b0091fd01112e338", + "0x923b00900900900e0071db00923b0091db00912500700723b00900712e", + "0x17400712500923b00912500e12e07400701f00923b00901f0091fd007009", + "0x97d222c00923b12e02600907600702602302512523b00901f0091db125", + "0x2c00907700702c22912e23b00922c00918000700723b00900712e00723c", + "0x902e1251fd1256a000700723b00900712e0070300097d302e00923b12e", + "0x4500923b00903122912e6a200703100923b0092250096a100722500923b", + "0x2300900e00702500923b00902500912500703300923b0090450096a3007", + "0x712e00703302302512500903300923b0090330096a500702300923b009", + "0x96a600700723b00912500915500700723b0091fd00910100700723b009", + "0x23b0090360096a300703600923b00922122912e6a200722100923b009030", + "0x6a500702300923b00902300900e00702500923b009025009125007219009", + "0x915500700723b00900712e00721902302512500921900923b009219009", + "0x703800923b00923c0096a700700723b0091fd00910100700723b009125", + "0x90380096a500702300923b00902300900e00702500923b009025009125", + "0x23b0091fd00910100700723b00900712e00703802302512500903800923b", + "0x1f12e6a200703a00923b0090200096a600700723b00900e00907f007007", + "0x923b0091db00912500712600923b00903b0096a300703b00923b00903a", + "0x1db12500912600923b0091260096a500700900923b00900900900e0071db", + "0x901100935500700723b00900e00907f00700723b00900712e007126009", + "0x703e00923b00903c22312e6a200703c00923b00901b0096a600700723b", + "0x900900900e0071db00923b0091db00912500714100923b00903e0096a3", + "0x712e6a80071410091db12500914100923b0091410096a500700900923b", + "0x6aa00700723b00900712e0071db0111fd1257d400e12512e12523b12e009", + "0x23b00912500922100701800923b00912e00900e00722300923b00900e009", + "0x900712e0070077d50090070ee00701f00923b00922300925500701b009", + "0x22100701800923b0091fd00900e00701500923b0091db0096ab00700723b", + "0x23b00901f0096ac00701f00923b00901500925500701b00923b009011009", + "0x700723b00900712e0070230097d602500923b12e02000954e007020009", + "0x922c0096ae00722c00923b0090260096ad00702600923b009025009550", + "0x701b00923b00901b00922100701800923b00901800900e00723c00923b", + "0x6b000700723b00900712e00723c01b01812500923c00923b00923c0096af", + "0x23b00901b00922100701800923b00901800900e00722900923b009023009", + "0x90071256b100722901b01812500922900923b0092290096af00701b009", + "0x900e0096b200700723b00900712e0071fd0097d700e12512e23b12e12e", + "0x712500923b0091250091250071db00923b0090110096b300701100923b", + "0x722900700723b00900712e0071db12512e0091db00923b0091db0096b4", + "0x701800923b00901800902e00701800923b0090076b500722300923b009", + "0x1b01f12e03100701f00923b00900722500701b00923b00901822312e030", + "0x1fd00923b0091fd00912500702000923b0090150096b600701500923b009", + "0x71fd00923b00900715f0070201fd12e00902000923b0090200096b4007", + "0x700900923b00900900900e00700723b0090070ea00700723b009007160", + "0x1620071db00e01112523b00912e00912e14d00712e00923b00912e009221", + "0x12e0070180097d822300923b12e1db00914e00700e00923b00900e1fd12e", + "0x1f00923b00901b00910a00701b00923b00922300914900700723b009007", + "0x3122503002e02c22923c22c02602302502001502023b00901f00910c007", + "0x23b00902600915500700723b00902300915e00700723b009020009101007", + "0x902e00915e00700723b00923c00915500700723b00922c009155007007", + "0x15300722100923b00900714b00703304512e23b00901500915300700723b", + "0x23b00903300916300700723b00903600915500721903612e23b009221009", + "0x14f00703800923b00903800902e00703a00923b009219009163007038009", + "0x923b00903b00902e00700723b00900710f00703b00923b00903a03812e", + "0x96b700722900923b0092290096b800702500923b0090250096b700703b", + "0x923b00922500902600703000923b00903000902600702c00923b00902c", + "0x910600704500923b00904500902e00703100923b0090310091fd007225", + "0x3c00923b00900716c00700723b00900712e0071260097d900723b12e03b", + "0x3e0090a500714100923b00904500902e00703e00923b00903c009144007", + "0x12600911100700723b00900712e0070077da0090070ee00704100923b009", + "0x714800923b00900711800704314512e23b00904500915300700723b009", + "0x904300916300700723b00904700915500704904712e23b009148009153", + "0x15200923b00904c15012e14f00704c00923b00904900916300715000923b", + "0x12e0071530097db00723b12e15200910600715200923b00915200902e007", + "0x715700923b00915500914400715500923b00900716c00700723b009007", + "0x700723b00900712e0070077dc0090070ee00705200923b0091570090a5", + "0x923b00905400911300705400923b00900716c00700723b009153009111", + "0x90a500714100923b00914500902e00705200923b0091590090a5007159", + "0x900712e0070580097dd05700923b12e04100914000704100923b009052", + "0x22900914600700723b00902c00914700700723b00905700905400700723b", + "0x902000700723b00922500902000700723b00903100915e00700723b009", + "0x5d00923b00900714300715d05a12e23b00914100915300700723b009030", + "0x15d00916300700723b00915e00915500706015e12e23b00905d009153007", + "0x923b00916015f12e14f00716000923b00906000916300715f00923b009", + "0x71610097de00723b12e06400910600706400923b00906400902e007064", + "0x12e0070077df0090070ee00700723b00905a00915500700723b00900712e", + "0x6716212e23b00905a00915300700723b00916100911100700723b009007", + "0x23b00916400915300716400923b00900711500700723b009162009155007", + "0x16300716b00923b00906700916300700723b00916600915500716816612e", + "0x906e00902e00706e00923b00906d16b12e14f00706d00923b009168009", + "0x700723b00900712e00706f0097e000723b12e06e00910600706e00923b", + "0x2507100712525400707100923b0090710096b700707100923b0090076ba", + "0x23b0090070ea00700723b00900712e00717407412e7e107216e12e23b12e", + "0x1100900e00707600923b00916e00912500700723b009072009147007007", + "0x90070ea00700723b00900712e0070077e20090070ee00718000923b009", + "0x900722900700723b00912500902000700723b00917400914700700723b", + "0x3000707800923b00907800902e00707800923b0090076bb00707700923b", + "0x918607b12e03100707b00923b00900722500718600923b00907807712e", + "0x707400923b00907400912500708d00923b00918700962000718700923b", + "0x908d00961f00700e00923b00900e00922100701100923b00901100900e", + "0x23b0090070ea00700723b00900712e00708d00e01107400e00908d00923b", + "0x902500914700700723b00912500902000700723b00906f009111007007", + "0x8e00902e00708e00923b00900713b00707f00923b00900722900700723b", + "0x9000923b00900722500708f00923b00908e07f12e03000708e00923b009", + "0x912500709200923b00909100962000709100923b00908f09012e031007", + "0x923b00900e00922100701100923b00901100900e00700700923b009007", + "0x23b00900712e00709200e01100700e00909200923b00909200961f00700e", + "0x914100915500700723b00902500914700700723b009058009054007007", + "0x2500700723b00909300902000709409312e23b00903000901500700723b", + "0x23b00909600902000709709612e23b00909500901500709500923b009007", + "0x12e22c00709900923b00909700902300709800923b009094009023007007", + "0x723b00912500902000700723b00900712e0070077e300723b12e099098", + "0x23b00903100915e00700723b00922900914600700723b00902c009147007", + "0x723b00900712e0070077e40090070ee00700723b009225009020007007", + "0x900702500700723b0091a500902000709c1a512e23b009225009015007", + "0x700723b00903700902000705b03712e23b0091a70090150071a700923b", + "0x1ac09f12e22c0071ac00923b00905b00902300709f00923b00909c009023", + "0x14700700723b00912500902000700723b00900712e0070077e500723b12e", + "0x700723b00903100915e00700723b00922900914600700723b00902c009", + "0x71b200923b0090076bd0071b000923b00900722900700723b0090070ea", + "0x90072250070a300923b0091b21b012e0300071b200923b0091b200902e", + "0x1b500923b0090a50096200070a500923b0090a304a12e03100704a00923b", + "0xe00922100701100923b00901100900e00700700923b009007009125007", + "0x12e0071b500e01100700e0091b500923b0091b500961f00700e00923b009", + "0xa900923b0090a700901f0070a700923b00903100901b00700723b009007", + "0x900702500700723b0091b80090200070ac1b812e23b0090a9009015007", + "0x700723b0091bc0090200070b01bc12e23b0090ae0090150070ae00923b", + "0x90b20090260071bd00923b0090b00090230070b200923b0090ac009023", + "0x700723b00900712e0070077e600723b12e1bd0b212e22c0070b200923b", + "0x700723b00902c00914700700723b00912500902000700723b0090070ea", + "0xb600923b0090076be0070b400923b00900722900700723b009229009146", + "0x72250071bb00923b0090b60b412e0300070b600923b0090b600902e007", + "0x923b0090ba0096200070ba00923b0091bb0b812e0310070b800923b009", + "0x922100701100923b00901100900e00700700923b0090070091250071ba", + "0x71ba00e01100700e0091ba00923b0091ba00961f00700e00923b00900e", + "0x6bf0070bc00923b0090076bf00700723b0090070ea00700723b00900712e", + "0x923b00901100900e00700700923b0090070091250070be00923b009007", + "0x96b70070be00923b0090be0096b700722900923b0092290096b8007011", + "0xbe2290110070116c000702c00923b00902c0096b70070bc00923b0090bc", + "0x70c40097e71b600923b12e0c20096c10070c20c01b912523b00902c0bc", + "0xc60091460071b70c71b30c600e23b0091b60096c200700723b00900712e", + "0x6b70071b900923b0091b900912500700723b0091b700905400700723b009", + "0x90c90096b70070c90c712e23b0090c70092530071b300923b0091b3009", + "0x23b12e0cb0096c40070cb1ad12e23b0090c91b31b91256c30070c900923b", + "0x6b70070cf00923b0090076c500700723b00900712e0071aa0097e80cd009", + "0xd112e7e91a31a812e23b12e0c70cf1ad1252540070cf00923b0090cf009", + "0x23b0090cd0096c600700723b0091a300914700700723b00900712e0071a1", + "0x1252540070d500923b0090d50096b70070d500923b0090076c70071a0009", + "0x14700700723b00900712e0070da0d812e7ea19b19f12e23b12e1a00d51a8", + "0x923b0090c000900e00707600923b00919f00912500700723b00919b009", + "0x761256c900719800923b00919800902600719800923b0090076c8007180", + "0x902000700723b00900712e0070df18e12e7eb0dd19712e23b12e198125", + "0x2e00718a00923b0090076ca0070e100923b00900722900700723b0090dd", + "0x23b00900722500718900923b00918a0e112e03000718a00923b00918a009", + "0x718b00923b00918c00962000718c00923b00918918812e031007188009", + "0x900e00922100718000923b00918000900e00719700923b009197009125", + "0x712e00718b00e18019700e00918b00923b00918b00961f00700e00923b", + "0x961c0070e500923b00900716c00700723b0090df00902000700723b009", + "0x923b00918e00912500718300923b00918400961d00718400923b0090e5", + "0x961f00700e00923b00900e00922100718000923b00918000900e00718e", + "0x914700700723b00900712e00718300e18018e00e00918300923b009183", + "0x6bb0070a000923b00900722900700723b00912500902000700723b0090da", + "0x23b0090e80a012e0300070e800923b0090e800902e0070e800923b009007", + "0x6200070ea00923b00917917b12e03100717b00923b009007225007179009", + "0x23b0090c000900e0070d800923b0090d800912500717500923b0090ea009", + "0xe00917500923b00917500961f00700e00923b00900e0092210070c0009", + "0x902000700723b0091a100914700700723b00900712e00717500e0c00d8", + "0x6cc00717100923b00900722900700723b0090cd0096cb00700723b009125", + "0x23b0090ec17112e0300070ec00923b0090ec00902e0070ec00923b009007", + "0x6200070f000923b0090ee16c12e03100716c00923b0090072250070ee009", + "0x23b0090c000900e0070d100923b0090d100912500716900923b0090f0009", + "0xe00916900923b00916900961f00700e00923b00900e0092210070c0009", + "0x914700700723b00912500902000700723b00900712e00716900e0c00d1", + "0x1ad00923b0091ad00912500716500923b0091aa00962000700723b0090c7", + "0x16500961f00700e00923b00900e0092210070c000923b0090c000900e007", + "0x12500902000700723b00900712e00716500e0c01ad00e00916500923b009", + "0x71b900923b0091b90091250070f300923b0090c400962000700723b009", + "0x90f300961f00700e00923b00900e0092210070c000923b0090c000900e", + "0x912500902000700723b00900712e0070f300e0c01b900e0090f300923b", + "0xe00700700923b00900700912500716300923b00901800962000700723b", + "0x23b00916300961f00700e00923b00900e00922100701100923b009011009", + "0x7ec00e12512e23b12e12e0090071256cd00716300e01100700e009163009", + "0x91250071db00923b00900e0096ce00700723b00900712e0070111fd12e", + "0x70077ed0090070ee00701800923b0091db0096cf00722300923b009125", + "0x923b0091fd00912500701b00923b0090110096d000700723b00900712e", + "0x1f00902e00701f00923b0090076d100701800923b00901b0096cf007223", + "0x923b12e0150090dd00701500923b00901f01812e6d200701f00923b009", + "0x51100702300923b00902000918e00700723b00900712e0070250097ee020", + "0x23b00922300912500722c00923b00902600951200702600923b009023009", + "0x723b00900712e00722c22312e00922c00923b00922c009513007223009", + "0x23c00951300722300923b00922300912500723c00923b009025009514007", + "0x901b0071db01112e23b0090110096d300723c22312e00923c00923b009", + "0x12e23b00901800901500701800923b00922300901f00722300923b0091db", + "0x1500901500701500923b0090076d400700723b00901b00902000701f01b", + "0x2300923b00901f00902300700723b00902000902000702502012e23b009", + "0x2500902300700723b00902600902000722c02612e23b009023009015007", + "0x723b00922900902000702c22912e23b00923c00901500723c00923b009", + "0x2e00902600703000923b00902c00902300702e00923b00922c009023007", + "0x723b00900712e0070077ef00723b12e03002e12e22c00702e00923b009", + "0x23b00901100915e00700723b00900e00915200700723b0091fd009155007", + "0x3100939900703100923b00922500911300722500923b00900716c007007", + "0x700923b00900700912500703300923b00904500939a00704500923b009", + "0x12500922100712e00923b00912e00900e00700900923b009009009033007", + "0x703312512e0090071fd00903300923b00903300939b00712500923b009", + "0x923b00900702500703622112e23b0090110096d500700723b00900712e", + "0x912500703a00923b0090380096d600703800923b00903600901b007219", + "0x923b00921900902600703a00923b00903a0090b400700700923b009007", + "0x3c00923b12e1260096d800712603b12e23b00921903a0071256d7007219", + "0x916500714100923b00903c0096d900700723b00900712e00703e0097f0", + "0x23b00914500915e00704314512e23b0092210096d500704100923b009141", + "0x470096d600704700923b00904300901b00714800923b009007563007007", + "0x4900923b0090490090b400703b00923b00903b00912500704900923b009", + "0x704c15012e23b00914804903b1256d700714800923b009148009026007", + "0x12e0071530097f115200923b12e04c0096d800704100923b00904100902e", + "0x15700923b00915500916500715500923b0091520096d900700723b009007", + "0x5805715905422323b00905200936900705200e12e23b00900e0095de007", + "0x37600700723b00915900937100700723b00905400937000715e05d15d05a", + "0x700723b00915d00937400700723b00905a00937500700723b009058009", + "0x923b00912e00900e00700723b00915e00937200700723b00905d009373", + "0x15f06012523b00905712512e1253da00712500923b00912500922100712e", + "0x1610097f206400923b12e16000907b00715700923b00915700902e007160", + "0x23b00915700916300716200923b00904100916300700723b00900712e007", + "0x3300715000923b00915000912500716400923b009064009187007067009", + "0x916600902e0071661fd12e23b0091fd00936b00700900923b009009009", + "0x16816212e23b00916200936b00716400923b00916400902e00716600923b", + "0x902e00716b06712e23b00906700936b00716800923b00916800902e007", + "0x6f06e06d12523b00916b16816416600915001165300716b00923b00916b", + "0x905400700723b00900712e00716e0097f307100923b12e06f009140007", + "0x718607807718007617407407222323b00900e00936900700723b009071", + "0x723b00917400937700700723b00907400937100700723b009072009370", + "0x23b00907800937300700723b00907700937400700723b009180009375007", + "0x15f00922100706000923b00906000900e00700723b009186009372007007", + "0x8d00907b00708d18707b12523b00907615f0601253de00715f00923b009", + "0x923b00907f00918700700723b00900712e00708e0097f407f00923b12e", + "0x902e00706e00923b00906e00903300706d00923b00906d00912500708f", + "0x923b00916200902e00708f00923b00908f00902e0071fd00923b0091fd", + "0x23b00906716208f1fd06e06d01165300706700923b00906700902e007162", + "0x9400923b00909100903300709300923b009090009125007092091090125", + "0x920090a500709600923b00918700922100709500923b00907b00900e007", + "0x6700915500700723b00900712e0070077f50090070ee00709700923b009", + "0x939c00700723b0091fd00915500700723b00916200915500700723b009", + "0x923b00906e00903300706d00923b00906d00912500709800923b00908e", + "0x939b00718700923b00918700922100707b00923b00907b00900e00706e", + "0x5400700723b00900712e00709818707b06e06d1fd00909800923b009098", + "0x700723b00906700915500700723b0091fd00915500700723b00916e009", + "0x9900923b00900716c00700723b00900e00915200700723b009162009155", + "0x6e00903300709300923b00906d0091250071a500923b009099009144007", + "0x9600923b00915f00922100709500923b00906000900e00709400923b009", + "0x9c00939a00709c00923b00909700939900709700923b0091a50090a5007", + "0x9400923b00909400903300709300923b0090930091250071a700923b009", + "0x1a700939b00709600923b00909600922100709500923b00909500900e007", + "0x915500700723b00900712e0071a70960950940931fd0091a700923b009", + "0x15500700723b00904100915500700723b00900e00915200700723b0091fd", + "0x923b00915000912500703700923b00916100939c00700723b009157009", + "0x922100706000923b00906000900e00700900923b009009009033007150", + "0x3715f0600091501fd00903700923b00903700939b00715f00923b00915f", + "0x723b00900e00915200700723b0091fd00915500700723b00900712e007", + "0x915000912500705b00923b00915300939c00700723b009041009155007", + "0x712e00923b00912e00900e00700900923b00900900903300715000923b", + "0x12e0091501fd00905b00923b00905b00939b00712500923b009125009221", + "0x900e00915200700723b0091fd00915500700723b00900712e00705b125", + "0x912500709f00923b00903e00939c00700723b00922100915e00700723b", + "0x923b00912e00900e00700900923b00900900903300703b00923b00903b", + "0x3b1fd00909f00923b00909f00939b00712500923b00912500922100712e", + "0x923b0091db00901b0071db01112e23b0090110096d300709f12512e009", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b0090076d400700723b00901b009", + "0x2300901500702300923b00901f00902300700723b009020009020007025", + "0x23c00923b00902500902300700723b00902600902000722c02612e23b009", + "0x22c00902300700723b00922900902000702c22912e23b00923c009015007", + "0x2e00923b00902e00902600703000923b00902c00902300702e00923b009", + "0x1fd00915500700723b00900712e0070077f600723b12e03002e12e22c007", + "0x716c00700723b00901100915e00700723b00900e00915200700723b009", + "0x4500923b00903100939900703100923b00922500911300722500923b009", + "0x900903300700700923b00900700912500703300923b00904500939a007", + "0x12500923b00912500922100712e00923b00912e00900e00700900923b009", + "0x23b00900712e00703312512e0090071fd00903300923b00903300939b007", + "0x901b00721900923b00900702500703622112e23b0090110096d5007007", + "0x923b00900700912500703a00923b0090380096d600703800923b009036", + "0x1256d700721900923b00921900902600703a00923b00903a0090b4007007", + "0x703e0097f703c00923b12e1260096d800712603b12e23b00921903a007", + "0x923b00914100916500714100923b00903c0096d900700723b00900712e", + "0x756300700723b00914500915e00704314512e23b0092210096d5007041", + "0x4900923b0090470096d600704700923b00904300901b00714800923b009", + "0x14800902600704900923b0090490090b400703b00923b00903b009125007", + "0x904100902e00704c15012e23b00914804903b1256d700714800923b009", + "0x723b00900712e0071530097f815200923b12e04c0096d800704100923b", + "0xe00936900715700923b00915500916500715500923b0091520096d9007", + "0x37700700723b00905200937000705d15d05a05805715905405222323b009", + "0x700723b00905800937500700723b00905700937600700723b009159009", + "0x723b00905d00937200700723b00915d00937300700723b00905a009374", + "0x12e1253d200712500923b00912500922100712e00923b00912e00900e007", + "0x15f00907b00715700923b00915700902e00715f06015e12523b009054125", + "0x923b00904100916300700723b00900712e0070640097f916000923b12e", + "0x912500706700923b00916000918700716200923b009157009163007161", + "0x923b0091fd00902e00700900923b00900900903300715000923b009150", + "0x902e00716100923b00916100902e00706700923b00906700902e0071fd", + "0x16816616412523b0091621610671fd00915001165300716200923b009162", + "0x16400912500706d00923b00916b00939a00716b00923b009168009399007", + "0x15e00923b00915e00900e00716600923b00916600903300716400923b009", + "0x1661641fd00906d00923b00906d00939b00706000923b009060009221007", + "0x15700915500700723b00904100915500700723b00900712e00706d06015e", + "0x12500706e00923b00906400939c00700723b0091fd00915500700723b009", + "0x23b00915e00900e00700900923b00900900903300715000923b009150009", + "0x1fd00906e00923b00906e00939b00706000923b00906000922100715e009", + "0x15500700723b0091fd00915500700723b00900712e00706e06015e009150", + "0x6f00923b00915300939c00700723b00900e00915200700723b009041009", + "0x12e00900e00700900923b00900900903300715000923b009150009125007", + "0x6f00923b00906f00939b00712500923b00912500922100712e00923b009", + "0x723b0091fd00915500700723b00900712e00706f12512e0091501fd009", + "0x23b00903e00939c00700723b00900e00915200700723b00922100915e007", + "0xe00700900923b00900900903300703b00923b00903b009125007071009", + "0x23b00907100939b00712500923b00912500922100712e00923b00912e009", + "0x90071600071db00923b00900715f00707112512e00903b1fd009071009", + "0x922300903800722300923b00900721900700723b0090070ea00700723b", + "0x12e00701501f12e7fa01b01812e23b12e22300900712503a00722300923b", + "0x12500700723b00900710f00702000923b00912500956100700723b009007", + "0x12e0070260097fb02302512e23b12e02000964400701800923b009018009", + "0x23c00923b00902500956900722c00923b00902300964500700723b009007", + "0x723b00900712e0070077fc0090070ee00722900923b00922c009646007", + "0x902600956900702e00923b00902c00964700702c00923b00900716c007", + "0x703000923b00923c00912800722900923b00902e00964600723c00923b", + "0x12e0070310097fd22500923b12e22900964800703000923b009030009123", + "0x4500923b00904500964900704500923b00922500956e00700723b009007", + "0x721903622112523b00903300957100703304512e23b009045009570007", + "0x923b00922100910200700723b00921900957200700723b009036009155", + "0x3c12603b12523b00903a00957100703a04512e23b009045009570007038", + "0x23b00912600916300700723b00903c00957200700723b00903b009101007", + "0x700723b00914100910100714504114112523b00904500957100703e009", + "0x23b0090430091fd00704300923b00914500905800700723b009041009155", + "0x111501257fe04904714812523b12e04303e03812e01b1fd6da007043009", + "0x723b0091db00906400700723b0090070ea00700723b00900712e00704c", + "0x714300715200923b0090491fd12e6db00704900923b0090490091fd007", + "0x923b00901800912500715500923b00915300e12e6dc00715300923b009", + "0x912300704700923b00904700922100714800923b00914800900e007018", + "0x923b0091520095b800715500923b00915500902e00703000923b009030", + "0x95ba00715905405215700e23b0091521550300471480180115b9007152", + "0x23b0090570095bb00700723b00900712e0070580097ff05700923b12e159", + "0x600096df00706000923b00915e05d15d05a00e6de00715e05d15d05a00e", + "0x5200923b00905200900e00715700923b00915700912500715f00923b009", + "0x5215700e00915f00923b00915f0096e000705400923b009054009221007", + "0x15700912500716000923b0090580096e100700723b00900712e00715f054", + "0x5400923b00905400922100705200923b00905200900e00715700923b009", + "0x723b00900712e00716005405215700e00916000923b0091600096e0007", + "0x723b0091fd00916800700723b00903000936500700723b0090070ea007", + "0x23b00916100902e00716100923b0090076e300706400923b009007229007", + "0x6700923b00900e16212e03000716200923b00916106412e030007161009", + "0x4c00915700715000923b00915000900e00701800923b009018009125007", + "0x923b0090111db12e16200706700923b00906700915700704c00923b009", + "0x23b12e1680095c500716816616412523b00906704c15001800e6e4007011", + "0x6f06e12523b00916b0095c600700723b00900712e00706d00980016b009", + "0x23b00900722500700723b00907100905400700723b00906e009057007071", + "0x707400923b0090720096e100707200923b00906f16e12e03100716e009", + "0x901100922100716600923b00916600900e00716400923b009164009125", + "0x712e00707401116616400e00907400923b0090740096e000701100923b", + "0x716400923b00916400912500717400923b00906d0096e100700723b009", + "0x91740096e000701100923b00901100922100716600923b00916600900e", + "0x23b0090070ea00700723b00900712e00717401116616400e00917400923b", + "0x23b00900716c00700723b0091db00906400700723b009031009054007007", + "0x923b0091800096df00718000923b00907600e1fd03000e6de007076009", + "0x922100701b00923b00901b00900e00701800923b009018009125007077", + "0x707712e01b01800e00907700923b0090770096e000712e00923b00912e", + "0x700723b00912500936500700723b00900e00915500700723b00900712e", + "0x7800923b00900722900700723b0091db00906400700723b0091fd009168", + "0x18607812e03000718600923b00918600902e00718600923b00900705d007", + "0x8d00923b00907b18712e03100718700923b00900722500707b00923b009", + "0x1500900e00701f00923b00901f00912500707f00923b00908d0096e1007", + "0x7f00923b00907f0096e000712e00923b00912e00922100701500923b009", + "0x23b0090090095c300700900923b0090070096e500707f12e01501f00e009", + "0x8011fd00923b02012e0096e600700723b0090070ea007009009009009009", + "0x1500980701f00980601b0098050180098042230098031db009802011009", + "0x23b00900712e00722c00980c02600980b02300980a025009809020009808", + "0x12512e03000723c00923b00923c00902e00723c00923b0090076e8007007", + "0x923b0092290091570071fd00923b0091fd00953d00722900923b00923c", + "0x2e02c12523b00900e2291fd1256e900700e00923b00900e009157007229", + "0x900900e00722500923b00900700912500700723b009030009054007030", + "0x3300923b00902e00915700704500923b00902c00915700703100923b009", + "0x722100923b0090076ea00700723b00900712e00700780d0090070ee007", + "0x700912500703600923b00922112512e03000722100923b00922100902e", + "0x1100923b00901100930f00700900923b00900900900e00700700923b009", + "0x71fd6eb00700e00923b00900e00915700703600923b009036009157007", + "0x980e03b00923b12e03a0095c500703a03821912523b00900e036011009", + "0x905400714103e03c12523b00903b0095c600700723b00900712e007126", + "0x3100923b00903800900e00722500923b00921900912500700723b009141", + "0x90070ee00703300923b00903e00915700704500923b00903c009157007", + "0x21900912500704100923b0091260096ec00700723b00900712e00700780d", + "0x4100923b0090410096ed00703800923b00903800900e00721900923b009", + "0x2e00714500923b0090076ee00700723b00900712e007041038219125009", + "0x91db0094b500704300923b00914512512e03000714500923b009145009", + "0x700e00923b00900e00915700704300923b0090430091570071db00923b", + "0x12500700723b00904900905400704904714812523b00900e0431db1256f0", + "0x23b00914800915700703100923b00900900900e00722500923b009007009", + "0x900712e00700780d0090070ee00703300923b009047009157007045009", + "0x12e03000715000923b00915000902e00715000923b0090076f100700723b", + "0x23b00904c00915700722300923b0092230094c700704c00923b009150125", + "0x15212523b00900e04c2231256f200700e00923b00900e00915700704c009", + "0x900e00722500923b00900700912500700723b009155009054007155153", + "0x923b00915300915700704500923b00915200915700703100923b009009", + "0x15700923b0090076f300700723b00900712e00700780d0090070ee007033", + "0x94d700705200923b00915712512e03000715700923b00915700902e007", + "0x923b00900e00915700705200923b00905200915700701800923b009018", + "0x723b00905700905400705715905412523b00900e0520181256f400700e", + "0x5400915700703100923b00900900900e00722500923b009007009125007", + "0x12e00700780d0090070ee00703300923b00915900915700704500923b009", + "0x705800923b00905800902e00705800923b0090076f500700723b009007", + "0x5a00915700701b00923b00901b0094e700705a00923b00905812512e030", + "0x23b00900e05a01b1256f600700e00923b00900e00915700705a00923b009", + "0x722500923b00900700912500700723b00915e00905400715e05d15d125", + "0x905d00915700704500923b00915d00915700703100923b00900900900e", + "0x23b00900725b00700723b00900712e00700780d0090070ee00703300923b", + "0x715f00923b00906012512e03000706000923b00906000902e007060009", + "0x15f01f1256f800700e00923b00900e00915700715f00923b00915f009157", + "0x23b00900700912500700723b00916100905400716106416012523b00900e", + "0x15700704500923b00916000915700703100923b00900900900e007225009", + "0x6f900700723b00900712e00700780d0090070ee00703300923b009064009", + "0x23b00916212512e03000716200923b00916200902e00716200923b009007", + "0x15700706700923b00906700915700701500923b009015009460007067009", + "0x5400716816616412523b00900e0670151256fa00700e00923b00900e009", + "0x923b00900900900e00722500923b00900700912500700723b009168009", + "0x70ee00703300923b00916600915700704500923b009164009157007031", + "0x16b00902e00716b00923b0090076fb00700723b00900712e00700780d009", + "0x923b00902000948100706d00923b00916b12512e03000716b00923b009", + "0x1256fc00700e00923b00900e00915700706d00923b00906d009157007020", + "0x700912500700723b00907100905400707106f06e12523b00900e06d020", + "0x4500923b00906e00915700703100923b00900900900e00722500923b009", + "0x723b00900712e00700780d0090070ee00703300923b00906f009157007", + "0x16e12512e03000716e00923b00916e00902e00716e00923b0090076fd007", + "0x7200923b00907200915700702500923b00902500949b00707200923b009", + "0x7617407412523b00900e0720251256fe00700e00923b00900e009157007", + "0x900900900e00722500923b00900700912500700723b009076009054007", + "0x703300923b00917400915700704500923b00907400915700703100923b", + "0x2e00718000923b00900780f00700723b00900712e00700780d0090070ee", + "0x90230093bd00707700923b00918012512e03000718000923b009180009", + "0x700e00923b00900e00915700707700923b00907700915700702300923b", + "0x12500700723b00907b00905400707b18607812523b00900e077023125810", + "0x23b00907800915700703100923b00900900900e00722500923b009007009", + "0x900712e00700780d0090070ee00703300923b009186009157007045009", + "0x12e03000718700923b00918700902e00718700923b00900781100700723b", + "0x23b00908d00915700702600923b0090260093f500708d00923b009187125", + "0x7f12523b00900e08d02612581200700e00923b00900e00915700708d009", + "0x900e00722500923b00900700912500700723b00908f00905400708f08e", + "0x923b00908e00915700704500923b00907f00915700703100923b009009", + "0x9000923b00900781300700723b00900712e00700780d0090070ee007033", + "0x946400709100923b00909012512e03000709000923b00909000902e007", + "0x923b00900e00915700709100923b00909100915700722c00923b00922c", + "0x723b00909400905400709409309212523b00900e09122c12581400700e", + "0x9200915700703100923b00900900900e00722500923b009007009125007", + "0x709500923b00900716c00703300923b00909300915700704500923b009", + "0x912500709700923b00909600981600709600923b009095033045125815", + "0x923b0090970096ed00703100923b00903100900e00722500923b009225", + "0x712e00712e00981800900923b12e007009817007097031225125009097", + "0x700e00923b00912500961d00712500923b00900900961c00700723b009", + "0x900722500700723b00900712e00700e00900900e00923b00900e00961f", + "0x1db00923b00901100962000701100923b00912e1fd12e0310071fd00923b", + "0x96d300700723b0090070ea0071db0090091db00923b0091db00961f007", + "0x23b0091fd00901b0071fd00923b00900e00981900700e12e12e23b00912e", + "0x701822312e23b0091db0090150071db00923b00901100901f007011009", + "0x23b00901b0090df00701b00923b00901800902300700723b009223009020", + "0x701500923b00901f12512e03000701f00923b00901f00902e00701f009", + "0x900900900e00700700923b00900700912500702000923b00912e009819", + "0x701500923b00901500915700702000923b0090200091fd00700900923b", + "0x22c00923b12e02600906e00702602302512523b00901502000900700e3cb", + "0x31800702c22912e23b00922c00906f00700723b00900712e00723c00981a", + "0x902500912500703000923b00902e00931900702e00923b00902c22912e", + "0x903000923b00903000931a00702300923b00902300900e00702500923b", + "0x12500722500923b00923c00931b00700723b00900712e007030023025125", + "0x23b00922500931a00702300923b00902300900e00702500923b009025009", + "0x12e00901b00712e00912e23b0090090096d3007225023025125009225009", + "0x1fd12e23b00900e00901500700e00923b00912500901f00712500923b009", + "0x91db0090150071db00923b0090076d400700723b0091fd009020007011", + "0x701b00923b00901100902300700723b00922300902000701822312e23b", + "0x1f01b12e22c00701b00923b00901b00902600701f00923b009018009023", + "0x1500912e23b0090090096d300700723b00900712e00700781b00723b12e", + "0x2500901500702500923b00902000901f00702000923b00901500901b007", + "0x722c00923b00900781c00700723b00902300902000702602312e23b009", + "0x902600902300700723b00923c00902000722923c12e23b00922c009015", + "0x702c00923b00902c00902600702e00923b00922900902300702c00923b", + "0x900900915e00700723b00900712e00700781d00723b12e02e02c12e22c", + "0x22500902e00722500923b00900781e00703000923b00900722900700723b", + "0x4500923b00900722500703100923b00922503012e03000722500923b009", + "0x912500722100923b00903300981f00703300923b00903104512e031007", + "0x712e00722100712e00922100923b00922100982000700700923b009007", + "0x96d300721900923b0090076d400703600923b00900702500700723b009", + "0x23b00903600902600703a00923b00903800901b00703800912e23b009009", + "0x12e23b12e21903603a00700e82100721900923b009219009026007036009", + "0x6d400703e00923b0090076d400700723b00900712e00703c00982212603b", + "0x923b00903e00902600704100923b00900900901b00714100923b009007", + "0xe82100712600923b0091260090b400714100923b00914100902600703e", + "0x5800700723b00900712e00714800982304314512e23b12e14103e04103b", + "0x904904712e82400704900923b00904300905800704700923b009126009", + "0x715200923b00904c00982600704c00923b00915000982500715000923b", + "0x715214512e00915200923b00915200982000714500923b009145009125", + "0x715300923b00900722900700723b00912600957200700723b00900712e", + "0x915515312e03000715500923b00915500902e00715500923b0090076b5", + "0x705400923b00915705212e03100705200923b00900722500715700923b", + "0x915900982000714800923b00914800912500715900923b00905400981f", + "0x723b00900900915e00700723b00900712e00715914812e00915900923b", + "0x23b00905800902e00705800923b0090076b500705700923b009007229007", + "0x3100715d00923b00900722500705a00923b00905805712e030007058009", + "0x903c00912500715e00923b00905d00981f00705d00923b00905a15d12e", + "0x23b00900712e00715e03c12e00915e00923b00915e00982000703c00923b", + "0x905700716015f12e23b00906000915900706000923b009007229007007", + "0x923b00906400912e82400706400923b00916000905800700723b00915f", + "0x912500706700923b00916200982600716200923b009161009825007161", + "0x900e00706700712e00906700923b00906700982000700700923b009007", + "0x23b00900900712e54d00700900923b00900900922100700700923b009007", + "0x23b00900712e0070110098271fd00923b12e00e00954e00700e12512e125", + "0x955200722300923b0091db0095510071db00923b0091fd009550007007", + "0x1f00910100700723b00901b00955400702001501f01b0181fd23b009223", + "0x982800700723b00902000915500700723b00901500910100700723b009", + "0x923b00912e00900e00702300923b00902500982900702500923b009018", + "0x12e12500902300923b00902300982a00712500923b00912500922100712e", + "0x12e00900e00702600923b00901100982b00700723b00900712e007023125", + "0x2600923b00902600982a00712500923b00912500922100712e00923b009", + "0x700e00923b00900782c00700723b00912e00937400702612512e125009", + "0x901100902e00701100923b0091fd00937d0071fd00923b00900e00937b", + "0x23b00922300937b0072231db12e23b00912501100912537e00701100923b", + "0x82d00701b00923b00901b00902e00701b00923b00901800937d007018009", + "0x1db00909900701f00923b00901f00912500701501f12e23b00901b00712e", + "0x982e0070151db01f12500901500923b0090150096550071db00923b009", + "0x23b00900900939900700723b00900712e00712e00982f00900923b12e007", + "0x900900e00923b00900e00939b00700e00923b00912500939a007125009", + "0x912e1fd12e0310071fd00923b00900722500700723b00900712e00700e", + "0x91db00923b0091db00939b0071db00923b00901100939c00701100923b", + "0x23b0090070ea00700723b0090071600071db00923b0090078300071db009", + "0x712503a00722300923b00922300903800722300923b009007219007007", + "0x956100700723b00900712e00701501f12e83101b01812e23b12e223009", + "0x701800923b00901800912500700723b00900710f00702000923b009125", + "0x964500700723b00900712e00702600983202302512e23b12e020009644", + "0x923b00922c00964600723c00923b00902500956900722c00923b009023", + "0x2c00923b00900716c00700723b00900712e0070078330090070ee007229", + "0x2e00964600723c00923b00902600956900702e00923b00902c009647007", + "0x923b0090111db12e83400701100923b00923c00912800722900923b009", + "0xea00700723b00900712e00722500983503000923b12e229009648007011", + "0x1800923b00901800912500703100923b00903000956e00700723b009007", + "0x3100964900712e00923b00912e00909900701b00923b00901b00900e007", + "0x7b00703622103304500e23b00903112e01b01800e83600703100923b009", + "0x921900918700700723b00900712e00703800983721900923b12e036009", + "0x12e23b00903a03b22112537e00703b00923b00900e00937d00703a00923b", + "0xe00704500923b00904500912500703e00923b00903c00937b00703c126", + "0x23b00901100912300712600923b00912600909900703300923b009033009", + "0x6020071fd00923b0091fd00902e00703e00923b00903e009600007011009", + "0x23b12e04300924c00704314504114100e23b0091fd03e011126033045011", + "0x15004912523b00914800960400700723b00900712e007047009838148009", + "0x715300923b00915200983a00715200923b00904c15004912583900704c", + "0x914500909900704100923b00904100900e00714100923b009141009125", + "0x712e00715314504114100e00915300923b00915300983b00714500923b", + "0x714100923b00914100912500715500923b00904700983c00700723b009", + "0x915500983b00714500923b00914500909900704100923b00904100900e", + "0x91fd00915500700723b00900712e00715514504114100e00915500923b", + "0x3800983c00700723b00900e00960500700723b00901100936500700723b", + "0x3300923b00903300900e00704500923b00904500912500715700923b009", + "0x3304500e00915700923b00915700983b00722100923b009221009099007", + "0x23b00922500905400700723b0090070ea00700723b00900712e007157221", + "0x37e00705400923b00905200937d00705200e12e23b00900e00983d007007", + "0x937d00705800923b00905700937b00705715912e23b0091fd05412e125", + "0x915d00983a00715d00923b00905a00e01112583900705a00923b009058", + "0x701b00923b00901b00900e00701800923b00901800912500705d00923b", + "0x15901b01800e00905d00923b00905d00983b00715900923b009159009099", + "0x23b00900e00960500700723b0091fd00915500700723b00900712e00705d", + "0x23b00900722900700723b00912500936500700723b0091db00983e007007", + "0x12e03000706000923b00906000902e00706000923b00900705d00715e009", + "0x23b00915f16012e03100716000923b00900722500715f00923b00906015e", + "0xe00701f00923b00901f00912500716100923b00906400983c007064009", + "0x23b00916100983b00712e00923b00912e00909900701500923b009015009", + "0x712e00984000900923b12e00700983f00716112e01501f00e009161009", + "0x923b00912500915d00712500923b00900900905a00700723b00900712e", + "0x22500700723b00900712e00700e00900900e00923b00900e00903600700e", + "0x23b00901100904500701100923b00912e1fd12e0310071fd00923b009007", + "0x923b00900700901b0071db0090091db00923b0091db0090360071db009", + "0x700723b00900712e00700e00984112512e12e23b12e009009175007009", + "0x91fd0090ec00701100923b00912e0090b40071fd00923b009125009171", + "0x23b00900716c00700723b00900712e0070078420090070ee0071db00923b", + "0xec00701100923b00900e0090b400701800923b0092230090f0007223009", + "0x23b00901b0091fd00701b00923b0090110090580071db00923b009018009", + "0x700723b00900712e00701500984301f00923b12e1db00916900701b009", + "0x902500915300702500923b00902000916300702000923b00901f009165", + "0x15300722c00923b00900714c00700723b00902300915500702602312e23b", + "0x23b00902600916300700723b00923c00915500722923c12e23b00922c009", + "0x16300700723b00902e00915500703002e12e23b00902c00915300702c009", + "0x903100915500704503112e23b00922500915300722500923b009229009", + "0x2e00722100923b00904500916300703300923b00903000916300700723b", + "0x903600902e00703600923b00922103312e14f00703300923b009033009", + "0x700723b00900712e00721900984400723b12e03600910600703600923b", + "0x23b00903a0090a500703a00923b00903800914400703800923b00900716c", + "0x23b00921900911100700723b00900712e0070078450090070ee00703b009", + "0x3c0090a500703c00923b00912600911300712600923b00900716c007007", + "0x14100923b00903e00925d00703e00923b00903b00936e00703b00923b009", + "0x14101b12e00914100923b00914100984600701b00923b00901b0091fd007", + "0x4100923b00900716c00700723b00901500905400700723b00900712e007", + "0x14500984600701b00923b00901b0091fd00714500923b009041009847007", + "0x712500984812e00923b12e00700981700714501b12e00914500923b009", + "0xe00923b00912e00961c00700723b00900900915500700723b00900712e", + "0x71fd0090091fd00923b0091fd00961f0071fd00923b00900e00961d007", + "0x701100923b00900722900700723b00912500905700700723b00900712e", + "0x1db22312e03100722300923b0090072250071db00923b00900901112e030", + "0x1b00923b00901b00961f00701b00923b00901800962000701800923b009", + "0x900900923b0090090095c300700900923b00900700984900701b009009", + "0x700723b00900712e00712e00984b00900923b12e00700984a007009009", + "0x900e00933100700e00923b00912500933000712500923b00900900932f", + "0x71fd00923b00900722500700723b00900712e00700e00900900e00923b", + "0x1db0093310071db00923b00901100933200701100923b00912e1fd12e031", + "0xe00984c12512e12e23b12e00900712e3a10071db0090091db00923b009", + "0x23b00912e0091250071fd00923b0091250093a300700723b00900712e007", + "0x900712e00700784d0090070ee0071db00923b0091fd0093a4007011009", + "0x912500701800923b0092230093a500722300923b00900716c00700723b", + "0x984e0071db01112e0091db00923b0090180093a400701100923b00900e", + "0x23b00900900963a00700723b00900712e00712e00984f00900923b12e007", + "0x900900e00923b00900e00963700700e00923b00912500963b007125009", + "0x912e1fd12e0310071fd00923b00900722500700723b00900712e00700e", + "0x91db00923b0091db0096370071db00923b00901100963600701100923b", + "0x900900900923b0090090095c300700900923b0090070098500071db009", + "0x910400712500923b00912e00910200712e00923b009007009102007009", + "0x923b0091fd0091020071fd00923b00900900910200700e00923b009125", + "0x15500701822312e23b00900e0091530071db00923b009011009104007011", + "0x23b00901b00915500701f01b12e23b0091db00915300700723b009223009", + "0x12e14f00702000923b00901f00916300701500923b009018009163007007", + "0x23b12e02500910600702500923b00902500902e00702500923b009020015", + "0x914400702600923b00900716c00700723b00900712e007023009851007", + "0x70078520090070ee00723c00923b00922c0090a500722c00923b009026", + "0x722900923b00900716c00700723b00902300911100700723b00900712e", + "0x36b00723c00900923c00923b00902c0090a500702c00923b009229009113", + "0x712e0071db00985300723b12e0110091060070111fd12e23b0091fd009", + "0x915500700723b00912e00915500700723b0091fd00915500700723b009", + "0x11300722300923b00900716c00700723b00912500915500700723b00900e", + "0x23b00900900903300700700923b00900700912500701800923b009223009", + "0x23b00900712e00701800900712500901800923b0090180090a5007009009", + "0x91fd00936b00701b00923b00900785400700723b0091db009111007007", + "0x923b00901500902e00701500923b00901b01f12e14f00701f1fd12e23b", + "0x915500700723b00900712e00702000985500723b12e015009106007015", + "0x15500700723b00900e00915500700723b00912e00915500700723b0091fd", + "0x2300923b00902500911300702500923b00900716c00700723b009125009", + "0x230090a500700900923b00900900903300700700923b009007009125007", + "0x902000911100700723b00900712e00702300900712500902300923b009", + "0x14f00722c00e12e23b00900e00936b00702600923b00900785400700723b", + "0x12e23c00910600723c00923b00923c00902e00723c00923b00902622c12e", + "0x15500700723b0091fd00915500700723b00900712e00722900985600723b", + "0x700723b00912500915500700723b00900e00915500700723b00912e009", + "0x23b00900700912500702e00923b00902c00911300702c00923b00900716c", + "0x12500902e00923b00902e0090a500700900923b009009009033007007009", + "0x712e25c00700723b00922900911100700723b00900712e00702e009007", + "0x922500985800700723b00900712e00703100985722503012e23b12e125", + "0x3300e12e23b00900e00936b00704500923b00922500985900722500923b", + "0x700723b00900712e00721900985a03622112e23b12e03303012e25c007", + "0x23b00900785b00703800923b00903600985900703600923b009036009858", + "0x902e00703a00923b00903a00902e00703b00923b00900785c00703a009", + "0x23b12e03b03a12e85d00722100923b00922100912500703b00923b00903b", + "0x85900712600923b00912600985800700723b00900712e00700785e126009", + "0x23b00903800985f00700900923b00900900903300703c00923b009126009", + "0x3e12e23b0091fd0380091258600071fd00923b0091fd00902e007038009", + "0x986300700723b00900712e00704100986200723b12e141009861007141", + "0x86300700723b00912e00915500700723b00900e00915500700723b009045", + "0x4300923b00914500911300714500923b00900716c00700723b00903c009", + "0x430090a500703e00923b00903e00903300722100923b009221009125007", + "0x904100986400700723b00900712e00704303e22112500904300923b009", + "0x703e00923b00903e00903300700723b00904700915500704714812e23b", + "0x3c03e12586000712e00923b00912e00902e00703c00923b00903c00985f", + "0x23b00904500985f00704900923b00904900903300715004912e23b00912e", + "0x4c12e23b00900e04504912586000700e00923b00900e00902e007045009", + "0x86500715300923b00915300985f00715315012e23b009150009865007152", + "0x15515312e86600715500923b00915500985f00715515212e23b009152009", + "0x723b00900712e00705200986700723b12e15700986100715700923b009", + "0x5412e23b00905200986400700723b00900712e0070078680090070ee007", + "0x12e14f00705714812e23b00914800936b00700723b009159009155007159", + "0x23b12e05800910600705800923b00905800902e00705800923b009057054", + "0x986300700723b00914800915500700723b00900712e00705a009869007", + "0x14400715d00923b00900716c00700723b00915000986300700723b009152", + "0x23b00904c00903300722100923b00922100912500705d00923b00915d009", + "0x23b00900712e00705d04c22112500905d00923b00905d0090a500704c009", + "0x15200985f00715000923b00915000985f00700723b00905a009111007007", + "0x723b12e15e00986100715e00923b00915215012e86a00715200923b009", + "0x90070ee00700723b00914800915500700723b00900712e00706000986b", + "0x915500716015f12e23b00906000986400700723b00900712e00700786c", + "0x923b00906400902e00706400923b00914815f12e14f00700723b009160", + "0x716c00700723b00900712e00716100986d00723b12e064009106007064", + "0x22100923b00922100912500706700923b00916200914400716200923b009", + "0x4c22112500906700923b0090670090a500704c00923b00904c009033007", + "0x923b00900716c00700723b00916100911100700723b00900712e007067", + "0x903300722100923b00922100912500716600923b009164009113007164", + "0x12e00716604c22112500916600923b0091660090a500704c00923b00904c", + "0x15500700723b00900e00915500700723b00904500986300700723b009007", + "0x700723b00903800986300700723b0091fd00915500700723b00912e009", + "0x23b00922100912500716b00923b00916800911300716800923b00900716c", + "0x12500916b00923b00916b0090a500700900923b009009009033007221009", + "0x4500986300700723b0091fd00915500700723b00900712e00716b009221", + "0x716c00700723b00912e00915500700723b00900e00915500700723b009", + "0x21900923b00921900912500706e00923b00906d00911300706d00923b009", + "0x921912500906e00923b00906e0090a500700900923b009009009033007", + "0x23b00912e00915500700723b0091fd00915500700723b00900712e00706e", + "0x906f00911300706f00923b00900716c00700723b00900e009155007007", + "0x700900923b00900900903300703100923b00903100912500707100923b", + "0xe12e23b00900e00986e00707100903112500907100923b0090710090a5", + "0x5f80071db12512e23b00912500957900701100923b0091fd0095f70071fd", + "0x900712e00702001501f12586f01b01822312523b12e0111db12e00900e", + "0x33d00701b00923b00901b00902e00700700923b00900700912500700723b", + "0x1800922100722300923b00922300900e00702302512e23b00901b00712e", + "0x23b00900712e00722c00987002600923b12e02300933e00701800923b009", + "0x925a00722900e12e23b00900e00986e00723c00923b009007508007007", + "0x912500957900702e00923b00902c22912e87100702c23c12e23b00923c", + "0x12e02e03001822300e5f800702e00923b00902e00962900703012512e23b", + "0x900750800700723b00900712e00703622103312587204503122512523b", + "0x723c00923b00923c00987300702500923b00902500912500721900923b", + "0xe00703a03812e23b00921923c02512587400721900923b009219009873", + "0x23b00904500902e00703100923b00903100922100722500923b009225009", + "0x700723b00900712e00712600987603b00923b12e03a009875007045009", + "0x3e00962900703e00923b00903c00e12e87100703c00923b00903b009877", + "0x4312587814504114112523b12e03e12503122500e5f800703e00923b009", + "0x87900704900923b00914504502612544000700723b00900712e007047148", + "0x23b00904c00987b00704c00923b00915000987a00715000923b009049009", + "0x22100714100923b00914100900e00703800923b009038009125007152009", + "0x15204114103800e00915200923b00915200987c00704100923b009041009", + "0x723b00902600934f00700723b00904500915500700723b00900712e007", + "0x15500987b00715500923b00915300987a00715300923b00904700987d007", + "0x4300923b00904300900e00703800923b00903800912500715700923b009", + "0x4303800e00915700923b00915700987c00714800923b009148009221007", + "0x902600934f00700723b00904500915500700723b00900712e007157148", + "0x12600987f00700723b00900e00987e00700723b00912500902000700723b", + "0x22500923b00922500900e00703800923b00903800912500705200923b009", + "0x22503800e00905200923b00905200987c00703100923b009031009221007", + "0x902600934f00700723b00900e00987e00700723b00900712e007052031", + "0x3600987d00700723b00912500902000700723b00923c00950c00700723b", + "0x5700923b00915900987b00715900923b00905400987a00705400923b009", + "0x22100922100703300923b00903300900e00702500923b009025009125007", + "0x12e00705722103302500e00905700923b00905700987c00722100923b009", + "0x2000700723b00900e00987e00700723b00922c00905400700723b009007", + "0x705a00923b00900788000705800923b00900722900700723b009125009", + "0x900722500715d00923b00905a05812e03000705a00923b00905a00902e", + "0x6000923b00915e00987f00715e00923b00915d05d12e03100705d00923b", + "0x1800922100722300923b00922300900e00702500923b009025009125007", + "0x12e00706001822302500e00906000923b00906000987c00701800923b009", + "0x87d00700723b00912500902000700723b00900e00987e00700723b009007", + "0x23b00916000987b00716000923b00915f00987a00715f00923b009020009", + "0x22100701f00923b00901f00900e00700700923b009007009125007064009", + "0x6401501f00700e00906400923b00906400987c00701500923b009015009", + "0x94ff00700723b00900712e00712e00988200900923b12e007009881007", + "0x923b00900e00950100700e00923b00912500950000712500923b009009", + "0x12e0310071fd00923b00900722500700723b00900712e00700e00900900e", + "0x23b0091db0095010071db00923b00901100950200701100923b00912e1fd", + "0x700723b00900900905400700723b0090070090540071db0090091db009", + "0x23b0091250090a500712500923b00912e00914400712e00923b00900716c", + "0x90110095050072231db01112523b0091fd009246007125009009125009", + "0x1f00923b00901b0095f700701b00e12e23b00900e00986e00701800923b", + "0x12e23b12e01801f01512e0091fd60800701512512e23b009125009579007", + "0x23c00923b00900750800700723b00900712e00722c026023125883025020", + "0x87100702c23c12e23b00923c00925a00722900e12e23b00900e00986e007", + "0x2000900e00703012512e23b00912500957900702e00923b00902c22912e", + "0x1db02e0300250201fd60800702e00923b00902e00962900702000923b009", + "0x900750800700723b00900712e00722103304512588403122512e23b12e", + "0x723c00923b00923c00987300700700923b00900700912500703600923b", + "0xe00703821912e23b00903623c00712587400703600923b009036009873", + "0x23b12e03800987500703100923b00903100922100722500923b009225009", + "0x712600923b00903a00987700700723b00900712e00703b00988503a009", + "0x2251fd60800703c00923b00903c00962900703c00923b00912600e12e871", + "0x723b00900712e00704314504112588614103e12e23b12e22303c125031", + "0x904700988700704700923b0091480093b400714800923b00900716c007", + "0x721900923b00921900912500715000923b00904900925900704900923b", + "0x915000988800714100923b00914100922100703e00923b00903e00900e", + "0x90430093b700700723b00900712e00715014103e21900e00915000923b", + "0x715300923b00915200925900715200923b00904c00988700704c00923b", + "0x914500922100704100923b00904100900e00721900923b009219009125", + "0x712e00715314504121900e00915300923b00915300988800714500923b", + "0x987e00700723b00912500902000700723b00922300915500700723b009", + "0x21900923b00921900912500715500923b00903b00988900700723b00900e", + "0x15500988800703100923b00903100922100722500923b00922500900e007", + "0xe00987e00700723b00900712e00715503122521900e00915500923b009", + "0x902000700723b00923c00950c00700723b00922300915500700723b009", + "0x5200923b00915700988700715700923b0092210093b700700723b009125", + "0x4500900e00700700923b00900700912500705400923b009052009259007", + "0x5400923b00905400988800703300923b00903300922100704500923b009", + "0x700723b00900e00987e00700723b00900712e00705403304500700e009", + "0x723b00912500902000700723b0091db00915500700723b009223009155", + "0x5700925900705700923b00915900988700715900923b00922c0093b7007", + "0x2300923b00902300900e00700700923b00900700912500705800923b009", + "0x2300700e00905800923b00905800988800702600923b009026009221007", + "0x900900900923b0090090095c300700900923b00900700988a007058026", + "0x900900900900923b0090090095c300700900923b00900700988b007009", + "0x700900900900900923b0090090095c300700900923b00900700988c007", + "0x88e00700900900900900923b0090090095c300700900923b00900700988d", + "0x988f00700900900900900923b0090090095c300700900923b009007009", + "0x23b00900900915500700723b00900712e00712500989012e00923b12e007", + "0x924d0071fd00923b00900e0095f400700e00923b00912e0095f3007007", + "0x23b00912500934f00700723b00900712e0071fd0090091fd00923b0091fd", + "0x72250071db00923b00900901112e03000701100923b009007229007007", + "0x923b0090180095f500701800923b0091db22312e03100722300923b009", + "0x900923b00900700989100701b00900901b00923b00901b00924d00701b", + "0x700900923b00900700989200700900900900900923b0090090095c3007", + "0x5c300700900923b00900700989300700900900900900923b0090090095c3", + "0x95c300700900923b00900700989400700900900900900923b009009009", + "0x989612512e12e23b12e00900712e89500700900900900900923b009009", + "0x912e0091250071fd00923b00912500989700700723b00900712e00700e", + "0x712e0070078990090070ee0071db00923b0091fd00989800701100923b", + "0x12500701800923b00922300989a00722300923b00900716c00700723b009", + "0x89b0071db01112e0091db00923b00901800989800701100923b00900e009", + "0x900900951100700723b00900712e00712e00989c00900923b12e007009", + "0x900e00923b00900e00951300700e00923b00912500951200712500923b", + "0x12e1fd12e0310071fd00923b00900722500700723b00900712e00700e009", + "0x1db00923b0091db0095130071db00923b00901100951400701100923b009", + "0x915700712e00923b00900716c00700723b0090070090540071db009009", + "0x95c300700900923b00900700989d00712e00912e00900900923b009009", + "0x712e00989f00900923b12e00700989e00700900900900900923b009009", + "0x923b0091250096ae00712500923b0090090096ad00700723b00900712e", + "0x22500700723b00900712e00700e00900900e00923b00900e0096af00700e", + "0x23b0090110096b000701100923b00912e1fd12e0310071fd00923b009007", + "0x700723b0090070ea0071db0090091db00923b0091db0096af0071db009", + "0x1100900712503a00701100923b00901100903800701100923b009007219", + "0x912e0098a100700723b00900712e00701b01812e8a02231db12e23b12e", + "0x98a20071db00923b0091db00912500700723b00900710f00701f00923b", + "0x90200098a400700723b00900712e0070250098a302001512e23b12e01f", + "0x722c00923b0090230098a600702600923b0090150098a500702300923b", + "0x8a800723c00923b00900716c00700723b00900712e0070078a70090070ee", + "0x23b0092290098a600702600923b0090250098a500722900923b00923c009", + "0x8aa00702c00923b00902c0096b800702c00923b0090260098a900722c009", + "0x902e0098ac00700723b00900712e0070300098ab02e00923b12e22c009", + "0x3122512e23b0092250098ae00722500923b0092250098ad00722500923b", + "0x914700700723b00904500915500722103304512523b0090310098af007", + "0x21900923b0090360098b000703600923b00903300950400700723b009221", + "0x712603b03a12523b0090380098af00703822512e23b0092250098ae007", + "0x923b0091260098b100700723b00903b00934f00700723b00903a009155", + "0x925300703c00923b00903c0096b70071db00923b0091db00912500703c", + "0x3e03c1db1258b200703e00923b00903e0096b700703e21912e23b009219", + "0x900712e0070430098b314500923b12e0410096c400704114112e23b009", + "0x6b700714100923b00914100912500714800923b0091450096c600700723b", + "0x14800e1411256c300714800923b0091480096b700700e00923b00900e009", + "0x900712e00704c0098b415000923b12e0490096c400704904712e23b009", + "0x700723b00915300934f00715515315212523b0092250098af00700723b", + "0x923b0090078b500715700923b00915200916300700723b009155009147", + "0x2e00715900923b0091500096c600705400923b00905215712e14f007052", + "0x900712e0070570098b600723b12e05400910600705400923b009054009", + "0x70581fd12e23b0091fd00925300704700923b00904700912500700723b", + "0x580471258b200721900923b0092190096b700705800923b0090580096b7", + "0x712e00715e0098b705d00923b12e15d0096c400715d05a12e23b009219", + "0x705a00923b00905a00912500706000923b00905d0096c600700723b009", + "0x12505a1256c300706000923b0090600096b700712500923b0091250096b7", + "0x712e0071610098b806400923b12e1600096c400716015f12e23b009060", + "0x706700923b00915f00912500716200923b0090640096c600700723b009", + "0x700723b00900712e0070078b90090070ee00716400923b0091620096b7", + "0x700723b00915900914700700723b0091fd00914700700723b0090070ea", + "0x23b00915f00912500716600923b0091610098ba00700723b00902c009146", + "0x12500916600923b0091660098bb00722300923b00922300900e00715f009", + "0x91fd00914700700723b0090070ea00700723b00900712e00716622315f", + "0x12500914700700723b00902c00914600700723b00915900914700700723b", + "0x705a00923b00905a00912500716800923b00915e0098ba00700723b009", + "0x16822305a12500916800923b0091680098bb00722300923b00922300900e", + "0x723b00921900914700700723b00905700911100700723b00900712e007", + "0x90070ea00716400923b0091250096b700706700923b009047009125007", + "0x6b800722300923b00922300900e00706700923b00906700912500700723b", + "0x23b0091590096b700716400923b0091640096b700702c00923b00902c009", + "0x91fd15916402c2230670116c00071fd00923b0091fd0096b7007159009", + "0x900712e0070710098bc06f00923b12e06e0096c100706e06d16b12523b", + "0x17407407216e00e8bd00717407407216e00e23b00906f0096c200700723b", + "0x16b00923b00916b00912500718000923b0090760098be00707600923b009", + "0x6d16b12500918000923b0091800098bb00706d00923b00906d00900e007", + "0x916b00912500707700923b0090710098ba00700723b00900712e007180", + "0x907700923b0090770098bb00706d00923b00906d00900e00716b00923b", + "0x1fd00914700700723b0090070ea00700723b00900712e00707706d16b125", + "0x914700700723b00902c00914600700723b0092250098bf00700723b009", + "0x707800923b00904c0098ba00700723b00921900914700700723b009125", + "0x90780098bb00722300923b00922300900e00704700923b009047009125", + "0x723b0090070ea00700723b00900712e00707822304712500907800923b", + "0x23b00902c00914600700723b0092250098bf00700723b0091fd009147007", + "0x900e00914700700723b00921900914700700723b009125009147007007", + "0xe00714100923b00914100912500718600923b0090430098ba00700723b", + "0x718622314112500918600923b0091860098bb00722300923b009223009", + "0x14700700723b00903000905400700723b0090070ea00700723b00900712e", + "0x907b12500e02c00e8bd00707b00923b00900716c00700723b0091fd009", + "0x71db00923b0091db00912500708d00923b0091870098be00718700923b", + "0x8d2231db12500908d00923b00908d0098bb00722300923b00922300900e", + "0x723b00900e00914700700723b0091fd00914700700723b00900712e007", + "0x923b00900722900700723b00912e00914600700723b009125009147007", + "0x7f12e03000708e00923b00908e00902e00708e00923b00900705d00707f", + "0x923b00908f09012e03100709000923b00900722500708f00923b00908e", + "0x900e00701800923b00901800912500709200923b0090910098ba007091", + "0x8c000709201b01812500909200923b0090920098bb00701b00923b00901b", + "0x700723b00900712e0070111fd12e8c100e12512e23b12e12e009007125", + "0x91db0098c300722300923b0091250091250071db00923b00900e0098c2", + "0x90110098c500700723b00900712e0070078c40090070ee00701800923b", + "0x701800923b00901b0098c300722300923b0091fd00912500701b00923b", + "0x901f01812e8c700701f00923b00901f00902e00701f00923b0090078c6", + "0x723b00900712e0070250098c802000923b12e0150096c400701500923b", + "0x260098ca00702600923b0090230098c900702300923b0090200096c6007", + "0x22c00923b00922c0098cb00722300923b00922300912500722c00923b009", + "0x12500723c00923b0090250098cc00700723b00900712e00722c22312e009", + "0x8cd00723c22312e00923c00923b00923c0098cb00722300923b009223009", + "0x900900915500700723b00900712e0071250098ce12e00923b12e007009", + "0x5130071fd00923b00900e00951200700e00923b00912e00951100700723b", + "0x912500902000700723b00900712e0071fd0090091fd00923b0091fd009", + "0x2250071db00923b00900901112e03000701100923b00900722900700723b", + "0x23b00901800951400701800923b0091db22312e03100722300923b009007", + "0x12e12e0090071258cf00701b00900901b00923b00901b00951300701b009", + "0x923b00900e0098d100700723b00900712e0071fd0098d000e12512e23b", + "0x98d300712500923b0091250091250071db00923b0090110098d2007011", + "0x23b00900722900700723b00900712e0071db12512e0091db00923b0091db", + "0x12e03000701800923b00901800902e00701800923b0090076b5007223009", + "0x23b00901b01f12e03100701f00923b00900722500701b00923b009018223", + "0x8d30071fd00923b0091fd00912500702000923b0090150098d4007015009", + "0x900721900700723b0090070ea0070201fd12e00902000923b009020009", + "0x12e23b12e00e00900712503a00700e00923b00900e00903800700e00923b", + "0x12500700723b00900710f00700723b00900712e0072231db12e8d50111fd", + "0x12e00701f0098d701b01812e23b12e12e0098d60071fd00923b0091fd009", + "0x2000923b00901500931f00701500923b00901b00916500700723b009007", + "0x90070ee00702300923b00902000932000702500923b009018009157007", + "0x902600932100702600923b00900716c00700723b00900712e0070078d8", + "0x702300923b00922c00932000702500923b00901f00915700722c00923b", + "0x90070ea00700723b00900712e0072290098d923c00923b12e023009072", + "0x71fd00923b0091fd00912500702c00923b00923c12512e03000700723b", + "0x902c00915700702500923b00902500915700701100923b00901100900e", + "0x2250095c500722503002e12523b00902c0250111fd00e6e400702c00923b", + "0x12523b0090310095c600700723b00900712e0070450098da03100923b12e", + "0x923b00921900981600721900923b009036221033125815007036221033", + "0x96ed00703000923b00903000900e00702e00923b00902e009125007038", + "0x450096ec00700723b00900712e00703803002e12500903800923b009038", + "0x3000923b00903000900e00702e00923b00902e00912500703a00923b009", + "0x700723b00900712e00703a03002e12500903a00923b00903a0096ed007", + "0x703b00923b00900716c00700723b00922900905400700723b0090070ea", + "0x912500703c00923b00912600981600712600923b00903b125025125815", + "0x923b00903c0096ed00701100923b00901100900e0071fd00923b0091fd", + "0x700723b00912e00905700700723b00900712e00703c0111fd12500903c", + "0x14100923b00900705d00703e00923b00900722900700723b009125009057", + "0x722500704100923b00914103e12e03000714100923b00914100902e007", + "0x923b0090430096ec00704300923b00904114512e03100714500923b009", + "0x96ed00722300923b00922300900e0071db00923b0091db009125007148", + "0x712500712e23b0090070098db0071482231db12500914800923b009148", + "0x900e00902e00700723b0091fd0091550071fd00e12e23b0091250098dc", + "0x1112e23b00900900e12e05200700900923b00900900915700700e00923b", + "0x915500701822312e23b0090070098dc00700723b0091db0090540071db", + "0x12e00923b00912e00915700701800923b00901800902e00700723b009223", + "0x716c00700723b00901f00905400701f01b12e23b00912e01812e052007", + "0x1b00923b00901b00915700701100923b00901100915700701500923b009", + "0xea00700723b00900716000701100923b0090078dd00701501b011125009", + "0x12e23b0091db0098df0071db12e12e23b00912e0098de00700723b009007", + "0x915700722300923b00922300902e00700723b0090180095d8007018223", + "0x901b00905400701b1fd12e23b00912522312e05200712500923b009125", + "0x12500700723b00901f00915500701501f12e23b00912e0098df00700723b", + "0x23b00901500931500700900923b00900900900e00700700923b009007009", + "0x71fd00923b0091fd01112e26200700e00923b00900e009157007015009", + "0x2600923b12e02300906e00702302502012523b00900e01500900700e8e0", + "0x5400722923c12e23b00902600906f00700723b00900712e00722c0098e1", + "0x23b00902c23c1fd12581500702c00923b00900716c00700723b009229009", + "0xe00702000923b00902000912500703000923b00902e00981600702e009", + "0x703002502012500903000923b0090300096ed00702500923b009025009", + "0x22500923b00922c0096ec00700723b0091fd00905700700723b00900712e", + "0x2250096ed00702500923b00902500900e00702000923b009020009125007", + "0x8e300712500712e23b0090070098e200722502502012500922500923b009", + "0x23b00900e00950400700723b0091fd0091550071fd00e12e23b009125009", + "0x722300923b0091db12e12e0300071db00923b009011009505007011009", + "0x901b00902e00700723b00901800934f00701b01812e23b0090070098e3", + "0x1f12e23b00922301b12e05200722300923b00922300915700701b00923b", + "0x900900915700702000923b00900716c00700723b009015009054007015", + "0x70098e400702001f00912500901f00923b00901f00915700700900923b", + "0x23b0091fd0091550071fd00e12e23b0091250098e500712500712e23b009", + "0x12e0300071db00923b00901100950500701100923b00900e009504007007", + "0x901800934f00701b01812e23b0090070098e500722300923b0091db12e", + "0x5200722300923b00922300915700701b00923b00901b00902e00700723b", + "0x23b00900716c00700723b00901500905400701501f12e23b00922301b12e", + "0x12500901f00923b00901f00915700700900923b009009009157007020009", + "0x712500923b00912500902e00712500923b0090070098e600702001f009", + "0x90540071fd00e12e23b00912e12512e05200712e00923b00912e009157", + "0x700900923b00900900915700701100923b00900716c00700723b0091fd", + "0x12500923b0090070098e700701100e00912500900e00923b00900e009157", + "0x12512e05200712e00923b00912e00915700712500923b00912500902e007", + "0x1100923b00900716c00700723b0091fd0090540071fd00e12e23b00912e", + "0xe00912500900e00923b00900e00915700700900923b009009009157007", + "0x900900915700712500923b00900716c00700723b0090070098e8007011", + "0x70098e900712512e00912500912e00923b00912e00915700700900923b", + "0x12e00923b00912e00915700712500923b00912500902e00712500923b009", + "0x716c00700723b0091fd0090540071fd00e12e23b00912e12512e052007", + "0xe00923b00900e00915700700900923b00900900915700701100923b009", + "0x923b00912500902e00712500923b0090070098ea00701100e009125009", + "0x71fd00e12e23b00912e12512e05200712e00923b00912e009157007125", + "0x923b00900900915700701100923b00900716c00700723b0091fd009054", + "0x23b0090070098eb00701100e00912500900e00923b00900e009157007009", + "0x5200712e00923b00912e00915700712500923b00912500902e007125009", + "0x23b00900716c00700723b0091fd0090540071fd00e12e23b00912e12512e", + "0x12500900e00923b00900e00915700700900923b009009009157007011009", + "0x712500923b0091250091bc00712500923b0090070098ec00701100e009", + "0x90540071fd00e12e23b00912e12512e8ed00712e00923b00912e009157", + "0x700900923b00900900915700701100923b00900716c00700723b0091fd", + "0x12500923b0090070098ee00701100e00912500900e00923b00900e009157", + "0x12512e05200700900923b00900900915700712500923b00912500902e007", + "0x1100923b00900716c00700723b0091fd0090540071fd00e12e23b009009", + "0x923b0090070098ef00701112e00e12500912e00923b00912e009157007", + "0x12e05200700900923b00900900915700712500923b00912500902e007125", + "0x923b00900716c00700723b0091fd0090540071fd00e12e23b009009125", + "0x923b00900755f00701112e00e12500912e00923b00912e009157007011", + "0x12e23b00912500957000700723b0090070ea00700723b0090071600071fd", + "0x700723b0091db0091010070182231db12523b009011009571007011125", + "0x900e1fd12e57a00700e00923b00901800901f00700723b009223009155", + "0x37b00701f00923b00900714c00701b00923b00900e0090df00700e00923b", + "0x902000957100702012512e23b00912500957000701500923b00901f009", + "0x700723b00902300915500700723b00902500910100702602302512523b", + "0x900900900e00700700923b00900700912500722c00923b009026009058", + "0x722c00923b00922c0091fd00712e00923b00912e00909900700900923b", + "0x23c00902e00723c01b12e23b00901b00936b00701500923b009015009600", + "0x3002e02c22900e23b00923c01522c12e0090070118f000723c00923b009", + "0x714c00700723b00900712e0070310098f222500923b12e0300098f1007", + "0x722100923b0090078f300703300923b00904500937b00704500923b009", + "0x922100902e00703600923b00903600902e00703600923b00903300937d", + "0x23b00912500957000703821912e23b00922103602e12537e00722100923b", + "0x723b00912600915500703c12603b12523b00903a00957100703a12512e", + "0x903e00910400703e00923b00903b00910200700723b00903c009572007", + "0x714500923b00904100937d00704100923b00903800937b00714100923b", + "0x37b00714804312e23b00914114521912537e00714500923b00914500902e", + "0x4900910100704c15004912523b00912500957100704700923b009148009", + "0x37d00715200923b00915000916300700723b00904c00957200700723b009", + "0x15215304312537e00715300923b00915300902e00715300923b009047009", + "0x923b00905200937d00705200923b00915700937b00715715512e23b009", + "0x5715912e23b00901b05415512537e00705400923b00905400902e007054", + "0x960500700723b00905800915e00715d05a05812523b0092250098f4007", + "0x15e00923b00905d00937d00705d00923b00905700937b00700723b00905a", + "0x715f06012e23b00915d15e15912537e00715e00923b00915e00902e007", + "0x23b00916000937d00706400923b0090078f500716000923b00915f00937b", + "0x37e00706400923b00906400902e00716100923b00916100902e007161009", + "0x937d00716400923b00906700937b00706716212e23b009064161060125", + "0x923b00916800933000716800923b00916600932f00716600923b009164", + "0x909900702c00923b00902c00900e00722900923b00922900912500716b", + "0x716b16202c22900e00916b00923b00916b00933100716200923b009162", + "0x700723b00912500958100700723b00901b00915500700723b00900712e", + "0x902c00900e00722900923b00922900912500706d00923b009031009332", + "0x906d00923b00906d00933100702e00923b00902e00909900702c00923b", + "0x23b12e12500986100712500912e23b00900900986500706d02e02c22900e", + "0x903300700723b00912e00915500700723b00900712e00700e0098f6007", + "0x70078f70090070ee00701100923b00900900985f0071fd00923b009007", + "0x71db00923b0090078f800700723b00900900986300700723b00900712e", + "0x701800923b0090180098fa00701822312e23b00900e12e1db00700e8f9", + "0x712e0070078fc01b00923b12e0180098fb00722300923b009223009033", + "0x701500923b00901f00985f00701f00923b00901b00985900700723b009", + "0x85f00702000923b0090078fe00700723b00900712e0070078fd0090070ee", + "0x23b00901500985f0071fd00923b00922300903300701500923b009020009", + "0x12e12e00986100712e00712e23b0090070098650070111fd12e009011009", + "0x85f00700723b00900700986300700723b00900712e0071250098ff00723b", + "0x12e00900986100700723b00900712e00700900900900900923b009009009", + "0x85f00700723b00912500990100700723b00900712e00700e00990000723b", + "0x900700986300700723b00900712e00700700900900700923b009007009", + "0x8fa00701100923b0091251fd12e9020071fd00923b0090078f800700723b", + "0x91db0098fa0071db00923b00900e01112e90200701100923b009011009", + "0x700723b00900712e00700790322300923b12e1db0098fb0071db00923b", + "0x9040090070ee00701b00923b00901800985f00701800923b009223009859", + "0x23b00901f00985f00701f00923b0090078fe00700723b00900712e007007", + "0x23b12e12e00986100712e00912e23b00900900986500701b00900901b009", + "0x985f00700723b00900900986300700723b00900712e007125009905007", + "0x23b00912500990100700723b00900712e00700700900900700923b009007", + "0x985f00700700923b00900700985f00700e00923b009009009906007007", + "0x1259070071fd0090091fd00923b00900e00712e86600700e00923b00900e", + "0x90900700723b00900712e0070111fd12e90800e12512e23b12e12e009007", + "0x23b0091db00990a00722300923b0091250091250071db00923b00900e009", + "0x23b00901100990c00700723b00900712e00700790b0090070ee007018009", + "0x90d00701800923b00901b00990a00722300923b0091fd00912500701b009", + "0x23b00901f01812e90e00701f00923b00901f00902e00701f00923b009007", + "0x700723b00900712e00702500990f02000923b12e015009875007015009", + "0x902600991100702600923b00902300991000702300923b009020009877", + "0x922c00923b00922c00991200722300923b00922300912500722c00923b", + "0x912500723c00923b00902500991300700723b00900712e00722c22312e", + "0x912500723c22312e00923c00923b00923c00991200722300923b009223", + "0x923b00912e0096b700700900923b0090090096b700700700923b009007", + "0x1fd00923b12e00e00991500700e12512e23b00912e00900712591400712e", + "0x98ca0071db00923b0091fd0098c900700723b00900712e007011009916", + "0x923b0092230098cb00712500923b00912500912500722300923b0091db", + "0x22900700723b00901100905400700723b00900712e00722312512e009223", + "0x1b00923b00901b00902e00701b00923b00900791700701800923b009007", + "0x1512e03100701500923b00900722500701f00923b00901b01812e030007", + "0x923b00912500912500702500923b0090200098cc00702000923b00901f", + "0x923b12e00700991800702512512e00902500923b0090250098cb007125", + "0x98c900700723b00900900915500700723b00900712e00712500991912e", + "0x923b0091fd0098cb0071fd00923b00900e0098ca00700e00923b00912e", + "0x722900700723b00912500914700700723b00900712e0071fd0090091fd", + "0x22300923b0090072250071db00923b00900901112e03000701100923b009", + "0x98cb00701b00923b0090180098cc00701800923b0091db22312e031007", + "0x23b00912e00991a00700723b0090070ea00701b00900901b00923b00901b", + "0x701100923b0091fd0095ca0071fd00923b00900e00991b00700e12e12e", + "0x22300902000701822312e23b0091db0090150071db00923b009011009240", + "0x701f00923b00901b0090df00701b00923b00901800902300700723b009", + "0x12e00991b00701500923b00901f12512e03000701f00923b00901f00902e", + "0x900923b00900900900e00700700923b00900700912500702000923b009", + "0x700e31600701500923b00901500915700702000923b009020009315007", + "0x23c00991c22c00923b12e02600906e00702602302512523b009015020009", + "0x2c22912e31800702c22912e23b00922c00906f00700723b00900712e007", + "0x2500923b00902500912500703000923b00902e00931900702e00923b009", + "0x2302512500903000923b00903000931a00702300923b00902300900e007", + "0x902500912500722500923b00923c00931b00700723b00900712e007030", + "0x922500923b00922500931a00702300923b00902300900e00702500923b", + "0x12500923b00912e00963e00712e00923b00900700963c007225023025125", + "0x1fd00902e00700723b00900e0091550071fd00e12e23b009125009153007", + "0x12e23b0090091fd12e05200700900923b0090090091570071fd00923b009", + "0x22301112e00922300923b00900716c00700723b0091db0090540071db011", + "0x923b00901100903800701100923b00900721900700723b0090070ea007", + "0x900712e00701b01812e91d2231db12e23b12e01100900712503a007011", + "0x1db00912500700723b00900710f00701f00923b00912500901b00700723b", + "0x900712e00702500991e02001512e23b12e01f0091750071db00923b009", + "0xec00702600923b0090150090b400702300923b00902000917100700723b", + "0x16c00700723b00900712e00700791f0090070ee00722c00923b009023009", + "0x923b0090250090b400722900923b00923c0090f000723c00923b009007", + "0x91fd00702c00923b00902600905800722c00923b0092290090ec007026", + "0x900712e00703000992002e00923b12e22c00916900702c00923b00902c", + "0x22500916300722500923b00902e00916500700723b0090070ea00700723b", + "0x3100923b00903100902e00704500923b00900e00937d00703100923b009", + "0x703600923b00922100937b00722103312e23b00903104512e12537e007", + "0x903300909900722300923b00922300900e0071db00923b0091db009125", + "0x703600923b00903600960000702c00923b00902c0091fd00703300923b", + "0x21900e23b0091fd03602c0332231db0118f00071fd00923b0091fd00902e", + "0x723b00900712e00703c00992112600923b12e03b0098f100703b03a038", + "0x14500923b00904114103e12592200704114103e12523b0091260098f4007", + "0x3800900e00721900923b00921900912500704300923b009145009923007", + "0x4300923b00904300926500703a00923b00903a00909900703800923b009", + "0x14800923b00903c00992400700723b00900712e00704303a03821900e009", + "0x3a00909900703800923b00903800900e00721900923b009219009125007", + "0x12e00714803a03821900e00914800923b00914800926500703a00923b009", + "0x983d00700723b00903000905400700723b0090070ea00700723b009007", + "0x1fd04912e12537e00704900923b00904700937d00704700e12e23b00900e", + "0x923b00915200937d00715200923b00904c00937b00704c15012e23b009", + "0x715700923b00915500992300715500923b00915300e02c125922007153", + "0x915000909900722300923b00922300900e0071db00923b0091db009125", + "0x712e0071571502231db00e00915700923b00915700926500715000923b", + "0x960500700723b00912500915e00700723b0091fd00915500700723b009", + "0x2e00705400923b00900705d00705200923b00900722900700723b00900e", + "0x23b00900722500715900923b00905405212e03000705400923b009054009", + "0x705a00923b00905800992400705800923b00915905712e031007057009", + "0x912e00909900701b00923b00901b00900e00701800923b009018009125", + "0x992500705a12e01b01800e00905a00923b00905a00926500712e00923b", + "0x23b00900900915500700723b00900712e00712500992612e00923b12e007", + "0x99120071fd00923b00900e00991100700e00923b00912e009910007007", + "0x23b00912500950c00700723b00900712e0071fd0090091fd00923b0091fd", + "0x72250071db00923b00900901112e03000701100923b009007229007007", + "0x923b00901800991300701800923b0091db22312e03100722300923b009", + "0x12523b00912e00912e92700701b00900901b00923b00901b00991200701b", + "0x71fd00923b0091fd00992800700700923b0090070091250071fd00e125", + "0x12512e92a00700723b0091db0090540071db01112e23b0091fd00712e929", + "0x23b00901800992b00701b01812e23b00922300926400722300923b00900e", + "0x10600701b00923b00901b0096b700701f00923b00901f00902e00701f009", + "0x23b00901b00992d00700723b00900712e00701500992c00723b12e01f009", + "0x900712e00700792f0090070ee00702500923b00902000992e007020009", + "0x900716c00700723b00901b00914700700723b00901500911100700723b", + "0x702500923b00902600992e00702600923b00902300993000702300923b", + "0x702501112e00902500923b00902500992e00701100923b009011009125", + "0x912e00912500712500923b00900716c00712e00923b00900900712e931", + "0x1371131231060071fd01f1131231060071fd11112512e12e00912e00923b", + "0x12512e00900713711312300700e01f11312300700e00700e12512e009007", + "0x1136800e12512e0090071371131231060071fd01f1131231060071fd0cf", + "0x4b01fd00e12512e00900713711312310600710701101f113123106007107", + "0x1071fd63b00e12512e0090071371131230071071fd01f1131230071071fd", + "0x11312300700e6d100e12512e0090071371131230071071fd01f113123007", + "0x11312300700e01f11312300700e89812512e00900713711312300700e01f", + "0x90071371131231060071fd01f1131231060071fd93212512e009007137", + "0x12512e0090071371131231060071fd01f1131231060071fd93300e12512e", + "0x12512e00900713711312310600710701101f11312310600710701193400e", + "0x700e93612512e00900713711312300700e01f11312300700e9351fd00e", + "0x700e01f11312300700e93712512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e93812512e009007137113123", + "0x700e93a12512e00900713711312300700e01f11312300700e93912512e", + "0x700e01f11312300700e93b12512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e93c12512e009007137113123", + "0x700e93e12512e00900713711312300700e01f11312300700e93d12512e", + "0x700e01f11312300700e93f12512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94012512e009007137113123", + "0x700e94212512e00900713711312300700e01f11312300700e94112512e", + "0x700e01f11312300700e94312512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94412512e009007137113123", + "0x700e94612512e00900713711312300700e01f11312300700e94512512e", + "0x700e01f11312300700e94712512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94812512e009007137113123", + "0xe12512e0090071371131231060071fd01f1131231060071fd94912512e", + "0x1f12300712594b12512e00900713711312300700e01f11312300700e94a", + "0x1131231060071fd0380f611312310600701194c12e009007128123007125", + "0x1230071fd94e00900700e01812e01801512e94d1fd00e12512e00900713b", + "0x12501807812300700e94f00e12512e00900714311312300700e0380f6113", + "0x12501f12300712595100714601f12e01f00995012512e009007144123007", + "0x1131231060071fd0180150f61131231060071db95212e009007147123007", + "0x12e00900714c12300712501f1230071259530111fd00e12512e009007149", + "0x12e0090071431131071231060070110181010f6113107123106007223954", + "0x71491131071230071fd1010f61131071230070119551db0111fd00e125", + "0x71511131071230071fd0150f61131071230070119561fd00e12512e009", + "0x712501f00712e95800900700e01812e01806412e9571fd00e12512e009", + "0x12e00900715611312300700e0180600f611312300701195900900715401f", + "0x71fd95b12512e00900714412300712501801b12300700e95a1fd00e125", + "0x11312310600701195c00e12512e00900715611312300700e0180f6113123", + "0x11312310600701895d1fd00e12512e0090071491131231060071fd0150f6", + "0x2231db0111fd00e12512e0090071491131231060071fd0150150150150f6", + "0x900715c1131071231060070110150150150f611310712310600701895e", + "0x715c11312300700e0150f61131230071fd95f2231db0111fd00e12512e", + "0x12512e00900715c11312300700e0150f61131230071fd96000e12512e009", + "0x1fd96200e12512e00900715c11312300700e0150f61131230071fd96100e", + "0x11312300700e96300e12512e00900715c11312300700e0150f6113123007", + "0x11312300700e0f611312300700e96412512e00900715c11312300700e0f6", + "0x12512e00900715c11312300700e0f611312300700e96512512e00900715c", + "0x1131231250f611312312596712e0090071491131231250f6113123125966", + "0x12300700e96912e0090071491131231250f611312312596812e009007149", + "0x900700e01812e01805712e96a12512e00900716311312300700e0f6113", + "0x11312300700e96d00900700e01812e01816512e96c0071650090f600996b", + "0x11312300700e0f611312300700e96e12512e00900716911312300700e0f6", + "0x12512e00900716c11312300700e0f611312300700e96f12512e009007169", + "0xf612e9720090070640090150f612e97100900700e01812e0180ec12e970", + "0x1491131231060071fd0180150f61131231060071db973009007015009015", + "0x15c11312300700e0150150f61131230070119740111fd00e12512e009007", + "0x12e00900712812300712501503801f1230071fd9751fd00e12512e009007", + "0x17911312312511312312e97700900717511312312511312312e97600e125", + "0x715c1131231060071fd06401f01503b0f6113123106007018978009007", + "0x718411312300700e03b11312300700e9792231db0111fd00e12512e009", + "0xe12512e00900715c11312300700e08e0f61131230071fd97a12512e009", + "0x1801f1230071fd97c12512e00900714412300712501807f12300700e97b", + "0x1fd01f0150f61131231060071db97d00e12512e009007147123007125015", + "0x18801f00712501f00712e97e0111fd00e12512e009007151113123106007", + "0x18a12300712501f12300712598000900718900712e01500712e97f009007", + "0xd811310712300701198200900718e11312312511312312e98112e009007", + "0x11312312511312312e9831fd00e12512e0090071511131071230071fd015", + "0x1db98512512e00900714910712300700e10110712300700e984009007175", + "0x111fd00e12512e0090071981131071230071fd0640150d8113107123007", + "0x719f00905200998712512e00900715111312312501519b11312300e986", + "0x71fd98900e12512e00900715c11312300700e0970f61131230071fd988", + "0x1801f12300700e98a00e12512e0090071a111312300700e0181a0113123", + "0x12e0090071491131231250b411312312598b12512e009007144123007125", + "0x1131231250ac11312312598d12e0090071491131231250b011312312598c", + "0x98f12512e0090071a811312300700e0cb11312300700e98e12e009007149", + "0x12e0090071aa1131231250600cb11312300e99000900706400906006012e", + "0xe99200e12512e00900715c11312300700e0980f61131230071fd991125", + "0x150f61131231060071db99312512e0090071ad12300712506d03b123007", + "0x1071231060070189940111fd00e12512e00900719f1131231060071fd01f", + "0x1db0111fd00e12512e00900719f1131071231060070110150150150f6113", + "0x12300700e99612512e00900716311312300700e0c011312300700e995223", + "0x9980090070640090c40c412e99712512e0090071b311312300700e02c113", + "0xc40c412e99900e12512e0090071b611312300700e0570c01131230071fd", + "0x12512e00900715c11312300700e0930f61131230071fd99a009007064009", + "0xb811312300e99c12512e0090071b91131231250410bc11312300e99b00e", + "0x71bb1131231250150b411312300e99d12512e0090071ba113123125041", + "0xe12512e00900715c11312300700e0940f61131230071fd99e12512e009", + "0x12300e9a000e12512e00900715c11312300700e0990f61131230071fd99f", + "0x700e0950f61131230071fd9a112512e0090071bd1131231250150b0113", + "0x90071bc1131231250150ac11312300e9a200e12512e00900715c113123", + "0x9a400e12512e00900715c11312300700e0960f61131230071fd9a312512e", + "0x12300700e08f0f61131230071fd9a512e00900718e00712e02c02c007125", + "0x715c11312300700e0900f61131230071fd9a600e12512e00900715c113", + "0x12512e00900715c11312300700e0910f61131230071fd9a700e12512e009", + "0xe9a900e12512e00900715c11312300700e0920f61131230071fd9a800e", + "0xe0bc11312300700e9aa12512e00900716911312300700e0b8113123007", + "0x71fd9ac00900700e01812e0180c412e9ab12512e009007169113123007", + "0x12501f1230071259ad00e12512e00900715c11312300700e08d0f6113123", + "0x3a0071259af0090071b511312312511312312e9ae12e0090071b8123007", + "0x900719f11312300700e04111312300700e9b012e0090071ac00712e041", + "0xf61131231060071db9b212e00900716900712e0410410071259b112512e", + "0x1231060071db9b30111fd00e12512e0090071511131231060071fd01f015", + "0x70119b40111fd00e12512e0090071511131231060071fd01f0150f6113", + "0x908e0099b51fd00e12512e0090071a711312300700e07701503b113123", + "0x99b700e12512e0090071871230071250180181a51230071fd9b60071a5", + "0x12e9b912512e00900714412300712501801f12300700e9b800719f009052", + "0x700e9bb00900716e11312312511312312e9ba00900717400712e01f007", + "0x70119bd0071510091660099bc12512e00900716b1070071250150d8107", + "0x91620099be1fd00e12512e00900716410712300700e01502003b107123", + "0x970099c100900719f00901505212e9c000716101f12e01f0099bf007137", + "0x99c400900715400712e01500712e9c30071490091600099c20071a5009", + "0x119c700900706400906d06d12e9c60071a50090980099c50071a800915f", + "0x1230071fd9c81fd00e12512e009007064106007125015015015015106007", + "0x9ca0071630090580099c900e12512e00900715d11312300700e16b041113", + "0x15911312300700e05716b0411131230070119cb00900706400900e00e12e", + "0x99ce0071a50090940099cd0071a50090930099cc1fd00e12512e009007", + "0x1515712e9d10071a50090960099d00071a50090950099cf0071a5009099", + "0x90910099d40071a50090900099d30071a500908f0099d200900718e009", + "0x1530099d700900715500712e01500712e9d60071a50090920099d50071a5", + "0x99da0071a500908d0099d900900700e01812e01800e12e9d8007169009", + "0x12512e0090071501230071250090090090471230070119db0071b5009152", + "0x716900901514512e9dd12e00900714800712e0090090071259dc1fd00e", + "0x712501801812300700e9df12e00900714100712e04101b0071259de009", + "0x1fd9e112e00900700e01801812501801808d1259e012512e009007187123", + "0x12501801808f1259e200e12512e00900718712300712501801808e123007", + "0x1259e412e00900700e0180181250180180901259e312e00900700e018018", + "0x700e0180181250180180921259e512e00900700e018018125018018091", + "0x1250180180941259e712e00900700e0180181250180180931259e612e009", + "0x1259e912e00900700e0180181250180180951259e812e00900700e018018", + "0x700e0180181250180180971259ea12e00900700e018018125018018096", + "0x1250180180991259ec12e00900700e0180181250180180981259eb12e009", + "0x12e00900714910712300700e05b10712300700e9ed12e00900700e018018", + "0x900703600903603612e9ef12e00900703610612e0150361061259ee125", + "0x9f212e00900722100712e0110110071259f100900703600903603612e9f0", + "0xe9f400900714800901522912e9f312e00900714800712e009009007125", + "0x700e01812e01806012e9f512512e00900714412300712501807f123007", + "0x1fd00e12512e00900722c10712300700e01502001f1071230070119f6009", + "0x9f912e0090071fd00712e0090090071259f80090072210090151db12e9f7", + "0x9fa00900700e00712e12500712e" + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x233f7eb4ceacfd7c3e238afaf740a3ffcb352f9844a11df665e97c3b0370b6", + "function_idx": 4 + }, + { + "selector": "0x29ce6d1019e7bef00e94df2973d8d36e9e9b6c5f8783275441c9e466cb8b43", + "function_idx": 14 + }, + { + "selector": "0x7ec457cd7ed1630225a8328f826a29a327b19486f6b2882b4176545ebdbe3d", + "function_idx": 3 + }, + { + "selector": "0x9278fa5f64a571de10741418f1c4c0c4322aef645dd9d94a429c1f3e99a8a5", + "function_idx": 29 + }, + { + "selector": "0x960e70c0b7135476e33b1ba6a72e9b10cb5e261ebaa730d1ed01a0f21c22d3", + "function_idx": 12 + }, + { + "selector": "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "function_idx": 6 + }, + { + "selector": "0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283", + "function_idx": 27 + }, + { + "selector": "0x139562604eb722f14da2b8c1f8f681c99d31226bf9d57f148ec8b4d611f92f8", + "function_idx": 24 + }, + { + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "function_idx": 1 + }, + { + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "function_idx": 0 + }, + { + "selector": "0x1746f7542cac71b5c88f0b2301e87cd9b0896dab1c83b8b515762697e521040", + "function_idx": 10 + }, + { + "selector": "0x178e27745484c91a084e6a72059b13e3dbebef761175a63f4330bec3ad4aaa0", + "function_idx": 21 + }, + { + "selector": "0x1a1e41f464a235695e5050a846a26ca22ecc27acac54be5f6666848031efb8f", + "function_idx": 7 + }, + { + "selector": "0x1e6d35df2b9d989fb4b6bbcebda1314e4254cbe5e589dd94ff4f29ea935e91c", + "function_idx": 5 + }, + { + "selector": "0x213dfe25e2ca309c4d615a09cfc95fdb2fc7dc73fbcad12c450fe93b1f2ff9e", + "function_idx": 31 + }, + { + "selector": "0x22e07fe65aff1304b57cc48ee7c75a04ce2583b5ef2e7866eb8acbe09be43e2", + "function_idx": 25 + }, + { + "selector": "0x231c71f842bf17eb7be2cd595e2ad846543dbbbe46c1381a6477a1022625d60", + "function_idx": 17 + }, + { + "selector": "0x24fd89f2d8a7798e705aa5361f39154ca43e03721c05188285138f16018955d", + "function_idx": 19 + }, + { + "selector": "0x26e71b81ea2af0a2b5c6bfceb639b4fc6faae9d8de072a61fc913d3301ff56b", + "function_idx": 13 + }, + { + "selector": "0x28420862938116cb3bbdbedee07451ccc54d4e9412dbef71142ad1980a30941", + "function_idx": 2 + }, + { + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "function_idx": 8 + }, + { + "selector": "0x29e211664c0b63c79638fbea474206ca74016b3e9a3dc4f9ac300ffd8bdf2cd", + "function_idx": 30 + }, + { + "selector": "0x2a4bb4205277617b698a9a2950b938d0a236dd4619f82f05bec02bdbd245fab", + "function_idx": 22 + }, + { + "selector": "0x2aa20ff86b29546fd697eb81064769cf566031d56b10b8bba2c70125bd8403a", + "function_idx": 28 + }, + { + "selector": "0x2ad0f031c5480fdb7c7a0a026c56d2281dcc7359b88bd9053a8cf10048d44c4", + "function_idx": 20 + }, + { + "selector": "0x309e00d93c6f8c0c2fcc1c8a01976f72e03b95841c3e3a1f7614048d5a77ead", + "function_idx": 11 + }, + { + "selector": "0x31341177714d81ad9ccd0c903211bc056a60e8af988d0fd918cc43874549653", + "function_idx": 23 + }, + { + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "function_idx": 9 + }, + { + "selector": "0x395b662db8770f18d407bbbfeebf45fffec4a7fa4f6c7cee13d084055a9387d", + "function_idx": 15 + }, + { + "selector": "0x3ad2979f59dc1535593f6af33e41945239f4811966bcd49314582a892ebcee8", + "function_idx": 16 + }, + { + "selector": "0x3ce4edd1dfe90e117a8b46482ea1d41700d9d00c1dccbce6a8e2f812c1882e4", + "function_idx": 26 + }, + { + "selector": "0x3ee0bfaf5b124501fef19bbd1312e71f6966d186c42eeb91d1bff729b91d1d4", + "function_idx": 18 + } + ], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 32 + } + ], + "L1_HANDLER": [] + }, + "abi": "[{\"type\": \"impl\", \"name\": \"Account\", \"interface_name\": \"argent::common::account::IAccount\"}, {\"type\": \"struct\", \"name\": \"core::starknet::account::Call\", \"members\": [{\"name\": \"to\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}]}, {\"type\": \"struct\", \"name\": \"core::array::Span::\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::\"}]}, {\"type\": \"interface\", \"name\": \"argent::common::account::IAccount\", \"items\": [{\"type\": \"function\", \"name\": \"__validate__\", \"inputs\": [{\"name\": \"calls\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"__execute__\", \"inputs\": [{\"name\": \"calls\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::>\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"is_valid_signature\", \"inputs\": [{\"name\": \"hash\", \"type\": \"core::felt252\"}, {\"name\": \"signature\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"ExecuteFromOutsideImpl\", \"interface_name\": \"argent::common::outside_execution::IOutsideExecution\"}, {\"type\": \"struct\", \"name\": \"core::array::Span::\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::\"}]}, {\"type\": \"struct\", \"name\": \"argent::common::outside_execution::OutsideExecution\", \"members\": [{\"name\": \"caller\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"nonce\", \"type\": \"core::felt252\"}, {\"name\": \"execute_after\", \"type\": \"core::integer::u64\"}, {\"name\": \"execute_before\", \"type\": \"core::integer::u64\"}, {\"name\": \"calls\", \"type\": \"core::array::Span::\"}]}, {\"type\": \"enum\", \"name\": \"core::bool\", \"variants\": [{\"name\": \"False\", \"type\": \"()\"}, {\"name\": \"True\", \"type\": \"()\"}]}, {\"type\": \"interface\", \"name\": \"argent::common::outside_execution::IOutsideExecution\", \"items\": [{\"type\": \"function\", \"name\": \"execute_from_outside\", \"inputs\": [{\"name\": \"outside_execution\", \"type\": \"argent::common::outside_execution::OutsideExecution\"}, {\"name\": \"signature\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::>\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"is_valid_outside_execution_nonce\", \"inputs\": [{\"name\": \"nonce\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::bool\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_outside_execution_message_hash\", \"inputs\": [{\"name\": \"outside_execution\", \"type\": \"argent::common::outside_execution::OutsideExecution\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"UpgradeableImpl\", \"interface_name\": \"argent::common::upgrade::IUpgradeable\"}, {\"type\": \"interface\", \"name\": \"argent::common::upgrade::IUpgradeable\", \"items\": [{\"type\": \"function\", \"name\": \"upgrade\", \"inputs\": [{\"name\": \"new_implementation\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"execute_after_upgrade\", \"inputs\": [{\"name\": \"data\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::\"}], \"state_mutability\": \"external\"}]}, {\"type\": \"impl\", \"name\": \"ArgentAccountImpl\", \"interface_name\": \"argent::account::interface::IArgentAccount\"}, {\"type\": \"struct\", \"name\": \"argent::account::escape::Escape\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\"}, {\"name\": \"escape_type\", \"type\": \"core::felt252\"}, {\"name\": \"new_signer\", \"type\": \"core::felt252\"}]}, {\"type\": \"struct\", \"name\": \"argent::common::version::Version\", \"members\": [{\"name\": \"major\", \"type\": \"core::integer::u8\"}, {\"name\": \"minor\", \"type\": \"core::integer::u8\"}, {\"name\": \"patch\", \"type\": \"core::integer::u8\"}]}, {\"type\": \"enum\", \"name\": \"argent::account::escape::EscapeStatus\", \"variants\": [{\"name\": \"None\", \"type\": \"()\"}, {\"name\": \"NotReady\", \"type\": \"()\"}, {\"name\": \"Ready\", \"type\": \"()\"}, {\"name\": \"Expired\", \"type\": \"()\"}]}, {\"type\": \"interface\", \"name\": \"argent::account::interface::IArgentAccount\", \"items\": [{\"type\": \"function\", \"name\": \"__validate_declare__\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"__validate_deploy__\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::felt252\"}, {\"name\": \"contract_address_salt\", \"type\": \"core::felt252\"}, {\"name\": \"owner\", \"type\": \"core::felt252\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"change_owner\", \"inputs\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\"}, {\"name\": \"signature_r\", \"type\": \"core::felt252\"}, {\"name\": \"signature_s\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"change_guardian\", \"inputs\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"change_guardian_backup\", \"inputs\": [{\"name\": \"new_guardian_backup\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"trigger_escape_owner\", \"inputs\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"trigger_escape_guardian\", \"inputs\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"escape_owner\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"escape_guardian\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"cancel_escape\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"get_owner\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian_backup\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_escape\", \"inputs\": [], \"outputs\": [{\"type\": \"argent::account::escape::Escape\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_version\", \"inputs\": [], \"outputs\": [{\"type\": \"argent::common::version::Version\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_name\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian_escape_attempts\", \"inputs\": [], \"outputs\": [{\"type\": \"core::integer::u32\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_owner_escape_attempts\", \"inputs\": [], \"outputs\": [{\"type\": \"core::integer::u32\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_escape_and_status\", \"inputs\": [], \"outputs\": [{\"type\": \"(argent::account::escape::Escape, argent::account::escape::EscapeStatus)\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"Erc165Impl\", \"interface_name\": \"argent::common::erc165::IErc165\"}, {\"type\": \"interface\", \"name\": \"argent::common::erc165::IErc165\", \"items\": [{\"type\": \"function\", \"name\": \"supports_interface\", \"inputs\": [{\"name\": \"interface_id\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::bool\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"DeprecatedArgentAccountImpl\", \"interface_name\": \"argent::account::interface::IDeprecatedArgentAccount\"}, {\"type\": \"interface\", \"name\": \"argent::account::interface::IDeprecatedArgentAccount\", \"items\": [{\"type\": \"function\", \"name\": \"getVersion\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"getName\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"supportsInterface\", \"inputs\": [{\"name\": \"interface_id\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"isValidSignature\", \"inputs\": [{\"name\": \"hash\", \"type\": \"core::felt252\"}, {\"name\": \"signatures\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"constructor\", \"name\": \"constructor\", \"inputs\": [{\"name\": \"owner\", \"type\": \"core::felt252\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::AccountCreated\", \"kind\": \"struct\", \"members\": [{\"name\": \"owner\", \"type\": \"core::felt252\", \"kind\": \"key\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"struct\", \"name\": \"core::array::Span::>\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::>\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::TransactionExecuted\", \"kind\": \"struct\", \"members\": [{\"name\": \"hash\", \"type\": \"core::felt252\", \"kind\": \"key\"}, {\"name\": \"response\", \"type\": \"core::array::Span::>\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeOwnerTriggered\", \"kind\": \"struct\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\", \"kind\": \"data\"}, {\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeGuardianTriggered\", \"kind\": \"struct\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\", \"kind\": \"data\"}, {\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerEscaped\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianEscaped\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeCanceled\", \"kind\": \"struct\", \"members\": []}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianBackupChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian_backup\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::AccountUpgraded\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_implementation\", \"type\": \"core::starknet::class_hash::ClassHash\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerAdded\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner_guid\", \"type\": \"core::felt252\", \"kind\": \"key\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerRemoved\", \"kind\": \"struct\", \"members\": [{\"name\": \"removed_owner_guid\", \"type\": \"core::felt252\", \"kind\": \"key\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::Event\", \"kind\": \"enum\", \"variants\": [{\"name\": \"AccountCreated\", \"type\": \"argent::account::argent_account::ArgentAccount::AccountCreated\", \"kind\": \"nested\"}, {\"name\": \"TransactionExecuted\", \"type\": \"argent::account::argent_account::ArgentAccount::TransactionExecuted\", \"kind\": \"nested\"}, {\"name\": \"EscapeOwnerTriggered\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeOwnerTriggered\", \"kind\": \"nested\"}, {\"name\": \"EscapeGuardianTriggered\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeGuardianTriggered\", \"kind\": \"nested\"}, {\"name\": \"OwnerEscaped\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerEscaped\", \"kind\": \"nested\"}, {\"name\": \"GuardianEscaped\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianEscaped\", \"kind\": \"nested\"}, {\"name\": \"EscapeCanceled\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeCanceled\", \"kind\": \"nested\"}, {\"name\": \"OwnerChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerChanged\", \"kind\": \"nested\"}, {\"name\": \"GuardianChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianChanged\", \"kind\": \"nested\"}, {\"name\": \"GuardianBackupChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianBackupChanged\", \"kind\": \"nested\"}, {\"name\": \"AccountUpgraded\", \"type\": \"argent::account::argent_account::ArgentAccount::AccountUpgraded\", \"kind\": \"nested\"}, {\"name\": \"OwnerAdded\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerAdded\", \"kind\": \"nested\"}, {\"name\": \"OwnerRemoved\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerRemoved\", \"kind\": \"nested\"}]}]" +} diff --git a/crates/papyrus_common/resources/deprecated_block_hash_v0.json b/crates/papyrus_common/resources/deprecated_block_hash_v0.json new file mode 100644 index 00000000000..ab1a8785e5e --- /dev/null +++ b/crates/papyrus_common/resources/deprecated_block_hash_v0.json @@ -0,0 +1,1384 @@ +{ + "header": { + "block_hash": "0x2e8508c8488acca8cc1141afa714bb3c74a44b2ab47af60a117c8b85a599874", + "parent_hash": "0x43e4033e5c881610a6d6aff2ee84eb9ae703ea7e5412ed19b285852d5c3812b", + "block_number": 832, + "l1_gas_price": { + "price_in_fri": "0x0", + "price_in_wei": "0x0" + }, + "l1_data_gas_price": { + "price_in_fri": "0x1", + "price_in_wei": "0x1" + }, + "state_root": "0x3810b7805897aff09b3bba1d41fe2eb21a3853d98553794928684d1089f25cf", + "sequencer": "0x0", + "timestamp": 1643150436, + "l1_da_mode": "CALLDATA", + "transaction_commitment": "0x053191054b8acc338d6624212707ac73ec274150a032ac34fc2a5f22f0ff8104", + "event_commitment": "0x0", + "state_diff_commitment": "0x0", + "n_transactions": 31, + "n_events": 0, + "starknet_version": "" + }, + "body": { + "transactions": [ + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5a1c72d04a6bb4614ba1ad5408e455702a997c291c651776e228e16d05c96c0", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x589f448bcdf0676e3e40c8b925f1cde297beb1c14474f76058fac4eac788cb7", + "0x2", + "0x1613512d71bb7c24cd04e05bf2e0f4890ad9802319aa3eb2d6b4f888abc30a", + "0x1b2b8347d981d1fb52a1187b87434a90923d422b88cdc563e4d9ca94652daa8" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x758c58178ab051274fe5f3577a8d572dc6033ae9ee945333dd0e05b3c2a5a4f", + "0x5edb1c6ead7508a0e4e6bddd8123c2ea15e5d0b64259351b02484af0366eede" + ], + "contract_address": "0xd41e1cfc763a31bc40ee90e26a3d86dc8e1652e5c5d7d149dcc8421dd4354f", + "entry_point_selector": "0x240060cdb34fcc260f41eac7474ee1d7c80b7e3607daff9ac67c7ea2ebb1c44", + "calldata": [ + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x3", + "0xd41e1cfc763a31bc40ee90e26a3d86dc8e1652e5c5d7d149dcc8421dd4354f", + "0x3635c9adc5dea00000", + "0x0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x6c66d787fa0ef209ef00424dbfb14d9b5c3c1bae4cdb2dc7ba751ab82a75785", + "constructor_calldata": [ + "0x6e55d2ef40d669450f68cd707dadbae259683a47799cf04d9a38cd369854378", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4c1123582490a660db53ddabe3f3350696eeae4da0f5a888b7d3684cb9ed4f7", + "0x5808d98bac65618155f82fad5f4280ed4f7cfaf5edeaee7b5e70a940a3b303d" + ], + "contract_address": "0x264fb9fde6239924fc62381614ca914c23b077098e5e1a3c1869c82a8fec2e4", + "entry_point_selector": "0x240060cdb34fcc260f41eac7474ee1d7c80b7e3607daff9ac67c7ea2ebb1c44", + "calldata": [ + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x3", + "0x264fb9fde6239924fc62381614ca914c23b077098e5e1a3c1869c82a8fec2e4", + "0x3635c9adc5dea00000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x797c76447b6fa6066ef299fb27af18c1f41eb14055f9b5a6d1504e0e11dcad9", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x7b7dd36751cde056c35688a4331561fe7dc74d577e4a9659cda2f426fdd7c79", + "0x2", + "0x43d1611704b227832d2319ba6a0aaf0086a4e332504c8f59197f68707222e18", + "0x664f1e15f2858b4c4184c4539aa87cf4590d50c7a474b10acd8d8dfc259ece8" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x6284a3a7572a46396e47948f648073f910d910060d83a109d4b397ebefb8ae5", + "constructor_calldata": [ + "0x44ddc75b3aa3d78e1e8cb7098853b09444c39985007b30d29dd8a162e96af50", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x36568fc86a7e6b80034851f4ebbf1e9fffa1c1f5c6c2cd726a64912d66e4b6", + "entry_point_selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "calldata": [ + "0x74ba0dedffe72a878afb897e29367d66f80d01bfe603c40e21db64f9c75c4e0", + "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "0x1", + "0x4dd8f1dfe35b9f6d8d1ea6fabce1d2b9fbc20ee5" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x1ab044d5c1f60e81e0540489fc8826efa44b761b11957064d7c60c2f7e35fba", + "constructor_calldata": [ + "0xd8f0b5ebc9f68da34123d2b683b6d8d39b57f6e0646ba874df4d182e84d936", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3df0bb5abdbc086ee95bfe594ae6b88acc29c9db5d276c301a06f369388c86a", + "entry_point_selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "calldata": [ + "0x2eccfa4ce41fcfbbf7a57697f1f40d5f312a839eb873621980b51696ac7df0c", + "0x1cae039e74f4e53cae0b0c5f77276d79b5717d7bec99446663fc930bdbc6b4e" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x7c3a2c10eaf99b3178a8779f101e0163286387e9db1bb90a2fd98d2143ebebe", + "constructor_calldata": [ + "0x61c05e1cffd668be9043d81baca1a51b25b1af471d733dd7e39e926bf96160f", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x69df97419f82c708a28db1dc24af53840500291ea65eb8be9e6ac23cbe8f290", + "entry_point_selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "calldata": [ + "0xa4f3a273ddb9ce335c08a7cd5b96f9b18fbacbb7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x938cde0a187c81e2e0aa371ad43dd51077d9108f821df3f18dcacff393c741", + "entry_point_selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "calldata": [ + "0x5736c0ce6abec823cc7ef8fb0014a475b839de2b33b71aef1702e310ac663e7", + "0x8d73fb228e2beba4ff94da56e585b209eb484436a18cecacfe311e3caadb8e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6df6cddd8f5caaf1f901eb08263b50ca77cb988922134a2d7697f252c0a030a", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x4153007d6fd2e14b0913dc2f569523da97c42fb4ad2d2c23ff932adbaa32466", + "0x347455ac82bc9dd81138aaea0b7348b46192367cf560d95f4240f9f3c9a0b00" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x23f71c1f42f1c4e4d8bfae378c7673ccde1b74f7b39b247cc26d0cd7be687c8", + "constructor_calldata": [ + "0x1e281b63c6d3747bebfd2f9dba44df3573f71773bf760ecc91979c87ffb0f8", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x7949a80749de7adbdcc980bf6a5756727d665f868d2a5026149814097f01419", + "constructor_calldata": [ + "0x40b913a62dababf773313f2c7aeb98b96da287222417721bd3c00fbf4912634", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5736c0ce6abec823cc7ef8fb0014a475b839de2b33b71aef1702e310ac663e7", + "entry_point_selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "calldata": [ + "0xebd953b5acc8997f86a756def2053ae8eb6fb65bab5e483fceb98d56ae4f41", + "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "0x1", + "0x84f34acee6deb9ce07b61c464a526edd8fa80760" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x6ea3cd8aa3a6489f179038042d186386eb0e535ea70c1c89c3198afefae9025", + "constructor_calldata": [ + "0xeb2730f3642de854d4b9146b200f25644b7e6f9dfa44d32553425d79a73a2", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x2fac03c30c26985930b0cc561aa379b8da39f26882c9058544a7c888e888e40", + "constructor_calldata": [ + "0x45040e4065cd92f4fcd6cdc3610bc3344010793ef032f4ea3314a4da7f718d8", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x2fc7cb381f7307e218361c3fdd6eec4c384e34d57e3308965f0ca105dc01db7", + "constructor_calldata": [ + "0xeb2730f3642de854d4b9146b200f25644b7e6f9dfa44d32553425d79a73a2", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x77bc56c6a54f95243daf6fe2338d9268983207922fd05e952e49f114ac037e7", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x408c1f4b165eeaead68dce23810faae6bc55ab127023e46331bb2f5e340bff0", + "0x77d35e3ddf279c2f247fe8e47fc08febce193046a846574c1c2423222defc28" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x77bc56c6a54f95243daf6fe2338d9268983207922fd05e952e49f114ac037e7", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x408c1f4b165eeaead68dce23810faae6bc55ab127023e46331bb2f5e340bff0", + "0x494cc0daac2aa0384fefc18bc31cb7f80d59f1900a93b745692d7d2d62bcb1b" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x6f48ce162aa2b0b3567130883c85652dfcec96cf4fc718bdffdc2fc28f1342d", + "constructor_calldata": [ + "0x2d42c878d4f4e90477fa6495a90d2f38f8792177f026a357902cf61220c3f32", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x588b7763831d4228368d6b563b49de0e77072c0ce440ba5591bf90d620f4f14", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x107de40dc9a3c30a02a8282582aa249d615aebeca3fe2f4f168ff973efbd6b6", + "0x2", + "0x64ba150794c6878ab1fe86e1c6faed8d786cf2239bfb57b87ad2900017259c3", + "0x3f3dfb8aff54a502ea5ca3201e72f0e1961ac9b94995f9ed836c5b10d68fc3b" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x1037ae1ccb21525f82a3e9a624424aaf32d3fde7d3ab54ac003992fa57a32ee", + "constructor_calldata": [ + "0x4460fb2684a4405d6074b5a7bf1c4c82a1a67ed4352afd81c9bad44cbb1c0c4", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x35ca9511d6464ecb587708ea4e5bf1d9f54ecc1d6026daf9a8e2af416f90481", + "constructor_calldata": [ + "0x4460fb2684a4405d6074b5a7bf1c4c82a1a67ed4352afd81c9bad44cbb1c0c4", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x1b3471cdd9b2e13b58e14dc3e71494ef4e95195fed9d00addb096ac209af2a4", + "constructor_calldata": [ + "0x7271e8ae597fa6e03b21159ddae47ac107e4ed11058610370adf5baf8ad6881", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0xf7366277d85cfe73d28876e4bdf5d01b1ca56defba383873aa0a052d69a2ae", + "entry_point_selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "calldata": [ + "0x16b409f95a90d76be8dbcee8b340f5a0be88c9dc" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6cb9a95408ee959235581cd5a5eb67233953da92e9478c6ae8c970005943eab", + "0xc854b39cd419cd75db21a24115ccd97d76eb205c9c9860faca3a33607190e1" + ], + "contract_address": "0x2aa3dff04c25ced3b97ee95882d4101177daa2cf3e145f9685fe5825f2d9742", + "entry_point_selector": "0x240060cdb34fcc260f41eac7474ee1d7c80b7e3607daff9ac67c7ea2ebb1c44", + "calldata": [ + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x3", + "0x2aa3dff04c25ced3b97ee95882d4101177daa2cf3e145f9685fe5825f2d9742", + "0x3635c9adc5dea00000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x69df97419f82c708a28db1dc24af53840500291ea65eb8be9e6ac23cbe8f290", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x39853a5c94fc4d1d20adb9168e32be56491a9586767f109e18ba357e8df754d", + "0x1" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33", + "contract_address_salt": "0x3730786b0090339eb37b8df6987490b0f5981da70b751e2fc3fb2cf051212e7", + "constructor_calldata": [ + "0x4e21453b1e32b6000d34de6668eaf55f78308d6ae2912a760cae0255f24a540", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x725d875adcac44702c650c06fe2beff8e13d84ff769719b3db1bf9f15ce0198", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x290837ce7ae1f354cd559c78fce91d5b2bd3716bceea1d944f83d7f3342a278", + "0x0" + ] + } + } + } + ], + "transaction_outputs": [ + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 165, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 752, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 12, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 14, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x50eca84f6604030dc4ee03f2671ea5fec3018e06b18f4987bfab02f37f9a621", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 752, + "builtin_instance_counter": { + "range_check_builtin_applications": 14, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 12, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 165, + "builtin_instance_counter": { + "range_check_builtin_applications": 7, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x9c0f1a3183de4f38d9783d573ac745751b52de9a6b94e82a7ecfcb06abfb33", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x74ba0dedffe72a878afb897e29367d66f80d01bfe603c40e21db64f9c75c4e0", + "to_address": "0x4dd8f1dfe35b9f6d8d1ea6fabce1d2b9fbc20ee5", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 71, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x2488fbbd29d416b1de7e61b88be59d20c70b79e77267b4ce6d73c4bc9bf5a31", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 178, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x77daef0912ef4e76b0ed797e40ae4336382717e07836e26f0e1a35e3a87ed1a", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x69df97419f82c708a28db1dc24af53840500291ea65eb8be9e6ac23cbe8f290", + "to_address": "0xa4f3a273ddb9ce335c08a7cd5b96f9b18fbacbb7", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 178, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5f1aefe9fb4a9d11391028f099caf093ccc6593585dc5a20d04c9dd730cc696", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5e02084889c29c40e5a3699354be3972e972d69e87c1015f051802c9a333254", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0xebd953b5acc8997f86a756def2053ae8eb6fb65bab5e483fceb98d56ae4f41", + "to_address": "0x84f34acee6deb9ce07b61c464a526edd8fa80760", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 71, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 1, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x4158d9f714b237bb425e1807eda71969ecbe735d9e400a3f1891e3e71f4814", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3ae0666d5dd55d40a609cfa7448be4bd0175ad6d062d801c3fca568b62cca85", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x15f5a8f55058ca87d9756354bf092f62f063102d177b678ea9a611b0cd238e9", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1badfb22beee03081b998c1d2a6ae58b83b00be502ae489ac7e447f55a26ef", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 169, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x2806a1840f7bc1afefaac88f789aed52069814ddc0079682e1a224ae8555b8", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x170c2bdc1e65d5e7d2b448738208e1a22513c36b1dfa5b9da38e2c7fdd23067", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0xb37902344d8b2f4f5e3fa9b914b7420875a2405c6ca6f1ca046d1734e51d1c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0xf7366277d85cfe73d28876e4bdf5d01b1ca56defba383873aa0a052d69a2ae", + "to_address": "0x16b409f95a90d76be8dbcee8b340f5a0be88c9dc", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 752, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 14, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x69df97419f82c708a28db1dc24af53840500291ea65eb8be9e6ac23cbe8f290", + "to_address": "0x1", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 332, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x94967faea6ecf4ac049993c71a509a154600e12ff1da6b488dfe0d5dd08ac9", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 68, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 238, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + } + ], + "transaction_hashes": [ + "0x7530766189cc4c9a18a64c13f2a423e8ba76e32819508c58bd1a1991be61f3a", + "0x33a0074ae1ee07dac66186bc89695470ce07f1d7053d541262729c69c36411a", + "0xa0dcf3efd5ad211519deb024186473518944d4965fb3971ef921e436f3e066", + "0x828175387c16a9284403bd6cbd5449e4228b946a2f1754dbab25fee0940680", + "0x3e3ceb5b289b8ee2ef1068962517a18b3903e8002425736733ab966b73f0197", + "0x308a0a04278519553e5ec22dd448ae39da0f2ae8318c29b2b794a2c340c0c07", + "0x28567ba67494d276bd80b6b4042ba49ea4123e8eed612e4cc33c94c6bfcecc2", + "0x7b331914e7f3ee70431a08d10a7c62a971f12b8458a0df745944ef9817f7701", + "0x73a62d7353ebf2164131f41dd6755cbd47ff0c6aca9f633a570901b2f90bd72", + "0x5cf092532fd71695f41418b52d1996f41251b9f86f813c90647e3ebc3d7d923", + "0x6ab3b7057daae7fac3c941008398094e3538f83b9e21313ac89e2b9d5f88d34", + "0x4e6f94339807cfc03d116bb6d30022939df439c93d5e9b41a14b5b22049fa", + "0x3a1363fc34956e3a3a5fc6969c11a2acfa35a96164e9877b05fecda90b623d1", + "0x7c6c12ef8174806552bf9eb671c4ed16a72b08acd0514007d846a3869a63d3b", + "0x692990ed998865e550bacab8e493742b86633cd424164e206a87af12395d6c2", + "0x8cbe392e306c22e6b2f9f3314b3bfc72845934112aece6d8900faf756562f1", + "0x6442b8b01beca8e1509cd9321b3c89831f7983fdeed75f64165b9eeb0162e0", + "0x19cf745f167368c98a4b848b0fa3b92cd117d256fe3667ee49dc666c09f72d6", + "0x196a4d47e5f2018586bf2763dc5513b4da3b3dd0e7ae374181a14d396575f78", + "0x37d569e8974ed92d59e59268567e7cc514a9928c01c38402815add096a634b8", + "0x44cd9913b38b4d240a9670a305827ad5dfd9af89f5c1cc741ab33123541140c", + "0x5f1dcb9786e81a57e9f648035a1989b421f9e475d0ab4c3cdf9e39931be5839", + "0x7f21179edd3ccafd8a7d31cf47934c8a08964428479933024976b0ab6adc8b7", + "0x219a49d7d3b88001914d51a0295b745e9b4b1721209f024050baae84e22aa6c", + "0x11aa50ad6792c76046e740a83940d5bb733abda0d2744f9cca8ddb35b34b964", + "0x68ef27d3f35379839af692cb6d7e86554b821b78f17ed88adffd65407343483", + "0x7ec31b5415e3b58cf38c28a413923d66f8ac758ca4f7d3e724421e75115d6ba", + "0x58d15781b6b3130d1bbff4c58055ca0a9efad7d6909e8bfb6b1322ef83d2976", + "0x13fb3cc7b6b054296aaec1e79a287309782d33fb5bba03c8ae10124d769dabc", + "0x23dea100ac41500d28bb9426a08385c0af0f4546ff9abe8187c9446c5c23539", + "0x2cf9ed8ec288e35a2939ffc60be5edef318251a74af6f8ed85fb44aa2ec218f" + ] + } +} diff --git a/crates/papyrus_common/resources/deprecated_block_hash_v1.json b/crates/papyrus_common/resources/deprecated_block_hash_v1.json new file mode 100644 index 00000000000..f12b8911b5f --- /dev/null +++ b/crates/papyrus_common/resources/deprecated_block_hash_v1.json @@ -0,0 +1,2113 @@ +{ + "header": { + "block_hash": "0x671849e624ed7f8cb038aa9a18af6028e14345cdcee5cfb7e08b86072298ce5", + "parent_hash": "0x4ac38f03e70f1e2ba65357ac3b2d0e9380aa7f1669d9a7ba6b9086ff6ef3bf6", + "block_number": 867, + "l1_gas_price": { + "price_in_fri": "0x0", + "price_in_wei": "0x0" + }, + "l1_data_gas_price": { + "price_in_fri": "0x1", + "price_in_wei": "0x1" + }, + "state_root": "0x46a99896768700c5848dbc53a6048e554884ea6b0e881ba2f9a3d4e3096feb6", + "sequencer": "0x0", + "timestamp": 1643463800, + "l1_da_mode": "CALLDATA", + "transaction_commitment": "0x071b80fd924ec690bee7c0bfe7c60c2e222d97e00b8ec5f8cc9cb9dad096dd9d", + "event_commitment": "0x058795269651aea99e230f442a90ba2cf240f19a50b7e50bc36fc35bc7e29cfb", + "state_diff_commitment": "0x0", + "n_transactions": 44, + "n_events": 1, + "starknet_version": "" + }, + "body": { + "transactions": [ + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x242ae2f91ff3212761871c3e337a4239497125abb6a582d811604a4d9d6a469", + "0x51d842c8d088c479fbd62b54c34cb4d51b6925255a7b47632332d061bcb8934" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3e038d7f2d12831c524bb82d9af63b8947f81fdabc68e26413285a86c326f00", + "0x5ccec5d16f6cc0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5293b" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7974468a3abb4c5f952942fca1ce455e8131c9e3b853140f79b6d7334f97a97", + "0xc0045866c9702d608f64c9cbe0602c06b4a084a78c94ac9a88d2bc6c6db10a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x3e038d7f2d12831c524bb82d9af63b8947f81fdabc68e26413285a86c326f00", + "0x0", + "0x5ccec5d16f6cc0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5293f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6637edc5c68540ca0be637d973e732d6f110cf3f92a281067d69efcc5a215fd", + "0x5667c0d7f36661690cf22654141b914215795447d7b55f7f30db7a3bcc1762a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3e038d7f2d12831c524bb82d9af63b8947f81fdabc68e26413285a86c326f00", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5295b" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x60b0db957a34dbd2b6bbaaa5747052b6f486dfc45c2b61ee57980931f158b00", + "0xd32e0d5e695e85e5814980f9f7a4d07d3b4fe57897e5d1508faf9189cbe3ef" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x3e038d7f2d12831c524bb82d9af63b8947f81fdabc68e26413285a86c326f00", + "0x0", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5295e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x696d9ba32d4db221d22e4000567baa4c97f5b9aef669f6266ef3f578e256076", + "0x1cd43864fe2d9a4c539c40eb76340c4540159c7eec306b282b83a2999f29122" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x2f8c3f12bdf248fb3df7c61e4330287d6ad0015af43a9ef121d5b9c5f0e58cb", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f529e1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x54eac954650dff6670d7973cc99b87004f93ad0d55ac50992102670447db3e0", + "0x250f302c5a107b822fca8ed8578c9fe7e17051a45b96e9d67bb7f751bfd0250" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x2f8c3f12bdf248fb3df7c61e4330287d6ad0015af43a9ef121d5b9c5f0e58cb", + "0x0", + "0x3f3580264469780000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f52a05" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1de522ef9f6e5a943a70d0745dbf9c0a8712c8a5730bcbdc428bf8f229607b8", + "entry_point_selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "calldata": [ + "0x3a10e6ce02ad464d3e417d7ae96478b8ad85ed5d202a50d23998a39d9529b6f", + "0x701e59854c43f2fa51eb475bfbe673c646d41d4dcdd6948d84c2d12111c55a2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5875bfb533c5b8439070e44a0bf7b7216c070220aad465ea3b331be6a8d888c", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x6d81810eee65969f02029a66e0ebd8fb452bf1e85cc0e3d47449b51ac5e01e", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6d81810eee65969f02029a66e0ebd8fb452bf1e85cc0e3d47449b51ac5e01e", + "entry_point_selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "calldata": [ + "0x57acc060b5d15b2290e37676ba34b0399a4fe3667e824bb0f0e311ca55af187", + "0xbd7daa40535813d892224da817610f4c7e6fe8983abe588a4227586262d9d3", + "0x1", + "0x57acc060b5d15b2290e37676ba34b0399a4fe3667e824bb0f0e311ca55af187" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1df4bc5f28f4a62bb6711f2e293ec3d4c6efed2bbad5783930a62102b6621e5", + "entry_point_selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "calldata": [ + "0x63d5cd032105d01782c69a24d3b3e63ccec72f8191359a26c6fd1255f389980", + "0x2e68f4dbde9e3f2dc504937e60d474d4e57d42380cc850970a0059463558ecb" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x735d66786de27ae1e223798b4cf9aa6542a655d4abbf57c7fb414294438bf4f", + "0x3699f36f7f0eddf50ea9b0f223fa61726afce30ca4918306006b2af8922f6bf" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x19315ec25b1957b6b6bb40c86d8cfef60903c212c80b0b21b509b94137cf339", + "0x0", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f5336f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4c2f7af56254754e4294156ca54474081180c439375727b1ae2354108d4ac0f", + "entry_point_selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "calldata": [ + "0x4", + "0x7d49816d9365ec64b7339c658ff6f9b62adda6b06289078daa3009a24e75428", + "0x4377e32c252f35f6a6e436c4a406d681271e85bd54c2bbf472c26e68351369e", + "0x154928ae85aa272bf2493a6c3ebb79718cf3b0843ca6650d02c1228b286b755", + "0x36d88d8730ca9b56bbb7c94de23e46a2bb8ae8d2a117a666b50f3e9b156ef92", + "0x3", + "0x32aa94442c76cc8f0b164f52f1f377feef41cc34d3eb9a3c100caca6c108518", + "0x6dc3caaffd8a79f6da7b4be7f068caf7b1d9a60249c7d4aa77508dcd1808aca", + "0x63a372e360a722f67dab74627ad31be819255f380e4517ededf1cde3f11f76a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x12773e3f6000556c18f112f385da9053794cce0e62859c263dca9e1bf2a60cd", + "0x10041ff35c0e19792f59b22bdde34edca0a50aeede9f9d976d531aa821320dc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x37dd54839e02e4c49a0b512cddfc3726a8a351db96e7356a4a8652cb973ff3", + "0x6124fee993bc00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53411" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6f29296144383c1d8c07f68eaf555fd62909870474f0f07df7ead4ba722bd65", + "0x56645136ad4d905e07017d9f98e4f8cb139ab850e98a48a21358b2028652096" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x37dd54839e02e4c49a0b512cddfc3726a8a351db96e7356a4a8652cb973ff3", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5341b" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x743359d3771023ecefda608e67f02b83e1fb0a68b7b88deb7e8f9b5394fb287", + "0x46757288467dc2c226cfcc3bce42c6c1585f8f4a134d0a456107aaf8c5aab1c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x37dd54839e02e4c49a0b512cddfc3726a8a351db96e7356a4a8652cb973ff3", + "0x0", + "0x3c48199c5f1a600000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f5342a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x38ddae9d0b800ad55489c46cf3206983d018bf3540ed65b4bee4f229349d866", + "0x6daf6949e660b0d7dda9ad1af59545c93e252dbf06ca1f33ab940216c49c181" + ], + "contract_address": "0x6603956f3aa790cb6f2a0e6d7d54743c4b45b126b508f7558f63f74142ebd2c", + "entry_point_selector": "0x240060cdb34fcc260f41eac7474ee1d7c80b7e3607daff9ac67c7ea2ebb1c44", + "calldata": [ + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x3", + "0x6603956f3aa790cb6f2a0e6d7d54743c4b45b126b508f7558f63f74142ebd2c", + "0x3635c9adc5dea00000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5eb9552b992aeb6a43df5f7c3968f75abaee9de7dbf06ca91e53e6f22a8751c", + "entry_point_selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "calldata": [ + "0x6bb6d3094f2782400781da1bded82858725575f443e60618b77a31bd3fff1c4", + "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "0x4", + "0x6555dd1199ec72b44b0fe872335490c8aef8660da094620d1a4c829ade9e4e2", + "0x2", + "0x66d79861ced88d122b395aa50577910492d0d731c0970e0e5a2bd0359d6bd70", + "0x36c90c24a093a8a90286761327d5e7c223cbfcfad30aecedd4dd8170c587448" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x31da92cf5f54bcb81b447e219e2b791b23f3052d12b6c9abd04ff2e5626576", + "contract_address_salt": "0x30d397ca6d01add24363e8d9a75b465fb77c2bee54a55a47aa6a42992687702", + "constructor_calldata": [ + "0xcd37e86c6b8d24c21959b773b7fa71e54da41af044bc3e026db53bf666b884", + "0x78009c752bf3b6dc7419d95a21c01d7e793fee537b97314bbdddba050f3812" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4e0ad685768a38be42c3cbd7d6b84c6291c84146ee5dc04d62e4f6771702a0e", + "0x7ed23f13551e95f9bebd2cd76d6378464e92e4f68957112f6edd108afeda93f" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4903021947e10c74f56ca2cde78e68af9969bd78979bf2974d6f3038c733fd1", + "0x5f68e8131ecf80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f539de" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4eb5637d72ea308e7249e908f74d1fd219b1cdcfe7d64603b25f5d5fdd62f3c", + "0x77342de6ee8bc36ae5965978bbed2baa6cbd463e7d69c44b8a680b473e2c970" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x4903021947e10c74f56ca2cde78e68af9969bd78979bf2974d6f3038c733fd1", + "0x0", + "0x5f68e8131ecf80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f539f9" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4fffed32f0ce8f642d46b7aad7907cfe5668fc15fea5debf6d0ccb3458f8e21", + "0x2e5e22d6cb9f1f984ce55bd31d49ecbb07a9bcfdbb3bcb9edcae9b0e554e8b0" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4903021947e10c74f56ca2cde78e68af9969bd78979bf2974d6f3038c733fd1", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53a65" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3a10e6ce02ad464d3e417d7ae96478b8ad85ed5d202a50d23998a39d9529b6f", + "entry_point_selector": "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "calldata": [ + "0x2f3109a4036d5ed4d78cbb69ce0be20bfa2d45dfa2528b2d3f616ebfd03cb9c", + "0x7437f6e3d9e744ed7c8f8c00f91e7d861ee750d41f49c73ac89a3281ff2acb0", + "0x792d268fec4e04ea62589e6b5b07f309f1a3d0cfb20a9d84ad4d09f2abcace3" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x245c0ff42b2761b322fbdaa6513c9036207a41225f7b087ed4f185f7a909713", + "0x2c467cb3522ba633ff9d5ede32549b12b44eaf3dda8867fad61910c02c12b0b" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x4903021947e10c74f56ca2cde78e68af9969bd78979bf2974d6f3038c733fd1", + "0x0", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53aba" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x105713f3f2c6c65ba81461ad64143d5350fc54499168b48de98748afdbb4d78", + "0x349fae3037c3ea8ed5738ae5015df636b2ec208b5253547eb9d2dcba64c7dc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2a1bcb8fb1380e0c7309c92f894e7b42dc9e72d3d29ce1f8f094d07115ee417", + "calldata": [ + "0x6661498cfab87f9cdfe85e4812da3253fb6cc45537704603faa5f03ab2604c4", + "0xcfeb68e1889f3b90c57368f6c7282dcd8f3135e0", + "0x61f53bd5" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6c48a1dfa479a9cca7387cb05dcf3178c7faa45e927d226e1a0862df1aad40b", + "0x57115f4180975b901b2c591de2c8d3088c74d84889d7605b3ff75daf68741b9" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x6661498cfab87f9cdfe85e4812da3253fb6cc45537704603faa5f03ab2604c4", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53c50" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x99b4265e9d6e791d4369343dce61ef712da72f69e28a0cc73f68d7964ee6b8", + "0x393ed22ec40c7a9c1c0afd275574cbf0de9568d406cecf49c258ae6ca73c04a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6661498cfab87f9cdfe85e4812da3253fb6cc45537704603faa5f03ab2604c4", + "0x0", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53c74" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2c836e1169b24a0ff69f4c30ae9ae934afa2dacce2ae288476ba743e6a028d1", + "0x1e6bd5ab8ad756527e55a45bb64903ff1965916aeb173207801868e323f1694" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x6661498cfab87f9cdfe85e4812da3253fb6cc45537704603faa5f03ab2604c4", + "0x70c1cc73b00c80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53c9d" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x494e71309838bc4042cdb66b87652c6853fa75e38b011a90daddcfd6ea7f20c", + "0xa4305571b10b157691f2d4380178c1119eccd72edb9024dc17669f43efb0d2" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6661498cfab87f9cdfe85e4812da3253fb6cc45537704603faa5f03ab2604c4", + "0x0", + "0x70c1cc73b00c80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f53ca1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x143e8b9d00046a804f43a7c6c7c409aaa8d459a57fe32f44005253f41853dca", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x7ea09f00840299a19744627b21ae846c976e014612b591964f2269bbe151efb", + "0x49d2990837636cabadc522bba515c4697908c3cce0e89534f7a404422cf0144" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x143e8b9d00046a804f43a7c6c7c409aaa8d459a57fe32f44005253f41853dca", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x7ea09f00840299a19744627b21ae846c976e014612b591964f2269bbe151efb", + "0x4fd7e7112bcc11713a5949c545a2ad2f4e9a305319796fc78d339809931aeb8" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x2e315586ec819cff3cdf30e65f9ebe0290f8abafe7e58a7b2087a7ba60fc770", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x3539d81a2d889a1bdb5489e1c26bf8da7ddc66210481261658d1dd72e95500d", + "0x2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x41e3ebef8b2d51f5c49d7a70c4214170088c4aa022ee5292fe23e5e560b6b23", + "0xbb4d38a820e3a065a6bd22b51f86a1a68369bf9ade9ff5955060f9f588b955" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4e6ae62e59fbc91c20569f7e6e3c323d7566360e74577a5ff979cb436fca359", + "0x579a814e10a740000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f540cb" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x86264cd78b4ebe347934a19440fd735812f71c140594d1be5e0dd6a6fdcd8b", + "0x6ac904db5f491905c042e034382c9183c0bfa43c66b31d61f5f50004a588443" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x4e6ae62e59fbc91c20569f7e6e3c323d7566360e74577a5ff979cb436fca359", + "0x0", + "0x579a814e10a740000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f540e4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x57acc060b5d15b2290e37676ba34b0399a4fe3667e824bb0f0e311ca55af187", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x3264231eaa8766704a5a16e412620e6a181cd71a1e276d55c080ea84d5ac558", + "0xb252f321a0f69076b932559cd997bed210e81f1fc357649f42407cda1ee4b" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6914628d68c3bb0977c2e33a91170eb32e1912688eb9d8c8dcdb2a1363db156", + "0x47e7aba8fe121878354262bca712594f18a4e704ec82936723abd8f3998ed8d" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5f5ef0a04d2b76949185158afb8cb3cd4f0b7e76634a2cfb3e3b15220e9a6c1", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f541cf" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4850f308f6cac73f016a6617f9fa615f445b861e14e0aceed7f575543368766", + "0x26635f07422ea94e577c07e62198de62e2331a66ddf33bf3a7d860751542c6a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5f5ef0a04d2b76949185158afb8cb3cd4f0b7e76634a2cfb3e3b15220e9a6c1", + "0x89e917994f71c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f541d2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x760f5db95700b672b99eaf8c45b5cc1c83b8d5e5779ce3994194c3f3a1c0e7d", + "0x7f59ab2e8e26ede72eecb7f6e63cccbfe426cf1479118b84caad55c0a874848" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x5f5ef0a04d2b76949185158afb8cb3cd4f0b7e76634a2cfb3e3b15220e9a6c1", + "0x0", + "0x3ed45b275ad5bc0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f541d4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2b7c58620865152e59af83fd34baf41ed9153a1169873b8c69a494d4671b79e", + "0x53a423d44bc40da43f40307dca672bb456983053b2341ffc51abe8d59436ca7" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xb43e4cd358c89c0b32a37439270cd04d13c583385198218d04e7e509f403ce", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f542de" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x48c7e67f182a75462c1bf2045aadc8599e6d350f8968328fbf0d37a0ae4150d", + "0x4f25a730a58c3d0bff7a6ae8c8d9fa1505e0fb480320a5d41b0e99585591d31" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xb43e4cd358c89c0b32a37439270cd04d13c583385198218d04e7e509f403ce", + "0x8e3f50b173c100000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f542e4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x403ab3b66bc438475a4302fddb7ea24962e21d3f41ed62a39163947b20cc98d", + "0x420f9c96cd042a5406b3cefce4a350b7c9b1a8cdfbac3943c2e2a15c9d7bf5" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0xb43e4cd358c89c0b32a37439270cd04d13c583385198218d04e7e509f403ce", + "0x0", + "0xaa00be18c28900000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f542e7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x59cbbe782540a0bd6f5e824c5b59277f333c9d22f9d658ceb8a66ef61ccd2c9", + "0x145e2dbebee3e17d8349b1e0baa9a0e48a8867a006f52c7f9b2eb8e8be8e5e1" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x7edde9eb6764a4984c32541eb51fb7b76d562f3e502f8764367aa2be093a71a", + "0x2664", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x61b381103fcb441ba4c3dc791ded09d0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2fd07f86e65b63a5534773743abcc3c98a938c4ebcf7ce16597c7d38491f481", + "0x17628fce3348cef7452384c9de1d477cb7b56c7eba62f02faaa824b29789af5" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x7edde9eb6764a4984c32541eb51fb7b76d562f3e502f8764367aa2be093a71a", + "0x2657", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xaa09bcf58e1146de9e49929ab8a9e01e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x349adfd096ef67fdd7aed1ae4234219568377521a89c6552bc0557287bc2c14", + "entry_point_selector": "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "calldata": [ + "0x2ce6916c85b483be885ac1f400878036839a7a1b85ca1dc63e84815a84a7d27", + "0x1d1613613a4869f7acc1142c5eff6d5f3b0632fb475868ce9315ac6475c5e86", + "0x20735f8c084b998c51945aefba177cf173d34eee9b3bded58ab097cea7fd8c1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x3824816c7da5292d3aa2a1cb70a20dc90407939c6cdcb39990399d57afe125c", + "0x61c1f3fa7722c557ea0e9d0714db1668deea10e951cce5a2484e82658dca3af" + ], + "contract_address": "0x55fe97a62a6e27d4036ce95e35ca03438ad857fa35870ebae598c5258cbb355", + "entry_point_selector": "0x240060cdb34fcc260f41eac7474ee1d7c80b7e3607daff9ac67c7ea2ebb1c44", + "calldata": [ + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x3", + "0x7fa63ea8c58ba6791c9db699c2c44c2bb201667a91fadfc906b55f1882bceb5", + "0x1b1ae4d6e2ef500000", + "0x0", + "0x1" + ] + } + } + } + ], + "transaction_outputs": [ + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 178, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 238, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 63, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 178, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x4c2f7af56254754e4294156ca54474081180c439375727b1ae2354108d4ac0f", + "keys": [ + "0x7d49816d9365ec64b7339c658ff6f9b62adda6b06289078daa3009a24e75428", + "0x4377e32c252f35f6a6e436c4a406d681271e85bd54c2bbf472c26e68351369e", + "0x154928ae85aa272bf2493a6c3ebb79718cf3b0843ca6650d02c1228b286b755", + "0x36d88d8730ca9b56bbb7c94de23e46a2bb8ae8d2a117a666b50f3e9b156ef92" + ], + "data": [ + "0x32aa94442c76cc8f0b164f52f1f377feef41cc34d3eb9a3c100caca6c108518", + "0x6dc3caaffd8a79f6da7b4be7f068caf7b1d9a60249c7d4aa77508dcd1808aca", + "0x63a372e360a722f67dab74627ad31be819255f380e4517ededf1cde3f11f76a" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 43, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 752, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 12, + "range_check_builtin_applications": 14, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 209, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "range_check_builtin_applications": 8, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x7b06424b1f4b2e59392059674fea4cb9f9c7fc28b606763024a7976e1b67722", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 29, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 180, + "builtin_instance_counter": { + "range_check_builtin_applications": 6, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 245, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 4, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 6, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x2e315586ec819cff3cdf30e65f9ebe0290f8abafe7e58a7b2087a7ba60fc770", + "to_address": "0x1", + "payload": [ + "0xc", + "0x22" + ] + }, + { + "from_address": "0x2e315586ec819cff3cdf30e65f9ebe0290f8abafe7e58a7b2087a7ba60fc770", + "to_address": "0x2", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 426, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 443, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 176, + "builtin_instance_counter": { + "range_check_builtin_applications": 6, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 2, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 931, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 23, + "pedersen_builtin_applications": 14, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + } + ], + "transaction_hashes": [ + "0x5e386ac3bdf6f5431c270aec427a44204060f45ffd94944cd4b87b9d7a01115", + "0x5d3406b24e5563d94fa4c6da9a60e172ce66748f8ba4bed05acd706008edf88", + "0x492b8b796e4c45bab2b735e8eac6e0705bc008f00210e0e02828533a9f050be", + "0x26073f1e5b041df78246c7f4723fbe594ad711bba3064404aa6a6acd6915161", + "0x14bf4ca1d84391e510d59eba7bfae54d40b73bff1140e9ec2da0d5d6ce59790", + "0x461453bafe4ff8c0037393f424927a822b5925d7e7110d8cd898f0d52c1e527", + "0x5ccfe55cad7864ed2e6e3637c65039ed7d000b865ebfa5c264d827a6dba4303", + "0x30197c5f5b23ced8388fd14498653c0ea469a73a7c24c69e1885623599adafd", + "0x74aa4535229c586feab6762b6e86fe2692630accdd798649624576042fbf13b", + "0x6a94a0bbfd74e1e645ea96b8b2be208bdd039a7f7aea561343b43a06d36f85e", + "0x4b4bcec3b583ed097219493ab578957ca6b843a01882696532bcd31af3a2697", + "0x7e10a41a431219fc2d7795182857a25f6a6bd3a5b79fc2fcc8f401bc78edb30", + "0x2a7f153d473f8b01d76bcd3134a1b14e9e7ba5c5f785c28a9eebc89896cce93", + "0xa0c0d53b7ecd4e1a0f77aa2b7854d30f1657c2f0163c1f0635c30e2b27a85", + "0x1f9a998710f6cb79996e37b41f8f65615f5ae35493dcf0c86121ae61d62e4a2", + "0x7461090f09ee88d813455c9fc99867c17bd1dcccf613d3e17e9b112a23f8322", + "0x7a7be251f727a31ed4838eaef95d8e331bcd50cc4612c3fadbe2b493574fe2b", + "0x45c0b1418aaef1b83ad394e5b5db709ba4c7bc94033982df5f29c5ff448380b", + "0x3837fc6d59d76c3b64f75d21e2699ad9430fb82d32b2f64301a6625894b545e", + "0x5b7bf19f67c477fd9574be68ef63c0d40c732ae5500640a1c5a474b59e10d6", + "0x40d1b2d4ba481d673ebe69a19e5abb835b4a05bd94418978581c3bbabda292f", + "0x33b9bb91ff841bbefc142c97d91a6d58bb5ff4fb2229b180235c294c8a9f5a", + "0x486e8203f22f9f0996b5a7da5069a64c2d1becada2032c292b1eb89a5180b0f", + "0x4748f905e588076529afef2c237db380b548ded17d15dad2a7477e90ce9cdf9", + "0x6480bd924d9edb4a11bc46ad2569b95503e95ad853e8368c5580152f5b240be", + "0x10caeb07faf230c3e657a58856a62160db6681eedbd7b4bab09a844f48a7d84", + "0x70f5e73f122d47a4149f220a467c87a17fc8bad7566f40e1311ef54eac4d2ce", + "0x36e619ae95bfdaa02aad6e35c8dd99bb6e47eb286e2487bd4d152eb376e6cd8", + "0x3ddee04bf8325b5c19873bac1090a9e4982fe80af7630f8e4c425a32297b24f", + "0x3834e360b2ad9780338460efd33bc23f4b94482519281156d77d736982e858a", + "0xacae99ce81c796be2dfa77a2baa18e23ab981d48eba8b43c20537e31047557", + "0x70615daedb9387a884c6dc960ee3c79c269cd39f5bcc8e5340531b725176d86", + "0x18993b2e21a0cf4ab9853749b26a42ad8b66019a6860c58b036ac19eafee68e", + "0x71dfab97f659fc26883fe14ceeab11b4faf41582ca87dfe7e001856b58b0324", + "0x691a003b4fec3f001de339ff4607a52ac1400c8eb3a5b4f4a5960a60f3d9dc5", + "0x6a26fe2427ebd4e8a20d5739cb45b79d5cb0763298359246ea3a3ad19062785", + "0x2f262a85052d3640066acb0a2e9a274b469458a1c9c04b6c9440c9d512c9a92", + "0x5871801b537db7e9d2bf1ec6f308bde37a4b070ec46afa940aabc39f7f739aa", + "0x2c5eae3ab18850b6a839f8d66e53ed29accc3936e97fbfd2f219a470d11ed7", + "0x52d98d5752cd8843490dd89e3755ac5dc56ccdea5002440761fd214b34212e1", + "0x79787b6cd0c35e30c66c4bdb43d0bcdf5a391b613a4337e8786578720d6069b", + "0x6cb029e68634dbced5f094a9237d6c17ea049a366803673a40e4e82ca1bb748", + "0x6b0559b7931b5e47492c6a9df64559fb34b4117c7e26a5e12875fa49f9eded", + "0x405d74766b46c3509843514f59a2b0fddd9c3ab193e0accd1f3168be36a2f0f" + ] + } +} diff --git a/crates/papyrus_common/resources/deprecated_block_hash_v1_no_events.json b/crates/papyrus_common/resources/deprecated_block_hash_v1_no_events.json new file mode 100644 index 00000000000..15bddca5356 --- /dev/null +++ b/crates/papyrus_common/resources/deprecated_block_hash_v1_no_events.json @@ -0,0 +1,5296 @@ +{ + "header": { + "block_hash": "0x114f581e913add809ad070737778b9775df029cc2264dd6d40cf8efee7a8e76", + "parent_hash": "0x59974302ff646a2804d613bf379ec3ad5f42f8e991be37b2f33daa9504b765", + "block_number": 887, + "l1_gas_price": { + "price_in_fri": "0x0", + "price_in_wei": "0x0" + }, + "l1_data_gas_price": { + "price_in_fri": "0x1", + "price_in_wei": "0x1" + }, + "state_root": "0x5a5f26ce761d20ac9dfdc3a009b6adeaabac74b97de38c7633af690efd9b175", + "sequencer": "0x0", + "timestamp": 1643609156, + "l1_da_mode": "CALLDATA", + "transaction_commitment": "0x018990b555b92ed88c651f0e7e49fe22a3250c1f1d51766ed8c74f33eddb31ca", + "event_commitment": "0x0", + "state_diff_commitment": "0x0", + "n_transactions": 111, + "n_events": 0, + "starknet_version": "" + }, + "body": { + "transactions": [ + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x9ec95ae0b2b24e1898685d78b2fa57b46cddc0e1d5a89ddbdb30ebde6400c2", + "0x5a08860dca173daa5714fdca09c86415072aa9268f972a414afaa53b31db6e0" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x251c", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x9f04ecaf04c45eb98d7303782c8c0a9" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5e527e91adae6af52917a22eecfdb3f529f43bb781111b0e0bbdaa9fd6f3744", + "0x2d514e03e0bc0c0d97d417dacfbf98a5f468d5e56866306fa518f7859b62411" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x255d", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x542ccd7c48654e03be87d021ee830002" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x511c74dff0fe743d35170f4f3bdfefea79008eec1a3e1a9051fcf8263f27517", + "0x58120c107526c9492e3a8c4c419a6786859be2c913bae360d880f25ace2568b" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x255c", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xec7eb9497fce4ff2a80981833db4d65c" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x64023a79e602bffc9b724db576aa23c2ba0e8f76269bef51aa394f7f4dcbc08", + "0x14e88aed8a901d3eb921ac68430a9734d87084d59434360282cfbcd466f3a38" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x256b", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x996aec3860b345668280e598f9bdeba1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xe0c70ef566af49df751c0300aba598f4e5a4fdb4d830a601dbe147e672bd91", + "0x4ab6b796ae5b48c7261e50abe594b3a2876b57dcb520103329cda9cf28e27e0" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x251d", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xbccdf76d142f493987d2c33168c67cf2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x408f6c6f0f14177d246fe01d0bdaaf6c3e31dc9dc6ebc210fc68b559ffb39e0", + "0x5e3abd49e2e279c6dfe2d7e342137e693c1b1bad1f59d0a7fead10d1dae2dc5" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x2561", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xe8a4bbc03b174df5a4a383d5257ba9fb" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x417234f2577e453e603d1509cbb66e3c20f8aad61cf2f7adab79782e1b4e602", + "0x295db53c38666b9980ca230ccf6661535ab4676ba84c80a6d8d1da170f85472" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x252f", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x49262117de5d4eabbfb524039e8035d7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4e3a1a1ed66c6b2ccf010ce9fd5e54764e7f57fc07bbaefbe00b1687878c94d", + "0x50593cd89377d0ac27fbbe02cf7c7e7bec3eb53b6f3427cd24a18c077153ada" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3e0ad99ab7af09feb6561d759b0edc7c0754c7cc79531ddaadf5c2c9c966e56", + "0x253f", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xf1ebf1ff9ff04a89b71e9d9f04bf9251" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x759985747a2267e68503b071d75c27752ad22a58f86584e5276a792485bee6", + "0x33e4ac32e1b5c1dcc3cf81cfbc80c649fb79315d5b719247e8b41f04be79682" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x1c743d9d042bc6174720205779a71f4d89c0bd3ab449c3f497a9a0ed0e3e256", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f7616e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x1424e3fb77766e764e0d1992743cda694ec98f42e957fcc3f5fb79d4f1d780a", + "0x4333ba912b77e6b0d7867be12427f834f91f48575f11828dafda1ce46a096d7" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2a1bcb8fb1380e0c7309c92f894e7b42dc9e72d3d29ce1f8f094d07115ee417", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x1f70cd2b2910041f9608c117b8f18cfcbf73ccb1", + "0x61f7619e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4ea78029294e95721baaa966b60692291c6c64d7e7191ad7cd725464be360e6", + "0x2844367d7800b29166ee05b92017729c52cbeac8f63308c48b0ebced57ee6bb" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2523", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xb980d3a8489648e1bb34eeb0d02df6df" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x72d58fdc04b2c2d54b976f0e97162ec865ea5c5e365dd3c95a6ca87640bffa4", + "0x1d917ec8189362c9c8285877e7ca851cc9c2f0b59027e50e82cfc4c0042f6ea" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x253d", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x19502b4f8d664d59b92b33eeac2edea4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4f4168aeb877f3feaf78dbc8b233bd84ec4b93b3dc78624bb7b0549f9b88e6b", + "0x3e24cbcdadae663eb3c4d53237d39bbbee217acb6fd97e4d6102df6746ccf1" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2519", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x9d29e2702c1b4efb98dbd546f1df1293" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x2f7848b4eb83a758682f748dcad4617aa171cc40f976616eb7b3671d9183992", + "entry_point_selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "calldata": [ + "0xeee4fecd206515a6c56caa9ca30aed1cf38cd7ee" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x355e9eafe213448adc6f30d6435d86653df2bd4ae39975e795b15369720acc6", + "0x7de5c9304ddc7e0441a4bcf34d5741375e521b5f3c6e39aeb9bb5f267edc2a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x257b", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xe30158c3c1184e26bf0569007898aa9d" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x65b6a4e81e2ab4c5bddc57fad63f03f76e8e99102284d3e74565b193f3c7af4", + "0x4d456b7db40511ed6f136353534264a3af8efc0e0084e91ba4698ea56e7f2ae" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2522", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x631f6a66a9de4dc7b4fe754af6c15263" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x337b28dc3cb19d5385ab4d1732d376ebb2a792c669a6cd4f358d59d3cf1ea22", + "0x626de90274843d050dc565643dd00b08b248f11feb30df4b1672e16bdcb1c31" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x252c", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xfe38126ce77b44be80c6029bfbc5b27e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2d835d33e6674f05e083941c51f0196d69f1863e7e102c512dcbd8c61c71392", + "0x7a64c2ec8f3bd0dd3881e6576f2513567ad088a6f588341ce7a6cc8dd43ae90" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2567", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xdbbe8df80562434396316931d3a4d260" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x704c1c942f75905028ee019a7f55fabb9d8b46ec297d84408b9b25e88632007", + "0x5722c7e4fd4620a69989714cd84e9ddd4d25d42eaa3e623b0c29ba6f8201119" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2541", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xc32b5adb2d0640cfb67c947bded12a3a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x1851cfa6d2001d84e376630f517f9e37bf1b0093c0dd47ed79824a0ae9e09e", + "0xedfab53261bf6218b2b501d5eb41f30a64193a128248df0588e37c837a4884" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x539ba7e78b8d96f9b3eeff2b9c99fa2fa82ecf77422fc10e52a66cd8a9045d9", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f762bc" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x49d6824cb9ce48368c5d3e6d57c811d9c4114675da9e5c4ae330a99191eb0bc", + "0x729ef5e5d6c38d14afccf4813280f6d0fe80ff1a4418e2837ad7bfc0a8c314a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x539ba7e78b8d96f9b3eeff2b9c99fa2fa82ecf77422fc10e52a66cd8a9045d9", + "0x98a7d9b8314c00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f762bf" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x3dda822ab0a880e17e00c044a26be4eae84994c7a0871e5348e3662f1a40153", + "0x7dd4103f5973f95a73797428c954898aaafbaf2ed12a70d349ea390b85c8d75" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x539ba7e78b8d96f9b3eeff2b9c99fa2fa82ecf77422fc10e52a66cd8a9045d9", + "0x0", + "0x3fc0474948f3600000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f762c3" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x44d4ef71ec8a237be3e1db2a55c161c3cf9f62b2467dac887db030d5cbea9de", + "0x1501957edc18bfdacb6f7ab758cf1978597803d2daf6182a8ab078158018dd1" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2569", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xc6b80c74390c445089d510e21e6d1ac0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4cca5a85f26b19b88c1a86b093580286ab538be17ea54277240a3d2437d7559", + "0x20fa4562f3188e80c0f93e21d859858ac2cfb55575583859d038fce8d6c23d7" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2537", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x87ab0e530b1242ca8b0f9e312731af26" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x47f9a3e093fa0275e9bd033d97a6757740771d1903c2e753b6de0fe2c5aa5bf", + "0x4e97b0406daed264ae211ce54be76b5a5e69ecea12834c5e732c04d30183502" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x404be6fc10d2bca4dbb39ef303bf954ac951e4a173492d100049fd81755a264", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7630a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7b6ac37f9439516c5c9aa81c74427afbfdd06f2d3d71f2eeef3f62f11fa210c", + "0x644991caee2dfcf77578ef65af7c762e623dd2d0db7ee70039f9c2479f3f517" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x404be6fc10d2bca4dbb39ef303bf954ac951e4a173492d100049fd81755a264", + "0x8670e9ec6598c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7630e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x16b9853bc3c91cafadd52d4426a2d72c46515039b525b6c1c3ec414ca5842eb", + "0x612afbb8ed1fa5b4cea953f1812d0a03eb5d5b085404e9baa6679fb4a75b336" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x404be6fc10d2bca4dbb39ef303bf954ac951e4a173492d100049fd81755a264", + "0x0", + "0x3e9cd84c8c382c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76312" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2eef38236aee8538b78fda485d831fe48c8ae988dc0f988c1ec16f934001e57", + "0x3eb799c6ccb9632fda53c6a74a53351f5d97c2f9779e47c32d3f799d85a9639" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x2568", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xb45d9aefba654a2ebd0aaa00158be24c" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2e9a014c486669515c88ff28e23561c072b1940163f8fbb46e759c796d55d35", + "0x49a0ed8e1f22596a289aefc8867a3ca2e95ffb441efa88c87953b71cd4ad446" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4d7f5327c30af1b1c7503eaebb00a9779189ad8d65afe7318cd0110b62ba894", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76339" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5fdbaad8332b819e5082c0f39812bcd5d93a8a8a780c32995cab775ccf915b5", + "0x1b35c8bc88efea62c91d612a4054c665c06126b90ec8503b2c5afae9c50757c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4d7f5327c30af1b1c7503eaebb00a9779189ad8d65afe7318cd0110b62ba894", + "0x890b0c2e14fb80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76342" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x507ef65e342f0a3dbf2b438ac68c20bd45e3843b8d17b6eebc5b62f75c7ee4d", + "0x2acf2cb5c180c6bca6afac2bac24b48cb734da2c78f351aea8bd2454a573768" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x4d7f5327c30af1b1c7503eaebb00a9779189ad8d65afe7318cd0110b62ba894", + "0x0", + "0x3ec67a70a72e580000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76346" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6244e740cac07e11a4813e665f870bbdd00536c4b129bc1e30e40566612e115", + "0x31803fb7c5c043c4fff1700f13d8fdbd971d3b98eb7b19c66f7c3adb11189be" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x73f1de3ecc5222f138168393bfb9235468badbb9bd8b7619afda148619cc1ae", + "0x253e", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x2e300b3c562433290926d1899eb3d89" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x10354974212ff90be08abbcb1c1641f60278f1d6bddc2ea4b9508634af78524", + "0x728936bad7b78b922daf9d48e300d1d9c75da0b9b242ae1f8ffb2f385721e5e" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x2ed042e54f0fa1fdf2e61f96402328c1923750c9566008586d505b61c0b77e6", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76386" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7b37c0e976b48d4d3276da9baf67a732ae9a268a189e62d0e7bcaaeba448abd", + "0x7be7ec7259a3a17b7fce8c269d6d813a1a1d3cb9c7dce0e9da9535d57e0896e" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x2ed042e54f0fa1fdf2e61f96402328c1923750c9566008586d505b61c0b77e6", + "0xa076407d3f7440000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7638a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xbf9def53ee22513a87e83f066719ca3dda1807ced34ae7a1f8c58bf22f7c6d", + "0x4d4c76404a2cc659a7ba507dbc1c9fc678aa8579be6d120699a0cd225f5ba4c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x2ed042e54f0fa1fdf2e61f96402328c1923750c9566008586d505b61c0b77e6", + "0x0", + "0x403d2db599d5e40000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7638c" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6ad93a6bd258813e70cf33ae8073f73f4c912b9d1b974744ecee394b7aad573", + "0x1761d4d3ba7ae982969f5a87016b2ce35666eed6ae087488af0e160f44f1165" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2a1bcb8fb1380e0c7309c92f894e7b42dc9e72d3d29ce1f8f094d07115ee417", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0xea5418d4457b5485e69af54387750ddfb6162bc3", + "0x61f76416" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6f1739b30d5dd3f715a630d03e8a9837aef9775a14ae7166a69700b9f653957", + "0x431fcb22e571e96ce741b70ea8e9d95b3cca2c4cafa1a89d8d00abcf593e32b" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x2518", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xcce4a6791627466abf80fd597f009dc1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5d43e1db9407facb0a4be56e321fefaa796e514ce7a67ed186104364e1d2732", + "0x2e1442761d5f46f7c58479a464a431a03b92d6bc366c561efe1bc3756ce3b2b" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3ef6f8a3b75399c376871d2a3772beec30fa77e94af10f5f8aee47b33b88465", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7645c" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x349adfd096ef67fdd7aed1ae4234219568377521a89c6552bc0557287bc2c14", + "entry_point_selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "calldata": [ + "0x17c378e4fa718fd3405324eee83c5c7c515d72010fb30977b08b84b0fa217a9", + "0x2251f3d412d16fdaa13fdae9b29b30d743f6774af33a7a444c68a9c137ce213" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x69e01c7c62212e3fea50213d8cd1e255a915a6a01f653e08708ce85ad357431", + "0x574348f7d58ff9e569d8579f4e60b81f38f51415b5f887aac7e1d1cb858fd85" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3ef6f8a3b75399c376871d2a3772beec30fa77e94af10f5f8aee47b33b88465", + "0x6c6b935b8bbd40000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76460" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x51d83c301a15eb7a15bd4f556fca7adb6c2fb4950ef65d8b2590424fa467175", + "0x562b81c5e99b7117ca61c7c4cc8706993132a02e660f6105f4eb11e28128f6" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x254b", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x1748929ce37745c9bfec7705a440d2ad" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x539536df3f455acf1daf4bcdf178c3c12db9749d3ea4ae804b59fa1cd53f1fe", + "0x33d576774399c60178e059fb89ca5fa29c280ea66a42897e8a7b01e5401acb8" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x3ef6f8a3b75399c376871d2a3772beec30fa77e94af10f5f8aee47b33b88465", + "0x0", + "0x3cfc82e37e9a740000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f76464" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x640b4326e35c400409be1142e32e4f374f2ee193ab9795abe79a1cfc0a2580", + "0x62e66648e9dc15c05af1f6b9059e137a6d68badf1fefdd25e01ecb16d7644fc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x254d", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x6c688cb1ee5a4d368b9a3e5e469e9883" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x71a5ee39454df21b8a01a8c081694d03b5150084885f4e24049b4e2ab3863da", + "0x14e96eaea3fe5661ce6de945b192f99af26ad531a1e2553d1b234bc9aa7fce" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x7439fa2099e580000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f764ab" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x46b4ac106ca08577bd677c9d54ff7412891f2b17769b5b2b5f30731c40cf00f", + "0xb985924fb1fb9144c50317454c3f88a4373ec8b6cf3f276aeef35f59cef533" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x2528", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xdd05e5a96a5f481eaa433013841a6573" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x225494cac10af52e349c256d5a266c19c650c1ce00410e0ebdb7d7b059c158d", + "0x781070eb7186972cd59e3d01671bb970db8ab731c73ed467d1e298353d8e09c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x2526", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x956f3efd83924a4aa2a238d7cbc98790" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x3504185e29541722fce0fa097a297238c3801a5616f715d4adccb581504950b", + "0xdb2b976f2b03021eda5135ae203524764d1807c63e575d71de267a22223c57" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x252b", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xfbe722a390454fb491e1a0e9c60778fd" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7a32454eff810a280cfebdd4dd819cd828450ff8a57085009235e395876a2c9", + "0x4d743fbb0eb5eab8de1ea4f96e6510b6ed67d6583c5b8521122d5d9ba86abe2" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x253c", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x9a6a6a921581411d866227ac60469f0f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x53e5515ab16837701b3d26d47a3a1252bbc56261ea0816abbe53e294259dc4f", + "0x13475b4fa8da44a4acfc53a8a9c7207c97823d905f07b09a21d87afe1511085" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x251a", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x5158e4d67b014874904fab686cfe892f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x70de89accb27b197d55b99b33200301cb813b2e8a474da07a49bd8d5f733e69", + "0x714a2659d49ef7befd37be0f063e4525fccdd389a23d17391c0dcb22cf4cb48" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x202c7a5d65db6e132dc60f658f68e7a191e2032837ceec65b433f3f1eed7d84", + "0x2524", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x39b5caadd4b7414e85589fdc76cab479" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x31da92cf5f54bcb81b447e219e2b791b23f3052d12b6c9abd04ff2e5626576", + "contract_address_salt": "0x31b14a54343c56c18d206b0c7b1e0e9543c94ef85493a0cca519634f520a69c", + "constructor_calldata": [ + "0x418916a80e5e10a0b7d7cbd958cdf1c790285c59af873efd8bd2439ec65bfda", + "0x34086d0388c307c9190e3d4b8da8192633c6424a942f1b314c371385f67a71d" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x596c96f5ba340a7ceaa4126c9c34c788b4469fa4b31997b00beff6eebf042a9", + "0x29fe8dd49406d8eb375e0b65e4851d388aafe2d7a3e02e302b127ce8b2696c2" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x0", + "0x7439fa2099e580000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f766fe" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1d46ca40a575db6fa9381ba0d7bc2cc01ac9c4967ca37e0ae40bace15c3ecb1", + "entry_point_selector": "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "calldata": [ + "0x31d203dceb3b6ae381e2a6d371b214195ae164eb4a0ff0261cec858df1218f2", + "0x3aa260d24ef29ad3172755072abefd38871a19d3e06e9846293e1f916502b2f", + "0x233aa83a08148ff21d1c022257168c84843e3f0da96d609aeb55726bc5bb5e8" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2e3882aa1aefb56fcbb6152e48b979d5faf6e7eb2ffba5f4af8c7a30cc1b57", + "0x4066e7827cc9719ec2fa6afdc85e6fd886a3f5d72fc6c4d81bc767785eb0483" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xfb7aeaf2be3776ae8ae718c11e01d2b499cb9155199c20a2b5e58812f68ede", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76a96" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xf9f274821fab72891adddc510d7484f803d7bd31f840de8f8a187c2ccb8b77", + "0x32942663307377c541b69c42cdd84f9c05c094080b065a396b57026675abad0" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x4931ac2997bd913df5d050af645da8ab3ecfaac3c4649604e2e107024cbaf48", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76ad6" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2e92c554b6fc3a47a9a0ba41943cd4756bd9c40dfefcd207d7d1a9c50d78f3c", + "0xb967140e65350729e427af81fa22d21c3fe1bdb916ce463470c0b142fbaf0f" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5e9aa0273aa08d49089783a4aa426e8ce61dbf4ef4cc9822f2b5636e11350a0", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76ad6" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x2ba4213bb7f2d1980fe590b6a4151570414ffe2cb1adef79e52f0c7eddf638c", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x2ed40111307b6d527147f60053a6f8e32b53ef63a18eb8ca842952ec29467b9", + "0x2", + "0x30eb86f8620bd5a0787ee160e01293ea5facc2fa557b33b3c0069706247cf4a", + "0x30bc0764c6d6a06b1373c634dffb73aeef2db68bd8be15e28ddbe3e50976b00" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6b5417698dcb1242743c007daa6818d0550d550baa3481bb9cefef0a4338275", + "0x52a340550ba33a9a9314cf16d94005af29f683cbc82e5c1cadea919d39c041" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x54b5ee812d259c836e2753ed75e6b91ac9678bca21313d9a0e4bba626768ed0", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76d07" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x49914757c2e8c54b2620d67c58b403e21cbd8f91d421652a93357810f6c45c8", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x9a7ae073dcb311ddc7883ec991e53192badce6546b0e7b145b7a112ef2744", + "0x1" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x58c5e5ac7437e1d03682402e87a54de02054f79d7e6bc22877457cec24a0b05", + "0x4b3997530aafbc15dc026954393906254ade60164aedf9f6883ac6cb370d02e" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x166d", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x7f4ec9976dde4b618a8c938ef5c10878" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x49f09127d0d0485dae1830d3f233e0b5e884286c65fe91f23081470437af9c9", + "0x4aa7f3d04425e6b011985ad064a28d997e142a224b46a29a4b6264f0c25e515" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76eea" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x60c722491ee4e7b90efacaaf6b15d772d17d538edc8acc3553e188d2eb5613b", + "0x72cde47949287265475a8a814414de55e4c969fbb4e6337e5c4a5e63c31592" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x6118e2ccd833cd831c61f1161f77201ea48e843cf70cbd261c8049f1d97ed43", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76eea" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4ee81302efe2cfcdb2ae4838c2bbb536282e5065180e38569433845fb3f3ad7", + "0x247102bb7687dacfddd052bfb7de099acc85de54e4cdb5d8db4eec142622abc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5d7f3182056c9633d437f58738a646f0a40aecf210a289d72915a0f90b33330", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76f66" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x118fc0aad496faf489170721bc877a486fda96712edd5e918794a59ce4f2c4a", + "0x79b5f404ed898b9d8b16a171055b3c212f2fef37316984f10988e909e4d7b8e" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x7491926fec76bcb95a45f8adbffa831e74e7d2a98b3f8430c2379f1c2b52bb3", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76f8f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5e6a7f5719d045f44a5fbb032f6f67aeb5c4ebc05416c9de54978bc200e6a94", + "0x4d90b4ecdf99f1aad2b15036732b86a539326da1206e55f891c3d1c9a5bbf2f" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x1858", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x885176860c3c42a6978064f944c88a63" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7d839f88233c2898d63e85f720a77467cae49f0d84f41d787273b30e62c339d", + "0x55186ced9cb60658037509f96f9a773f128a597e8763e9df9a1fc37338c6602" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x7808b7fda151be6b5784b2a340bf7fb1194675266da8d76df2edcfb74ed018d", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f76fd3" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x27163442aa136d3305d49e25a2e501e2d5e318bd08847ab1657121e3bd2f87c", + "0x2c5287148148d67562c20c34547d1c937feed5a0577cd25f2f31dedc6f86fc9" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x112f", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xc7242927226442e29e1d3d9b7f3ea0c7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4c2f7af56254754e4294156ca54474081180c439375727b1ae2354108d4ac0f", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x3adc3db8d9eef3c2d64dc98f79749f77e1d0cb73d6731ba5173a4dbda730618", + "0x2", + "0x68a03e4dd6402f01f44cb8013a8a55f440fe43364f616e5a0ab184fbcfd6c02", + "0x7128e5d2970e061165c2c4801999738c3bfc8642149654fe607abb1b46dfcd4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x9aedb6b554fb208961f0d18e2006d59431567ddaae15dda95b42274cf60cdc", + "0x90a1c14e3694fb37c4d7d36730eb5bf3736b02187e63c027404cd725a3cd73" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77020" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x50dcf1243e4a3b59003a537d61f91e36a196cc5ab7e1e69a11b35eea0d0ba3e", + "0x33b4a413a22a1a91e7397818946c3c6e54bfa450c86109d4eef5174968025bb" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0xa7669bd7132640000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7702f" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x193e6c362667b41af57fbf1bee82c0e462ac2e7ebbb5209c6edd687ada947db", + "0x4961ef38a7427675cda830e1155518beb4ef0cdfa6517986a552e59564cb12f" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x1145fe5ac1a8ae349fbd784e47ac2e91340cef5204ed3a13f5df8a44495ab13", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f77030" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2d11968002b8568447623099a8260a038c57239c04dae5ac6c28d2f93e62add", + "0x46831bb9da07c5bda8a72e920f96854a3bc6811a449ee288203c7bb8c1816cc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x13f4a3b5617892783e4a8acb28c2be5fd2232f26f4d06b3b38703a4263602fe", + "0x0", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77040" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5e692c6efee2427b6b5f272f976a6fad3874a0a805b703d04cf599c0d65089f", + "0x5cf656a91fbf52ad092cb94670808056b1d625e2e110283045a60305fe355f4" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x18a7c85416f382f7101c69ce5e904dafe7b4adf6fde57fccf9e477786bdb2a4", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f7704d" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5ff1423f1f519e349f86b85571872c08992a5eb906fb0cd97d71afb430add76", + "0x2f6661777cf4db3e92d60e551a03f1d67a62265e15d31310aedc9ab07356619" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x41054b602b826fe737fcb0b8b1f405bc1dc2f82dc93aadc3fcc8c027a703a33", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f77096" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x213d4df5836a815ca479e5584674f6116672a5f4cd7a9939954915e27e6e8fc", + "0x17676896c9f1b319672a7da4ebedd7ebab946104bbc1301a7fc410102ce943d" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x44e4e113301f3979fa95874f3b4dbfc7aac9baf5360474070351cd9c4067e03", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f770d7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x9e34d4b019b86ccb34ab38b5f50cde248f412d34388de1a45db578f0e9db8f", + "0x5e5d3cac3d2d0c1c91cf24a5bbd828d95ed2abc5e98885387069cc01c8f3f97" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xfa7771129a5552e3bc3f0bc1abe58050363780761e25e3a0e1adbc14b49af0", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f770d8" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5b643e90c88780dd367e35a0f17e2067c7fcd6995a5d9ff8021b945d339d26b", + "0x1c5a58be2af6b65b05a550c9fd97a5c1f8248f8842e942e3ca9c9975158f8d5" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x3bfa0e91f91536ca2fe664d9c0bc096d72281c99677eaf8fb3644851a8e7eee", + "0x0", + "0x40ac336b3711040000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f770de" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4ca88f1947af71bf13f87ea1250a115249ac3018d119720ba31d8715b5774d3", + "0x78f5193991612f0011b1fedb170414f544e4938b875b2e4386ffb92619ecdcc" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x28790750dfbf96c4c90112861aa57d54ec7f2f72a732a97ce90d69d1a2548c", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f770f7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x1c2db03e7f92730a38b85a26ddcd97a13c53771874b66aafcedd1a7de289b6b", + "0x7a19f02d5e2082b50fafe64c7c42de9bf587ab79947ae9f9f61b109581d21e" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x28790750dfbf96c4c90112861aa57d54ec7f2f72a732a97ce90d69d1a2548c", + "0x8d614546394ac0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f770fa" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x291e966b672c6c5eff68ef9e4aa420d302854bd951acec4bbe21e40bfb256c1", + "0x6a57dadaa35e0468191ba22205dcd07809a30fdcd31cd08d7ccf36323b0b23a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x28790750dfbf96c4c90112861aa57d54ec7f2f72a732a97ce90d69d1a2548c", + "0x0", + "0x3f0bde0229734c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f770ff" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x191c2d538c5d5071d7439fdf8b8896559e34c8cedeb80e15c35cf01f6755185", + "0x6e58798a71e5d7464972f4c2e93bcd82e63bc6d5f0b9e674e81b64e609874d6" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x21654849d9385101af5c2680797abb7b5a71e50cfd09935760fbd743875e46e", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771ab" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x71c255b170875c8195ad8291d30be8985ec13189e7c522bd24279be073084f6", + "0xe83b8f457a82fce86450e4ae73c5284f96c364b2b9a4866eab9b7a47b37a68" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x21654849d9385101af5c2680797abb7b5a71e50cfd09935760fbd743875e46e", + "0x7ce66c50e28400000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771b0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x366436fabbf683e90b638aa88afa1416403e6784840359bad48e6f0375893d5", + "0x49b6802265ad47fb6aefef8e48aba2a5cb3dbbfac93119a480286bfe3e207b9" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x21654849d9385101af5c2680797abb7b5a71e50cfd09935760fbd743875e46e", + "0x0", + "0x7ae4f1e8eb528c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771b4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x93f57bd7ae4edec23c0a9b7bbcda8f1618bb7b2eb36ba63ced40d7c7a2660b", + "0x355fc313e2833db1d8ca8c437dea76d5f627300d4ee35f062d2223442836866" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x26a6c236233ae2c21eb414c59e005a91f99d3131498ed96808d97f1a18fe9a1", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f771c2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xccfb72c2d0f5f0c0a1ad8085ce08a3d5301987f337b8b4aa14544b250e1314", + "0x7ddc895d87cd0e8a51b5f9a68db61c8c21d0db43c463f57cf641716fb2a5869" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x7a9d193025ad9161b5d29f10aa70970931e8eb28a0ab3645e811f7dec7194a3", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771e4" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6f13121ec8798db280918c051abd2627817ad79ea3328bffdd46fe289f26e3d", + "0x5ed1d9eae7deae10b8aa028303a1c585303e50bf4824dab39bdb8047728c19d" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x1f138b6e98fa2b7de46269164e8add4a5972a5e8f73aa750f2a0e7bf5f2011c", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f771e5" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x1508f23f91a4a11e6377103a02a39a6b57e0811b5008444e8e3d1263a09f239", + "0x30f4535960892e3994acaf91be64932e0f3cea9e698643f790665920a0bc2bd" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x7a9d193025ad9161b5d29f10aa70970931e8eb28a0ab3645e811f7dec7194a3", + "0x63bf212b431ec0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771e8" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5dc23ff12a27fcacf78ffadea30c9ce038e34edf6fd0849dbc69a43db5961c6", + "0x1c83db28dd47064b0f0ff9948e5c2eb438ea67a85490af13fe23ea841ae3adf" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x7a9d193025ad9161b5d29f10aa70970931e8eb28a0ab3645e811f7dec7194a3", + "0x0", + "0x3c71bbc07a108c0000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f771eb" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x73238bdc96e228218b5f7f9a9f1f54e3c6b90e2974a457d607e074129a3ab68", + "entry_point_selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "calldata": [ + "0x1ae7051ac08ee220947cd50869fdd13792d078dbb9dca13301ef074ca7df919", + "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "0x3", + "0x585182034834ff3a477df45110096f4351026e48d686d1d074384edad20d9f", + "0x39fb545e19178cd564a7ee09848af70c3ac7d2d862509e3ebd4cb6e61ad5aa0", + "0x21495a80fac8c2c227c19bd8d9632b5b52d88857b231eff0e4fc321c0c4e820" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x23aa3ee14a546299efa8ac1a270d456eb634f8e828341a926bfcf5e1f2c979b", + "0x7a1a5ef7e046fbc9d4f85051af9f3fdb2cb659e2805c7e234381d9839e53403" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x5233b1468c3541463e0e768398912e0d4c7c7906f5ed5733511043bd19e2185", + "0x0", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f77407" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5e0ce4f78d65e8c5ccf8bd1a841916583291d40ee0aa615d1b9411930641b33", + "0x6fc52c6d0898dd0356b75e36246fc6c813d1fa5f015993ce25b5bf24f5727" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x70205b6c0c6330c2c03d3e4e7358a2d9d438df03fcfe7f80945fc89d68bb7b7", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x61f77496" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3539d81a2d889a1bdb5489e1c26bf8da7ddc66210481261658d1dd72e95500d", + "entry_point_selector": "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "calldata": [ + "0x307ee93f3d95b1964d09ea5252851c19b61a9cb841b1da21e3662d00743c5c3", + "0x66ae7638cd1c6b6a337ec0c4c8b501405419cd9e61caffcf5b39f03deebbfbe", + "0x25347a1184acef1bef94b9856b6e1ec52ba220c1ad4857d060f87c5bdd440ad" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6876a52d41b8ceb7770789c95420a82a322349524799f80cd01d6553b05ded4", + "0x34ec01e109cf1013ec315d96187fe6c0deec319c85107f42ca469232cb8a415" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x2d0bb702e40e645468b34f0f7d1bab4212d5e8231c662ecc2966ba2d8ae0761", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77570" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x3619f860f7360c4c1025be17aa06415e87ca1e7785f61b41bf990cb1922ab8c", + "0x5a8e32c8464cdeec8605258f45fc9a7dd55fbf035d8c46f3d8fe9bafa28444a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x2d0bb702e40e645468b34f0f7d1bab4212d5e8231c662ecc2966ba2d8ae0761", + "0x579a814e10a740000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77574" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4891201d8495184ff1e70052a24a901751331ca2665747141cf53a5c8c76174", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x2de8a3b7d8e145038eb5b0eda3cb202f332e2eb782d2dac4658f62d21c73cae", + "0x2", + "0x1a9ebda1874ff07323be586aa2b891e35a03d7e7e71223c492384e03e3e6787", + "0x5ec7bc359c01b80ab616c9f4fae399252972f167f3ce8fcfa35fd5d2be8ab46" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2d7d0589a68743efdd242a2d7ea6187d2f86796d33c78f06579eaad4582e947", + "0x3d8f2cb1c7401e762a0a4819cb0c5a6f556f0fed145fe5721a6e10be3491804" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x1755", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xfc62eccad1064e928066fae6966866fd" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6a1021f80a383d446d70c7e1b48ea7467dccdac49c60445acbbf3b9c669f751", + "0x178133652faf3b1e4f7d48ab35b2441a08ee42c0045914b6ef49fdc4892b685" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x1ad1", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0xe09cefb6b4d146d8833694b1714f0b0a" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x387c1d3ab6659af6e45b13d06a1056a7983b887281d183cc8f532cfb82fb621", + "0x630a24911e435f863c0e969a3903bd987c0efac459b4cb650fbd5cb3b63130d" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x2d0bb702e40e645468b34f0f7d1bab4212d5e8231c662ecc2966ba2d8ae0761", + "0x0", + "0x3baf71c2a6e9140000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f7793e" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x190f55009b2057ac6a02b25a00b0d22ef5a1b525de3270855afe3606cdfe5a1", + "0x48c6e6cac04581aea0468fe6c88e398c4ba449549582022ac7cca0e26633fdb" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "calldata": [ + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0xe57", + "0xa0c316cb0bb0c9632315ddc8f49c7921f2c80daa", + "0x95a7caa72b7e4658ad50a75da564ce49" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x7522b44cacf54404335b7853632400933075b2f6e8bd67a812356964c7b818c", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x349adfd096ef67fdd7aed1ae4234219568377521a89c6552bc0557287bc2c14", + "0x2" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6853589585f24d32061dd64fa1cf5c34cfd607473239f2e9d291ac6a4969fcb", + "0x251fb20a739487fb16c40d99749ac018024067474fd15b86ba769dfee00c7be" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x65d0a2db34bba93f7c7661fe3271489cbe92ae1fb2190a2d3adc7a783e640d2", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f779b6" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x5b42d8ce0a95603def172e694db9e4eacc3ef5f5a50ce189f3877be34bea355", + "0x1e9377cb2bdfd8fb0689dcd44abd6df53f441f801567f957a6dd47efa4d0ccb" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x65d0a2db34bba93f7c7661fe3271489cbe92ae1fb2190a2d3adc7a783e640d2", + "0xa844a7424d9c80000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f779bc" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6f3ae421e5b55f90ad31aecc463779b570c26e72e1b9f468b05eb38e2c78c6c", + "0x5c2dff1bfda53e6c2b2370c81f784dd54480f1c92dc2a64fd9cd4f83c193672" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x65d0a2db34bba93f7c7661fe3271489cbe92ae1fb2190a2d3adc7a783e640d2", + "0x0", + "0x40ba1421eab8680000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f779c7" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6ebf21abe68931aa138731513c9efa28932e2e19860216238a33a983f7dced7", + "0x4d0510efd7a5ee187168f76f560923ed3e86bda55af48cab7b6f27025a517bb" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77a5c" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x3a68278cc2ed51be1497160babeab64c03842e5b0e6a165f824ea9743ab39a7", + "0x525ab748415ee7babef4171b0baf603298fa5e249e58eba7498a3894237f84c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6fcfd936daf886ecc44dddd9b9e707cf78f6e5ac9fe1e75afc3c4622948a89a", + "0x0", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77a62" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x7c7906c5394b886cfc3f52dad9056c8a52052bd722b5ab02d82036f1e944cc9", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x2747b554f697831d1ed54a3b193bc6a0b5ad331555efed9c55312dcab2e4184", + "0x2", + "0x4bec04375caa49c1aaaee5eff1aac05c30b32dab7ef43372ba40459f4277032", + "0x12e9e25277b9f4efcdf8df9c70d12e809474fb23a2fa211b17f7910c69e909b" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x10049b9e8e07a1692923dfbc88bee71add8e9577a0d6f6e7da22f841438708f", + "0x71424d4b8571dba7b053c780b35974f311baa82bdc8aaf365d8c307fc53f259" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5a65c0be62daa4b4e3da2c863db1fab3e0818b08067803194fb57f0db2f4d75", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77bf6" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x77930cebe8d1405d4ace93a23a6336834635d4639948f5a6ccb37799e11f315", + "0x6b04197f77f1078bfa31d785951aa326fb3aab6e695f7842eb1c8f11ba26148" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5a65c0be62daa4b4e3da2c863db1fab3e0818b08067803194fb57f0db2f4d75", + "0x6fe3c108759640000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77bfa" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4937347aff604dae7942f72d0e1ed7d807f1db4d91f2d2e08f3056856a2467c", + "0x10d0f814d661c4e484a62f52b439582c14a427d58c08f425163d986321f09a1" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x5a65c0be62daa4b4e3da2c863db1fab3e0818b08067803194fb57f0db2f4d75", + "0x0", + "0x3d3405be4d38040000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77c02" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x31672264dc63859c4534a8eb33f47efe29e11f119a824502a5863b428b81de4", + "0x5b8f9022a2815a98f020b1d35aba790021bbb2c55f24daae6938bdbc8c9ed4c" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xa8ab1e8efc5dbee6f0937b257f7c423e9ef3f1f32acdfcec7218b2bfe135a2", + "0x3635c9adc5dea00000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77c34" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xe76a6a903aa7ed97131d0b67c8bf15fb3c17178a2c73404ba0f99ddcb995e1", + "0x488fd1d7420d20e33aff579eb536c3f9b2e94638e28e76326dbf3fef4f0d66b" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0xa8ab1e8efc5dbee6f0937b257f7c423e9ef3f1f32acdfcec7218b2bfe135a2", + "0x649d2c967d9500000", + "0x8df3def6e79044379456207659cf89a628a7527f", + "0x61f77c39" + ] + } + } + } + ], + "transaction_outputs": [ + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 443, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 11 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 245, + "builtin_instance_counter": { + "pedersen_builtin_applications": 4, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 6 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x2f7848b4eb83a758682f748dcad4617aa171cc40f976616eb7b3671d9183992", + "to_address": "0xeee4fecd206515a6c56caa9ca30aed1cf38cd7ee", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 443, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 443, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 249, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 6, + "pedersen_builtin_applications": 4, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 178, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 11 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 443, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 11, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x734c83d8c2fa72e781f0030b4906720485e6a1291bf5258e3065f8e03f97a19", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 29, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 180, + "builtin_instance_counter": { + "bitwise_builtin_applications": 2, + "range_check_builtin_applications": 6, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 169, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x49914757c2e8c54b2620d67c58b403e21cbd8f91d421652a93357810f6c45c8", + "to_address": "0x1", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 332, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "range_check_builtin_applications": 13, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 169, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 216, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 7, + "bitwise_builtin_applications": 2, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 533, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 541, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 180, + "builtin_instance_counter": { + "range_check_builtin_applications": 6, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 2, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 169, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 441, + "builtin_instance_counter": { + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 447, + "builtin_instance_counter": { + "range_check_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 11, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 445, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 13, + "pedersen_builtin_applications": 11 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x7522b44cacf54404335b7853632400933075b2f6e8bd67a812356964c7b818c", + "to_address": "0x1", + "payload": [ + "0xc", + "0x22" + ] + }, + { + "from_address": "0x7522b44cacf54404335b7853632400933075b2f6e8bd67a812356964c7b818c", + "to_address": "0x2", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 426, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 531, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 165, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "range_check_builtin_applications": 7 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 539, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 535, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + } + ], + "transaction_hashes": [ + "0x5a35a38d5a3c05dc0963641211506ee9518a1b008a49930cbcb762a09539d95", + "0x3390f9cffc5c30d6a760d75153f7cac98480ade8c6cf0b6e3476c0e588793f5", + "0x6f2b37bb1156c6c8cd8be02891c3581d620990e0ce8943ed6052f66ea3dfcd3", + "0x375c7204c56cd85a8b886a7285c03e70341513b0bcfdd211a852384facd5a69", + "0x7403dea259abd42d1313480cc076e169ea5b97a5cd104e33cbb7052ba2f0153", + "0x8c6edd917b38da0594bcc02ed7f70fc377bea37a7297d70c56e933760749b0", + "0x6559e2ff031150a85668006203d8b9bf662e3b4fe92a7845497e3084f9b1d51", + "0x51984d09cff88d6872da974b10039a551345e64b33e9525901bbf83c7e8775c", + "0x32f00b8cdd73c9634494699e029015fae0970521d2da9c83877a7cbbdd50b35", + "0x60a05a0c5b5e88e1ddf06b9a86aaa8fdada13a4c34cee0cb6ff6a1b9aa43dbb", + "0x1697af77119d43b38a16a1ec9923b03e1cdebff89df52ee238b39aa1130b8d0", + "0x1733914b5c09067d46d04f3b609eb63ff818aa636c184a84b8628a4421a2fe1", + "0x9f353294e224f700e1fdc446d87ae3cea680de69250859db53aa96d1d75e81", + "0x486f50e8d6629667dc3b2d9fa57a750ae7614ceea4bbdaa4dd91133d27e6d6", + "0x1663f789e47cbf54eb1f8af43d1b2183f765a0cb57495eb8a5f10b976bd42a", + "0x75a6c3fb728b83de0f1bcc87cfebc5aeb427060553adde23dc865e96ffba13a", + "0x5ed119fb12fca30ea76ee841367f06ec26d3286ffcd6a367dce13e374f47f59", + "0x558ce4cc7183c6678a6738568bbeb20687875cc56bbcc1f9a246d80e2d30c5d", + "0x7727cad8aaad43e8d76e6a63a978b2ded6346bd342cecf13b31c63edc8c7d6d", + "0x3155e1e91662ee2aa6ffad006a3d8b45b976cecf07379a7db20524f0df15497", + "0x15b17794c65a0a54da2016f39bffd33c879b6349a8d2c69c13027dc6df535d9", + "0x7c6f7cf48f8526cd4f439c0fbf268760b758012f9dab0d68092ef4fb0e4fef7", + "0x6016fc7bd3494597e8d6fc02cb218e9f28333afa3613bada47e032dce6914e", + "0x430b6df8273ff706777b8b15903e1a7f6417dde343aaef550e6fcddcb2aaefc", + "0x4e4a5c5125b1447293716cbbb7011f9b251f425770660bbf9e8496926c95f88", + "0x25359573aa9964db79b489fd1e1ed0d4373c82c3fd1582d39932b47d7a86f10", + "0x48fb4d7b30e6d33654e8a6546f308f3885111e8ae677445673c35840f4f4add", + "0x26eb4ba885bcc38a3a918cd11de953b538bec5be8432fc1776f0074eedc0c59", + "0x33049424b25a6861eed1a9d7d4d2f15d059989a38e02e74db7d096222dea7ab", + "0x130ae2ea41d8e64720dcee0850871604fbd8728e97a0017efcc4a65447c93e4", + "0x4d0e420beab09228df0762125287ec258f18b6a17942a990933fd7f38dbd1da", + "0x5e7a80fc361a9a8b51730bf9dcb0a35d4ad47b04b7b358a0311ca7416bdd4fe", + "0xb473a5d31ce50aa6d4474c7dd6035aa50359459721a94031b577e44e07a1a2", + "0xdd0a501c4163a64703664d1a0744c565fc0bd2cb64d0c916916288ffdbdfcb", + "0x60a643260f9964108b0ca7eb2b188245790a41cc01f7351eadef207417bdee0", + "0x39b9433624070ef24a81acfba79b3f8bc6064e32da137ae3ae99d83242566c7", + "0x52747b768fa38f0913f18a90aedf59d5fbb32026b72a55da33fff73c85bb315", + "0x2e9ed1e96cf81dc73bd41305bca47d74e745c1d1d7a592a7cd70d6813fa5a74", + "0x55efa068743a71f5aef2b3d8483491704cdf99bf7894501492025967f3b7973", + "0x2d96179cf82f298e9f8b55cd4f5d8f004d89919651012b93b352469b194c857", + "0x4b0680402ba98589ed2e129410d0b33e8fcbfc267327ae56420f5ba13aee4ea", + "0x37666e15499dd303c68e11c72c3617d9a1869258fa2bccc7e2238c939191306", + "0x24a48c25fd752a34e2ccf040e38ae42f82ad1e44371172abd82e5f121df856e", + "0x6d1a84b7d638aa2f287b4c7a985aa770fc830e28a1253f21bbf4666a39d82ed", + "0x401e98d289a1fbbf4b543ef191cc1f1c1e50a863b7ad848ac0ecd3d2e04b708", + "0x684d1168903c3b159c4eb33a5b98d4e56792642346b6357c251b968c9dbdbdf", + "0x51243c4adedc0c87c86e3c8269754ce00f78f5126022f550cdaf9bcd808a00f", + "0x5493292205c08c1cac5b301b428c0aee44670ce9e98cb9bab20e73b490db62b", + "0x7ce40c8b935705ba45ec21b2c64eb7c6788d14bb6991e4747cce23f8137cb90", + "0x3c540dc90e083570dc3c2be3584542c778ade24035c862dae98a2bc8814a60c", + "0x65d5f6b72491733c6b8c1afdedf10be4839d2bf9e9350168094e0bc43370d9", + "0x1cf6ef7345fba4a2e18cb2d73e858ee5c6fc604454f99e8415ffa06b4ecde66", + "0xa28ee486f362c88f670aa32f3f4f8aaf17f12672a2f65109fab98e7deaf017", + "0xb5f2cd72c6096b72abf995844144d88abf43a7c71519a2f1ffe5850fe95aa2", + "0x3d6beb00f93edfe37ba562b61859fa79453abd4936418f1d63199c6b34e7086", + "0x64c1ae8ec6b2427d72d8c93c158d30f39fcc554348e87ef23227b0a1c6cf790", + "0x640ad8ebf19d0dc20c8aef60c18bb5ee525835ae3cc997d8ec062e98ecd7859", + "0x61ff8d49cf71a534f66c2464e17da34420ed624e7d04eaaed4e7ff5a2c3f091", + "0x317b849a5a5fbd68613b2bf0ce1c486a51dde34ebbcb7f44c663fdaad026297", + "0x35715e67f2244ed572815675170dc3c4d0166232384f245aefd305a3f5d44ed", + "0x9fc3967b52b007c7b1957775b9bf27b6ac69016f73ae4faec0e9be90e56318", + "0x560763c44cd04686111e2847a0a0fe33add0ebf1967933ace1b4d2f2ae56ede", + "0x4b4cc9eefb7688b8e7d147e4af5f619f3b3e3229dc9d535335db4f3cca0ccf7", + "0x18fcef5f1a3943cf4a19d07bf1b8d39412fbd0e02fb15a25ef82fb4623b6196", + "0x70240ac10c30f8fc1edc8450d523fecc3d5213a6c69e1ca9478f7f6468586f7", + "0x1218460c5e3175b2abbc0c7ab433bc6374188157e8c9e365bff3a65766e7e1c", + "0x66c7bd2f7be75eaf1f68e1b95c48bcc6c308d1250810e0c254b0acf0b5c838a", + "0x3ba0553c408ed8f8b637183876987bbbc8f9f140eddd8631755866a9788a556", + "0x6b6457eeda7d0be209d5ce85cbba73d4835fd0601b1d4d90e6d65d31a16e7f3", + "0x3016abf4b3eb022820aba72c0d05f687bb0db842d752b61fd0f21c22f666227", + "0xcc90dbab7d209f7a02f8fcaf0f4f6279cdf605e3b494be981e67ee0863caf1", + "0x30bb46cac12831adff5c252a043b1dde1513b8970eae3b07fa6da0f223b730a", + "0x7cd41dd714c52a0f49abefa862ad1366e5f7c37264191faf94e859d083161f0", + "0x702039365c0496db23ac9e6f01acdafbb56f73456651e7a1c66d9f668eae963", + "0x49da784c5ad64e873b70e5dc1c876620c6b4b70e6d7e79a80422a5c46ff1ff1", + "0x2f289b25ea1569faf8a5b6d8f701df1be6a0eea559c148bae2968712dd876b1", + "0x42c48653233164bf39b2e14528bd0494b746e08b15f08bf41c868f125555290", + "0x390118608430876a0f831763e60d8e9542b3b077c56ca554a93725d8e3bebfd", + "0x34b810d0e271f647a779cee1caa7dc69956f715c2094a760fef7af80d106a85", + "0x690d729e92b62eefefd6a58a3e1d92979b1679393ad6eefbdf66a09cb25e4a7", + "0x5fe9c14a2ade4c9c591a5cdb2084952fa3c7381d940a072c940f42165266157", + "0x36755d88da7b9b6556da1c138a997ad600beac5d77f48e8b5294e9c3797f425", + "0x63958e70f8cbbba282dfdc47df109d5021f5d83ec8ba6521f99edea0d13aac2", + "0x7b9a83d4e67e9609a83c11dda9e0cc9d200895fb187aac77f606d44b8ab370f", + "0x4108d0fdc833f37f1d81b87732ff631263a9c343b3a11c51c5b256292659dc1", + "0x819078317d43863d4a396d25494215e44756251772fbd4be4dee1eb3efcd11", + "0x3c1c33a2bc3efea6fe0c57678c3d87c0fd6d1c8ceadcc4745ac25c4cab82bd7", + "0x26caf8129460e77b9dc9ef93f2424ced9a817827dae0e550d78adeeb5c07578", + "0x2f8d2c332cde85fe91466aad077c1a446034f38ea3c46bb5111fdab55dd7e3a", + "0x35cff6564d666d13c9389ea30f2895035c665eded365721bb35e63c054f05fc", + "0x712e16d2703b665388a675c495daa579e5bcd2487278cd116238682454b3584", + "0x4ca1a7757123cf15af97eefde680fc51a5bb964ef8bfddc9b9cd44760840569", + "0x37af2caf724593c0f51b37b7bc61d398a172e628b955b2e29d121eff265f3e0", + "0x237d56e4f1e3a1eb3c934f6107b5066e18e17e78ec1f6e1388f55bb67d8c0bd", + "0x63e37e9bf351ebeae9f1066de3f76315a0f1aacbeaa1509f867051a3130ff1d", + "0x3acf9b17f23f4a617e25906e398575f4f144bbb41cc5683a78929573be2c2a0", + "0x3b1aa1b55e47c01bd636e72ba9a6525d7829026b7f58bbb32a3cd87ad79e6fb", + "0x2dd58d2d23ed47bbe4378c4039c45aaeacfbf5cc8ce49ce14af09181526041c", + "0x672a10d971a940523d563442331b73c1234b72978f54b8bb3c5f3872b7b1d08", + "0x36a586da3d8e481767f3dbbc0f808d49722a2daaff0545159fcc7c55a053624", + "0x5ba2e197b3c66d17c555f4c06641dfccbd300fd09b811d81ac5342b4086274", + "0xe882e2d7358995c4f6e3fbe923ab62c4fef1c04ba373a86937bd295d5ab8f0", + "0x39d159e064bb4a3c4e38992a4352e8d57a9fdcd0ff121f4caa75d6e4f2f5d5", + "0x4db3c69e5c3edcff331baafa835022da1ee67bad15ce4dded9906b3bd77b061", + "0x1ce117174fff65adb293fd919928478043b04c3ebab820d16a40358eccab928", + "0x185f73d056960f56769b34515444a7af2f39bedc2ce2916a3431926f518a9a1", + "0x66b31e60bf9e89e90cf65fbda49534e3a47b7a33e01f95d387b2eb9f8cd9809", + "0x28d7a9f3c1fc076062d89d64e585fc37cc3e76e895094925f77c27835b9ede8", + "0x5a7bb642e83636b9b5f8745d074844aba74d4a21f019b8fbb0494f6ba85ec3e", + "0x912170b6c5b0454e66fb8dab8da03f8cd9a32acfe9df6690d05dcdca19e52", + "0x4822394e8699126997fbdc7d4427926e01876e19970fadbfa0307653ec53e47" + ] + } +} diff --git a/crates/papyrus_common/resources/deprecated_block_hash_v2.json b/crates/papyrus_common/resources/deprecated_block_hash_v2.json new file mode 100644 index 00000000000..d509716b6df --- /dev/null +++ b/crates/papyrus_common/resources/deprecated_block_hash_v2.json @@ -0,0 +1,7644 @@ +{ + "header": { + "block_hash": "0x1bd1f64828cf2aff0023881344e63f982494b220d5d27057994864680a7f946", + "parent_hash": "0x4ea8578693532db895a0b2117a8561aa2f062d31898b6bc39cca0f2507f4820", + "block_number": 2242, + "l1_gas_price": { + "price_in_fri": "0x0", + "price_in_wei": "0x38ae2e27b" + }, + "l1_data_gas_price": { + "price_in_fri": "0x1", + "price_in_wei": "0x1" + }, + "state_root": "0x67d06ffd8b41a4a4d4bbe0b6f991760e365aa499add0180b7ee52c0d6b67843", + "sequencer": "0x0", + "timestamp": 1652680274, + "l1_da_mode": "CALLDATA", + "transaction_commitment": "0x04d94f068f4ed885b4df1c88c7630d7a8d7fb5eb2293a3b302f94d291aff4d0e", + "event_commitment": "0x05a778a5ae9b99428744b982fdb13c4cf5f08db15694c74ce0133c88faf26ba9", + "state_diff_commitment": "0x0", + "n_transactions": 171, + "n_events": 36, + "starknet_version": "" + }, + "body": { + "transactions": [ + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7d46ccf844ff699f50efbd4dc723a6ffcc0c2a2aea833748647b05214c1bf6d", + "0x2e76863044c53914d7a6742c6c8051c970b2cd2801802dd4422345149b29607" + ], + "contract_address": "0x7420ea6ddb8758de13f77a8dac5c2b130c451e2b9ccdf273f5a1f5bf790d64a", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "0xe48e45e0642d5f170bb832c637926f4c85b77d555848b693304600c4275f26", + "0x0", + "0x3", + "0x3", + "0xd03db443721db1a014e4b7a47c6f91fdb279fad6", + "0x174876e800", + "0x0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0xc0c8f75f1a53790b0d0e72d46f1e01d21efe673156eec7fb704d0c726cf29b", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0xc0c8f75f1a53790b0d0e72d46f1e01d21efe673156eec7fb704d0c726cf29b", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x2721ab12ab8c0f9517439c0cedc86cb63683978656c95b5d1645ad3c3b474b7", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4a7c3c8dc3aa1b928c13c57c12382d775ceb844e13a85775fd9f0269740caf5", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x2721ab12ab8c0f9517439c0cedc86cb63683978656c95b5d1645ad3c3b474b7", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1722", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "0x8bb2c97000", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4356702e9264398c522a267fbb2e6d4877335680b40981c7f5c0f33f40fbe15", + "0x15ff59c1065a5c65828ae8f7cca9117d2481b1ae90dca428d9709cb7587c24c" + ], + "contract_address": "0x734092b38fc693b36ff103cdd71ef9fea1b49c6935580660d5c08544c2b7ac3", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x734092b38fc693b36ff103cdd71ef9fea1b49c6935580660d5c08544c2b7ac3", + "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "0x0", + "0x1", + "0x1", + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x68967b78875ea60efb9b0fde92d03b5d279b1cff60cb961f5ad696fb2f090c4", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1e45719466671df50a764e0ac8844aca009011e0b734bab64e91fcf5c11edbf", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x68967b78875ea60efb9b0fde92d03b5d279b1cff60cb961f5ad696fb2f090c4", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x754cd9574b51d0458c540e7993fd226a315207548b12dd7de5573f1346c17fa", + "0x3ffba5da17f4c74a5d72b72e5bc6f53a52ad969249e3c7819dd5759bc687583" + ], + "contract_address": "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "0xe48e45e0642d5f170bb832c637926f4c85b77d555848b693304600c4275f26", + "0x0", + "0x3", + "0x3", + "0xe937b3b8d2827644f14a93c8c7a8680f7fe6a82e", + "0x2e90edd000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x835c16d591a242bc3a935019f89740d5b3b324ae527c51d033cd08ba1d200e", + "0x6685219afa924ad970b9d9f0c10b641ca12113e053a47f17642bbafe30eebb5" + ], + "contract_address": "0x474e816648673a9a60d67b404b4de2a13457c8c671f43cc6a24f362dd9be6fd", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x17ae81331494a8de74752b3a7ee39a52af3cad6c6d49f9fbb7d5b9087d90f60", + "0x18de76816d8000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4e48d6df6ee18922fa0c6302674e0eb596dec5530c9e4e3410b682591a5dc0c", + "0x4f5b7f36a12031bb7651f59205de41a41c267aa4f510c415e9536a3d29f696" + ], + "contract_address": "0x17ae81331494a8de74752b3a7ee39a52af3cad6c6d49f9fbb7d5b9087d90f60", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "0xe48e45e0642d5f170bb832c637926f4c85b77d555848b693304600c4275f26", + "0x0", + "0x3", + "0x3", + "0x443cbebd09101f988977eebcb011c6db011d41bf", + "0x2e2f6e5e148000", + "0x0", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4ab6b948d90f1fe8564565ca301dd372a1de55d6b2f261f81db2a9911c33955", + "entry_point_selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "calldata": [ + "0x2b851b4b210ae056400ef15496fc25a8280f00080f305d92871bf5ff8c42317", + "0x1172b01373a2b897b8429248756701741175aac9e55ac7c223ec701edd027e3" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x174334452e7e368c59c685a22e7b4b85afd434c54471af9384d7f37683f1e7f", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x174334452e7e368c59c685a22e7b4b85afd434c54471af9384d7f37683f1e7f", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x614383fe2d5ff12dc08b5fc212d343800b90bfc50e5958b1eb34fb952d7ede0", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x95334f9e7c4a3b5e0545b276120127c6b243719b4e6ab9d8d62d2141f05dbb", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x614383fe2d5ff12dc08b5fc212d343800b90bfc50e5958b1eb34fb952d7ede0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x173ecc9393a4eaffd4bc1d43de0e23ea98a1cf5dd1f9cb826b228758f900d41", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x466b32659e9971e401e01395315f20f52d718f885a214b5d17d3d8fba4cfff0", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x173ecc9393a4eaffd4bc1d43de0e23ea98a1cf5dd1f9cb826b228758f900d41", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1723", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x24da2b69a7a1788fd0d8cfaf3e2bb87b048cd5177b25e27f166c7723f5f817d", + "0x45eadb112e000", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7a46c86a46927bb4f3c291294d746eaeaabf0e0fce8c4e573a327881e61a6d6", + "0x31ccfe598e06244505014f43dc9572dda69eb86344b04639330d51a005a4f3" + ], + "contract_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x3", + "0x3", + "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "0xa2f413f04241feb540000", + "0x0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0xd523d0804e2b8d7d580a27783f199e8ee03e04d54de3c9ef969ef36b3d9b69", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5efef871d4235ff241de741f257027c0bade52c55dea7b40c40a3e88847177f", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0xd523d0804e2b8d7d580a27783f199e8ee03e04d54de3c9ef969ef36b3d9b69", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5c58297715804d1470a21ced13ac89dcdd9fa29ab0c8ec595467b4996ca57f9", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0xe52e514a61d43a2b1bbffc65ab85ee406c00b60752199d377f4aedae3586f9", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5c58297715804d1470a21ced13ac89dcdd9fa29ab0c8ec595467b4996ca57f9", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x4ee35f145cee7327e282e885dc696cc7862b9e4329020ba6744317e52f7b2a9", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6f207d5654f37869a61bfd8568fd21a5a6fb364697ee8d26ba7fc39aeb39402", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x4ee35f145cee7327e282e885dc696cc7862b9e4329020ba6744317e52f7b2a9", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x126342c768f828ebcb248c204a3325cd4ee6062c58f858bd2d63bdd2b2d595c", + "0x340ddfab0ea33b3bb33da061093b6681ee4ebe03387f8d05443baa374ac9440" + ], + "contract_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x57a37019aabf681c23f69e3187869e95da6669b1", + "0x1166c51744e4640000", + "0x0", + "0x1" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x372f73c5cd2ada868952ed25a5555f9dbbdbafabc5040c9f4c86288b162754a", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x764f9f76bdfcfee213ac2a044f40277ab9f6648a1961a89a77e34430098bac2", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x372f73c5cd2ada868952ed25a5555f9dbbdbafabc5040c9f4c86288b162754a", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x26fa244c1b827ac5d9b8de904d2a1a238fc771cc27269adca0c7d850dd558ec", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3191d9225c42a574879abe55223fe980ae6a48be768651a1f7e0c7d37b39f43", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x26fa244c1b827ac5d9b8de904d2a1a238fc771cc27269adca0c7d850dd558ec", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5ea81852784415c3042fc149b0eea0483da03a12f2a4d79f753d50f38a6893d", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5ea81852784415c3042fc149b0eea0483da03a12f2a4d79f753d50f38a6893d", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1cc2cecdac673ecf9844f0402c13983c86705da73f16cda8b70fe69f52bc746", + "entry_point_selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "calldata": [ + "0x7ddd6ff6c7daf7ca26e6c7e65dacd92cd170d39b" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x3447c40d2834973878a821f3318b264d0f8c01c89c7b6dde6328c6a532ac5d6", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5e151b8be8e454be726840486f5e00ccdb30064c91f3623f36ba38a1598efd", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x3447c40d2834973878a821f3318b264d0f8c01c89c7b6dde6328c6a532ac5d6", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x67c5772b484fff68f7ed5283fb20535ed096a8d68cd88cd63621710eed9b703", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x13941c2fb1aeda4511c6dc65d7ebf69e86648184b487c975c889474796ae8bd", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x67c5772b484fff68f7ed5283fb20535ed096a8d68cd88cd63621710eed9b703", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x6aa7e13e241fe6ad7fde52ac560cb6f8e98259a012d93af3d237aef0c18fcf", + "0x5b20c24c0963b720781848edd10e6aef9e3f4a9917cf80218377233dde0d835" + ], + "contract_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x3", + "0x3", + "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "0x1bafc0f8d3699ec5d0e00000", + "0x0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5218e60bd22640477c1c81d52e532b6c71a87cbc3d01b97591d72850710aa63", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x7a733b77d20a401542755d644d8c98ef3db9d15f93fdf3c086fcb1a9d0842e1", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5218e60bd22640477c1c81d52e532b6c71a87cbc3d01b97591d72850710aa63", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x3ff80e4fda1ef1d8a4ac9976b920c53d00eb1aa0f42759117228fc0265490b1", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x43e0db82095e09231cc48e6fcc59dbc9b884797c787d08a7e631a6fab6d8521", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x3ff80e4fda1ef1d8a4ac9976b920c53d00eb1aa0f42759117228fc0265490b1", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x786c07f054c9e98eb9934f215731ac33780a042e638ec6fa78a6d82a036b5f9", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4b319a2b2ced69b61d2049627d16567801292ae9653ee8127b525c0b50d2e61", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x786c07f054c9e98eb9934f215731ac33780a042e638ec6fa78a6d82a036b5f9", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0xde8e6af4af29673f8092705878a1ca5fe32553e904b6c15eda2f364c0595c9", + "0x52f61ba9722326f06c170d705dad45cbb4c7ab8fd86ae72ed3c2f1f0e916ef6" + ], + "contract_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x6a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x57a37019aabf681c23f69e3187869e95da6669b1", + "0x719fd7deea82c0000", + "0x0", + "0x1" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1724", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x4d9bd0afd4dce6c14cc4acd36a2983935cee93f49fd3c859e5bfc748b56f89b", + "0x60a24181e4000", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4ab6b948d90f1fe8564565ca301dd372a1de55d6b2f261f81db2a9911c33955", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x5faf83c7f563088ad97a857f264f26940a9d4f8782bff255ed8c7e548558102", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x28d948edcf7243f0e190516d5de6650ebcd522b9ebd85ab9ef4354da58785f5", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x55c539a33dbc73dd1f0ec78341c45e48782bb4c1a5007b56a4243bd40192bf7", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x28d948edcf7243f0e190516d5de6650ebcd522b9ebd85ab9ef4354da58785f5", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1725", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x957b7e5d60240fbd7f26b4566ae9828fae915c0685984c22058eb60c38892c", + "0x2d79883d2000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0xa78bf0ca4a357ccad78d50d1f80ffa04bb05387a3bf7473d8771f2673825c1", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x214adff2853bb38e41f61b3e3038f995e77f27a416425f4c4ea698f6322a43c", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0xa78bf0ca4a357ccad78d50d1f80ffa04bb05387a3bf7473d8771f2673825c1", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x442a79dc335666416d3e551ec542afbb673e44e65cc82f6e2625906219425fc", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x50e90305e7ebd55490f5e57a6f8e0850dbd578bf0d67805961f45dee84f40a0", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x442a79dc335666416d3e551ec542afbb673e44e65cc82f6e2625906219425fc", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x2877323192f1bf97c8e4deb82eb9b52bc3ccbf32b7903ebad132a0b512dd5e5", + "0x7cdcee633ce5a5b62491238b075edff3c352e54896ad727631da8bda06dd55a" + ], + "contract_address": "0x4351164daf569e13a17f62e5719f69e91dbb5994394b446d35e6e7e7cd687a", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "0x0", + "0x3", + "0x3", + "0x43e0db82095e09231cc48e6fcc59dbc9b884797c787d08a7e631a6fab6d8521", + "0x2386f26fc10000", + "0x0", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x3aed72ccb165adff3a1e390f837522a94219617383f11384b1735aae1818ec3", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0xfa050b047785ea7285f468f6abcff63816c04ae7a8b403446d9e40aa1a3490", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x3aed72ccb165adff3a1e390f837522a94219617383f11384b1735aae1818ec3", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5824f9c2805dd62df7b629041bc1990d3455999a39b76116ff04649386ec8d5", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x9e36291bfa019b8280f4e51d8c7d75387207cec045908e29570deb20ae98d9", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x7081ea15bc1789337a8f041f1d79a57cccad569121324606b5df675d0dcecd", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x54825ac526fe9f305fece68c1167018de73ced2fd168ef34754a9d391aad204", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5824f9c2805dd62df7b629041bc1990d3455999a39b76116ff04649386ec8d5", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x2d8c25405a90b1d2677716313c391419360812f39546f21ba8ad68b0d9877ae", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x4810fd51d7323de91d0b268beeaa892492f071f48a965e914d40f7cfff35374", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5d8fced0cc766480711762a04cc5116ad3343d8901188a342e2dde9a1ee44fd", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x79b04a570706b59699968a6b1be36867bf1730891ab1bedcbe3912e83b4f559", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1bf21f8ee6a3ba7d1b11c612d054993df2349f321d12e79d7b96ba04258cd67", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x79b04a570706b59699968a6b1be36867bf1730891ab1bedcbe3912e83b4f559", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1365c1219db2ba002e0889675170e7ca4548309ea002e6fae34503ff9efc00c", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5a3a0804c22dc3d3ae9be054ad1ad9206231fdac101da5307d3369d4c25f657", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1365c1219db2ba002e0889675170e7ca4548309ea002e6fae34503ff9efc00c", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x69b67786f27d334fdc08e3a86d50802d3a809436d4fadbc62e04b049882b2b", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x56981c39ce0a48774c7690b86bab46e6585bd6d742cb1c2e071fcd63bc929d2", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x3628f2876455aa2a73f1a06a05cd6d8a75bfddc6882cd1fccaea624056555f2", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x655ca38500b72eae6fce47b73c1d69700d13bb055ad97bc545fcb804098efce", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1f3e77319a16ee4c07b8cda493ca539829269bb575cca7eb5e8643e0e57e89b", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x2b8315b98fcdf4e2adfa21ffff30e55ebbb1dcb8191f69b16e392b2262719e2", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x2d8c25405a90b1d2677716313c391419360812f39546f21ba8ad68b0d9877ae", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5e934ccc1947481143006ce2ea1a5807e12958114b81015a2cda7424fb9b9d3", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x581d2e8c205abf6057113902695a45dd1e1ad0089c2477aa1f71abf7855c839", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1f8ebe80358febe69df095f2844465c563d290264cda90bb3fac9e4f071434e", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x45b834dcac92e34ff21d95bd3b652adce1971a54b56d068da2673a98eaabce3", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1f3e77319a16ee4c07b8cda493ca539829269bb575cca7eb5e8643e0e57e89b", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x496ce2d0bc9fe2ced6c865c1f0511645c514fa5788aabc1bbd448630963cd4", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5b3fe66b093eb4fa3544564bd0e267b1587e06a3eaf06f6c3c3c2b821dd7adf", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5d8fced0cc766480711762a04cc5116ad3343d8901188a342e2dde9a1ee44fd", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1d9d03bc3e894db259cf2edbe4a3872d73e29d4b358455436c79a344aa90d87", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x4810fd51d7323de91d0b268beeaa892492f071f48a965e914d40f7cfff35374", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x56cb84824ce4dfc735e302b7f9599c70b2c9e2204806ec76353532916c6ac68", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x3628f2876455aa2a73f1a06a05cd6d8a75bfddc6882cd1fccaea624056555f2", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5d61bb8c958cf93b3a1425a5f9b01703e8d431eab19d1ff55d36875692b6f1f", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x496ce2d0bc9fe2ced6c865c1f0511645c514fa5788aabc1bbd448630963cd4", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x71708006eec5194d50444fdee7dac0e2b9da018dbc775377bf57d3262a6868a", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x9e36291bfa019b8280f4e51d8c7d75387207cec045908e29570deb20ae98d9", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x17f5869a14fa3659e2a36882bd279863cdad5a5459ead67cbb90297bf903eaf", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5e934ccc1947481143006ce2ea1a5807e12958114b81015a2cda7424fb9b9d3", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1cdd95e8f6fe8f3486bf0c98191504479e00424d5b8307da2dc8485d99017e8", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x69b67786f27d334fdc08e3a86d50802d3a809436d4fadbc62e04b049882b2b", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x65df96ca7b2bab828e9ddc5cc7796ffb15876555a2705a8510dc9650461e5d2", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x487f031212a3c560bf3f8787b872040a70192fa7f8fd2e23dbd9b24acea0bc2", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x581d2e8c205abf6057113902695a45dd1e1ad0089c2477aa1f71abf7855c839", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x27c5ebc3b15c36591331020bc9a1b5efa6e52266328ab3765e03f1b733c4aca", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x7081ea15bc1789337a8f041f1d79a57cccad569121324606b5df675d0dcecd", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3240e9465808ed9d39e5bcba4e4a4ff37fbfef3b3609d19788dc0924385759d", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x655ca38500b72eae6fce47b73c1d69700d13bb055ad97bc545fcb804098efce", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x9f22e539261cb3e48da2a49b16c18f3b2bb9d7d21e959b8668b5c70bfd6493", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x65df96ca7b2bab828e9ddc5cc7796ffb15876555a2705a8510dc9650461e5d2", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x943f8759952d9396d2cfc20c5a6f68d203470aa5cf2aeb7f16c8eafc495733", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x56981c39ce0a48774c7690b86bab46e6585bd6d742cb1c2e071fcd63bc929d2", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x44841185b27006d0de588d3a9a7328774979cd3503e22290a814d77fcb814d5", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3c4e67767a553bb6bb7d97bf148f356c047d84d2b86bfab2708835d91f7c788", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1f8ebe80358febe69df095f2844465c563d290264cda90bb3fac9e4f071434e", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x74e5c365640bbc30a9c0ca105bc35c2e38674ebe3166c40144d50fc9c06f240", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x44841185b27006d0de588d3a9a7328774979cd3503e22290a814d77fcb814d5", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5d74c2b3c84368f518183419b6cdb1240102cde45cca335ccc9931913857f5e", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x31461a87f8292c50e372ef290bdb3fd2f1974343a5b3d70c363af0de9488202", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5d74c2b3c84368f518183419b6cdb1240102cde45cca335ccc9931913857f5e", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x64b5aff7dfd0a6f4b1f0de137be4684ca65b621e694bd4ff498356ac579ef16", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x656570945ce70a0984ed88b448f370242f0d39443627f1816180ddffbfd2303", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x64b5aff7dfd0a6f4b1f0de137be4684ca65b621e694bd4ff498356ac579ef16", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x12b64861e30b79ffe3ce9fcf27644eabb0d8f46ca1cbe14229a2923b78c846", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5f514801588940a279a37514da53879e1ce38dbfeb39a69a8ba56e0fb5ba4f6", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x12b64861e30b79ffe3ce9fcf27644eabb0d8f46ca1cbe14229a2923b78c846", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x250e12c6aa2ea1aab40cec95c616244a2c969826c8258201da67af46daa3fb4", + "0x22bab18d5bae2137c6cd4170b5d223780b9cf1f084a8f5379b9526b290ba272" + ], + "contract_address": "0x3be8b9aa60ff4bf1cbd4afc2e30bd8abcee2903fbd90f233215f18e8a99c075", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x3be8b9aa60ff4bf1cbd4afc2e30bd8abcee2903fbd90f233215f18e8a99c075", + "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "0x0", + "0x1", + "0x1", + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1febf354eb7bfca51edfc964313729c949f747e32ad97cd3c42ce0cd21be912", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x493de11aa57feef9988f7e987438a91743529bda8d46c6baaf3dce0a723773c", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1febf354eb7bfca51edfc964313729c949f747e32ad97cd3c42ce0cd21be912", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x339b1c5998e5687c1f68c6d5dbbc8d6cb265678c2d67346555627b993115186", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1a1784a0cadb9c5ff16924ff780194450039315dade195157e6bc72d564fb02", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x339b1c5998e5687c1f68c6d5dbbc8d6cb265678c2d67346555627b993115186", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x37616586eaf32a352b481903a820703893b9c077f893eb0a5786b5b38b2106d", + "entry_point_selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "calldata": [ + "0xec6be85c0fd3fbdbb23c47d62c639b7f0d0efc94" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1726", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x1cc42734a3a94d26c997d927133b8134c3f8a6e1c122749f8ab8a9c2599481d", + "0x2386f26fc10000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x540864273a8905a39b70f384b3c08869d3b1fde9ea90530e34f8b90ab5c6872", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x2222593150a7dbf64b513ef8ef84b7a861c7f6b1a68914a1201625bd2e9fea5", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x540864273a8905a39b70f384b3c08869d3b1fde9ea90530e34f8b90ab5c6872", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1727", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x50e90305e7ebd55490f5e57a6f8e0850dbd578bf0d67805961f45dee84f40a0", + "0x4c6222d6abc000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1728", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x3532a244aab52b5ca4891da82e8a653e3a8f66baf0eb09c5c532ee40382d7b3", + "0x2aa1efb94e0000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x452c71a7215116dcc5e954cf98783555fbeb81476da702e1dc63c1f068e6cbb", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x43ef92c4ef87f22e465fb6a1671e7db838f4618da40c686df0ec0df7d59c366", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x452c71a7215116dcc5e954cf98783555fbeb81476da702e1dc63c1f068e6cbb", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x41ce6d8995c9dff18f99f1ea2fd0134c472d61486df910dd0b9eebe1a596f4f", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1da9d2446ab0439399c2ae4694dd72c49b72cf528e909b6a7420c9779e7bb8a", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x41ce6d8995c9dff18f99f1ea2fd0134c472d61486df910dd0b9eebe1a596f4f", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1729", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x2e5ec0c1a5ed41f4f6b6b65987d07a509546d9fd485a24eb977a6acfc9790c8", + "0x38d7ea4c68000", + "0x0" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x8ac608c0c3afd34afec8ee3e8424d7592e322dd254e6b5ba19035e105f78d2", + "0x72814bcb0e2613e91c7eef662d5548d5008e2c490f31da9dfb4919d70956199" + ], + "contract_address": "0x36fb4083cf619660da3b7d4794c5a65af8c6b9ec98da6f8ef375d88ed607e0d", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x36fb4083cf619660da3b7d4794c5a65af8c6b9ec98da6f8ef375d88ed607e0d", + "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "0x0", + "0x1", + "0x1", + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x78b1646b893a5690f5ca4a186ed0f6c60bfbd0c95948c706a628fc5814ee4ec", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0xe6005c33ccda5da777de207bf043f85e6d4615377d2b96255452ce6f116c4d", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x78b1646b893a5690f5ca4a186ed0f6c60bfbd0c95948c706a628fc5814ee4ec", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172a", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x165f2accbcb241ff9147a52caf88286ea27ff2ac1174e9e050d41f570027228", + "0x58d15e17628000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x45ad31150bf2e497d1f55f2a7a7a31633e24281f783d5af7990195d8573656c", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x7581238060c7738cf01250432d7c6874d1777320d5f9ba2629ce980e0e24f5d", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x45ad31150bf2e497d1f55f2a7a7a31633e24281f783d5af7990195d8573656c", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x4aa56776db18f70845814f7abe3e7141466d349d185ee18d09cfce81f806ef5", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x7cf47a98c5d96ea6db67df8719fcc8025a39c74c88cc6f61bd7682bff15122f", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x4aa56776db18f70845814f7abe3e7141466d349d185ee18d09cfce81f806ef5", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x6b4b4f357959b8c118be6a50246f06937d9ae0ccf43264c40c21aa1308f3158", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6f5bc4338594774ac0ae80c5dd95b12ffec77df045878aaddb891d80678b769", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x6b4b4f357959b8c118be6a50246f06937d9ae0ccf43264c40c21aa1308f3158", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x12ca42a652241f5c3a72d320f8b5711c3f4cf763d8e45aa8bb1c3c7dfed7119", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6571abf611d953bdc83153d4bc0e09b75ffebb4b924131ad5bb00824a6b446d", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x12ca42a652241f5c3a72d320f8b5711c3f4cf763d8e45aa8bb1c3c7dfed7119", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172b", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x1711f42060bed15aec90d43d3459e52956c72e0f7f06fa8998faeacff424812", + "0x58d15e17628000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x78b62ae47937695a35c6afaa7c1ea8bd3caa468249329e7ad16c43614526848", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6245131adbf53cc0020a67b5528f4d7ec4be8715b9e3d7410a9a1538dce6e02", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x78b62ae47937695a35c6afaa7c1ea8bd3caa468249329e7ad16c43614526848", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172c", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x95334f9e7c4a3b5e0545b276120127c6b243719b4e6ab9d8d62d2141f05dbb", + "0x4b088731a8000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172d", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x688bb4e77f9645b6eab0613c59d752e7b8d0426f03186f758b2c32afe119320", + "0x58d15e17628000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1083346d7a3b44ce9bf5362b8a78afa56812357f4d61a839e28601b15f1a9c4", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x590b98d76eab15779c419e04ccc249c2db48120e6b720483214cee296f4b1d", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1083346d7a3b44ce9bf5362b8a78afa56812357f4d61a839e28601b15f1a9c4", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x47c20d68b8d04afeb1b340d0d320d0f236f372cc000db730d5d457ac752dbd5", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1efe63733a1441efb3bc058c6357ac0cb020af72ce28867c96916fea8c72be3", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x47c20d68b8d04afeb1b340d0d320d0f236f372cc000db730d5d457ac752dbd5", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x6eae6ad979c44c2f2fb64a8af8e54cddcee6fed326be1fb1b4da686ec718ac3", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1b1b01fa2623ce4f0f4d9dcfecbf0e281445c92f90a52026bdec42ce6674a78", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x6eae6ad979c44c2f2fb64a8af8e54cddcee6fed326be1fb1b4da686ec718ac3", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x1288aa5003497074ec6222922edea95209056ac73d34d6bbb21f7780b2ec8", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x33a067b2d9c0d3f93570fe962028804adc27d2b42f2b307d53c217a91cc607f", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x1288aa5003497074ec6222922edea95209056ac73d34d6bbb21f7780b2ec8", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172e", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x43e0db82095e09231cc48e6fcc59dbc9b884797c787d08a7e631a6fab6d8521", + "0x2386f26fc10000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x172f", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x384487deed895fd98cab1a9b37b5f158dc961687c1f70475f77f9ee0d632847", + "0x2386f26fc10000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1730", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x7620aefb45499704840bd5ff016dd45db6947295c53ff7923f89c73ee4153c2", + "0xab1943cc62000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x76a75fec139058bbb13f451b76e458bedcd2da3da25a94f9f3845e08f33b7e8", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x18559827578e1d10f1a5f0cfd327499e85812b4191c18ba94e3f65dbfc68883", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x76a75fec139058bbb13f451b76e458bedcd2da3da25a94f9f3845e08f33b7e8", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x5744522a878d355add36e5208f7f6756ebd87f36722d142b9a3a8e2a4f53b19", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x6f17d6322ba10ed941363dad876be92554d6af2ceae2109712d0a1ce1a0a0e1", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x5744522a878d355add36e5208f7f6756ebd87f36722d142b9a3a8e2a4f53b19", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x332fef1cd59c56dfd39f4b6a4c566a729b0daba0892435e929344f20c4731fc", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x5dfaebae1974b009fdbba7d61eb8270aebdaed3f59d03cf77f469c65b818445", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x332fef1cd59c56dfd39f4b6a4c566a729b0daba0892435e929344f20c4731fc", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x2884f9aabbc27c35271047fca52fbe1ad906f9ef185e2a6629271e54f1f7988", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1bfddda4780f53984bd9c81678ccf0211b5c2be55af130cf5de4cbb180fd17c", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x2884f9aabbc27c35271047fca52fbe1ad906f9ef185e2a6629271e54f1f7988", + "0x0" + ] + } + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1731", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x7eac3aa1497e5d5841043dc0b1e4083e00b6967e465327509ce5f0ba3d364ba", + "0x470de4df82000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1732", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x7850136168437677ce24320a42dce30feaaf7cbd04cab42bf12a424c5755d63", + "0x7b59a7f29a000", + "0x0" + ] + } + }, + { + "L1Handler": { + "version": "0x0", + "nonce": "0x1733", + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x25e6047d46eb42122babdd6431e5676329db0b611e12ab4a004d48b915a408b", + "0x71afd498d0000", + "0x0" + ] + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x12ad8f53d9606239f743cac5be267125e20b3c55acdcd9a615de0f7eb8b5a8", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0xb33dbed2a0fd463f0e2c5311c76c6e9a64062224a38ef69deaa9ac19cdf24", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x12ad8f53d9606239f743cac5be267125e20b3c55acdcd9a615de0f7eb8b5a8", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1cc2cecdac673ecf9844f0402c13983c86705da73f16cda8b70fe69f52bc746", + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x11cd893e69689b5930952a8551c65da2aecb814131e56eeddf2bfca7acb281d", + "0x2", + "0x40e3ca06e0583b3fa4c8bd898de9f877185c2a7a0b869add5862a3cf26a905b", + "0xdd345b97d3062b7458c29a86b87c7b07655d4b2d965a70a47012c523c67217" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x4d41eeb6765201863e1db093db79f9bca14901742fd6d12a6335f0bb2a2a95b", + "0x39aa7070605c113447d10ff86b6e40a7f2fa2843ffc0f0ad7736c2575a45596" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5233b1468c3541463e0e768398912e0d4c7c7906f5ed5733511043bd19e2185", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x6281e3c3" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x7b3f7f7ff7760d1f3688947fc7f4105d014075c44869e79153882488749e016", + "0x36e2e277f17c59064581bad3a1b7d156deb6458979d7f5dc8ac8fbbd926605f" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5233b1468c3541463e0e768398912e0d4c7c7906f5ed5733511043bd19e2185", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x6281e3ce" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [ + "0x37738edc115d93ed696091cdc20bca94b32797f50b42553968fed835447b7e4", + "0x4e68d08ae8e26268ab1f2376f82e566834b61eb71fba26c9eb0d45ba38d945a" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "calldata": [ + "0x6922feb0d562f91baddd100c1e17fe56ccba96b44627879de05080b56fb853b", + "0x5233b1468c3541463e0e768398912e0d4c7c7906f5ed5733511043bd19e2185", + "0x21e19e0c9bab2400000", + "0x5733f73a51bfd18994293f8ba02bea76998ef50b", + "0x6281e3d8" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x7891136ce5a9d4011af56f0ae4c3e48ecd19ebe20b8d884cde705bfe1a344bd", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x4921d3f8e3b7decc2fa18f1e1c3c2cb8881755699da0184a0bd1e829039bcd", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x7891136ce5a9d4011af56f0ae4c3e48ecd19ebe20b8d884cde705bfe1a344bd", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x3cb45c38a3fdc90ac45c49d681d4bc6c24fc967c480249526db5fde312b310", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x1c77c621ea712f3a322cbc5e9ebc2e22a7232408d02cdd4e90dda866ceb8e0c", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x3cb45c38a3fdc90ac45c49d681d4bc6c24fc967c480249526db5fde312b310", + "0x0" + ] + } + } + }, + { + "Deploy": { + "version": "0x0", + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "contract_address_salt": "0x10403e88a828b121d500eaba5763376c1a8762472f231c33801c163bcf19aa7", + "constructor_calldata": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x3abc831776314adadd2bf533a6a5099ee361efd099ad925bbfe093dc81e50e7", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "calldata": [ + "0x10403e88a828b121d500eaba5763376c1a8762472f231c33801c163bcf19aa7", + "0x0" + ] + } + } + }, + { + "Invoke": { + "V0": { + "max_fee": "0x0", + "signature": [], + "contract_address": "0x8f0dcc497a997ab8b465e026632ed149a87b53460d71905867ec9dd0d8fd47", + "entry_point_selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "calldata": [ + "0x4ab6b948d90f1fe8564565ca301dd372a1de55d6b2f261f81db2a9911c33955", + "0x2" + ] + } + } + } + ], + "transaction_outputs": [ + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "to_address": "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "payload": [ + "0x0", + "0xd03db443721db1a014e4b7a47c6f91fdb279fad6", + "0x174876e800", + "0x0" + ] + } + ], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x194fc63c49b0f07c8e7a78476844837255213824bd6cb81e0ccfb949921aad1" + ], + "data": [ + "0xd03db443721db1a014e4b7a47c6f91fdb279fad6", + "0x174876e800", + "0x0", + "0x7420ea6ddb8758de13f77a8dac5c2b130c451e2b9ccdf273f5a1f5bf790d64a" + ] + }, + { + "from_address": "0x7420ea6ddb8758de13f77a8dac5c2b130c451e2b9ccdf273f5a1f5bf790d64a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x2249c1305d1249feec9ad4fc489e352465673e96b0fb9e531fad6c14c24abdf", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1352, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 35, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x4a7c3c8dc3aa1b928c13c57c12382d775ceb844e13a85775fd9f0269740caf5", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "0x8bb2c97000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "range_check_builtin_applications": 12, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x734092b38fc693b36ff103cdd71ef9fea1b49c6935580660d5c08544c2b7ac3", + "keys": [ + "0x112d26124b60e4d99e8c4387c732086fd96b159bf3d72e6d8f5f60c944533f1" + ], + "data": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + }, + { + "from_address": "0x734092b38fc693b36ff103cdd71ef9fea1b49c6935580660d5c08544c2b7ac3", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x1ba597a079b560c2b8c7d69a3e16a434b339e8d183cb1c68478d012e0ce0903", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1042, + "builtin_instance_counter": { + "pedersen_builtin_applications": 15, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 5, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1e45719466671df50a764e0ac8844aca009011e0b734bab64e91fcf5c11edbf", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "to_address": "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "payload": [ + "0x0", + "0xe937b3b8d2827644f14a93c8c7a8680f7fe6a82e", + "0x2e90edd000", + "0x0" + ] + } + ], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x194fc63c49b0f07c8e7a78476844837255213824bd6cb81e0ccfb949921aad1" + ], + "data": [ + "0xe937b3b8d2827644f14a93c8c7a8680f7fe6a82e", + "0x2e90edd000", + "0x0", + "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b" + ] + }, + { + "from_address": "0x3ef70268ff9447cfbef81b96d3446be94afcb38bcb018efaa1e22f94894a97b", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x63cc15b079c7ef882b53e4d2c238286ee5575636e2c4e5bb3abcb5163ddc562", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1352, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 35 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x474e816648673a9a60d67b404b4de2a13457c8c671f43cc6a24f362dd9be6fd", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4574ad7eec27879bc9c96e09eaa1aa8884c19403c28875259a59126f4529511", + "0x1", + "0x1" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 960, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 25, + "pedersen_builtin_applications": 4, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "to_address": "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "payload": [ + "0x0", + "0x443cbebd09101f988977eebcb011c6db011d41bf", + "0x2e2f6e5e148000", + "0x0" + ] + } + ], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x194fc63c49b0f07c8e7a78476844837255213824bd6cb81e0ccfb949921aad1" + ], + "data": [ + "0x443cbebd09101f988977eebcb011c6db011d41bf", + "0x2e2f6e5e148000", + "0x0", + "0x17ae81331494a8de74752b3a7ee39a52af3cad6c6d49f9fbb7d5b9087d90f60" + ] + }, + { + "from_address": "0x17ae81331494a8de74752b3a7ee39a52af3cad6c6d49f9fbb7d5b9087d90f60", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5e49983d70ec8b91d2c81a6aae7c77d9afef7b4f80042d58792e7e3dff011bc", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1348, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 35, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 25, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x95334f9e7c4a3b5e0545b276120127c6b243719b4e6ab9d8d62d2141f05dbb", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x466b32659e9971e401e01395315f20f52d718f885a214b5d17d3d8fba4cfff0", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x24da2b69a7a1788fd0d8cfaf3e2bb87b048cd5177b25e27f166c7723f5f817d", + "0x45eadb112e000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x4afd4c4cfab6d6ac91e2a8ec48c7a409f96c99382679d4d95ffd6d0d7c23566", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 702, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 16, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5efef871d4235ff241de741f257027c0bade52c55dea7b40c40a3e88847177f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0xe52e514a61d43a2b1bbffc65ab85ee406c00b60752199d377f4aedae3586f9", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x6f207d5654f37869a61bfd8568fd21a5a6fb364697ee8d26ba7fc39aeb39402", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x14d3b1054aaf959d5a88c09c93570744968ed05936ad6c614506b8c6ea66ebc", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x45bf55bc49320a76c548b41298e7b965cb02a14dc3b524c7f351b473e77da5a", + "0x1", + "0x1" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 901, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 4, + "range_check_builtin_applications": 25, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x764f9f76bdfcfee213ac2a044f40277ab9f6648a1961a89a77e34430098bac2", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3191d9225c42a574879abe55223fe980ae6a48be768651a1f7e0c7d37b39f43", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x1cc2cecdac673ecf9844f0402c13983c86705da73f16cda8b70fe69f52bc746", + "to_address": "0x7ddd6ff6c7daf7ca26e6c7e65dacd92cd170d39b", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5e151b8be8e454be726840486f5e00ccdb30064c91f3623f36ba38a1598efd", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x13941c2fb1aeda4511c6dc65d7ebf69e86648184b487c975c889474796ae8bd", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x274ecc0d1702057a12736153249acbe8f689933200a8ab6c151be4a4a777b97", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 702, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 16 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x7a733b77d20a401542755d644d8c98ef3db9d15f93fdf3c086fcb1a9d0842e1", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x43e0db82095e09231cc48e6fcc59dbc9b884797c787d08a7e631a6fab6d8521", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x4b319a2b2ced69b61d2049627d16567801292ae9653ee8127b525c0b50d2e61", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x3923cf5ebb05f9e2731c098f8b32f70494cda856d27430852e87e37f9105ef4", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x690b4c00ddc336455c2d19f9552532b0547757fcd948542b1f61ebb397f986d", + "0x1", + "0x1" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 901, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 4, + "ecdsa_builtin_applications": 1, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 25 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x4d9bd0afd4dce6c14cc4acd36a2983935cee93f49fd3c859e5bfc748b56f89b", + "0x60a24181e4000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 238, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x55c539a33dbc73dd1f0ec78341c45e48782bb4c1a5007b56a4243bd40192bf7", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x957b7e5d60240fbd7f26b4566ae9828fae915c0685984c22058eb60c38892c", + "0x2d79883d2000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x214adff2853bb38e41f61b3e3038f995e77f27a416425f4c4ea698f6322a43c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x50e90305e7ebd55490f5e57a6f8e0850dbd578bf0d67805961f45dee84f40a0", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x4351164daf569e13a17f62e5719f69e91dbb5994394b446d35e6e7e7cd687a", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x110eed300b582814a06a40a865fa48abcd13e8891e86bc54b29d476ce99a4ef", + "0x1", + "0x1" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 964, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "range_check_builtin_applications": 25, + "pedersen_builtin_applications": 4, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0xfa050b047785ea7285f468f6abcff63816c04ae7a8b403446d9e40aa1a3490", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x54825ac526fe9f305fece68c1167018de73ced2fd168ef34754a9d391aad204", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x71708006eec5194d50444fdee7dac0e2b9da018dbc775377bf57d3262a6868a", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x27c5ebc3b15c36591331020bc9a1b5efa6e52266328ab3765e03f1b733c4aca", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x2b8315b98fcdf4e2adfa21ffff30e55ebbb1dcb8191f69b16e392b2262719e2", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1d9d03bc3e894db259cf2edbe4a3872d73e29d4b358455436c79a344aa90d87", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5b3fe66b093eb4fa3544564bd0e267b1587e06a3eaf06f6c3c3c2b821dd7adf", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1bf21f8ee6a3ba7d1b11c612d054993df2349f321d12e79d7b96ba04258cd67", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5a3a0804c22dc3d3ae9be054ad1ad9206231fdac101da5307d3369d4c25f657", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1cdd95e8f6fe8f3486bf0c98191504479e00424d5b8307da2dc8485d99017e8", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x943f8759952d9396d2cfc20c5a6f68d203470aa5cf2aeb7f16c8eafc495733", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x56cb84824ce4dfc735e302b7f9599c70b2c9e2204806ec76353532916c6ac68", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3240e9465808ed9d39e5bcba4e4a4ff37fbfef3b3609d19788dc0924385759d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x45b834dcac92e34ff21d95bd3b652adce1971a54b56d068da2673a98eaabce3", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x17f5869a14fa3659e2a36882bd279863cdad5a5459ead67cbb90297bf903eaf", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x487f031212a3c560bf3f8787b872040a70192fa7f8fd2e23dbd9b24acea0bc2", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3c4e67767a553bb6bb7d97bf148f356c047d84d2b86bfab2708835d91f7c788", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5d61bb8c958cf93b3a1425a5f9b01703e8d431eab19d1ff55d36875692b6f1f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x9f22e539261cb3e48da2a49b16c18f3b2bb9d7d21e959b8668b5c70bfd6493", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x74e5c365640bbc30a9c0ca105bc35c2e38674ebe3166c40144d50fc9c06f240", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x31461a87f8292c50e372ef290bdb3fd2f1974343a5b3d70c363af0de9488202", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x656570945ce70a0984ed88b448f370242f0d39443627f1816180ddffbfd2303", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5f514801588940a279a37514da53879e1ce38dbfeb39a69a8ba56e0fb5ba4f6", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x3be8b9aa60ff4bf1cbd4afc2e30bd8abcee2903fbd90f233215f18e8a99c075", + "keys": [ + "0x112d26124b60e4d99e8c4387c732086fd96b159bf3d72e6d8f5f60c944533f1" + ], + "data": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + }, + { + "from_address": "0x3be8b9aa60ff4bf1cbd4afc2e30bd8abcee2903fbd90f233215f18e8a99c075", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x60fc274e8a71272f6f4ca13c2ee9e3ab2f269337737c5d6a8ecd16a205d6dcb", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1042, + "builtin_instance_counter": { + "range_check_builtin_applications": 5, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 15 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x493de11aa57feef9988f7e987438a91743529bda8d46c6baaf3dce0a723773c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1a1784a0cadb9c5ff16924ff780194450039315dade195157e6bc72d564fb02", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x37616586eaf32a352b481903a820703893b9c077f893eb0a5786b5b38b2106d", + "to_address": "0xec6be85c0fd3fbdbb23c47d62c639b7f0d0efc94", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 31, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x1cc42734a3a94d26c997d927133b8134c3f8a6e1c122749f8ab8a9c2599481d", + "0x2386f26fc10000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 12, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x2222593150a7dbf64b513ef8ef84b7a861c7f6b1a68914a1201625bd2e9fea5", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x50e90305e7ebd55490f5e57a6f8e0850dbd578bf0d67805961f45dee84f40a0", + "0x4c6222d6abc000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12, + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x3532a244aab52b5ca4891da82e8a653e3a8f66baf0eb09c5c532ee40382d7b3", + "0x2aa1efb94e0000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x43ef92c4ef87f22e465fb6a1671e7db838f4618da40c686df0ec0df7d59c366", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1da9d2446ab0439399c2ae4694dd72c49b72cf528e909b6a7420c9779e7bb8a", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x2e5ec0c1a5ed41f4f6b6b65987d07a509546d9fd485a24eb977a6acfc9790c8", + "0x38d7ea4c68000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 12, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x36fb4083cf619660da3b7d4794c5a65af8c6b9ec98da6f8ef375d88ed607e0d", + "keys": [ + "0x112d26124b60e4d99e8c4387c732086fd96b159bf3d72e6d8f5f60c944533f1" + ], + "data": [ + "0x1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac" + ] + }, + { + "from_address": "0x36fb4083cf619660da3b7d4794c5a65af8c6b9ec98da6f8ef375d88ed607e0d", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x5e5895469a274c64c73078e58a033f5166c55c07f056359541c52069a1f5cc3", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 1042, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 15, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 5 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0xe6005c33ccda5da777de207bf043f85e6d4615377d2b96255452ce6f116c4d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x165f2accbcb241ff9147a52caf88286ea27ff2ac1174e9e050d41f570027228", + "0x58d15e17628000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "range_check_builtin_applications": 12, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x7581238060c7738cf01250432d7c6874d1777320d5f9ba2629ce980e0e24f5d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x7cf47a98c5d96ea6db67df8719fcc8025a39c74c88cc6f61bd7682bff15122f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x6f5bc4338594774ac0ae80c5dd95b12ffec77df045878aaddb891d80678b769", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x6571abf611d953bdc83153d4bc0e09b75ffebb4b924131ad5bb00824a6b446d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x1711f42060bed15aec90d43d3459e52956c72e0f7f06fa8998faeacff424812", + "0x58d15e17628000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "range_check_builtin_applications": 12, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x6245131adbf53cc0020a67b5528f4d7ec4be8715b9e3d7410a9a1538dce6e02", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x95334f9e7c4a3b5e0545b276120127c6b243719b4e6ab9d8d62d2141f05dbb", + "0x4b088731a8000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x688bb4e77f9645b6eab0613c59d752e7b8d0426f03186f758b2c32afe119320", + "0x58d15e17628000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "range_check_builtin_applications": 12, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x590b98d76eab15779c419e04ccc249c2db48120e6b720483214cee296f4b1d", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1efe63733a1441efb3bc058c6357ac0cb020af72ce28867c96916fea8c72be3", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1b1b01fa2623ce4f0f4d9dcfecbf0e281445c92f90a52026bdec42ce6674a78", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x33a067b2d9c0d3f93570fe962028804adc27d2b42f2b307d53c217a91cc607f", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x43e0db82095e09231cc48e6fcc59dbc9b884797c787d08a7e631a6fab6d8521", + "0x2386f26fc10000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x384487deed895fd98cab1a9b37b5f158dc961687c1f70475f77f9ee0d632847", + "0x2386f26fc10000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "range_check_builtin_applications": 12, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x7620aefb45499704840bd5ff016dd45db6947295c53ff7923f89c73ee4153c2", + "0xab1943cc62000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 635, + "builtin_instance_counter": { + "pedersen_builtin_applications": 2, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x18559827578e1d10f1a5f0cfd327499e85812b4191c18ba94e3f65dbfc68883", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x6f17d6322ba10ed941363dad876be92554d6af2ceae2109712d0a1ce1a0a0e1", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x5dfaebae1974b009fdbba7d61eb8270aebdaed3f59d03cf77f469c65b818445", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1bfddda4780f53984bd9c81678ccf0211b5c2be55af130cf5de4cbb180fd17c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ec_op_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x7eac3aa1497e5d5841043dc0b1e4083e00b6967e465327509ce5f0ba3d364ba", + "0x470de4df82000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x7850136168437677ce24320a42dce30feaaf7cbd04cab42bf12a424c5755d63", + "0x7b59a7f29a000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "L1Handler": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x25e6047d46eb42122babdd6431e5676329db0b611e12ab4a004d48b915a408b", + "0x71afd498d0000", + "0x0" + ] + } + ], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 631, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 12 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0xb33dbed2a0fd463f0e2c5311c76c6e9a64062224a38ef69deaa9ac19cdf24", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 169, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 2, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 7, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 1, + "pedersen_builtin_applications": 13, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 18 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "range_check_builtin_applications": 18, + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 1, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 13 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 537, + "builtin_instance_counter": { + "pedersen_builtin_applications": 13, + "ec_op_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "range_check_builtin_applications": 18, + "ecdsa_builtin_applications": 1 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x4921d3f8e3b7decc2fa18f1e1c3c2cb8881755699da0184a0bd1e829039bcd", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x1c77c621ea712f3a322cbc5e9ebc2e22a7232408d02cdd4e90dda866ceb8e0c", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "range_check_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Deploy": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "contract_address": "0x3abc831776314adadd2bf533a6a5099ee361efd099ad925bbfe093dc81e50e7", + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 50, + "builtin_instance_counter": { + "ecdsa_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 154, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "ecdsa_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + }, + { + "Invoke": { + "actual_fee": "0x0", + "messages_sent": [ + { + "from_address": "0x8f0dcc497a997ab8b465e026632ed149a87b53460d71905867ec9dd0d8fd47", + "to_address": "0x1", + "payload": [ + "0xc", + "0x22" + ] + }, + { + "from_address": "0x8f0dcc497a997ab8b465e026632ed149a87b53460d71905867ec9dd0d8fd47", + "to_address": "0x2", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_status": "SUCCEEDED", + "execution_resources": { + "steps": 426, + "builtin_instance_counter": { + "ec_op_builtin_applications": 0, + "range_check_builtin_applications": 0, + "pedersen_builtin_applications": 0, + "bitwise_builtin_applications": 0, + "ecdsa_builtin_applications": 0 + }, + "memory_holes": 0, + "da_gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + }, + "gas_consumed": { + "l1_gas": 0, + "l1_data_gas": 0 + } + } + } + } + ], + "transaction_hashes": [ + "0x2249c1305d1249feec9ad4fc489e352465673e96b0fb9e531fad6c14c24abdf", + "0x3ff7ab93650c64fced8a9b8825ad3dcdd7143469b8c599bd57a3af68d8c697a", + "0x11900cd910b4de8f549bc6182b3a07f22ec3c32e4f6bb80dd90bd520d4b7f60", + "0x9d66d878a5d9967cc214680018437da6959647d68cb90113336d82fa3f0f2c", + "0x8d3a05b2900bdf7a2a67b13248f191ce019a17d3587ce7d4eec96691e198b0", + "0x74911e605dc1d3c0b0e3d60f92dfb4e2271ca5e967bfaed5748d172c841029e", + "0x5ca4c50cc518e4876d7fcb67f9a0e2830b1b22c10583d09978e24d59c86c07b", + "0x3fef3f29e8227452dce00ece29449d9ab87be57caaddcfa2c48a55d2e2cc90a", + "0x244055047a5238f0a15e9bd2a69ecc5b7356b94cde625f29de3357bfe3b6d39", + "0x63cc15b079c7ef882b53e4d2c238286ee5575636e2c4e5bb3abcb5163ddc562", + "0x4574ad7eec27879bc9c96e09eaa1aa8884c19403c28875259a59126f4529511", + "0x5e49983d70ec8b91d2c81a6aae7c77d9afef7b4f80042d58792e7e3dff011bc", + "0x123ac086d2c94a334710c03513c591d009046706c6be866540b2b17335a4f4a", + "0x137aac78b9a8723c4041f4919a1d98f5100a72836a4a339bd01dbb5d50e599c", + "0x18b6a2cf4e0d3f24b7a0825421f30f000aa9042126b9fd7d308ee6db63cc0ae", + "0x5fbca3890aee916c72975f18b8c90c874358c3e6a64362196102e54fed5c0b9", + "0x77f78f0ea35913e90040407908ed060445cd6fa6c544bb609f94bf5a6059d0d", + "0x567a9cefb8ff76ca246bf1b7f2a5b04620e06908f2e59d04d80c9a455210b09", + "0x6a89bb21104af0837d665f58df6bc680f9274917e9f7bb945408c777dcfa34f", + "0x17be5af3606de875cc320a8bdd742772466ed11afc09214b0e96ca11383ccbe", + "0x4afd4c4cfab6d6ac91e2a8ec48c7a409f96c99382679d4d95ffd6d0d7c23566", + "0x132878265ce4ecfddbf93632b1d334a0164b5151f65a8bd3dc87805a10375b4", + "0x54c5c200387d99c03e5f01f234a58f9ab71c51f58055a59c4e58e201843d5f3", + "0xf67d2e0cf575ce7f3274a5242b4cb226514d5434c85c5ab9fa9b536f6a273d", + "0x59ff8c743488f162d7514d87bd423b1b99e504076f38f432aacb51eb2a8e2", + "0x909357365fb2706cf7d646e677848fe59f573bf31fe2d493fe42ce392a349b", + "0x101fe0ed2fc47b5e932078820663ce32dca6115b5538375df18835ad37c596e", + "0x45bf55bc49320a76c548b41298e7b965cb02a14dc3b524c7f351b473e77da5a", + "0x54f01b4d63f9e11d8535d84c2671153ae53b4605131c8dd73e82673865618cc", + "0x5c5b65e852722bb2284f070bd28f0458e3cb679afcc77ba25a91ea7797901c3", + "0x70f16fb7fe9d448f61285bd23809970e4c197ddc29d09ebd43004c46f23101b", + "0x58dd54c4d5d87b70bad4e63826f38827df4917c4ca778573372f1f4f0fe1360", + "0x7d23967c7903e700abe8f55f596c50d547184e306f608ac616caa023078fddb", + "0x48a9b528b34229a89b59e5cd489bb574fff4534244fce3762c474599df5fa07", + "0x4d95b2c979ea1abc6a9e7a6ea6dd358946f0f1220cd4946ee80dd45489bb244", + "0x1333f1f7d046bf13ec2cfb3176a0a2884f93e128fa223f0926a14014af46682", + "0x20f52c34952c493321ad6e0881c42a2bcd57f33c667ce7be7601c59725fd3f", + "0x37bccf2124e8a64510e87c45e81e1448cdae05fbf02f8c935e690395c436be9", + "0x58e6fafbe10ec5729d829b636965e38c2da4ed5bf03d54b71a11d6e10b82820", + "0x274ecc0d1702057a12736153249acbe8f689933200a8ab6c151be4a4a777b97", + "0x2dd7f3b4cb140c2bd453a0c5d3cf7695f3ff3ab8245d3f386328a4de7b38a07", + "0x620e73ec5ba915cef3f171afbe77f081ea1f92afa194ef8ebb6157e77e21614", + "0x79dddc2dc6370ad20efb968abb71f6b36aec3e6468c78e7fd4585ecbdb4ee3c", + "0x4ac8310cac7225e7bd1b01188bfa2311fd7c545f8e98ff7f7afdb0eadd90064", + "0x272c7114fb2754b61a3b891ea2b12ff5a0a8ace1ff91b721c61a4d089856574", + "0x48bb814c2e20f770f91e2d752b29e5b82d41a7448c18ddb9674260992f4a83b", + "0x690b4c00ddc336455c2d19f9552532b0547757fcd948542b1f61ebb397f986d", + "0x5a24762b051c25f7f413804d7771585be42e74c7510cacacef519a03329ef5d", + "0x4d156ec2e4e0bbaedc2e69f1104fb13f7cf29936112ee50cc12a6e1bae9a5c2", + "0x2baacfc1ef164a86633c1ebfe2645c0461e07af05939f8766ae55b998ae7624", + "0xe87f438df3c4e580260723a3392c0252825326a6ceeefb8010006d06b13e30", + "0x6dfadeb252c445656bd703c50872d95c3a3ec1a1e9b4ebba36fec5e1f059a0d", + "0x273839eafb7163f663aa4f0985d8c02137ddbec0e7b6dbd5814caf069746fdb", + "0x7f6893deaecc5e49dbaa73f8d6cda0553d74c9e592bdea9dd9152aab7e3c414", + "0x1bfd5f25b14f97c79b170ef211f76982cbbbf466f7ac5b151c2bc990c17899d", + "0x49e7ac40f689f3ec28d2070a65c0a361df35a38d23ce9a7b2c56e4d75d19530", + "0x110eed300b582814a06a40a865fa48abcd13e8891e86bc54b29d476ce99a4ef", + "0x3efa0578e569a70584903bc31d4dfed57ce9c7a2e90b73d102a9344d9a054d8", + "0x7a1315da3032e848bb615e79a96a7965a2dfa8655ebf1275b6a9615bd477e9a", + "0x37880402ec1ae44e041fac4fb82313b363576c2c842731b9bc56f4188f29b17", + "0x35b2dc546851abd21b371e17c0ceb65ea8fe8d70519bef12114db4c2a409482", + "0x4ed35951364e989564b8774c2d46fcee457238669a5d44f56ce66a3a74fc725", + "0x25824d9de588131869354b5f5f20ddc462f0434532b7df64188638529e6059b", + "0x6ec22e049e1b51cf8d17591cf2e2bd5173954a824c9439bf76b492af74019aa", + "0x158203bb25538683b89d67b02bedd6c2837adf7a00f68a9432d1ddab6ab29b1", + "0x479daed2dbe5aebcf522ed8e0bcba2924216b7923664d0472e1972043101165", + "0x7bc28dcb854b71b63a8d8371b454e10594e1d4c12a82a1e84da28ba4f9d7599", + "0x5b068a413c9fdd34638cd248f4524fe2c2f3d59665a4c96902c2c173ef0f00c", + "0xa3a0b224f7099539eee91064a407ce6cecca0952910888f8e601351217478c", + "0x1f3ec4f771eb41c4d908f319610d204983dcfc59a224c6cd50b3548ee626bc2", + "0x6b94f2dc4f092d8820a3791f34a5e6da8e9c4aac8f16f27bc5411fe01212858", + "0x3f11792cb10ff9a8a568e186433637139d1ff3a408d8adfb7cc5228cdf8d1b6", + "0x2756ec5e2c35f4aa5fdb0e31ec0ce1cd0f9389bdb84d92ed83593a885ecf1a4", + "0x7faa9d73d05061164e71f0eb1224e78581bf1482ebeb87590e21261676c67d7", + "0x2bf01fcf0c232b4c1aaa9672bcc275cf8d5d007a91229c15a91413705baaa90", + "0x599647e2771cc5d3e0bab9dd4b54c553fbdeae78bdf16ad235ac502ad440309", + "0x4e6e8eb0b79edcc6a5e6cead0231bc3094a61f69192f7cf28b913d8b33b5445", + "0x2d01e0e711eea53fa1ab7c3317d57ab292f68bf3d810d24eddd010cebca2b80", + "0x50d770d9b2335e24aea7c31b19bbe377c280fb5e5dce77c024da1f2c3487161", + "0x3b86d8396967eaa696473c065985dc4795348ad516e549d958d351c27da8ca7", + "0x377b012af4a885898b4b42d09d3c676496a00f05796360037a8028964a8d5d7", + "0x247f5ed03c34fbd2f5302733c990b6ab99729c9372f2a5038740a3179f0417d", + "0x292100e0a625638eb78bfc3fcb54ed71f19f7338aadd34275c1cddb502ad16a", + "0x6070f73b666b35032fa258ea511844c840fd7be8e18ba77b49f28c6b714a2c", + "0x18c6a711f0f6bf3bc32828187951e7ff8379e35e4cf3d637f0d02634f1bf4c4", + "0x27bcb3758756b60c1c1e3c279314ec64e2af758df45d6124dc1073a56e38aa0", + "0x444cef3e3e19c1b5195554b26277a7525fc0cc17a1f8b0c5e2607ac0e528db9", + "0x50c647f1462bb164005bd12df5b9414e7fa0905807218ef3618fc5be3f8386a", + "0x32a7d3a4fc033d1a00a7ff4977635a4337dae4c480831b081510b86e91367", + "0x296bfec2fcc2e919d550dac3c62248fb5ed7fe3c1ef376509d9982560f6b5c8", + "0x5fedb01aecf903145aa4ed7448e31a4b26ea94004d6fd13db77077dfbd0e7b2", + "0x13a843271c36569496a20ffabaed760f1a29fb5a6b4870723f2683344d62ce4", + "0x3f40449c16c10f542b3ea210f138d42664892cbc7fe40d79fa23bf7d51b7ffd", + "0x1ef83c615fb1b2034e6f14ddacdb04b19aabd10710eca23c347b9783ab952d4", + "0x1f3f77c128799ff72f9b53b104bafb7b28ef62740888fa70a634ef46b8d1fee", + "0x11e6bbc25b84bc9cf43ccaab80ab66d8bb1c53834fbcb5cef33b7b8ae77d7db", + "0x7f9e471d41e8fb317f24c455f406b7dc22b11fdf0469d8b52adcec92ba9adf9", + "0x168fe4e90068aa47026b4485a8e2ab831050ee750becda5cbbd287bb0af3ac1", + "0x6ef89dc9cdfaee1f9524e4d0f12f2c5c051e7c0a33dd3981f5c8115c5243aee", + "0x49d826326ffde459c5fa85df799b507224616c233b93246ec0a3f633f0e3081", + "0x21f17e8844c9d1e9ab658057589c86e050fee0b5298c9b9c5b9ad7b58e47b86", + "0x2f7441729b42c9c43baa046787ada85ee44b85d134eef15edec30a5e917d23f", + "0x36b812096f7e0738f67899da8f89c2ee1cfb5d231c9cb499765f4125d91e3a9", + "0x608bc34fd34ab09dae13853fd04fcb4d775132a9de8e9f325f3d08d408261b4", + "0x5892eed3138b1a4e059958567593cd166215e13ca1d6628ed99772c2c5db03d", + "0x62ba49f5399fce36bb6f05153a5e1378fb57f44e65a315978cae0ba9b61a6a7", + "0x78228506a245f710617fcd9a4840facbcbc011474eb90da9ce167d62efc5fc7", + "0x6854f9438cd85c53bd589111ce13106442bd7b837e9404353f505f9658d3941", + "0x35dedbb30f61f81723117f2262dbfc5d860ec3eb4e1e8b0e2b5efe7f5c61dab", + "0x700d98c060ffabe7af715abe6f647fde08040aa5c9b178724fd9e2443d9b3a3", + "0x2285100f5cf6022344af3c1257a1655e60d23003a993d5a6c59c09df1511295", + "0x73521aecb70f9805b1de4f9edc7a12c7f6e5d01a959d55f9a084b83973eee58", + "0x19e08e92118221eb2f49d2284c049dc62845c1e11e9ebc3f1abb7aade6bd029", + "0x6c8423c59e4e2234b2fd3537bc72433141b1a9431fca90f11cec15ec3a578fc", + "0x76dc31f8bd349123a3afb7c0953ce5a6570452ae0181ab739ad5ec50c64e222", + "0x2ae2337de9f7223d344d7b6dc6d5d3e714addb914c6dfc18fe1887ebd300de4", + "0xd95b71b900083429c874b0f7507e9a2977019f789bf49c2f76e10a2d13bdd7", + "0xfdfdd24b75231412bac0c594482d50c35f4710b247f7d50819bb8fbf759097", + "0x28c4fde9fcd97a4225813140563dd7acaf695dde2e77099d5a7f654e45f71a3", + "0x737132e897a0818e578499c82e2be8d69fc427a92887b6aeec79bf693a91ddf", + "0x3dc934f4f009916bdb1b2bdf46744e746973195a582751cdc58987b81abc327", + "0x6588dac0be0a9e8e39a00e3d48be42f0aa9011c4998814778429129230aac67", + "0x5613b9862600260c7a86e3269dc66e5c7ca9c8ff44de007ef71b09c11150a58", + "0x1c6a6ec307d37be6cd340b21fae5e9c290e4cea19cb734fe36e096ecc0dc334", + "0x7050e8da6daf0c55f4c6c2c4c5f1891ef159faf2d9d0d370f21dae929a0e610", + "0x4357215cb155d33f4ccb55ed750b32d5594907f2fde64a07135ce49fcd5ea50", + "0x26f1a091d8a93ed2dcbfbcba9d6e2053fa393ce7675c53bde4d5d99a5c94aaf", + "0x745b20fd39fbae818afb627f3bd79551f39231dcb36f22f157d106b40598df1", + "0x314465bb78b34015f9926377baf360a23cb78cc4eb4a82d9e042b478c1c72dc", + "0x58eab21384fb011174303e35deefb831ed566ca78758aae014b9c449c108f6e", + "0x2f54519aa1e59718522a14b941ebb0298e01570d50c2cfc6a3fc9c17acecbd3", + "0x82a6975ce9d3e9580f7d15a3a2ab7cbe133cfd5b78fbd880371cee0d22c314", + "0x6a3762e488815ba2f4086d0e6e50b2c19df9ca121c4df2c326a89880c72ae21", + "0xfa02b8bfccfa7190a820158e97549c2c3bf7c3005014f3f35ca8324f9fbfe1", + "0x6a9203e84cd59e0272f8cd4509408bfa8f4556630514adaffce1ec520cf85ab", + "0x271de10d6b21323f537e582d24532635dbf2d43eb72bf7baf0684a098e2e79a", + "0xf54b268f21aaa19c7e4029f4f1df26117c716efba7597437da3a65054431f8", + "0xa55be0e6796d138fb2d557c07c61d7b7ad399f792fb768d6986eda1286f8cd", + "0x304262ff9de027b2ebfc24eba283996baceaf6acce35609f3457fc06b4bdcd5", + "0x7dd80570e05ea0eb0fe2b6a538c33c77afb938239fe09f4b556363d97fca7f1", + "0x2abab7538e42df0e282835fdb1ed2f433c57924aa08bd9cc38efea4cc779ec6", + "0x14d4b3e508fa09548c2823e8d4692af06ea45bdda7d805e3254e36996de8411", + "0xaf949bfc7d21f53da1cd2479c61c4173bf0dffa55c8a199f5ff7d6f49766fa", + "0xee0496703281818945ed75e06455ae32e44082a7f8805a3624aa5f18c4bf14", + "0x62d5b91d16517cbe667fb6ea20c790424cc8b37a3a8b02ccdf5e853e0a27a58", + "0x71c6a309dc5aa95c3396ce189b72615ffd02fe6bfecedb6e4b94d8196602ba0", + "0x35e6d6517b07a515cde7785565d532ad2e426c4d59c32c28b661933c13e79f", + "0x6fd41d1bbb6415d62e8c63a3e9a7300ba69fd5a1c95d3e498c823202cf0c2aa", + "0x2a8bd55bfa6cfc19c070e598233f9e57e04ab2c4356baf9f637389a3a4783be", + "0x7015701edf756ffe1e9a5771e41dae44cce83457eb44d393d2b7787682b65e2", + "0x792907697da7dbc3b0bdbbb390a8d8b4842c11282d610cd9577d48d840bfd71", + "0x69950877c498316a211e782173bfb0aa5e4be617a679b42571c06901e178102", + "0x3ea4bd2216f5a57d69f13d97565ed7916b5b7f58451df62ae7d4de42dbfccb3", + "0x1a89638a8579d41e457c8fd1c1458bd85e0e94b3d4cd9df6ad6a16d5a4f1831", + "0x3ca6414f4dfeb48dfceaa0138fe13b84b40aef70a7f225656873331c8b39e48", + "0x596861483771e9b0691e795219ec2ba84a8ac584a684bbc86ff726cdea20889", + "0x7bf4b65f3d7a8e5eb8005f07b87dc5db5faf7cf38d39a549483dda32ec62358", + "0x909d40e1b18fc73571e9db7a8d000dd2b7f863b436e1cd1e83a6c96e52c28f", + "0x4cb09375d44b80d1e148568c55215ea97e06a2e272b07c0e7b9d1018ff6d514", + "0x45393255b47d2da9363864cd6a2ec8f4757233f264d6845182c9806dbd4c4a", + "0xe531cdf2d46e0961b08d82f07b7d956fe805c69c7de14f2ee261fbde17fb", + "0x4b6784735816fd2a9ecfb1f1a218e72e85cdf4f6924fcf1889f6ea1a3435ae0", + "0x4cca12d5a496f17969059bb48973071f43e529672939ae6770b2af782574e54", + "0x61b2e782f47396c01f24c92216721ccb58b282f1fbac9302641400d7d0e93c5", + "0x5546f8fd693f37aa09ac584ea4e96c8d0d9b09ef3dfdfba4eb55e4ef1652109", + "0x44861e9c4af2c3fce1de7269fc6780d5eb2e08d626ec984c922af8c767c64ec", + "0x162bf811814647656c9315e3adc28e303cd303806a7afc7d7b09b6397f114b5", + "0x589e334f5c411c436969c18e27a5efdfbea1db397aabf44b4dc23857bb4a72f", + "0x7a8a846a33c27f89cc5e3e49f45f42056cab21c91f77fb69d8de158b6399e3f", + "0x445cbfe77407c2092e2906b1e0319dac9cde3a27d7b4b1108cbeb8ba5bfd4a", + "0x521761e9ed44deb91b85e46f2f93b35fca588784424fecda7d44d14b70a2939" + ] + } +} diff --git a/crates/papyrus_common/resources/deprecated_transaction_hash.json b/crates/papyrus_common/resources/deprecated_transaction_hash.json new file mode 100644 index 00000000000..a89f16bbc08 --- /dev/null +++ b/crates/papyrus_common/resources/deprecated_transaction_hash.json @@ -0,0 +1,55 @@ +[ + { + "block_number": 1470, + "chain_id": "SN_MAIN", + "transaction": { + "Deploy": { + "class_hash": "0x71c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64", + "constructor_calldata": [ + "0x5f28c66afd8a6799ddbe1933bce2c144625031aafa881fa38fa830790eff204" + ], + "contract_address_salt": "0x1cb8f5514ceac8a6abdf232cd24ea9eacfb310eaba427432784b80b5f95bc8d", + "version": "0x0" + } + }, + "transaction_hash": "0x2b30ab254aaac75326e5d6a1ed6f040ddd61902155381a754a849e9aa616153" + }, + { + "block_number": 1470, + "chain_id": "SN_MAIN", + "transaction": { + "Invoke": { + "V0": { + "calldata": [ + "0x1cb8f5514ceac8a6abdf232cd24ea9eacfb310eaba427432784b80b5f95bc8d", + "0x0" + ], + "contract_address": "0x67b664b0ea8df2687352cbd636cd0782bf8f563a0072b233853e3c5a70b5897", + "entry_point_selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "max_fee": "0x0", + "signature": [] + } + } + }, + "transaction_hash": "0x1d7b514ed5f8d37c36bbb70db9df33994e0e77bb8d6f62790894f0b56462e62" + }, + { + "block_number": 1367, + "chain_id": "SN_MAIN", + "transaction": { + "L1Handler": { + "calldata": [ + "0x142273bcbfca76512b2a05aed21f134c4495208", + "0xd9aa5ef3a8b31910ad5f26fcd782ce18bcfcfc45", + "0x2", + "0x453b0310bcdfa50d3c2e7f757e284ac6cd4171933a4e67d1bdcfdbc7f3cbc93" + ], + "contract_address": "0xda8054260ec00606197a4103eb2ef08d6c8af0b6a808b610152d1ce498f8c3", + "entry_point_selector": "0xe3f5e9e1456ffa52a3fbc7e8c296631d4cc2120c0be1e2829301c0d8fa026b", + "nonce": "0x6", + "version": "0x0" + } + }, + "transaction_hash": "0x76e77f01890b45e0b0e90e50e5e30cf6e401e7110ffb67ca9a55716d9bc1c0e" + } +] \ No newline at end of file diff --git a/crates/papyrus_common/resources/transaction_hash.json b/crates/papyrus_common/resources/transaction_hash.json new file mode 100644 index 00000000000..450f46ebbb4 --- /dev/null +++ b/crates/papyrus_common/resources/transaction_hash.json @@ -0,0 +1,332 @@ +[ + { + "block_number": 206864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x3ac7f2ee20a3b32988b812dcfba3ace9d4f87702d2dc09ecdf3dabb15bf5b6e", + "transaction": { + "Invoke": { + "V0": { + "calldata": [ + "0x1", + "0x16ba3e98d91e73aa2037bf80fa55f82be38211530632dc7e9ac47223688e34e", + "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "0x0", + "0x1", + "0x1", + "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + "0x0" + ], + "contract_address": "0x16ba3e98d91e73aa2037bf80fa55f82be38211530632dc7e9ac47223688e34e", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "max_fee": "0x892a33adefe4", + "signature": [ + "0x4d9f6a54e158cf0cfb086e8cdb30c0dd1e29809e504130ae5065b3c56f4d1d4", + "0x49e753a978b34ade8b32c319e2f225121b5bb1f12c040046c85549ef7ab1344" + ] + } + } + }, + "transaction_hash": "0x7b199bef92f4d2dc7713c53927060b3388ccd6873dc084ee7c12cdac4209d3b" + }, + { + "block_number": 636864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x34cc38c334e26a3761851fdf631e3bcbc1ff6e8c5af1bcc21642f0023ce07aa", + "transaction": { + "Invoke": { + "V1": { + "calldata": [ + "0x2", + "0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x1114c7103e12c2b2ecbd3a2472ba9c48ddcbf702b1c242dd570057e26212111", + "0xb67495", + "0x0", + "0x1114c7103e12c2b2ecbd3a2472ba9c48ddcbf702b1c242dd570057e26212111", + "0x15543c3708653cda9d418b4ccd3be11368e40636c10c44b18cfe756b6d88b29", + "0x7", + "0x30baaaf1b243f6e74c656f98dcb24b98687dcbe783d25f35854148c4c602d41", + "0x0", + "0xb67495", + "0x0", + "0x1", + "0x3a1045717884ca9abbc2e", + "0x0" + ], + "max_fee": "0x7f49b0d6d7c", + "nonce": "0x62", + "sender_address": "0x6f7afd58d20aedbdb694ff539d3280ae497c1a510caddcc6a06c97eebd001dc", + "signature": [ + "0x1", + "0xd8744b5d5c0da02d6562bd48d4271e95ac7753aae044c8e736862875ce2092", + "0x4f24eb09e7e8c2105e204dfeaa737948cf9c5c4fb2749074c73fdbb2400a68f" + ] + } + } + }, + "transaction_hash": "0x215b2e7efdedc5d9c056dd6a691b8117f292997d2cc8c15a9cebfa90620e35" + }, + { + "block_number": 636864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x63548034064bb4bc4aff845f0350e286e695225480627c1048d3216735bc9af", + "transaction": { + "Invoke": { + "V3": { + "account_deployment_data": [], + "calldata": [ + "0x1", + "0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05", + "0x3943907ef0ef6f9d2e2408b05e520a66daaf74293dbf665e5a20b117676170e", + "0x2", + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "0x16345785d8a0000" + ], + "fee_data_availability_mode": "L1", + "nonce": "0x9d", + "nonce_data_availability_mode": "L1", + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0xa9e", + "max_price_per_unit": "0x7f2a1ad4f2f1" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x69c0f9bcd79697bdceaf7748e3ff8f34aa39e4063ce44896af664c0c96f6c10", + "signature": [ + "0x1", + "0x1c3a868705399362140bf5ae33f955f1c946a8f836d4c052f2aff397bcfe80a", + "0x78163ce5979e2bc8a944ba353a63c194ca4f63d393bbaaa95857daa9223e93c" + ], + "tip": "0x0" + } + } + }, + "transaction_hash": "0x1d4735f4ba73a67be2f648d9b21cab3783383b8c229566b46b027c46012219" + }, + { + "block_number": 2700, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x29486d2b24527399b8e6d00d36554c9b5af4262da1ef79a5550a9ee8702ff7", + "transaction": { + "Declare": { + "V0": { + "class_hash": "0x7319e2f01b0947afd86c0bb0e95029551b32f6dc192c47b2e8b08415eebbc25", + "max_fee": "0x0", + "nonce": "0x0", + "sender_address": "0x1", + "signature": [] + } + } + }, + "transaction_hash": "0x2f2ef64daffdc72bf33b34ad024891691b8eb1d0ab70cc7f8fb71f6fd5e1f22" + }, + { + "block_number": 346864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x67ca9b823b4da32b06ec58ee1b2e87684d64f083b97b6bc14f64b5ef76533c2", + "transaction": { + "Declare": { + "V1": { + "class_hash": "0x4dae654c7b6707667a178729b512d61494fe590ab4accc46923d6409b97e617", + "max_fee": "0x1f04d0693837", + "nonce": "0x15", + "sender_address": "0x3e2a6434cebce4475cdf8843859f2137259918171eba8d462e3d34c5c4fd110", + "signature": [ + "0x72d657c8bed37c254615966b94178bbaeb87edbe9ebd176657b80d538c8d7c5", + "0x2fd512374a9eb0277338bf95fbf29315d449a35120a0880dfeff5fd39e7fe80" + ] + } + } + }, + "transaction_hash": "0x70fb3ea4b786b752817a32d4835eaba19da495392df90f7f827cd9b60b2c925" + }, + { + "block_number": 446864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x147b15cef8590ac21e43629bc7c99a8570b08a2b5675c4ee7cc2931e834b032", + "transaction": { + "Declare": { + "V2": { + "class_hash": "0x4d90a3b52871831b34bc936d9aee304b7205202e649dceef5ee4392659ab33", + "compiled_class_hash": "0x3c1296b5f7e6a30bc0167bf30e0700eebb2e9a06228e24cc3ad386502125bcf", + "max_fee": "0xb48df232e93750", + "nonce": "0x1f9", + "sender_address": "0x75341b8090a4257f22dafffe3a4cb882006bd26302720d6a80a1fde154a3430", + "signature": [ + "0x10fe9fe438cd3c5bd2c4aa94ea8723d1d0a7a2da63ea42a328bf4f8eb3812d7", + "0x40c359c942fd1ce5f8fc3effe53c8943273df95418ecadef1cd71c1c667d016" + ] + } + } + }, + "transaction_hash": "0x7debe525c66a929048236c8f6da5903e4f141e5cb5e6cb23e9af33ecaabe062" + }, + { + "block_number": 630721, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x71aa91a887080fa2fb1e473713123dca182eae42433c5422bbada8125819dc9", + "transaction": { + "Declare": { + "V3": { + "account_deployment_data": [], + "class_hash": "0x7a9d1cd5dcf3d47b10e638eb1330d101f7d471f08eff9664b42dfa90f6973bf", + "compiled_class_hash": "0x4fc6444f59a2fb0b2c67e1e22caba0edc3b48727e8a9cc19e59e5c3e5dc8270", + "fee_data_availability_mode": "L1", + "nonce": "0x3", + "nonce_data_availability_mode": "L1", + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0xe38c2", + "max_price_per_unit": "0x24e2649cc098" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x46d3a562c606077c14c3479946e4145b7a372538875eb4e635e758fcd1d2c80", + "signature": [ + "0x14bdaa66720b2f7cb5d55041de921f38bca2b8133e903f446a43e78943a1d05", + "0x6ed9788306ec1f51157fdeeacb1094b2c1e001bcc7c4eaf31d2b66f02cdc5b0" + ], + "tip": "0x0" + } + } + }, + "transaction_hash": "0x50ca961fd1b5f7f1ea1e8620ac980cc3c3fb4e434f0661c3a2d50893082b9fb" + }, + { + "block_number": 636864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0xbdaff4caa84e6d32cfd7ff9b51c04d398df9bfeaa5ba3d4fafd327e4e8840e", + "transaction": { + "DeployAccount": { + "V1": { + "class_hash": "0x13bfe114fb1cf405bfc3a7f8dbe2d91db146c17521d40dcf57e16d6b59fa8e6", + "constructor_calldata": [ + "0x54c617a2e91df5344958e0eb2c30c58a1134b3f8e59e88deba60a24f95c0a2c" + ], + "contract_address_salt": "0x54c617a2e91df5344958e0eb2c30c58a1134b3f8e59e88deba60a24f95c0a2c", + "max_fee": "0x3a23c71d8b9", + "nonce": "0x0", + "signature": [ + "0x19bba00834026bc1a1045a71bfa909e6c6d41bc872b5bfa1364f1229144ac4a", + "0x48f9fd27ec3a8cb2420a930c72cb81e47c69790519cbc963c320ed2c9b36456", + "0x816dd0297efc55dc1e7559020a3a825e81ef734b558f03c83325d4da7e6253", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x534e5f4d41494e", + "0x1d474323258a89e5b5de7ef0bfc162f85357c8d5140388fcf33c0f93993f7cf", + "0x7f86bb20596368f23ca9a720e54dc05bf487f1c45b66da0d94ffab186ee1ac6" + ] + } + } + }, + "transaction_hash": "0x40e7ac7efc374f3d1241c6f991de2ea534d84e8be307420658353527226c5e4" + }, + { + "block_number": 636864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0xe035fefb0a5f799d4c4b651f86937a848e1394fb161c80148024e143f6839c", + "transaction": { + "DeployAccount": { + "V3": { + "class_hash": "0x13bfe114fb1cf405bfc3a7f8dbe2d91db146c17521d40dcf57e16d6b59fa8e6", + "constructor_calldata": [ + "0x1f218cfa725d1679ff028c53d094a765dfd1de632787cab37ffe10f3915dcc7" + ], + "contract_address_salt": "0x1f218cfa725d1679ff028c53d094a765dfd1de632787cab37ffe10f3915dcc7", + "fee_data_availability_mode": "L1", + "nonce": "0x0", + "nonce_data_availability_mode": "L1", + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x4c", + "max_price_per_unit": "0x8ab967606cb9" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "signature": [ + "0x516550aaa957b0f931b1f9347304bb557e29036b5056c0b97b047778c1c8fec", + "0x782d87c2df96241acb2d88260e6ae2f18ad36fd68bd1036cfb2166a30bb9e14", + "0x816dd0297efc55dc1e7559020a3a825e81ef734b558f03c83325d4da7e6253", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x534e5f4d41494e", + "0x3d4d482132b50ef44c8308b7102ca9a21dcaec5b24a8a00b363f6b4824d35f9", + "0x18099527f0007975481b3e34ea897c07d3f137117d382e49859436f8eb25140" + ], + "tip": "0x0" + } + } + }, + "transaction_hash": "0x25cbbc1e197e1e6dd8886b4b359c2dbe26245a282547624d7e54e7c3e2cf15" + }, + { + "block_number": 6864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x457120e60bc4a88d54bbc96046b71366c9fc35c7834d0b52d6cc314c4e075e0", + "transaction": { + "Deploy": { + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "constructor_calldata": [ + "0x3e327de1c40540b98d05cbcb13552008e36f0ec8d61d46956d2f9752c294328", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x77d0eb177b763933debc8596399528e720951662ad078752302f9c447fa59ef", + "0x0" + ], + "contract_address_salt": "0x77d0eb177b763933debc8596399528e720951662ad078752302f9c447fa59ef", + "version": "0x0" + } + }, + "transaction_hash": "0x44ce170a27953fec1809b3d2a03a44ad6b475355748a5f1c01db972f20b295e" + }, + { + "block_number": 546864, + "chain_id": "SN_MAIN", + "only_query_transaction_hash": "0x6eeda9cad938237b5587dcc7205b606b84d29f9624e08f045c0bbd05abbf430", + "transaction": { + "L1Handler": { + "calldata": [ + "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419", + "0x455448", + "0xc27947400e26e534e677afc2e9b2ec1bab14fc89", + "0x4af4754baf89f1b8b449215a8ea7ce558824a33a5393eaa3829658549f2bfa2", + "0x9184e72a000", + "0x0" + ], + "contract_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "entry_point_selector": "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19", + "nonce": "0x18e94d", + "version": "0x0" + } + }, + "transaction_hash": "0x439e12f67962c353182d72b4af12c3f11eaba4b36e552aebcdcd6db66971bdb" + } +] \ No newline at end of file diff --git a/crates/papyrus_common/src/block_hash.rs b/crates/papyrus_common/src/block_hash.rs new file mode 100644 index 00000000000..eaee133485d --- /dev/null +++ b/crates/papyrus_common/src/block_hash.rs @@ -0,0 +1,216 @@ +#[cfg(test)] +#[path = "block_hash_test.rs"] +mod block_hash_test; + +use std::iter::zip; + +use starknet_api::block::{BlockBody, BlockHash, BlockHeader}; +use starknet_api::core::{ + ChainId, + EventCommitment, + SequencerContractAddress, + TransactionCommitment, +}; +use starknet_api::crypto::patricia_hash::calculate_root; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::{ + DeployAccountTransaction, + Event, + Transaction, + TransactionHash, + TransactionOutput, +}; +use starknet_api::StarknetApiError; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Pedersen, StarkHash as CoreStarkHash}; + +use crate::transaction_hash::{ascii_as_felt, HashChain, ZERO}; +use crate::usize_into_felt; + +#[derive(Debug, thiserror::Error)] +pub enum BlockHashError { + #[error("Header is missing data (transaction_commitment / event_commitment)")] + MissingHeaderData, + #[error(transparent)] + StarknetApiError(#[from] StarknetApiError), +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +enum BlockHashVersion { + V0, + V1, + V2, + V3, +} + +/// Validates hash of a starknet header. +/// A hash is valid if it is the result of one of the hash functions that were ever used in +/// Starknet. +pub fn validate_header(header: &BlockHeader, chain_id: &ChainId) -> Result { + for version in + [BlockHashVersion::V3, BlockHashVersion::V2, BlockHashVersion::V1, BlockHashVersion::V0] + { + if calculate_block_hash_by_version(header, version, chain_id)? == header.block_hash { + return Ok(true); + } + } + Ok(false) +} + +/// Validates the body of a starknet block. +pub fn validate_body( + body: &BlockBody, + transaction_commitment: &TransactionCommitment, + event_commitment: &EventCommitment, +) -> Result { + for version in + [BlockHashVersion::V3, BlockHashVersion::V2, BlockHashVersion::V1, BlockHashVersion::V0] + { + let calculated_transaction_commitment = + calculate_transaction_commitment_by_version(body, &version)?; + if calculated_transaction_commitment != *transaction_commitment { + continue; + } + let calculated_event_commitment = + calculate_event_commitment_by_version(&body.transaction_outputs, &version); + if calculated_event_commitment != *event_commitment { + continue; + } + return Ok(true); + } + Ok(false) +} + +// Calculates hash of a starknet block by version, ignoring the block hash field in the given block. +fn calculate_block_hash_by_version( + header: &BlockHeader, + version: BlockHashVersion, + chain_id: &ChainId, +) -> Result { + // Can't implement as a closure because ascii_as_felt returns a Result. + let chain_id_as_felt = if version == BlockHashVersion::V0 { + Some(ascii_as_felt(chain_id.to_string().as_str())?) + } else { + None + }; + + Ok(BlockHash( + HashChain::new() + .chain(&header.block_number.0.into()) + .chain(&header.state_root.0) + .chain_if_fn( + || { + if header.sequencer != SequencerContractAddress::default() || version != BlockHashVersion::V2 { + return Some(*header.sequencer.0.key()); + } + // V2 block with no sequencer address. + Some(get_chain_sequencer_address(chain_id)) + } + ) + .chain_if_fn(|| { + if version >= BlockHashVersion::V1 { + Some(header.timestamp.0.into()) + } else { + Some(*ZERO) + } + }) + .chain(&usize_into_felt(header.n_transactions)) + .chain(&header.transaction_commitment.ok_or(BlockHashError::MissingHeaderData)?.0) + .chain(&usize_into_felt(header.n_events)) + .chain(&header.event_commitment.ok_or(BlockHashError::MissingHeaderData)?.0) + .chain(&ZERO) // Not implemented Element. + .chain(&ZERO) // Not implemented Element. + .chain_if_fn(|| { + chain_id_as_felt + }) + + .chain(&header.parent_hash.0).get_pedersen_hash(), + )) +} + +// Returns the transaction commitment. +fn calculate_transaction_commitment_by_version( + block_body: &BlockBody, + version: &BlockHashVersion, +) -> Result { + let transaction_patricia_leaves = + zip(block_body.transactions.iter(), block_body.transaction_hashes.iter()) + .map(|(transaction, transaction_hash)| { + get_transaction_leaf(transaction, transaction_hash, version) + }) + .collect::, _>>()?; + let transactions_patricia_root = calculate_root::(transaction_patricia_leaves); + Ok(TransactionCommitment(transactions_patricia_root)) +} + +// Returns a Patricia leaf value for a transaction. +fn get_transaction_leaf( + transaction: &Transaction, + transaction_hash: &TransactionHash, + version: &BlockHashVersion, +) -> Result { + let signature = if version >= &BlockHashVersion::V3 { + get_transaction_signature(transaction) + } else { + get_signature_only_from_invoke(transaction) + }; + let signature_hash = HashChain::new().chain_iter(signature.iter()).get_pedersen_hash(); + Ok(Pedersen::hash(&transaction_hash.0, &signature_hash)) +} + +fn get_transaction_signature(transaction: &Transaction) -> Vec { + match transaction { + Transaction::Declare(declare) => declare.signature().0, + Transaction::Deploy(_) => vec![], + Transaction::DeployAccount(deploy_account) => match deploy_account { + DeployAccountTransaction::V1(deploy_account_v1) => { + deploy_account_v1.signature.0.to_owned() + } + DeployAccountTransaction::V3(deploy_account_v3) => { + deploy_account_v3.signature.0.to_owned() + } + }, + Transaction::Invoke(invoke) => invoke.signature().0, + Transaction::L1Handler(_) => vec![], + } +} + +fn get_signature_only_from_invoke(transaction: &Transaction) -> Vec { + if let Transaction::Invoke(invoke) = transaction { invoke.signature().0 } else { vec![] } +} + +// Returns the number of the events, and the Patricia root of the events. +fn calculate_event_commitment_by_version( + transaction_outputs: &[TransactionOutput], + version: &BlockHashVersion, +) -> EventCommitment { + if version < &BlockHashVersion::V1 { + return EventCommitment(*ZERO); + } + let event_patricia_leaves: Vec<_> = + transaction_outputs.iter().flat_map(|output| output.events()).map(get_event_leaf).collect(); + let event_patricia_root = calculate_root::(event_patricia_leaves); + EventCommitment(event_patricia_root) +} + +// Returns a Patricia leaf value for an event. +fn get_event_leaf(event: &Event) -> StarkHash { + let event_keys: Vec<_> = event.content.keys.iter().map(|key| key.0).collect(); + HashChain::new() + .chain(event.from_address.0.key()) + .chain(&HashChain::new().chain_iter(event_keys.iter()).get_pedersen_hash()) + .chain(&HashChain::new().chain_iter(event.content.data.0.iter()).get_pedersen_hash()) + .get_pedersen_hash() +} + +// The fixed sequencer addresses of the chains that have historic blocks with block hash version 2. +fn get_chain_sequencer_address(chain_id: &ChainId) -> StarkHash { + match chain_id { + ChainId::Mainnet => StarkHash::from_hex_unchecked( + "0x021f4b90b0377c82bf330b7b5295820769e72d79d8acd0effa0ebde6e9988bc5", + ), + // TODO(yoav): Add sequencers for the rest of the supported chains that have historic blocks + // with block hash version 2. + _ => unimplemented!("Sequencer address for chain"), + } +} diff --git a/crates/papyrus_common/src/block_hash_test.rs b/crates/papyrus_common/src/block_hash_test.rs new file mode 100644 index 00000000000..676eedfa434 --- /dev/null +++ b/crates/papyrus_common/src/block_hash_test.rs @@ -0,0 +1,64 @@ +use assert_matches::assert_matches; +use starknet_api::block::Block; +use starknet_api::core::ChainId; +use test_utils::read_json_file; + +use crate::block_hash::{ + calculate_block_hash_by_version, + calculate_event_commitment_by_version, + calculate_transaction_commitment_by_version, + BlockHashError, + BlockHashVersion, +}; + +fn validate_block_hash_util(file_name: &str, version: BlockHashVersion) { + let chain_id = ChainId::Mainnet; + let block: Block = serde_json::from_value(read_json_file(file_name)).unwrap(); + let calculated_hash = + calculate_block_hash_by_version(&block.header, version, &chain_id).unwrap(); + assert_eq!(calculated_hash, block.header.block_hash); + + let calculated_transaction_commitment = + calculate_transaction_commitment_by_version(&block.body, &version).unwrap(); + assert_eq!(calculated_transaction_commitment, block.header.transaction_commitment.unwrap()); + + let calculated_event_commitment = + calculate_event_commitment_by_version(&block.body.transaction_outputs, &version); + assert_eq!(calculated_event_commitment, block.header.event_commitment.unwrap()); +} + +#[test] +fn test_block_hash() { + validate_block_hash_util("block_hash.json", BlockHashVersion::V3); +} + +#[test] +fn test_deprecated_block_hash_v2() { + validate_block_hash_util("deprecated_block_hash_v2.json", BlockHashVersion::V2); +} + +#[test] +fn test_deprecated_block_hash_v1_no_events() { + validate_block_hash_util("deprecated_block_hash_v1_no_events.json", BlockHashVersion::V1); +} + +#[test] +fn test_deprecated_block_hash_v1() { + validate_block_hash_util("deprecated_block_hash_v1.json", BlockHashVersion::V1); +} + +#[test] +fn test_deprecated_block_hash_v0() { + validate_block_hash_util("deprecated_block_hash_v0.json", BlockHashVersion::V0); +} + +#[test] +fn test_missing_header_data() { + let chain_id = ChainId::Mainnet; + let mut block: Block = serde_json::from_value(read_json_file("block_hash.json")).unwrap(); + block.header.transaction_commitment = None; + let err = calculate_block_hash_by_version(&block.header, BlockHashVersion::V3, &chain_id) + .unwrap_err(); + + assert_matches!(err, BlockHashError::MissingHeaderData); +} diff --git a/crates/papyrus_common/src/class_hash.rs b/crates/papyrus_common/src/class_hash.rs new file mode 100644 index 00000000000..11f7ab12c27 --- /dev/null +++ b/crates/papyrus_common/src/class_hash.rs @@ -0,0 +1,58 @@ +#[cfg(test)] +#[path = "class_hash_test.rs"] +mod class_hash_test; +use lazy_static::lazy_static; +use sha3::Digest; +use starknet_api::core::ClassHash; +use starknet_api::hash::PoseidonHash; +use starknet_api::state::{ContractClass, EntryPointType}; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Poseidon, StarkHash}; + +use crate::usize_into_felt; + +lazy_static! { + static ref API_VERSION: Felt = Felt::from_bytes_be_slice(b"CONTRACT_CLASS_V0.1.0"); +} + +/// Calculates the hash of a contract class. +// Based on Pathfinder code (the starknet.io doc is incorrect). +pub fn calculate_class_hash(class: &ContractClass) -> ClassHash { + let external_entry_points_hash = entry_points_hash(class, &EntryPointType::External); + let l1_handler_entry_points_hash = entry_points_hash(class, &EntryPointType::L1Handler); + let constructor_entry_points_hash = entry_points_hash(class, &EntryPointType::Constructor); + let abi_keccak = sha3::Keccak256::default().chain_update(class.abi.as_bytes()).finalize(); + let abi_hash = truncated_keccak(abi_keccak.into()); + let program_hash = Poseidon::hash_array(class.sierra_program.as_slice()); + + let class_hash = Poseidon::hash_array(&[ + *API_VERSION, + external_entry_points_hash.0, + l1_handler_entry_points_hash.0, + constructor_entry_points_hash.0, + abi_hash, + program_hash, + ]); + // TODO: Modify ClassHash Be be PoseidonHash instead of StarkFelt. + ClassHash(class_hash) +} + +fn entry_points_hash(class: &ContractClass, entry_point_type: &EntryPointType) -> PoseidonHash { + PoseidonHash(Poseidon::hash_array( + class + .entry_points_by_type + .get(entry_point_type) + .unwrap_or(&vec![]) + .iter() + .flat_map(|ep| [ep.selector.0, usize_into_felt(ep.function_idx.0)]) + .collect::>() + .as_slice(), + )) +} + +// Python code masks with (2**250 - 1) which starts 0x03 and is followed by 31 0xff in be. +// Truncation is needed not to overflow the field element. +fn truncated_keccak(mut plain: [u8; 32]) -> Felt { + plain[0] &= 0x03; + Felt::from_bytes_be(&plain) +} diff --git a/crates/papyrus_common/src/class_hash_test.rs b/crates/papyrus_common/src/class_hash_test.rs new file mode 100644 index 00000000000..0e905ec861e --- /dev/null +++ b/crates/papyrus_common/src/class_hash_test.rs @@ -0,0 +1,15 @@ +use starknet_api::core::ClassHash; +use starknet_api::state::ContractClass; +use starknet_api::{class_hash, felt}; +use test_utils::read_json_file; + +use crate::class_hash::calculate_class_hash; + +#[test] +fn class_hash() { + let class: ContractClass = serde_json::from_value(read_json_file("class.json")).unwrap(); + let expected_class_hash = + class_hash!("0x29927c8af6bccf3f6fda035981e765a7bdbf18a2dc0d630494f8758aa908e2b"); + let calculated_class_hash = calculate_class_hash(&class); + assert_eq!(calculated_class_hash, expected_class_hash); +} diff --git a/crates/papyrus_common/src/deprecated_class_abi.rs b/crates/papyrus_common/src/deprecated_class_abi.rs new file mode 100644 index 00000000000..19a7abcec59 --- /dev/null +++ b/crates/papyrus_common/src/deprecated_class_abi.rs @@ -0,0 +1,63 @@ +use std::io::{Result as IOResult, Write}; + +use serde::Serialize; +use serde_json::ser::{CompactFormatter, Formatter}; + +// TODO: Consider moving to SN API as a method of deprecated_contract_class::ContractClass. +pub fn calculate_deprecated_class_abi_length( + deprecated_class: &starknet_api::deprecated_contract_class::ContractClass, +) -> Result { + let Some(abi) = deprecated_class.abi.as_ref() else { + return Ok(0); + }; + let mut chars = vec![]; + abi.serialize(&mut serde_json::Serializer::with_formatter(&mut chars, PythonJsonFormatter))?; + Ok(chars.len()) +} + +/// Formats a json object in the same way that python's json.dumps() formats. +struct PythonJsonFormatter; + +impl Formatter for PythonJsonFormatter { + fn begin_array_value(&mut self, writer: &mut W, first: bool) -> IOResult<()> + where + W: ?Sized + Write, + { + CompactFormatter.begin_array_value(writer, first)?; + if first { Ok(()) } else { writer.write_all(b" ") } + } + + fn begin_object_key(&mut self, writer: &mut W, first: bool) -> IOResult<()> + where + W: ?Sized + Write, + { + CompactFormatter.begin_object_key(writer, first)?; + if first { Ok(()) } else { writer.write_all(b" ") } + } + + fn begin_object_value(&mut self, writer: &mut W) -> IOResult<()> + where + W: ?Sized + Write, + { + CompactFormatter.begin_object_value(writer)?; + writer.write_all(b" ") + } + + fn write_string_fragment(&mut self, writer: &mut W, fragment: &str) -> IOResult<()> + where + W: ?Sized + Write, + { + let mut buf = [0u16; 2]; + for ch in fragment.chars() { + if ch.is_ascii() { + writer.write_all(&[ch as u8])?; + } else { + let slice = ch.encode_utf16(&mut buf); + for num in slice { + write!(writer, r"\u{:4x}", num)?; + } + } + } + Ok(()) + } +} diff --git a/crates/papyrus_common/src/lib.rs b/crates/papyrus_common/src/lib.rs new file mode 100644 index 00000000000..fb9ab6c0b0a --- /dev/null +++ b/crates/papyrus_common/src/lib.rs @@ -0,0 +1,32 @@ +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_types_core::felt::Felt; + +pub mod block_hash; +pub mod class_hash; +pub mod deprecated_class_abi; +pub mod metrics; +pub mod pending_classes; +pub mod state; +pub mod state_diff_commitment; +pub mod storage_query; +pub mod transaction_hash; + +#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct BlockHashAndNumber { + pub block_hash: BlockHash, + pub block_number: BlockNumber, +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] +pub struct TransactionOptions { + /// Transaction that shouldn't be broadcasted to StarkNet. For example, users that want to + /// test the execution result of a transaction without the risk of it being rebroadcasted (the + /// signature will be different while the execution remain the same). Using this flag will + /// modify the transaction version by setting the 128-th bit to 1. + pub only_query: bool, +} + +pub(crate) fn usize_into_felt(u: usize) -> Felt { + u128::try_from(u).expect("Expect at most 128 bits").into() +} diff --git a/crates/papyrus_common/src/metrics.rs b/crates/papyrus_common/src/metrics.rs new file mode 100644 index 00000000000..c618ab06785 --- /dev/null +++ b/crates/papyrus_common/src/metrics.rs @@ -0,0 +1,42 @@ +use std::sync::OnceLock; + +/// The central marker is the first block number that doesn't exist yet. +pub const PAPYRUS_CENTRAL_BLOCK_MARKER: &str = "papyrus_central_block_marker"; + +/// The header marker is the first block number for which the node does not have a header. +pub const PAPYRUS_HEADER_MARKER: &str = "papyrus_header_marker"; + +/// The body marker is the first block number for which the node does not have a body. +pub const PAPYRUS_BODY_MARKER: &str = "papyrus_body_marker"; + +/// The state marker is the first block number for which the node does not have a state body. +pub const PAPYRUS_STATE_MARKER: &str = "papyrus_state_marker"; + +/// The compiled class marker is the first block number for which the node does not have all of the +/// corresponding compiled classes. +pub const PAPYRUS_COMPILED_CLASS_MARKER: &str = "papyrus_compiled_class_marker"; + +/// The base layer marker is the first block number for which the node does not guarantee L1 +/// finality. +pub const PAPYRUS_BASE_LAYER_MARKER: &str = "papyrus_base_layer_marker"; + +/// The latency, in seconds, between a block timestamp (as state in its header) and the time the +/// node stores the header. +pub const PAPYRUS_HEADER_LATENCY_SEC: &str = "papyrus_header_latency"; + +/// The number of peers this node is connected to. +pub const PAPYRUS_NUM_CONNECTED_PEERS: &str = "papyrus_num_connected_peers"; + +/// The number of active sessions this peer has in which it sends data. +pub const PAPYRUS_NUM_ACTIVE_INBOUND_SESSIONS: &str = "papyrus_num_active_inbound_sessions"; + +/// The number of active sessions this peer has in which it requests data. +pub const PAPYRUS_NUM_ACTIVE_OUTBOUND_SESSIONS: &str = "papyrus_num_active_outbound_sessions"; + +// TODO: consider making this value non static and add a way to change this while the app is +// running. e.g via a monitoring endpoint. +/// Global variable set by the main config to enable collecting profiling metrics. +pub static COLLECT_PROFILING_METRICS: OnceLock = OnceLock::new(); + +/// The height most recently decided by consensus. +pub const PAPYRUS_CONSENSUS_HEIGHT: &str = "papyrus_consensus_height"; diff --git a/crates/papyrus_common/src/pending_classes.rs b/crates/papyrus_common/src/pending_classes.rs new file mode 100644 index 00000000000..85abd49c6db --- /dev/null +++ b/crates/papyrus_common/src/pending_classes.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use starknet_api::core::ClassHash; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::ContractClass; + +pub trait PendingClassesTrait { + // TODO(shahak) Return an Arc to avoid cloning the class. This requires to re-implement + // From/TryFrom for various structs in a way that the input is passed by reference. + fn get_class(&self, class_hash: ClassHash) -> Option; + + fn add_class(&mut self, class_hash: ClassHash, class: ApiContractClass); + + // TODO(shahak) Return an Arc to avoid cloning the class. This requires to re-implement + // From/TryFrom for various structs in a way that the input is passed by reference. + fn get_compiled_class(&self, class_hash: ClassHash) -> Option; + + fn add_compiled_class(&mut self, class_hash: ClassHash, compiled_class: CasmContractClass); + + fn clear(&mut self); +} + +#[derive(Debug, Default, Eq, PartialEq, Clone)] +pub struct PendingClasses { + // Putting the contracts inside Arc so we won't have to clone them when we clone the entire + // PendingClasses struct. + pub classes: HashMap>, + pub compiled_classes: HashMap>, +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum ApiContractClass { + DeprecatedContractClass(DeprecatedContractClass), + ContractClass(ContractClass), +} + +impl ApiContractClass { + pub fn into_cairo0(self) -> Option { + match self { + Self::DeprecatedContractClass(class) => Some(class), + _ => None, + } + } + + pub fn into_cairo1(self) -> Option { + match self { + Self::ContractClass(class) => Some(class), + _ => None, + } + } +} + +impl PendingClassesTrait for PendingClasses { + fn get_class(&self, class_hash: ClassHash) -> Option { + self.classes.get(&class_hash).map(|class| (**class).clone()) + } + + fn add_class(&mut self, class_hash: ClassHash, class: ApiContractClass) { + self.classes.insert(class_hash, Arc::new(class)); + } + + fn get_compiled_class(&self, class_hash: ClassHash) -> Option { + self.compiled_classes.get(&class_hash).map(|compiled_class| (**compiled_class).clone()) + } + + fn add_compiled_class(&mut self, class_hash: ClassHash, compiled_class: CasmContractClass) { + self.compiled_classes.insert(class_hash, Arc::new(compiled_class)); + } + + fn clear(&mut self) { + self.classes.clear(); + self.compiled_classes.clear(); + } +} diff --git a/crates/papyrus_common/src/state.rs b/crates/papyrus_common/src/state.rs new file mode 100644 index 00000000000..badf6d7ba0b --- /dev/null +++ b/crates/papyrus_common/src/state.rs @@ -0,0 +1,62 @@ +use indexmap::indexmap; +use rand::RngCore; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::{StorageKey, ThinStateDiff}; +use starknet_types_core::felt::Felt; + +/// A storage entry in a contract. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StorageEntry { + pub key: StorageKey, + pub value: Felt, +} + +/// A deployed contract in StarkNet. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployedContract { + pub address: ContractAddress, + pub class_hash: ClassHash, +} + +/// A mapping from class hash to the compiled class hash. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeclaredClassHashEntry { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ReplacedClass { + pub address: ContractAddress, + pub class_hash: ClassHash, +} + +// TODO: move to used crate +pub fn create_random_state_diff(rng: &mut impl RngCore) -> ThinStateDiff { + let contract0 = ContractAddress::from(rng.next_u64()); + let contract1 = ContractAddress::from(rng.next_u64()); + let contract2 = ContractAddress::from(rng.next_u64()); + let class_hash = ClassHash(rng.next_u64().into()); + let compiled_class_hash = CompiledClassHash(rng.next_u64().into()); + let deprecated_class_hash = ClassHash(rng.next_u64().into()); + ThinStateDiff { + deployed_contracts: indexmap! { + contract0 => class_hash, contract1 => class_hash, contract2 => deprecated_class_hash + }, + storage_diffs: indexmap! { + contract0 => indexmap! { + 1u64.into() => Felt::ONE, 2u64.into() => Felt::TWO + }, + contract1 => indexmap! { + 3u64.into() => Felt::TWO, 4u64.into() => Felt::ONE + }, + }, + declared_classes: indexmap! { class_hash => compiled_class_hash }, + deprecated_declared_classes: vec![deprecated_class_hash], + nonces: indexmap! { + contract0 => Nonce(Felt::ONE), contract2 => Nonce(Felt::TWO) + }, + replaced_classes: Default::default(), + } +} diff --git a/crates/papyrus_common/src/state_diff_commitment.rs b/crates/papyrus_common/src/state_diff_commitment.rs new file mode 100644 index 00000000000..aac29949376 --- /dev/null +++ b/crates/papyrus_common/src/state_diff_commitment.rs @@ -0,0 +1,112 @@ +#[cfg(test)] +#[path = "state_diff_commitment_test.rs"] +mod state_diff_commitment_test; + +use itertools::Itertools; +use starknet_api::core::StateDiffCommitment; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::hash::PoseidonHash; +use starknet_api::state::ThinStateDiff; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Poseidon, StarkHash}; + +const SUPPORTED_DA_MODES_STATE_DIFF_V0: [DataAvailabilityMode; 1] = [DataAvailabilityMode::L1]; + +/// The version of the state diff for the state diff commitment. +// The version is used to support different data availability modes, currently only L1. +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] +pub enum StateDiffVersion { + #[default] + V0, +} + +impl StateDiffVersion { + /// Returns the supported data availability modes for the given state diff version. + pub fn supported_da_modes(&self) -> Vec { + match self { + StateDiffVersion::V0 => SUPPORTED_DA_MODES_STATE_DIFF_V0.to_vec(), + } + } +} + +impl From for Felt { + fn from(version: StateDiffVersion) -> Self { + match version { + StateDiffVersion::V0 => Felt::ZERO, + } + } +} + +/// Calculates the state diff commitment. +/// The computation is described here: . +pub fn calculate_state_diff_commitment( + state_diff: &ThinStateDiff, + state_diff_version: StateDiffVersion, +) -> StateDiffCommitment { + let mut flattened_total_state_diff = vec![Felt::from(state_diff_version)]; + + // Deployed contracts and replaced classes are squashed. + // Assumption: same contract address cannot be found in deployed and replaced in the same state + // diff. + let num_deployed_contracts = + state_diff.deployed_contracts.len() + state_diff.replaced_classes.len(); + let deployed_contracts_iter = state_diff + .deployed_contracts + .iter() + .chain(state_diff.replaced_classes.iter()) + .sorted_by_key(|(contract_address, _)| *contract_address); + let mut flattened_deployed_contracts = vec![Felt::from(num_deployed_contracts as u64)]; + for (contract_address, class_hash) in deployed_contracts_iter { + flattened_deployed_contracts.push(*contract_address.0.key()); + flattened_deployed_contracts.push(class_hash.0); + } + let hash_of_deployed_contracts = Poseidon::hash_array(&flattened_deployed_contracts); + flattened_total_state_diff.push(hash_of_deployed_contracts); + + let mut flattened_declared_classes = vec![Felt::from(state_diff.declared_classes.len() as u64)]; + for (class_hash, compiled_class_hash) in &state_diff.declared_classes { + flattened_declared_classes.push(class_hash.0); + flattened_declared_classes.push(compiled_class_hash.0); + } + let hash_of_declared_classes = Poseidon::hash_array(&flattened_declared_classes); + flattened_total_state_diff.push(hash_of_declared_classes); + + let mut flattened_deprecated_declared_classes = + vec![Felt::from(state_diff.deprecated_declared_classes.len() as u64)]; + for class_hash in &state_diff.deprecated_declared_classes { + flattened_deprecated_declared_classes.push(class_hash.0); + } + let hash_of_deprecated_declared_classes = + Poseidon::hash_array(&flattened_deprecated_declared_classes); + flattened_total_state_diff.push(hash_of_deprecated_declared_classes); + + let da_modes = state_diff_version.supported_da_modes(); + flattened_total_state_diff.push(Felt::from(da_modes.len() as u64)); + + for da_mode in da_modes { + flattened_total_state_diff.push(Felt::from(da_mode)); + // When more data availability modes are added, the following code should be updated so that + // only the data of the current mode is included. + let mut flattened_storage_diffs = vec![Felt::from(state_diff.storage_diffs.len() as u64)]; + for (contract_address, diffs) in &state_diff.storage_diffs { + flattened_storage_diffs.push(*contract_address.0.key()); + flattened_storage_diffs.push(Felt::from(diffs.len() as u64)); + for (key, value) in diffs { + flattened_storage_diffs.push(*key.0.key()); + flattened_storage_diffs.push(*value); + } + } + let mut flattened_nonces = vec![Felt::from(state_diff.nonces.len() as u64)]; + for (contract_address, nonce) in &state_diff.nonces { + flattened_nonces.push(*contract_address.0.key()); + flattened_nonces.push(nonce.0); + } + let storage_diffs_and_nonces: Vec<_> = + flattened_storage_diffs.into_iter().chain(flattened_nonces).collect(); + let hash_of_storage_domain_state_diff = + Poseidon::hash_array(storage_diffs_and_nonces.as_slice()); + flattened_total_state_diff.push(hash_of_storage_domain_state_diff); + } + + StateDiffCommitment(PoseidonHash(Poseidon::hash_array(flattened_total_state_diff.as_slice()))) +} diff --git a/crates/papyrus_common/src/state_diff_commitment_test.rs b/crates/papyrus_common/src/state_diff_commitment_test.rs new file mode 100644 index 00000000000..c49142367f4 --- /dev/null +++ b/crates/papyrus_common/src/state_diff_commitment_test.rs @@ -0,0 +1,85 @@ +use pretty_assertions::assert_eq; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + Nonce, + PatriciaKey, + StateDiffCommitment, +}; +use starknet_api::hash::PoseidonHash; +use starknet_api::state::{StateDiff, StorageKey, ThinStateDiff}; +use starknet_api::{class_hash, contract_address, felt, patricia_key}; + +use crate::state_diff_commitment::{calculate_state_diff_commitment, StateDiffVersion}; + +#[test] +fn state_diff_commitment() { + let contract_address = contract_address!("0x1"); + let storage_key = StorageKey(patricia_key!("0x1")); + let storage_value = felt!("0x999"); + let nonce = Nonce(felt!("0x1")); + let class_hash = class_hash!("0x70"); + let compiled_class_hash = CompiledClassHash(felt!("0x700")); + let old_class_hash = class_hash!("0x71"); + let replaced_contract_address = contract_address!("0x2"); + let replacing_class_hash = class_hash!("0x72"); + + let thin_state_diff = ThinStateDiff { + deployed_contracts: [(contract_address, class_hash)].into(), + storage_diffs: [(contract_address, [(storage_key, storage_value)].into())].into(), + declared_classes: [(class_hash, compiled_class_hash)].into(), + deprecated_declared_classes: vec![old_class_hash], + nonces: [(contract_address, nonce)].into(), + replaced_classes: [(replaced_contract_address, replacing_class_hash)].into(), + }; + + let calculated_commitment = + calculate_state_diff_commitment(&thin_state_diff, StateDiffVersion::V0); + + // The expected commitment was calculated using the Python implementation of Starknet. + let expected_commitment = StateDiffCommitment(PoseidonHash(felt!( + "0x30eec29bb733bc07197b0e0a41a53808860b2bf9dbb6b4472677a9fc6168a4f" + ))); + + assert_eq!(calculated_commitment, expected_commitment); +} + +#[test] +fn empty_storage_diff() { + // TODO: derive default in ThinStateDiff. + let state_diff = ThinStateDiff::from(StateDiff::default()); + let state_diff_with_empty_storage_diff = ThinStateDiff::from(StateDiff { + storage_diffs: [(ContractAddress::default(), [].into())].into(), + ..Default::default() + }); + + assert_ne!( + calculate_state_diff_commitment(&state_diff, StateDiffVersion::V0), + calculate_state_diff_commitment(&state_diff_with_empty_storage_diff, StateDiffVersion::V0) + ); +} + +#[test] +fn deployed_and_replaced_contracts_are_sorted_for_hashing() { + // Tests a bug fix where the squashing of deployed and replaced contracts was not sorted by + // contract address. + let state_diff = ThinStateDiff { + deployed_contracts: [(contract_address!("0x2"), class_hash!("0x2"))].into(), + storage_diffs: [].into(), + declared_classes: [].into(), + deprecated_declared_classes: [].into(), + nonces: [].into(), + replaced_classes: [ + (contract_address!("0x1"), class_hash!("0x1")), + (contract_address!("0x3"), class_hash!("0x3")), + ] + .into(), + }; + + let calculated_commitment = calculate_state_diff_commitment(&state_diff, StateDiffVersion::V0); + assert_eq!( + calculated_commitment.0.0.to_hex_string(), + "0x5264ab018246d1ab06704c6016285e90962e843561ebb82c4325d7254b1724b" + ); +} diff --git a/crates/papyrus_common/src/storage_query.rs b/crates/papyrus_common/src/storage_query.rs new file mode 100644 index 00000000000..c2eaccb5f09 --- /dev/null +++ b/crates/papyrus_common/src/storage_query.rs @@ -0,0 +1,28 @@ +//! Contains only the [StorageQuery] struct. +//! +//! The struct is used in the storage_benchmark binary and in the document_calls feature of the +//! [papyrus_storage] library. It is not part of the latter because it is not in +//! use without the document_calls feature enabled. +//! +//! [papyrus_storage]: https://docs.rs/papyrus_storage/latest/papyrus_storage/ + +// TODO(dvir): add links to the document for the storage_benchmark binary and the +// document_calls feature after they will be publish. + +use serde::{Deserialize, Serialize}; +use starknet_api::core::ContractAddress; +use starknet_api::state::{StateNumber, StorageKey}; + +/// A storage query. Used for benchmarking in the storage_benchmark binary and in the document_calls +/// feature of the [papyrus_storage](https://docs.rs/papyrus_storage/latest/papyrus_storage/). +// TODO(dvir): add more queries (especially get casm). +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum StorageQuery { + /// Get the class hash at a given state number. + GetClassHashAt(StateNumber, ContractAddress), + /// Get the nonce at a given state number. + GetNonceAt(StateNumber, ContractAddress), + /// Get the storage at a given state number. + GetStorageAt(StateNumber, ContractAddress, StorageKey), +} diff --git a/crates/papyrus_common/src/transaction_hash.rs b/crates/papyrus_common/src/transaction_hash.rs new file mode 100644 index 00000000000..6aa13d88daa --- /dev/null +++ b/crates/papyrus_common/src/transaction_hash.rs @@ -0,0 +1,692 @@ +#[cfg(test)] +#[path = "transaction_hash_test.rs"] +mod transaction_hash_test; + +use lazy_static::lazy_static; +use starknet_api::block::BlockNumber; +use starknet_api::core::{calculate_contract_address, ChainId, ContractAddress}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::{ + DeclareTransaction, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeclareTransactionV3, + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + DeployTransaction, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + L1HandlerTransaction, + Resource, + ResourceBounds, + ResourceBoundsMapping, + Tip, + Transaction, + TransactionHash, + TransactionVersion, +}; +use starknet_api::StarknetApiError; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Pedersen, Poseidon, StarkHash as CoreStarkHash}; + +use crate::TransactionOptions; + +type ResourceName = [u8; 7]; + +const DATA_AVAILABILITY_MODE_BITS: usize = 32; +const L1_GAS: &ResourceName = b"\0L1_GAS"; +const L2_GAS: &ResourceName = b"\0L2_GAS"; + +lazy_static! { + static ref DECLARE: Felt = + #[allow(clippy::unwrap_used)] ascii_as_felt("declare").unwrap(); + static ref DEPLOY: Felt = + #[allow(clippy::unwrap_used)] ascii_as_felt("deploy").unwrap(); + static ref DEPLOY_ACCOUNT: Felt = + #[allow(clippy::unwrap_used)] ascii_as_felt("deploy_account").unwrap(); + static ref INVOKE: Felt = + #[allow(clippy::unwrap_used)] ascii_as_felt("invoke").unwrap(); + static ref L1_HANDLER: Felt = + #[allow(clippy::unwrap_used)] ascii_as_felt("l1_handler").unwrap(); + // The first 250 bits of the Keccak256 hash on "constructor". + // The correctness of this constant is enforced by a test. + static ref CONSTRUCTOR_ENTRY_POINT_SELECTOR: Felt = + #[allow(clippy::unwrap_used)] + Felt::from_hex_unchecked("0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194"); + + pub(crate) static ref ZERO: Felt = Felt::from(0_u8); + static ref ONE: Felt = Felt::from(1_u8); + static ref TWO: Felt = Felt::from(2_u8); + static ref THREE: Felt = Felt::from(3_u8); +} + +/// Calculates hash of a Starknet transaction. +pub fn get_transaction_hash( + transaction: &Transaction, + chain_id: &ChainId, + transaction_options: &TransactionOptions, +) -> Result { + let tx_version = get_tx_version(transaction, transaction_options); + match transaction { + Transaction::Declare(declare) => match declare { + DeclareTransaction::V0(declare_v0) => { + get_declare_transaction_v0_hash(declare_v0, chain_id, &tx_version) + } + DeclareTransaction::V1(declare_v1) => { + get_declare_transaction_v1_hash(declare_v1, chain_id, &tx_version) + } + DeclareTransaction::V2(declare_v2) => { + get_declare_transaction_v2_hash(declare_v2, chain_id, &tx_version) + } + DeclareTransaction::V3(declare_v3) => { + get_declare_transaction_v3_hash(declare_v3, chain_id, &tx_version) + } + }, + Transaction::Deploy(deploy) => get_deploy_transaction_hash(deploy, chain_id, &tx_version), + Transaction::DeployAccount(deploy_account) => match deploy_account { + DeployAccountTransaction::V1(deploy_account_v1) => { + get_deploy_account_transaction_v1_hash(deploy_account_v1, chain_id, &tx_version) + } + DeployAccountTransaction::V3(deploy_account_v3) => { + get_deploy_account_transaction_v3_hash(deploy_account_v3, chain_id, &tx_version) + } + }, + Transaction::Invoke(invoke) => match invoke { + InvokeTransaction::V0(invoke_v0) => { + get_invoke_transaction_v0_hash(invoke_v0, chain_id, &tx_version) + } + InvokeTransaction::V1(invoke_v1) => { + get_invoke_transaction_v1_hash(invoke_v1, chain_id, &tx_version) + } + InvokeTransaction::V3(invoke_v3) => { + get_invoke_transaction_v3_hash(invoke_v3, chain_id, &tx_version) + } + }, + Transaction::L1Handler(l1_handler) => { + get_l1_handler_transaction_hash(l1_handler, chain_id, &tx_version) + } + } +} + +// On mainnet, from this block number onwards, there are no deprecated transactions, +// enabling us to validate against a single hash calculation. +pub const MAINNET_TRANSACTION_HASH_WITH_VERSION: BlockNumber = BlockNumber(1470); + +// Calculates a list of deprecated hashes for a transaction. +fn get_deprecated_transaction_hashes( + chain_id: &ChainId, + block_number: &BlockNumber, + transaction: &Transaction, + transaction_options: &TransactionOptions, +) -> Result, StarknetApiError> { + let tx_version = get_tx_version(transaction, transaction_options); + Ok(if chain_id == &ChainId::Mainnet && block_number > &MAINNET_TRANSACTION_HASH_WITH_VERSION { + vec![] + } else { + match transaction { + Transaction::Declare(_) => vec![], + Transaction::Deploy(deploy) => { + vec![get_deprecated_deploy_transaction_hash(deploy, chain_id, &tx_version)?] + } + Transaction::DeployAccount(_) => vec![], + Transaction::Invoke(invoke) => match invoke { + InvokeTransaction::V0(invoke_v0) => { + vec![get_deprecated_invoke_transaction_v0_hash( + invoke_v0, + chain_id, + &tx_version, + )?] + } + InvokeTransaction::V1(_) | InvokeTransaction::V3(_) => vec![], + }, + Transaction::L1Handler(l1_handler) => { + get_deprecated_l1_handler_transaction_hashes(l1_handler, chain_id, &tx_version)? + } + } + }) +} + +/// Validates the hash of a starknet transaction. +/// For transactions on testnet or those with a low block_number, we validate the +/// transaction hash against all potential historical hash computations. For recent +/// transactions on mainnet, the hash is validated by calculating the precise hash +/// based on the transaction version. +pub fn validate_transaction_hash( + transaction: &Transaction, + block_number: &BlockNumber, + chain_id: &ChainId, + expected_hash: TransactionHash, + transaction_options: &TransactionOptions, +) -> Result { + let mut possible_hashes = get_deprecated_transaction_hashes( + chain_id, + block_number, + transaction, + transaction_options, + )?; + possible_hashes.push(get_transaction_hash(transaction, chain_id, transaction_options)?); + Ok(possible_hashes.contains(&expected_hash)) +} + +// Collect elements for applying hash chain. +pub(crate) struct HashChain { + elements: Vec, +} + +impl HashChain { + pub fn new() -> HashChain { + HashChain { elements: Vec::new() } + } + + // Chains a felt to the hash chain. + pub fn chain(mut self, felt: &Felt) -> Self { + self.elements.push(*felt); + self + } + + // Chains the result of a function to the hash chain. + pub fn chain_if_fn Option>(self, f: F) -> Self { + match f() { + Some(felt) => self.chain(&felt), + None => self, + } + } + + // Chains many felts to the hash chain. + pub fn chain_iter<'a>(self, felts: impl Iterator) -> Self { + felts.fold(self, |current, felt| current.chain(felt)) + } + + // Returns the pedersen hash of the chained felts, hashed with the length of the chain. + pub fn get_pedersen_hash(&self) -> StarkHash { + Pedersen::hash_array(self.elements.as_slice()) + } + + // Returns the poseidon hash of the chained felts. + // TODO: add tests for this function. + pub fn get_poseidon_hash(&self) -> StarkHash { + Poseidon::hash_array(self.elements.as_slice()) + } +} + +pub(crate) fn ascii_as_felt(ascii_str: &str) -> Result { + Felt::from_hex(hex::encode(ascii_str).as_str()) + .map_err(|_| StarknetApiError::OutOfRange { string: ascii_str.to_string() }) +} + +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md +fn get_tip_resource_bounds_hash( + resource_bounds_mapping: &ResourceBoundsMapping, + tip: &Tip, +) -> Result { + let l1_resource_bounds = + resource_bounds_mapping.0.get(&Resource::L1Gas).expect("Missing l1 resource"); + let l1_resource = get_concat_resource(l1_resource_bounds, L1_GAS)?; + + let l2_resource_bounds = + resource_bounds_mapping.0.get(&Resource::L2Gas).expect("Missing l2 resource"); + let l2_resource = get_concat_resource(l2_resource_bounds, L2_GAS)?; + + Ok(HashChain::new() + .chain(&tip.0.into()) + .chain(&l1_resource) + .chain(&l2_resource) + .get_poseidon_hash()) +} + +// Receives resource_bounds and resource_name and returns: +// [0 | resource_name (56 bit) | max_amount (64 bit) | max_price_per_unit (128 bit)]. +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md. +fn get_concat_resource( + resource_bounds: &ResourceBounds, + resource_name: &ResourceName, +) -> Result { + let max_amount = resource_bounds.max_amount.to_be_bytes(); + let max_price = resource_bounds.max_price_per_unit.to_be_bytes(); + let concat_bytes = + [[0_u8].as_slice(), resource_name.as_slice(), max_amount.as_slice(), max_price.as_slice()] + .concat(); + Ok(Felt::from_bytes_be(&concat_bytes.try_into().expect("Expect 32 bytes"))) +} + +// Receives nonce_mode and fee_mode and returns: +// [0...0 (192 bit) | nonce_mode (32 bit) | fee_mode (32 bit)]. +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md. +fn concat_data_availability_mode( + nonce_mode: &DataAvailabilityMode, + fee_mode: &DataAvailabilityMode, +) -> Felt { + (data_availability_mode_index(fee_mode) + + (data_availability_mode_index(nonce_mode) << DATA_AVAILABILITY_MODE_BITS)) + .into() +} + +fn data_availability_mode_index(mode: &DataAvailabilityMode) -> u64 { + match mode { + DataAvailabilityMode::L1 => 0, + DataAvailabilityMode::L2 => 1, + } +} + +fn get_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_deploy_transaction_hash(transaction, chain_id, false, transaction_version) +} + +fn get_deprecated_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_deploy_transaction_hash(transaction, chain_id, true, transaction_version) +} + +fn get_common_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + is_deprecated: bool, + transaction_version: &TransactionVersion, +) -> Result { + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY) + .chain_if_fn(|| { + if !is_deprecated { + Some(transaction_version.0) + } else { + None + } + }) + .chain(contract_address.0.key()) + .chain(&CONSTRUCTOR_ENTRY_POINT_SELECTOR) + .chain( + &HashChain::new() + .chain_iter(transaction.constructor_calldata.0.iter()) + .get_pedersen_hash(), + ) + // No fee in deploy transaction. + .chain_if_fn(|| { + if !is_deprecated { + Some(*ZERO) + } else { + None + } + }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .get_pedersen_hash(), + )) +} + +fn get_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_invoke_transaction_v0_hash(transaction, chain_id, false, transaction_version) +} + +fn get_deprecated_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_invoke_transaction_v0_hash(transaction, chain_id, true, transaction_version) +} + +fn get_common_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + is_deprecated: bool, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain_if_fn(|| if !is_deprecated { Some(transaction_version.0) } else { None }) + .chain(transaction.contract_address.0.key()) + .chain(&transaction.entry_point_selector.0) + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + .chain_if_fn(|| if !is_deprecated { Some(transaction.max_fee.0.into()) } else { None }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .get_pedersen_hash(), + )) +} + +fn get_invoke_transaction_v1_hash( + transaction: &InvokeTransactionV1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&ZERO) // No entry point selector in invoke transaction. + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +fn get_invoke_transaction_v3_hash( + transaction: &InvokeTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let account_deployment_data_hash = HashChain::new() + .chain_iter(transaction.account_deployment_data.0.iter()) + .get_poseidon_hash(); + let calldata_hash = + HashChain::new().chain_iter(transaction.calldata.0.iter()).get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&data_availability_mode) + .chain(&account_deployment_data_hash) + .chain(&calldata_hash) + .get_poseidon_hash(), + )) +} + +#[derive(PartialEq, PartialOrd)] +enum L1HandlerVersions { + AsInvoke, + V0Deprecated, + V0, +} + +fn get_l1_handler_transaction_hash( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::V0, + transaction_version, + ) +} + +fn get_deprecated_l1_handler_transaction_hashes( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result, StarknetApiError> { + Ok(vec![ + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::AsInvoke, + transaction_version, + )?, + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::V0Deprecated, + transaction_version, + )?, + ]) +} + +fn get_common_l1_handler_transaction_hash( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + version: L1HandlerVersions, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain_if_fn(|| { + if version == L1HandlerVersions::AsInvoke { + Some(*INVOKE) + } else { + Some(*L1_HANDLER) + } + }) + .chain_if_fn(|| { + if version > L1HandlerVersions::V0Deprecated { + Some(transaction_version.0) + } else { + None + } + }) + .chain(transaction.contract_address.0.key()) + .chain(&transaction.entry_point_selector.0) + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + // No fee in l1 handler transaction. + .chain_if_fn(|| { + if version > L1HandlerVersions::V0Deprecated { + Some(*ZERO) + } else { + None + } + }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain_if_fn(|| { + if version > L1HandlerVersions::AsInvoke { + Some(transaction.nonce.0) + } else { + None + } + }) + .get_pedersen_hash(), + )) +} + +fn get_declare_transaction_v0_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&ZERO ) // No entry point selector in declare transaction. + .chain(&HashChain::new().get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.class_hash.0) + .get_pedersen_hash(), + )) +} + +fn get_declare_transaction_v1_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&ZERO) // No entry point selector in declare transaction. + .chain(&HashChain::new().chain(&transaction.class_hash.0).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +fn get_declare_transaction_v2_hash( + transaction: &DeclareTransactionV2, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&ZERO) // No entry point selector in declare transaction. + .chain(&HashChain::new().chain(&transaction.class_hash.0).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&transaction.compiled_class_hash.0) + .get_pedersen_hash(), + )) +} + +fn get_declare_transaction_v3_hash( + transaction: &DeclareTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let account_deployment_data_hash = HashChain::new() + .chain_iter(transaction.account_deployment_data.0.iter()) + .get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&data_availability_mode) + .chain(&account_deployment_data_hash) + .chain(&transaction.class_hash.0) + .chain(&transaction.compiled_class_hash.0) + .get_poseidon_hash(), + )) +} + +fn get_deploy_account_transaction_v1_hash( + transaction: &DeployAccountTransactionV1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let calldata_hash = HashChain::new() + .chain(&transaction.class_hash.0) + .chain(&transaction.contract_address_salt.0) + .chain_iter(transaction.constructor_calldata.0.iter()) + .get_pedersen_hash(); + + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY_ACCOUNT) + .chain(&transaction_version.0) + .chain(contract_address.0.key()) + .chain(&ZERO) // No entry point selector in deploy account transaction. + .chain(&calldata_hash) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +fn get_deploy_account_transaction_v3_hash( + transaction: &DeployAccountTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let constructor_calldata_hash = + HashChain::new().chain_iter(transaction.constructor_calldata.0.iter()).get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY_ACCOUNT) + .chain(&transaction_version.0) + .chain(contract_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&data_availability_mode) + .chain(&transaction.nonce.0) + .chain(&constructor_calldata_hash) + .chain(&transaction.class_hash.0) + .chain(&transaction.contract_address_salt.0) + .get_poseidon_hash(), + )) +} + +// Returns the transaction version taking into account the transaction options. +fn get_tx_version( + tx: &Transaction, + transaction_options: &TransactionOptions, +) -> TransactionVersion { + let mut version = match tx { + Transaction::Declare(tx) => tx.version(), + Transaction::Deploy(tx) => tx.version, + Transaction::DeployAccount(tx) => tx.version(), + Transaction::Invoke(tx) => tx.version(), + Transaction::L1Handler(tx) => tx.version, + }; + + // If only_query is true, set the 128-th bit. + if transaction_options.only_query { + let query_only_bit: Felt = Felt::from_hex_unchecked("0x100000000000000000000000000000000"); + let fe: Felt = version.0; + version = TransactionVersion(fe + query_only_bit); + } + version +} diff --git a/crates/papyrus_common/src/transaction_hash_test.rs b/crates/papyrus_common/src/transaction_hash_test.rs new file mode 100644 index 00000000000..95e19b0218e --- /dev/null +++ b/crates/papyrus_common/src/transaction_hash_test.rs @@ -0,0 +1,126 @@ +use pretty_assertions::assert_eq; +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Keccak256}; +use starknet_api::block::BlockNumber; +use starknet_api::core::ChainId; +use starknet_api::transaction::{Transaction, TransactionHash}; +use starknet_types_core::felt::Felt; +use test_utils::read_json_file; + +use super::{ + ascii_as_felt, + get_transaction_hash, + validate_transaction_hash, + CONSTRUCTOR_ENTRY_POINT_SELECTOR, +}; +use crate::TransactionOptions; + +#[test] +fn test_ascii_as_felt() { + let sn_main_id = ChainId::Mainnet; + let sn_main_felt = ascii_as_felt(sn_main_id.to_string().as_str()).unwrap(); + // This is the result of the Python snippet from the Chain-Id documentation. + let expected_sn_main = Felt::from(23448594291968334_u128); + assert_eq!(sn_main_felt, expected_sn_main); +} + +#[test] +fn test_constructor_selector() { + let mut keccak = Keccak256::default(); + keccak.update(b"constructor"); + let mut constructor_bytes: [u8; 32] = keccak.finalize().into(); + constructor_bytes[0] &= 0b00000011_u8; // Discard the six MSBs. + let constructor_felt = Felt::from_bytes_be(&constructor_bytes); + assert_eq!(constructor_felt, *CONSTRUCTOR_ENTRY_POINT_SELECTOR); +} + +#[derive(Deserialize, Serialize)] +struct TransactionTestData { + transaction: Transaction, + transaction_hash: TransactionHash, + only_query_transaction_hash: Option, + chain_id: ChainId, + block_number: BlockNumber, +} + +#[test] +fn test_transaction_hash() { + // The details were taken from Starknet Mainnet. You can found the transactions by hash in: + // https://alpha-mainnet.starknet.io/feeder_gateway/get_transaction?transactionHash= + let transactions_test_data_vec: Vec = + serde_json::from_value(read_json_file("transaction_hash.json")).unwrap(); + + for transaction_test_data in transactions_test_data_vec { + assert!( + validate_transaction_hash( + &transaction_test_data.transaction, + &transaction_test_data.block_number, + &transaction_test_data.chain_id, + transaction_test_data.transaction_hash, + &TransactionOptions::default(), + ) + .unwrap(), + "expected transaction hash {}", + transaction_test_data.transaction_hash + ); + let actual_transaction_hash = get_transaction_hash( + &transaction_test_data.transaction, + &transaction_test_data.chain_id, + &TransactionOptions::default(), + ) + .unwrap(); + assert_eq!( + actual_transaction_hash, transaction_test_data.transaction_hash, + "expected_transaction_hash: {:?}", + transaction_test_data.transaction_hash + ); + } +} + +#[test] +fn test_deprecated_transaction_hash() { + // The details were taken from Starknet Mainnet. You can found the transactions by hash in: + // https://alpha-mainnet.starknet.io/feeder_gateway/get_transaction?transactionHash= + let transaction_test_data_vec: Vec = + serde_json::from_value(read_json_file("deprecated_transaction_hash.json")).unwrap(); + + for transaction_test_data in transaction_test_data_vec { + assert!( + validate_transaction_hash( + &transaction_test_data.transaction, + &transaction_test_data.block_number, + &transaction_test_data.chain_id, + transaction_test_data.transaction_hash, + &TransactionOptions::default(), + ) + .unwrap(), + "expected_transaction_hash: {:?}", + transaction_test_data.transaction_hash + ); + } +} + +#[test] +fn test_only_query_transaction_hash() { + let transactions_test_data_vec: Vec = + serde_json::from_value(read_json_file("transaction_hash.json")).unwrap(); + + for transaction_test_data in transactions_test_data_vec { + // L1Handler only-query transactions are not supported. + if let Transaction::L1Handler(_) = transaction_test_data.transaction { + continue; + } + + dbg!(transaction_test_data.transaction_hash); + let actual_transaction_hash = get_transaction_hash( + &transaction_test_data.transaction, + &transaction_test_data.chain_id, + &TransactionOptions { only_query: true }, + ) + .unwrap(); + assert_eq!( + actual_transaction_hash, + transaction_test_data.only_query_transaction_hash.unwrap(), + ); + } +} diff --git a/crates/papyrus_config/Cargo.toml b/crates/papyrus_config/Cargo.toml new file mode 100644 index 00000000000..13054840b70 --- /dev/null +++ b/crates/papyrus_config/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "papyrus_config" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "A library for handling node configuration." + +[package.metadata.cargo-udeps.ignore] +development = ["tempfile"] # Dependency of a doc-test + +[dependencies] +clap = { workspace = true, features = ["env", "string"] } +itertools.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"]} +strum_macros.workspace = true +thiserror.workspace = true +validator = { workspace = true, features = ["derive"] } + +[dev-dependencies] +assert_matches.workspace = true +itertools.workspace = true +lazy_static.workspace = true +tempfile.workspace = true +test_utils = { path = "../test_utils" } diff --git a/crates/papyrus_config/README.md b/crates/papyrus_config/README.md new file mode 100644 index 00000000000..91a55406fc3 --- /dev/null +++ b/crates/papyrus_config/README.md @@ -0,0 +1,34 @@ +# papyrus-config + +## Description + +papyrus-config is a flexible and powerful layered configuration system designed specifically for Papyrus, a Starknet node. This system allows you to easily manage configurations for your Papyrus node by leveraging various sources and providing additional helpful features. + +## Configuration sources + +Supports multiple configuration sources in ascending order of overriding priority: + +- Default values +- Configuration files (from first to last) +- Environment variables +- Command-line arguments + +## Additional features + +- **Support for Nested Configuration Components:** Organize your configurations into nested components, making it easy to manage complex settings for different aspects of the application. + +- **Usage of Pointers:** Use pointers to merge parameters that are common to multiple components. This capability helps in streamlining configurations and avoiding duplication of settings. + +- **Automatically-Generated Command Line Parser:** To simplify the process of handling command-line arguments, the system automatically generates a command-line parser. This means you don't have to write complex argument parsing code; it's ready to use out-of-the-box. + +- **Automatically-Generated Reference Configuration File:** Makes it easier for users by generating a reference configuration file. This file serves as a template that highlights all available configuration options and their default values, enabling users to customize their configurations efficiently. + +## Documentation + +Developer reference documentation is available at https://docs.rs/papyrus_config/. The documentation on this site is updated periodically. + +To view the most up-to-date documentation, enter the following command at the root directory of the `papyrus` project: + +```shell +cargo doc --open -p papyrus_config +``` \ No newline at end of file diff --git a/crates/papyrus_config/resources/custom_config_example.json b/crates/papyrus_config/resources/custom_config_example.json new file mode 100644 index 00000000000..987a25a88ed --- /dev/null +++ b/crates/papyrus_config/resources/custom_config_example.json @@ -0,0 +1,3 @@ +{ + "param_path": "custom value" +} diff --git a/crates/papyrus_config/src/command.rs b/crates/papyrus_config/src/command.rs new file mode 100644 index 00000000000..3409f6fd257 --- /dev/null +++ b/crates/papyrus_config/src/command.rs @@ -0,0 +1,83 @@ +use std::collections::BTreeMap; +use std::path::PathBuf; + +use clap::{value_parser, Arg, ArgMatches, Command}; +use serde_json::{json, Value}; + +use crate::loading::update_config_map; +use crate::{ConfigError, ParamPath, SerializationType, SerializedParam}; + +pub(crate) fn get_command_matches( + config_map: &BTreeMap, + command: Command, + command_input: Vec, +) -> Result { + Ok(command.args(build_args_parser(config_map)).try_get_matches_from(command_input)?) +} + +// Takes matched arguments from the command line interface and env variables and updates the config +// map. +// Supports usize, bool and String. +pub(crate) fn update_config_map_by_command_args( + config_map: &mut BTreeMap, + types_map: &BTreeMap, + arg_match: &ArgMatches, +) -> Result<(), ConfigError> { + for param_path_id in arg_match.ids() { + let param_path = param_path_id.as_str(); + let new_value = get_arg_by_type(types_map, arg_match, param_path)?; + update_config_map(config_map, types_map, param_path, new_value)?; + } + Ok(()) +} + +// Builds the parser for the command line flags and env variables according to the types of the +// values in the config map. +fn build_args_parser(config_map: &BTreeMap) -> Vec { + let mut args_parser = vec![ + // Custom_config_file_path. + Arg::new("config_file") + .long("config_file") + .short('f') + .value_delimiter(',') + .help("Optionally sets a config file to use") + .value_parser(value_parser!(PathBuf)), + ]; + + for (param_path, serialized_param) in config_map.iter() { + let Some(serialization_type) = serialized_param.content.get_serialization_type() else { + continue; // Pointer target + }; + let clap_parser = match serialization_type { + SerializationType::Number => clap::value_parser!(usize).into(), + SerializationType::Boolean => clap::value_parser!(bool), + SerializationType::String => clap::value_parser!(String), + }; + + let arg = Arg::new(param_path) + .long(param_path) + .env(to_env_var_name(param_path)) + .help(&serialized_param.description) + .value_parser(clap_parser); + args_parser.push(arg); + } + args_parser +} + +// Converts clap arg_matches into json values. +fn get_arg_by_type( + types_map: &BTreeMap, + arg_match: &ArgMatches, + param_path: &str, +) -> Result { + let serialization_type = types_map.get(param_path).expect("missing type"); + match serialization_type { + SerializationType::Number => Ok(json!(arg_match.try_get_one::(param_path)?)), + SerializationType::Boolean => Ok(json!(arg_match.try_get_one::(param_path)?)), + SerializationType::String => Ok(json!(arg_match.try_get_one::(param_path)?)), + } +} + +fn to_env_var_name(param_path: &str) -> String { + param_path.replace("#is_none", "__is_none__").to_uppercase().replace('.', "__") +} diff --git a/crates/papyrus_config/src/config_test.rs b/crates/papyrus_config/src/config_test.rs new file mode 100644 index 00000000000..4fdff4a8886 --- /dev/null +++ b/crates/papyrus_config/src/config_test.rs @@ -0,0 +1,572 @@ +use std::collections::BTreeMap; +use std::env; +use std::fs::File; +use std::path::PathBuf; +use std::time::Duration; + +use assert_matches::assert_matches; +use clap::Command; +use itertools::chain; +use lazy_static::lazy_static; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use tempfile::TempDir; +use test_utils::get_absolute_path; +use validator::Validate; + +use crate::command::{get_command_matches, update_config_map_by_command_args}; +use crate::converters::deserialize_milliseconds_to_duration; +use crate::dumping::{ + append_sub_config_name, + combine_config_map_and_pointers, + ser_generated_param, + ser_optional_param, + ser_optional_sub_config, + ser_param, + ser_pointer_target_param, + ser_required_param, + SerializeConfig, +}; +use crate::loading::{ + load, + load_and_process_config, + split_pointers_map, + split_values_and_types, + update_config_map_by_pointers, + update_optional_values, +}; +use crate::presentation::get_config_presentation; +use crate::{ + ConfigError, + ParamPath, + ParamPrivacy, + ParamPrivacyInput, + SerializationType, + SerializedContent, + SerializedParam, +}; + +lazy_static! { + static ref CUSTOM_CONFIG_PATH: PathBuf = + get_absolute_path("crates/papyrus_config/resources/custom_config_example.json"); +} + +#[derive(Clone, Copy, Default, Serialize, Deserialize, Debug, PartialEq, Validate)] +struct InnerConfig { + #[validate(range(min = 0, max = 10))] + o: usize, +} + +impl SerializeConfig for InnerConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from([ser_param("o", &self.o, "This is o.", ParamPrivacyInput::Public)]) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Validate)] +struct OuterConfig { + opt_elem: Option, + opt_config: Option, + #[validate] + inner_config: InnerConfig, +} + +impl SerializeConfig for OuterConfig { + fn dump(&self) -> BTreeMap { + chain!( + ser_optional_param( + &self.opt_elem, + 1, + "opt_elem", + "This is elem.", + ParamPrivacyInput::Public + ), + ser_optional_sub_config(&self.opt_config, "opt_config"), + append_sub_config_name(self.inner_config.dump(), "inner_config"), + ) + .collect() + } +} + +#[test] +fn dump_and_load_config() { + let some_outer_config = OuterConfig { + opt_elem: Some(2), + opt_config: Some(InnerConfig { o: 3 }), + inner_config: InnerConfig { o: 4 }, + }; + let none_outer_config = + OuterConfig { opt_elem: None, opt_config: None, inner_config: InnerConfig { o: 5 } }; + + for outer_config in [some_outer_config, none_outer_config] { + let (mut dumped, _) = split_values_and_types(outer_config.dump()); + update_optional_values(&mut dumped); + let loaded_config = load::(&dumped).unwrap(); + assert_eq!(loaded_config, outer_config); + } +} + +#[test] +fn test_validation() { + let outer_config = + OuterConfig { opt_elem: None, opt_config: None, inner_config: InnerConfig { o: 20 } }; + assert!(outer_config.validate().is_err()); +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +struct TypicalConfig { + #[serde(deserialize_with = "deserialize_milliseconds_to_duration")] + a: Duration, + b: String, + c: bool, +} + +impl SerializeConfig for TypicalConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from([ + ser_param( + "a", + &self.a.as_millis(), + "This is a as milliseconds.", + ParamPrivacyInput::Public, + ), + ser_param("b", &self.b, "This is b.", ParamPrivacyInput::Public), + ser_param("c", &self.c, "This is c.", ParamPrivacyInput::Private), + ]) + } +} + +#[test] +fn test_update_dumped_config() { + let command = Command::new("Testing"); + let dumped_config = + TypicalConfig { a: Duration::from_secs(1), b: "bbb".to_owned(), c: false }.dump(); + let args = vec!["Testing", "--a", "1234", "--b", "15"]; + env::set_var("C", "true"); + let args: Vec = args.into_iter().map(|s| s.to_owned()).collect(); + + let arg_matches = get_command_matches(&dumped_config, command, args).unwrap(); + let (mut config_map, required_map) = split_values_and_types(dumped_config); + update_config_map_by_command_args(&mut config_map, &required_map, &arg_matches).unwrap(); + + assert_eq!(json!(1234), config_map["a"]); + assert_eq!(json!("15"), config_map["b"]); + assert_eq!(json!(true), config_map["c"]); + + let loaded_config: TypicalConfig = load(&config_map).unwrap(); + assert_eq!(Duration::from_millis(1234), loaded_config.a); +} + +#[test] +fn test_env_nested_params() { + let command = Command::new("Testing"); + let dumped_config = OuterConfig { + opt_elem: Some(1), + opt_config: Some(InnerConfig { o: 2 }), + inner_config: InnerConfig { o: 3 }, + } + .dump(); + let args = vec!["Testing", "--opt_elem", "1234"]; + env::set_var("OPT_CONFIG____IS_NONE__", "true"); + env::set_var("INNER_CONFIG__O", "4"); + let args: Vec = args.into_iter().map(|s| s.to_owned()).collect(); + + let arg_matches = get_command_matches(&dumped_config, command, args).unwrap(); + let (mut config_map, required_map) = split_values_and_types(dumped_config); + update_config_map_by_command_args(&mut config_map, &required_map, &arg_matches).unwrap(); + + assert_eq!(json!(1234), config_map["opt_elem"]); + assert_eq!(json!(true), config_map["opt_config.#is_none"]); + assert_eq!(json!(4), config_map["inner_config.o"]); + + update_optional_values(&mut config_map); + + let loaded_config: OuterConfig = load(&config_map).unwrap(); + assert_eq!(Some(1234), loaded_config.opt_elem); + assert_eq!(None, loaded_config.opt_config); + assert_eq!(4, loaded_config.inner_config.o); +} + +#[test] +fn test_config_presentation() { + let config = TypicalConfig { a: Duration::from_secs(1), b: "bbb".to_owned(), c: false }; + let presentation = get_config_presentation(&config, true).unwrap(); + let keys: Vec<_> = presentation.as_object().unwrap().keys().collect(); + assert_eq!(keys, vec!["a", "b", "c"]); + + let public_presentation = get_config_presentation(&config, false).unwrap(); + let keys: Vec<_> = public_presentation.as_object().unwrap().keys().collect(); + assert_eq!(keys, vec!["a", "b"]); +} + +#[test] +fn test_nested_config_presentation() { + let configs = vec![ + OuterConfig { + opt_elem: Some(1), + opt_config: Some(InnerConfig { o: 2 }), + inner_config: InnerConfig { o: 3 }, + }, + OuterConfig { + opt_elem: None, + opt_config: Some(InnerConfig { o: 2 }), + inner_config: InnerConfig { o: 3 }, + }, + OuterConfig { opt_elem: Some(1), opt_config: None, inner_config: InnerConfig { o: 3 } }, + ]; + + for config in configs { + let presentation = get_config_presentation(&config, true).unwrap(); + let keys: Vec<_> = presentation.as_object().unwrap().keys().collect(); + assert_eq!(keys, vec!["inner_config", "opt_config", "opt_elem"]); + let public_presentation = get_config_presentation(&config, false).unwrap(); + let keys: Vec<_> = public_presentation.as_object().unwrap().keys().collect(); + assert_eq!(keys, vec!["inner_config", "opt_config", "opt_elem"]); + } +} + +#[test] +fn test_pointers_flow() { + let config_map = BTreeMap::from([ + ser_param("a1", &json!(5), "This is a.", ParamPrivacyInput::Public), + ser_param("a2", &json!(5), "This is a.", ParamPrivacyInput::Private), + ]); + let pointers = vec![( + ser_pointer_target_param("common_a", &json!(10), "This is common a"), + vec!["a1".to_owned(), "a2".to_owned()], + )]; + let stored_map = combine_config_map_and_pointers(config_map, &pointers).unwrap(); + assert_eq!( + stored_map["a1"], + json!(SerializedParam { + description: "This is a.".to_owned(), + content: SerializedContent::PointerTarget("common_a".to_owned()), + privacy: ParamPrivacy::Public, + }) + ); + assert_eq!( + stored_map["a2"], + json!(SerializedParam { + description: "This is a.".to_owned(), + content: SerializedContent::PointerTarget("common_a".to_owned()), + privacy: ParamPrivacy::Private, + }) + ); + assert_eq!( + stored_map["common_a"], + json!(SerializedParam { + description: "This is common a".to_owned(), + content: SerializedContent::DefaultValue(json!(10)), + privacy: ParamPrivacy::TemporaryValue, + }) + ); + + let serialized = serde_json::to_string(&stored_map).unwrap(); + let loaded = serde_json::from_str(&serialized).unwrap(); + let (loaded_config_map, loaded_pointers_map) = split_pointers_map(loaded); + let (mut config_map, _) = split_values_and_types(loaded_config_map); + update_config_map_by_pointers(&mut config_map, &loaded_pointers_map).unwrap(); + assert_eq!(config_map["a1"], json!(10)); + assert_eq!(config_map["a1"], config_map["a2"]); +} + +#[test] +fn test_replace_pointers() { + let (mut config_map, _) = split_values_and_types(BTreeMap::from([ser_param( + "a", + &json!(5), + "This is a.", + ParamPrivacyInput::Public, + )])); + let pointers_map = + BTreeMap::from([("b".to_owned(), "a".to_owned()), ("c".to_owned(), "a".to_owned())]); + update_config_map_by_pointers(&mut config_map, &pointers_map).unwrap(); + assert_eq!(config_map["a"], config_map["b"]); + assert_eq!(config_map["a"], config_map["c"]); + + let err = update_config_map_by_pointers(&mut BTreeMap::default(), &pointers_map).unwrap_err(); + assert_matches!(err, ConfigError::PointerTargetNotFound { .. }); +} + +#[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq)] +struct CustomConfig { + param_path: String, + #[serde(default)] + seed: usize, +} + +impl SerializeConfig for CustomConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from([ + ser_param( + "param_path", + &self.param_path, + "This is param_path.", + ParamPrivacyInput::Public, + ), + ser_generated_param( + "seed", + SerializationType::Number, + "A dummy seed with generated default = 0.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +// Loads CustomConfig from args. +fn load_custom_config(args: Vec<&str>) -> CustomConfig { + let dir = TempDir::new().unwrap(); + let file_path = dir.path().join("config.json"); + CustomConfig { param_path: "default value".to_owned(), seed: 5 } + .dump_to_file(&vec![], file_path.to_str().unwrap()) + .unwrap(); + + load_and_process_config::( + File::open(file_path).unwrap(), + Command::new("Program"), + args.into_iter().map(|s| s.to_owned()).collect(), + ) + .unwrap() +} + +#[test] +fn test_load_default_config() { + let args = vec!["Testing"]; + let param_path = load_custom_config(args).param_path; + assert_eq!(param_path, "default value"); +} + +#[test] +fn test_load_custom_config_file() { + let args = vec!["Testing", "-f", CUSTOM_CONFIG_PATH.to_str().unwrap()]; + let param_path = load_custom_config(args).param_path; + assert_eq!(param_path, "custom value"); +} + +#[test] +fn test_load_custom_config_file_and_args() { + let args = vec![ + "Testing", + "--config_file", + CUSTOM_CONFIG_PATH.to_str().unwrap(), + "--param_path", + "command value", + ]; + let param_path = load_custom_config(args).param_path; + assert_eq!(param_path, "command value"); +} + +#[test] +fn test_load_many_custom_config_files() { + let custom_config_path = CUSTOM_CONFIG_PATH.to_str().unwrap(); + let cli_config_param = format!("{custom_config_path},{custom_config_path}"); + let args = vec!["Testing", "-f", cli_config_param.as_str()]; + let param_path = load_custom_config(args).param_path; + assert_eq!(param_path, "custom value"); +} + +#[test] +fn test_generated_type() { + let args = vec!["Testing"]; + assert_eq!(load_custom_config(args).seed, 0); + + let args = vec!["Testing", "--seed", "7"]; + assert_eq!(load_custom_config(args).seed, 7); +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +struct RequiredConfig { + param_path: String, + num: usize, +} + +impl SerializeConfig for RequiredConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from([ + ser_required_param( + "param_path", + SerializationType::String, + "This is param_path.", + ParamPrivacyInput::Public, + ), + ser_param("num", &self.num, "This is num.", ParamPrivacyInput::Public), + ]) + } +} + +// Loads param_path of RequiredConfig from args. +fn load_required_param_path(args: Vec<&str>) -> String { + let dir = TempDir::new().unwrap(); + let file_path = dir.path().join("config.json"); + RequiredConfig { param_path: "default value".to_owned(), num: 3 } + .dump_to_file(&vec![], file_path.to_str().unwrap()) + .unwrap(); + + let loaded_config = load_and_process_config::( + File::open(file_path).unwrap(), + Command::new("Program"), + args.into_iter().map(|s| s.to_owned()).collect(), + ) + .unwrap(); + loaded_config.param_path +} + +#[test] +fn test_negative_required_param() { + let dumped_config = RequiredConfig { param_path: "0".to_owned(), num: 3 }.dump(); + let (config_map, _) = split_values_and_types(dumped_config); + let err = load::(&config_map).unwrap_err(); + assert_matches!(err, ConfigError::MissingParam { .. }); +} + +#[test] +fn test_required_param_from_command() { + let args = vec!["Testing", "--param_path", "1234"]; + let param_path = load_required_param_path(args); + assert_eq!(param_path, "1234"); +} + +#[test] +fn test_required_param_from_file() { + let args = vec!["Testing", "--config_file", CUSTOM_CONFIG_PATH.to_str().unwrap()]; + let param_path = load_required_param_path(args); + assert_eq!(param_path, "custom value"); +} + +#[test] +fn deeply_nested_optionals() { + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Default)] + struct Level0 { + level0_value: u8, + level1: Option, + } + + impl SerializeConfig for Level0 { + fn dump(&self) -> BTreeMap { + let mut res = BTreeMap::from([ser_param( + "level0_value", + &self.level0_value, + "This is level0_value.", + ParamPrivacyInput::Public, + )]); + res.extend(ser_optional_sub_config(&self.level1, "level1")); + res + } + } + + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Default)] + struct Level1 { + pub level1_value: u8, + pub level2: Option, + } + + impl SerializeConfig for Level1 { + fn dump(&self) -> BTreeMap { + let mut res = BTreeMap::from([ser_param( + "level1_value", + &self.level1_value, + "This is level1_value.", + ParamPrivacyInput::Public, + )]); + res.extend(ser_optional_sub_config(&self.level2, "level2")); + res + } + } + + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Default)] + struct Level2 { + pub level2_value: Option, + } + + impl SerializeConfig for Level2 { + fn dump(&self) -> BTreeMap { + ser_optional_param( + &self.level2_value, + 1, + "level2_value", + "This is level2_value.", + ParamPrivacyInput::Public, + ) + } + } + + let dir = TempDir::new().unwrap(); + let file_path = dir.path().join("config2.json"); + Level0 { level0_value: 1, level1: None } + .dump_to_file(&vec![], file_path.to_str().unwrap()) + .unwrap(); + + let l0 = load_and_process_config::( + File::open(file_path.clone()).unwrap(), + Command::new("Testing"), + Vec::new(), + ) + .unwrap(); + assert_eq!(l0, Level0 { level0_value: 1, level1: None }); + + let l1 = load_and_process_config::( + File::open(file_path.clone()).unwrap(), + Command::new("Testing"), + vec!["Testing".to_owned(), "--level1.#is_none".to_owned(), "false".to_owned()], + ) + .unwrap(); + assert_eq!( + l1, + Level0 { level0_value: 1, level1: Some(Level1 { level1_value: 0, level2: None }) } + ); + + let l2 = load_and_process_config::( + File::open(file_path.clone()).unwrap(), + Command::new("Testing"), + vec![ + "Testing".to_owned(), + "--level1.#is_none".to_owned(), + "false".to_owned(), + "--level1.level2.#is_none".to_owned(), + "false".to_owned(), + ], + ) + .unwrap(); + assert_eq!( + l2, + Level0 { + level0_value: 1, + level1: Some(Level1 { level1_value: 0, level2: Some(Level2 { level2_value: None }) }), + } + ); + + let l2_value = load_and_process_config::( + File::open(file_path).unwrap(), + Command::new("Testing"), + vec![ + "Testing".to_owned(), + "--level1.#is_none".to_owned(), + "false".to_owned(), + "--level1.level2.#is_none".to_owned(), + "false".to_owned(), + "--level1.level2.level2_value.#is_none".to_owned(), + "false".to_owned(), + ], + ) + .unwrap(); + assert_eq!( + l2_value, + Level0 { + level0_value: 1, + level1: Some(Level1 { + level1_value: 0, + level2: Some(Level2 { level2_value: Some(1) }), + }), + } + ); +} diff --git a/crates/papyrus_config/src/converters.rs b/crates/papyrus_config/src/converters.rs new file mode 100644 index 00000000000..6cfb27995ac --- /dev/null +++ b/crates/papyrus_config/src/converters.rs @@ -0,0 +1,126 @@ +//! Utils for serialization and deserialization of nested config fields into simple types. +//! These conversions let the command line updater (which supports only numbers strings and +//! booleans) handle these fields. +//! +//! # example +//! +//! ``` +//! use std::collections::BTreeMap; +//! use std::time::Duration; +//! +//! use papyrus_config::converters::deserialize_milliseconds_to_duration; +//! use papyrus_config::loading::load; +//! use serde::Deserialize; +//! use serde_json::json; +//! +//! #[derive(Clone, Deserialize, Debug, PartialEq)] +//! struct DurationConfig { +//! #[serde(deserialize_with = "deserialize_milliseconds_to_duration")] +//! dur: Duration, +//! } +//! +//! let dumped_config = BTreeMap::from([("dur".to_owned(), json!(1000))]); +//! let loaded_config = load::(&dumped_config).unwrap(); +//! assert_eq!(loaded_config.dur.as_secs(), 1); +//! ``` + +use std::collections::HashMap; +use std::time::Duration; + +use serde::de::Error; +use serde::{Deserialize, Deserializer}; + +/// Deserializes milliseconds to duration object. +pub fn deserialize_milliseconds_to_duration<'de, D>(de: D) -> Result +where + D: Deserializer<'de>, +{ + let millis: u64 = Deserialize::deserialize(de)?; + Ok(Duration::from_millis(millis)) +} + +/// Deserializes seconds to duration object. +pub fn deserialize_seconds_to_duration<'de, D>(de: D) -> Result +where + D: Deserializer<'de>, +{ + let secs: u64 = Deserialize::deserialize(de)?; + Ok(Duration::from_secs(secs)) +} + +/// Serializes a map to "k1:v1 k2:v2" string structure. +pub fn serialize_optional_map(optional_map: &Option>) -> String { + match optional_map { + None => "".to_owned(), + Some(map) => map.iter().map(|(k, v)| format!("{k}:{v}")).collect::>().join(" "), + } +} + +/// Deserializes a map from "k1:v1 k2:v2" string structure. +pub fn deserialize_optional_map<'de, D>(de: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let raw_str: String = Deserialize::deserialize(de)?; + if raw_str.is_empty() { + return Ok(None); + } + + let mut map = HashMap::new(); + for raw_pair in raw_str.split(' ') { + let split: Vec<&str> = raw_pair.split(':').collect(); + if split.len() != 2 { + return Err(D::Error::custom(format!( + "pair \"{raw_pair}\" is not valid. The Expected format is name:value" + ))); + } + map.insert(split[0].to_string(), split[1].to_string()); + } + Ok(Some(map)) +} + +/// Serializes a vector to string structure. The vector is expected to be a hex string. +pub fn serialize_optional_vec_u8(optional_vector: &Option>) -> String { + match optional_vector { + None => "".to_owned(), + Some(vector) => { + format!( + "0x{}", + vector.iter().map(|num| format!("{:02x}", num)).collect::>().join("") + ) + } + } +} + +/// Deserializes a vector from string structure. The vector is expected to be a list of u8 values +/// separated by spaces. +pub fn deserialize_optional_vec_u8<'de, D>(de: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let raw_str: String = Deserialize::deserialize(de)?; + if raw_str.is_empty() { + return Ok(None); + } + + if !raw_str.starts_with("0x") { + return Err(D::Error::custom( + "Couldn't deserialize vector. Expected hex string starting with \"0x\"", + )); + } + + let hex_str = &raw_str[2..]; // Strip the "0x" prefix + + let mut vector = Vec::new(); + for i in (0..hex_str.len()).step_by(2) { + let byte_str = &hex_str[i..i + 2]; + let byte = u8::from_str_radix(byte_str, 16).map_err(|e| { + D::Error::custom(format!( + "Couldn't deserialize vector. Failed to parse byte: {} {}", + byte_str, e + )) + })?; + vector.push(byte); + } + Ok(Some(vector)) +} diff --git a/crates/papyrus_config/src/dumping.rs b/crates/papyrus_config/src/dumping.rs new file mode 100644 index 00000000000..f744b415d8d --- /dev/null +++ b/crates/papyrus_config/src/dumping.rs @@ -0,0 +1,293 @@ +//! Utils for serializing config objects into flatten map and json file. +//! The elements structure is: +//! +//! ```json +//! "conf1.conf2.conf3.param_name": { +//! "description": "Param description.", +//! "value": json_value +//! } +//! ``` +//! In addition, supports pointers in the map, with the structure: +//! +//! ```json +//! "conf1.conf2.conf3.param_name": { +//! "description": "Param description.", +//! "pointer_target": "target_param_path" +//! } +//! ``` +//! +//! Supports required params. A required param has no default value, but the type of value that the +//! user must set: +//! ```json +//! "conf1.conf2.conf3.param_name: { +//! "description": "Param description.", +//! "required_type": Number +//! } +//! ``` +//! +//! Supports flags for optional params and sub-configs. An optional param / sub-config has an +//! "#is_none" indicator that determines whether to take its value or to deserialize it to None: +//! ```json +//! "conf1.conf2.#is_none": { +//! "description": "Flag for an optional field.", +//! "value": true +//! } +//! ``` + +use std::collections::BTreeMap; +use std::fs::File; +use std::io::{BufWriter, Write}; + +use itertools::chain; +use serde::Serialize; +use serde_json::{json, Value}; + +use crate::{ + ConfigError, + ParamPath, + ParamPrivacy, + ParamPrivacyInput, + SerializationType, + SerializedContent, + SerializedParam, + IS_NONE_MARK, +}; + +/// Serialization for configs. +pub trait SerializeConfig { + /// Conversion of a configuration to a mapping of flattened parameters to their descriptions and + /// values. + /// Note, in the case of a None sub configs, its elements will not included in the flatten map. + fn dump(&self) -> BTreeMap; + + /// Serialization of a configuration into a JSON file. + /// Takes a vector of {target pointer params, SerializedParam, and vector of pointing params}, + /// adds the target pointer params with the description and a value, and replaces the value of + /// the pointing params to contain only the name of the target they point to. + /// + /// # Example + /// + /// ``` + /// # use std::collections::BTreeMap; + /// + /// # use papyrus_config::dumping::{ser_param, SerializeConfig}; + /// # use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; + /// # use serde::{Deserialize, Serialize}; + /// # use tempfile::TempDir; + /// + /// #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] + /// struct ConfigExample { + /// key: usize, + /// } + /// + /// impl SerializeConfig for ConfigExample { + /// fn dump(&self) -> BTreeMap { + /// BTreeMap::from([ser_param( + /// "key", + /// &self.key, + /// "This is key description.", + /// ParamPrivacyInput::Public, + /// )]) + /// } + /// } + /// + /// let dir = TempDir::new().unwrap(); + /// let file_path = dir.path().join("config.json"); + /// ConfigExample { key: 42 }.dump_to_file(&vec![], file_path.to_str().unwrap()); + /// ``` + /// Note, in the case of a None sub configs, its elements will not be included in the file. + fn dump_to_file( + &self, + config_pointers: &Vec<((ParamPath, SerializedParam), Vec)>, + file_path: &str, + ) -> Result<(), ConfigError> { + let combined_map = combine_config_map_and_pointers(self.dump(), config_pointers)?; + let file = File::create(file_path)?; + let mut writer = BufWriter::new(file); + serde_json::to_writer_pretty(&mut writer, &combined_map)?; + writer.flush()?; + Ok(()) + } +} + +/// Appends `sub_config_name` to the ParamPath for each entry in `sub_config_dump`. +/// In order to load from a dump properly, `sub_config_name` must match the field's name for the +/// struct this function is called from. +pub fn append_sub_config_name( + sub_config_dump: BTreeMap, + sub_config_name: &str, +) -> BTreeMap { + BTreeMap::from_iter( + sub_config_dump + .into_iter() + .map(|(field_name, val)| (format!("{sub_config_name}.{field_name}"), val)), + ) +} + +// Serializes a parameter of a config. +fn common_ser_param( + name: &str, + content: SerializedContent, + description: &str, + privacy: ParamPrivacy, +) -> (String, SerializedParam) { + (name.to_owned(), SerializedParam { description: description.to_owned(), content, privacy }) +} + +/// Serializes a single param of a config. +/// The returned pair is designed to be an input to a dumped config map. +pub fn ser_param( + name: &str, + value: &T, + description: &str, + privacy: ParamPrivacyInput, +) -> (String, SerializedParam) { + common_ser_param( + name, + SerializedContent::DefaultValue(json!(value)), + description, + privacy.into(), + ) +} + +/// Serializes expected type for a single required param of a config. +/// The returned pair is designed to be an input to a dumped config map. +pub fn ser_required_param( + name: &str, + serialization_type: SerializationType, + description: &str, + privacy: ParamPrivacyInput, +) -> (String, SerializedParam) { + common_ser_param( + name, + SerializedContent::ParamType(serialization_type), + format!("A required param! {}", description).as_str(), + privacy.into(), + ) +} + +/// Serializes expected type for a single param of a config that the system may generate. The +/// generation should be defined as serde default field attribute. +/// The returned pair is designed to be an input to a dumped config map. +pub fn ser_generated_param( + name: &str, + serialization_type: SerializationType, + description: &str, + privacy: ParamPrivacyInput, +) -> (String, SerializedParam) { + common_ser_param( + name, + SerializedContent::ParamType(serialization_type), + format!("{} If no value is provided, the system will generate one.", description).as_str(), + privacy.into(), + ) +} + +/// Serializes optional sub-config fields (or default fields for None sub-config) and adds an +/// "#is_none" flag. +pub fn ser_optional_sub_config( + optional_config: &Option, + name: &str, +) -> BTreeMap { + chain!( + BTreeMap::from_iter([ser_is_param_none(name, optional_config.is_none())]), + append_sub_config_name( + match optional_config { + None => T::default().dump(), + Some(config) => config.dump(), + }, + name, + ), + ) + .collect() +} + +/// Serializes optional param value (or default value for None param) and adds an "#is_none" flag. +pub fn ser_optional_param( + optional_param: &Option, + default_value: T, + name: &str, + description: &str, + privacy: ParamPrivacyInput, +) -> BTreeMap { + BTreeMap::from([ + ser_is_param_none(name, optional_param.is_none()), + ser_param( + name, + match optional_param { + Some(param) => param, + None => &default_value, + }, + description, + privacy, + ), + ]) +} + +/// Serializes is_none flag for a param. +pub fn ser_is_param_none(name: &str, is_none: bool) -> (String, SerializedParam) { + common_ser_param( + format!("{name}.{IS_NONE_MARK}").as_str(), + SerializedContent::DefaultValue(json!(is_none)), + "Flag for an optional field.", + ParamPrivacy::TemporaryValue, + ) +} + +/// Serializes a pointer target param of a config. +/// +/// # Example +/// Create config_pointers vector to be used in `dump_to_file`: +/// ``` +/// # use papyrus_config::dumping::ser_pointer_target_param; +/// +/// let pointer_target_param = ser_pointer_target_param( +/// "shared_param", +/// &("param".to_string()), +/// "A string parameter description.", +/// ); +/// let pointer_param_paths = +/// vec!["conf1.conf2.same_param".to_owned(), "conf3.same_param".to_owned()]; +/// let config_pointers = vec![(pointer_target_param, pointer_param_paths)]; +/// ``` +pub fn ser_pointer_target_param( + name: &str, + value: &T, + description: &str, +) -> (String, SerializedParam) { + common_ser_param( + name, + SerializedContent::DefaultValue(json!(value)), + description, + ParamPrivacy::TemporaryValue, + ) +} + +// Takes a config map and a vector of {target param, serialized pointer, and vector of params that +// will point to it}. +// Adds to the map the target params. +// Replaces the value of the pointers to contain only the name of the target they point to. +pub(crate) fn combine_config_map_and_pointers( + mut config_map: BTreeMap, + pointers: &Vec<((ParamPath, SerializedParam), Vec)>, +) -> Result { + for ((target_param, serialized_pointer), pointing_params_vec) in pointers { + config_map.insert(target_param.clone(), serialized_pointer.clone()); + + for pointing_param in pointing_params_vec { + let pointing_serialized_param = + config_map.get(pointing_param).ok_or(ConfigError::PointerSourceNotFound { + pointing_param: pointing_param.to_owned(), + })?; + config_map.insert( + pointing_param.to_owned(), + SerializedParam { + description: pointing_serialized_param.description.clone(), + content: SerializedContent::PointerTarget(target_param.to_owned()), + privacy: pointing_serialized_param.privacy.clone(), + }, + ); + } + } + Ok(json!(config_map)) +} diff --git a/crates/papyrus_config/src/lib.rs b/crates/papyrus_config/src/lib.rs new file mode 100644 index 00000000000..e1c97657477 --- /dev/null +++ b/crates/papyrus_config/src/lib.rs @@ -0,0 +1,175 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] +#![warn(missing_docs)] +//! Configuration utilities for a Starknet node. +//! +//! # Example +//! +//! ``` +//! use std::collections::BTreeMap; +//! use std::fs::File; +//! use std::path::Path; +//! +//! use clap::Command; +//! use papyrus_config::dumping::{ser_param, SerializeConfig}; +//! use papyrus_config::loading::load_and_process_config; +//! use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +//! use serde::{Deserialize, Serialize}; +//! use tempfile::TempDir; +//! +//! #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +//! struct ConfigExample { +//! key: usize, +//! } +//! +//! impl SerializeConfig for ConfigExample { +//! fn dump(&self) -> BTreeMap { +//! BTreeMap::from([ser_param( +//! "key", +//! &self.key, +//! "This is key description.", +//! ParamPrivacyInput::Public, +//! )]) +//! } +//! } +//! +//! let dir = TempDir::new().unwrap(); +//! let file_path = dir.path().join("config.json"); +//! ConfigExample { key: 42 }.dump_to_file(&vec![], file_path.to_str().unwrap()); +//! let file = File::open(file_path).unwrap(); +//! let loaded_config = load_and_process_config::( +//! file, +//! Command::new("Program"), +//! vec!["Program".to_owned(), "--key".to_owned(), "770".to_owned()], +//! ) +//! .unwrap(); +//! assert_eq!(loaded_config.key, 770); +//! ``` + +use clap::parser::MatchesError; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use validator::ValidationError; +use validators::ParsedValidationErrors; + +pub(crate) const IS_NONE_MARK: &str = "#is_none"; + +/// A nested path of a configuration parameter. +pub type ParamPath = String; +/// A description of a configuration parameter. +pub type Description = String; + +#[cfg(test)] +mod config_test; + +mod command; +pub mod converters; +pub mod dumping; +pub mod loading; +pub mod presentation; +pub mod validators; + +/// The privacy level of a config parameter, that received as input from the configs. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub enum ParamPrivacyInput { + /// The field is visible only by a secret. + Private, + /// The field is visible only to node's users. + Public, +} + +/// The privacy level of a config parameter. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +enum ParamPrivacy { + /// The field is visible only by a secret. + Private, + /// The field is visible only to node's users. + Public, + /// The field is not a part of the final config. + TemporaryValue, +} + +impl From for ParamPrivacy { + fn from(user_param_privacy: ParamPrivacyInput) -> Self { + match user_param_privacy { + ParamPrivacyInput::Private => ParamPrivacy::Private, + ParamPrivacyInput::Public => ParamPrivacy::Public, + } + } +} + +/// A serialized content of a configuration parameter. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum SerializedContent { + /// Serialized JSON default value. + #[serde(rename = "value")] + DefaultValue(Value), + /// The target from which to take the JSON value of a configuration parameter. + PointerTarget(ParamPath), + /// Type of a configuration parameter. + ParamType(SerializationType), +} + +impl SerializedContent { + fn get_serialization_type(&self) -> Option { + match self { + SerializedContent::DefaultValue(value) => match value { + Value::Number(_) => Some(SerializationType::Number), + Value::Bool(_) => Some(SerializationType::Boolean), + Value::String(_) => Some(SerializationType::String), + _ => None, + }, + SerializedContent::PointerTarget(_) => None, + SerializedContent::ParamType(ser_type) => Some(ser_type.clone()), + } + } +} + +/// A description and serialized content of a configuration parameter. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct SerializedParam { + /// The description of the parameter. + pub description: Description, + /// The content of the parameter. + #[serde(flatten)] + pub content: SerializedContent, + pub(crate) privacy: ParamPrivacy, +} + +/// A serialized type of a configuration parameter. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, strum_macros::Display)] +#[allow(missing_docs)] +pub enum SerializationType { + Number, + Boolean, + String, +} + +/// Errors at the configuration dumping and loading process. +#[allow(missing_docs)] +#[derive(thiserror::Error, Debug)] +pub enum ConfigError { + #[error(transparent)] + CommandInput(#[from] clap::error::Error), + #[error(transparent)] + MissingParam(#[from] serde_json::Error), + #[error(transparent)] + CommandMatches(#[from] MatchesError), + #[error(transparent)] + IOError(#[from] std::io::Error), + // TODO(Eitan): Improve error message + #[error("Insert a new param is not allowed: {param_path}.")] + ParamNotFound { param_path: String }, + #[error("{target_param} is not found.")] + PointerTargetNotFound { target_param: String }, + #[error("{pointing_param} is not found.")] + PointerSourceNotFound { pointing_param: String }, + #[error("Changing {param_path} from required type {required} to {given} is not allowed.")] + ChangeRequiredParamType { param_path: String, required: SerializationType, given: Value }, + #[error(transparent)] + ValidationError(#[from] ValidationError), + #[error(transparent)] + ConfigValidationError(#[from] ParsedValidationErrors), +} diff --git a/crates/papyrus_config/src/loading.rs b/crates/papyrus_config/src/loading.rs new file mode 100644 index 00000000000..8d86e7fa9a2 --- /dev/null +++ b/crates/papyrus_config/src/loading.rs @@ -0,0 +1,213 @@ +//! Loads a configuration object, and set values for the fields in the following order of priority: +//! * Command line arguments. +//! * Environment variables (capital letters). +//! * Custom config files, separated by ',' (comma), from last to first. +//! * Default config file. + +use std::collections::BTreeMap; +use std::fs::File; +use std::ops::IndexMut; +use std::path::PathBuf; + +use clap::parser::Values; +use clap::Command; +use command::{get_command_matches, update_config_map_by_command_args}; +use itertools::any; +use serde::Deserialize; +use serde_json::{json, Map, Value}; + +use crate::validators::validate_path_exists; +use crate::{ + command, + ConfigError, + ParamPath, + SerializationType, + SerializedContent, + SerializedParam, + IS_NONE_MARK, +}; + +/// Deserializes config from flatten JSON. +/// For an explanation of `for<'a> Deserialize<'a>` see +/// ``. +pub fn load Deserialize<'a>>( + config_map: &BTreeMap, +) -> Result { + let mut nested_map = json!({}); + for (param_path, value) in config_map { + let mut entry = &mut nested_map; + for config_name in param_path.split('.') { + entry = entry.index_mut(config_name); + } + *entry = value.clone(); + } + Ok(serde_json::from_value(nested_map)?) +} + +/// Deserializes a json config file, updates the values by the given arguments for the command, and +/// set values for the pointers. +pub fn load_and_process_config Deserialize<'a>>( + default_config_file: File, + command: Command, + args: Vec, +) -> Result { + let deserialized_default_config: Map = + serde_json::from_reader(default_config_file)?; + + // Store the pointers separately from the default values. The pointers will receive a value + // only at the end of the process. + let (default_config_map, pointers_map) = split_pointers_map(deserialized_default_config); + // Take param paths with corresponding descriptions, and get the matching arguments. + let mut arg_matches = get_command_matches(&default_config_map, command, args)?; + let (mut values_map, types_map) = split_values_and_types(default_config_map); + // If the config_file arg is given, updates the values map according to this files. + if let Some(custom_config_paths) = arg_matches.remove_many::("config_file") { + update_config_map_by_custom_configs(&mut values_map, &types_map, custom_config_paths)?; + }; + // Updates the values map according to the args. + update_config_map_by_command_args(&mut values_map, &types_map, &arg_matches)?; + // Set values to the pointers. + update_config_map_by_pointers(&mut values_map, &pointers_map)?; + // Set values according to the is-none marks. + update_optional_values(&mut values_map); + // Build and return a Config object. + load(&values_map) +} + +// Separates a json map into config map of the raw values and pointers map. +pub(crate) fn split_pointers_map( + json_map: Map, +) -> (BTreeMap, BTreeMap) { + let mut config_map: BTreeMap = BTreeMap::new(); + let mut pointers_map: BTreeMap = BTreeMap::new(); + for (param_path, stored_param) in json_map { + let Ok(ser_param) = serde_json::from_value::(stored_param.clone()) else { + unreachable!("Invalid type in the json config map") + }; + match ser_param.content { + SerializedContent::PointerTarget(pointer_target) => { + pointers_map.insert(param_path, pointer_target); + } + _ => { + config_map.insert(param_path, ser_param); + } + }; + } + (config_map, pointers_map) +} + +// Removes the description from the config map, and splits the config map into default values and +// types of the default and required values. +// The types map includes required params, that do not have a value yet. +pub(crate) fn split_values_and_types( + config_map: BTreeMap, +) -> (BTreeMap, BTreeMap) { + let mut values_map: BTreeMap = BTreeMap::new(); + let mut types_map: BTreeMap = BTreeMap::new(); + for (param_path, serialized_param) in config_map { + let Some(serialization_type) = serialized_param.content.get_serialization_type() else { + continue; + }; + types_map.insert(param_path.clone(), serialization_type); + + if let SerializedContent::DefaultValue(value) = serialized_param.content { + values_map.insert(param_path, value); + }; + } + (values_map, types_map) +} + +// Updates the config map by param path to value custom json files. +pub(crate) fn update_config_map_by_custom_configs( + config_map: &mut BTreeMap, + types_map: &BTreeMap, + custom_config_paths: Values, +) -> Result<(), ConfigError> { + for config_path in custom_config_paths { + validate_path_exists(&config_path)?; + let file = std::fs::File::open(config_path)?; + let custom_config: Map = serde_json::from_reader(file)?; + for (param_path, json_value) in custom_config { + update_config_map(config_map, types_map, param_path.as_str(), json_value)?; + } + } + Ok(()) +} + +// Sets values in the config map to the params in the pointers map. +pub(crate) fn update_config_map_by_pointers( + config_map: &mut BTreeMap, + pointers_map: &BTreeMap, +) -> Result<(), ConfigError> { + for (param_path, target_param_path) in pointers_map { + let Some(target_value) = config_map.get(target_param_path) else { + return Err(ConfigError::PointerTargetNotFound { + target_param: target_param_path.to_owned(), + }); + }; + config_map.insert(param_path.to_owned(), target_value.clone()); + } + Ok(()) +} + +// Removes the none marks, and sets null for the params marked as None instead of the inner params. +pub(crate) fn update_optional_values(config_map: &mut BTreeMap) { + let optional_params: Vec<_> = config_map + .keys() + .filter_map(|param_path| param_path.strip_suffix(&format!(".{IS_NONE_MARK}"))) + .map(|param_path| param_path.to_owned()) + .collect(); + let mut none_params = vec![]; + for optional_param in optional_params { + let value = config_map + .remove(&format!("{optional_param}.{IS_NONE_MARK}")) + .expect("Not found optional param"); + if value == json!(true) { + none_params.push(optional_param); + } + } + // Remove param paths that start with any None param. + config_map.retain(|param_path, _| { + !any(&none_params, |none_param| param_path.starts_with(none_param)) + }); + + // Set null for the None params. + for none_param in &none_params { + let mut is_nested_in_outer_none_config = false; + for other_none_param in &none_params { + if none_param.starts_with(other_none_param) && none_param != other_none_param { + is_nested_in_outer_none_config = true; + } + } + if is_nested_in_outer_none_config { + continue; + } + config_map.insert(none_param.clone(), Value::Null); + } +} + +pub(crate) fn update_config_map( + config_map: &mut BTreeMap, + types_map: &BTreeMap, + param_path: &str, + new_value: Value, +) -> Result<(), ConfigError> { + let Some(serialization_type) = types_map.get(param_path) else { + return Err(ConfigError::ParamNotFound { param_path: param_path.to_string() }); + }; + let is_type_matched = match serialization_type { + SerializationType::Number => new_value.is_number(), + SerializationType::Boolean => new_value.is_boolean(), + SerializationType::String => new_value.is_string(), + }; + if !is_type_matched { + return Err(ConfigError::ChangeRequiredParamType { + param_path: param_path.to_string(), + required: serialization_type.to_owned(), + given: new_value, + }); + } + + config_map.insert(param_path.to_owned(), new_value); + Ok(()) +} diff --git a/crates/papyrus_config/src/presentation.rs b/crates/papyrus_config/src/presentation.rs new file mode 100644 index 00000000000..ea8f3702470 --- /dev/null +++ b/crates/papyrus_config/src/presentation.rs @@ -0,0 +1,74 @@ +//! presentation of a configuration, with hiding or exposing private parameters. + +use std::ops::IndexMut; + +use itertools::Itertools; +use serde::Serialize; + +use crate::dumping::SerializeConfig; +use crate::{ConfigError, ParamPrivacy}; + +/// Returns presentation of the public parameters in the config. +pub fn get_config_presentation( + config: &T, + include_private_parameters: bool, +) -> Result { + let mut config_presentation = serde_json::to_value(config)?; + if include_private_parameters { + return Ok(config_presentation); + } + + // Iterates over flatten param paths for removing non-public parameters from the nested config. + for (param_path, serialized_param) in config.dump() { + match serialized_param.privacy { + ParamPrivacy::Public => continue, + ParamPrivacy::TemporaryValue => continue, + ParamPrivacy::Private => remove_path_from_json(¶m_path, &mut config_presentation)?, + } + } + Ok(config_presentation) +} + +// Gets a json in the format: +// { +// a: { +// b: { +// v1: 1, +// v2: 2 +// } +// } +// } +// and a param path, for example 'a.b.v1', and removes the v1 from the json if it exists. +// The result will be: +// { +// a: { +// b: { +// v2: 2 +// } +// } +// } +// If path not found in json then do nothing. +fn remove_path_from_json( + param_path: &str, + json: &mut serde_json::Value, +) -> Result<(), ConfigError> { + // given param_path = "a.b.v1", path_to_entry will be ["a", "b"] and entry_to_remove will + // be "v1". + let mut path_to_entry = param_path.split('.').collect_vec(); + let Some(entry_to_remove) = path_to_entry.pop() else { + // TODO: Can we expect this to never happen? + return Ok(()); // Empty param path. + }; + let mut inner_json = json; + for path in &path_to_entry { + if !inner_json.is_object() { + return Ok(()); // Path not found in json. + } + inner_json = inner_json.index_mut(path); + } + // Remove entry_to_remove from inner_json + if let Some(obj) = inner_json.as_object_mut() { + obj.remove(entry_to_remove); + } + Ok(()) +} diff --git a/crates/papyrus_config/src/validators.rs b/crates/papyrus_config/src/validators.rs new file mode 100644 index 00000000000..51c32caae5c --- /dev/null +++ b/crates/papyrus_config/src/validators.rs @@ -0,0 +1,147 @@ +//! Utils for config validations. + +use std::fmt::Display; +use std::path::Path; + +use validator::{Validate, ValidationError, ValidationErrors, ValidationErrorsKind}; + +use crate::ConfigError; + +/// Custom validation for ASCII string. +pub fn validate_ascii(name: &impl ToString) -> Result<(), ValidationError> { + if !name.to_string().is_ascii() { + return Err(ValidationError::new("The value is not ASCII")); + } + Ok(()) +} + +/// Custom validation for file or directory path existence. +pub fn validate_path_exists(file_path: &Path) -> Result<(), ValidationError> { + if !file_path.exists() { + let mut error = ValidationError::new("file or directory not found"); + error.message = Some( + "Please create the file/directory or change the path in the configuration.".into(), + ); + return Err(error); + } + Ok(()) +} + +/// Custom validation for a 32 byte vector representation. +pub fn validate_vec_u256(vec: &[u8]) -> Result<(), ValidationError> { + if vec.len() != 32 { + return Err(ValidationError::new("The value is not a 32 byte vector")); + } + Ok(()) +} + +/// Struct for parsing a validation error. +#[derive(Debug)] +pub struct ParsedValidationError { + /// The path of the field that failed validation. + pub param_path: String, + /// The error code. + pub code: String, + /// The error message. + pub message: Option, + /// The parameters of the error. + pub params: String, +} + +/// A vector of parsing validation errors. +#[derive(thiserror::Error, Debug)] +pub struct ParsedValidationErrors(pub Vec); + +impl From for ParsedValidationErrors { + fn from(errors: ValidationErrors) -> Self { + let mut parsed_errors: ParsedValidationErrors = ParsedValidationErrors(vec![]); + parse_validation_error(&errors, "".to_string(), &mut parsed_errors); + parsed_errors + } +} + +impl Display for ParsedValidationErrors { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut error_string = String::new(); + for error in &self.0 { + error_string.push_str(&format!( + "Configuration error: The field: {} has an error: {} with value: {}, {} \n", + &error.param_path, + &error.code, + &error.params, + &error.message.clone().unwrap_or("".to_string()), + )); + } + error_string = error_string.replace('\"', ""); + write!(f, "{}", error_string) + } +} + +/// Validates configuration structs that derive the Validate trait. +pub fn config_validate(config: &T) -> Result<(), ConfigError> { + config + .validate() + .map_err(|errors| ConfigError::ConfigValidationError(ParsedValidationErrors::from(errors))) +} + +// This function gets a ValidationError object and parses it recursively to a ParsedValidationError +// object to make it readable for the user. + +// Example of a ValidationError object printed: +// ValidationErrors({"storage": Struct(ValidationErrors({"db_config": +// Struct(ValidationErrors({"path_prefix": Field([ValidationError { code: "file or directory not +// found", message: Some("Please create the file/directory or change the path in the +// configuration."), params: {"value": String("./data")} }])}))}))}) + +// Example of a ParsedValidationError object printed: +// Configuration error: The field "storage.db_config.path_prefix" has an error "file or directory +// not found" with value: "./data" "Please create the file/directory or change the path in the +// configuration." + +fn parse_validation_error( + errors: &ValidationErrors, + current_path: String, + parsed_errors: &mut ParsedValidationErrors, +) { + for (field, error) in errors.errors().iter() { + let new_path = if current_path.is_empty() { + field.to_string() + } else { + format!("{}.{}", current_path, field) + }; + + match error { + ValidationErrorsKind::Struct(errors) => { + parse_validation_error(errors, new_path, parsed_errors); + } + ValidationErrorsKind::List(errors) => { + for (index, error) in errors.iter().enumerate() { + parse_validation_error( + error.1, + format!("{}[{}]", new_path, index), + parsed_errors, + ); + } + } + ValidationErrorsKind::Field(errors) => { + for error in errors { + let parsed_error = ParsedValidationError { + param_path: new_path.to_owned(), + code: error.code.to_string(), + message: error.message.as_ref().map(|cow_string| cow_string.to_string()), + params: { + let params = &error.params; + params + .iter() + .map(|(_k, v)| v.to_string().replace('\"', "")) + .collect::>() + .join(", ") + } + .to_owned(), + }; + parsed_errors.0.push(parsed_error); + } + } + } + } +} diff --git a/crates/papyrus_execution/Cargo.toml b/crates/papyrus_execution/Cargo.toml new file mode 100644 index 00000000000..0035f071ce1 --- /dev/null +++ b/crates/papyrus_execution/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "papyrus_execution" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Transaction and entry point execution functionality for a Papyrus node." + +[features] +testing = ["rand", "rand_chacha", "test_utils"] + +[dependencies] +anyhow.workspace = true +blockifier.workspace = true +cairo-lang-starknet-classes.workspace = true +cairo-vm.workspace = true +indexmap.workspace = true +itertools.workspace = true +lazy_static.workspace = true +once_cell.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +rand = { workspace = true, optional = true } +rand_chacha = { workspace = true, optional = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +starknet_api.workspace = true +starknet-types-core.workspace = true +test_utils = { path = "../test_utils", optional = true } +thiserror.workspace = true +tracing.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +cairo-lang-casm.workspace = true +cairo-lang-utils.workspace = true +indexmap = { workspace = true, features = ["serde"] } +papyrus_storage = { path = "../papyrus_storage", features = ["testing"] } +pretty_assertions.workspace = true +rand.workspace = true +rand_chacha.workspace = true +test_utils = { path = "../test_utils" } + +[package.metadata.cargo-machete] +# The `rand` crate is used in the `testing` feature, which is optional. +ignored = ["rand"] diff --git a/crates/papyrus_execution/resources/account_class.json b/crates/papyrus_execution/resources/account_class.json new file mode 100644 index 00000000000..9aa492285ce --- /dev/null +++ b/crates/papyrus_execution/resources/account_class.json @@ -0,0 +1,2255 @@ +{ + "abi": [ + { + "inputs": [], + "name": "assert_only_self", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "__validate_declare__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + } + ], + "name": "__validate_deploy__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "__validate__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "__execute__", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + } + ], + "name": "deploy_contract", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": 133, + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad" + }, + { + "offset": 94, + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775" + }, + { + "offset": 175, + "selector": "0x2730079d734ee55315f4f141eaed376bddd8c2133523d223a344c5604e0f7f8" + }, + { + "offset": 61, + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3" + }, + { + "offset": 47, + "selector": "0x2de154d8a89be65c1724e962dc4c65637c05532a6c2825d0a7b7d774169dbba" + }, + { + "offset": 77, + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check" + ], + "compiler_version": "0.11.1.1", + "data": [ + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff9", + "0x400380027ff87ffa", + "0x400380037ff87ffb", + "0x400380047ff87ffc", + "0x400380057ff87ffd", + "0x482680017ff88000", + "0x9", + "0x480280067ff88000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x47657443616c6c657241646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574436f6e747261637441646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff9", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x40127fff7fff7ff9", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x40780017fff7fff", + "0x1", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff84", + "0x48127ffd7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff8c", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6a", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe4", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "7": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.call_contract" + ], + "code": "syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": 0 + } + } + } + ], + "20": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.deploy" + ], + "code": "syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.deploy.syscall_ptr": 1 + } + } + } + ], + "27": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_caller_address" + ], + "code": "syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": 2 + } + } + } + ], + "34": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_contract_address" + ], + "code": "syscall_handler.get_contract_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr": 3 + } + } + } + ], + "51": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.assert_only_self" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 16 + }, + "reference_ids": {} + } + } + ], + "67": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate_declare__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 4 + }, + "reference_ids": {} + } + } + ], + "84": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate_deploy__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 5 + }, + "reference_ids": {} + } + } + ], + "109": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 11, + "offset": 11 + }, + "reference_ids": {} + } + } + ], + "166": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.deploy_contract_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 15, + "offset": 0 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.__execute__": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 120, + "type": "function" + }, + "__main__.__execute__.Args": { + "full_name": "__main__.__execute__.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.__execute__.ImplicitArgs": { + "full_name": "__main__.__execute__.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.__execute__.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.__execute__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate__": { + "decorators": [ + "external" + ], + "pc": 93, + "type": "function" + }, + "__main__.__validate__.Args": { + "full_name": "__main__.__validate__.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.__validate__.ImplicitArgs": { + "full_name": "__main__.__validate__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate_declare__": { + "decorators": [ + "external" + ], + "pc": 60, + "type": "function" + }, + "__main__.__validate_declare__.Args": { + "full_name": "__main__.__validate_declare__.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.__validate_declare__.ImplicitArgs": { + "full_name": "__main__.__validate_declare__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate_declare__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate_declare__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate_deploy__": { + "decorators": [ + "external" + ], + "pc": 76, + "type": "function" + }, + "__main__.__validate_deploy__.Args": { + "full_name": "__main__.__validate_deploy__.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.__validate_deploy__.ImplicitArgs": { + "full_name": "__main__.__validate_deploy__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate_deploy__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate_deploy__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.assert_only_self": { + "decorators": [ + "view" + ], + "pc": 38, + "type": "function" + }, + "__main__.assert_only_self.Args": { + "full_name": "__main__.assert_only_self.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.assert_only_self.ImplicitArgs": { + "full_name": "__main__.assert_only_self.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.assert_only_self.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.assert_only_self.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.call_contract": { + "destination": "starkware.starknet.common.syscalls.call_contract", + "type": "alias" + }, + "__main__.deploy": { + "destination": "starkware.starknet.common.syscalls.deploy", + "type": "alias" + }, + "__main__.deploy_contract": { + "decorators": [ + "external" + ], + "pc": 154, + "type": "function" + }, + "__main__.deploy_contract.Args": { + "full_name": "__main__.deploy_contract.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.deploy_contract.ImplicitArgs": { + "full_name": "__main__.deploy_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.deploy_contract.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.deploy_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "__main__.get_contract_address": { + "destination": "starkware.starknet.common.syscalls.get_contract_address", + "type": "alias" + }, + "__wrappers__.__execute__": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 133, + "type": "function" + }, + "__wrappers__.__execute__.Args": { + "full_name": "__wrappers__.__execute__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__execute__.ImplicitArgs": { + "full_name": "__wrappers__.__execute__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__execute__.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__execute__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__execute__.__wrapped_func": { + "destination": "__main__.__execute__", + "type": "alias" + }, + "__wrappers__.__execute___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate__": { + "decorators": [ + "external" + ], + "pc": 94, + "type": "function" + }, + "__wrappers__.__validate__.Args": { + "full_name": "__wrappers__.__validate__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate__.ImplicitArgs": { + "full_name": "__wrappers__.__validate__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate__.__wrapped_func": { + "destination": "__main__.__validate__", + "type": "alias" + }, + "__wrappers__.__validate___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate_declare__": { + "decorators": [ + "external" + ], + "pc": 61, + "type": "function" + }, + "__wrappers__.__validate_declare__.Args": { + "full_name": "__wrappers__.__validate_declare__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_declare__.ImplicitArgs": { + "full_name": "__wrappers__.__validate_declare__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_declare__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate_declare__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate_declare__.__wrapped_func": { + "destination": "__main__.__validate_declare__", + "type": "alias" + }, + "__wrappers__.__validate_declare___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate_deploy__": { + "decorators": [ + "external" + ], + "pc": 77, + "type": "function" + }, + "__wrappers__.__validate_deploy__.Args": { + "full_name": "__wrappers__.__validate_deploy__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_deploy__.ImplicitArgs": { + "full_name": "__wrappers__.__validate_deploy__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_deploy__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate_deploy__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate_deploy__.__wrapped_func": { + "destination": "__main__.__validate_deploy__", + "type": "alias" + }, + "__wrappers__.__validate_deploy___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.assert_only_self": { + "decorators": [ + "view" + ], + "pc": 47, + "type": "function" + }, + "__wrappers__.assert_only_self.Args": { + "full_name": "__wrappers__.assert_only_self.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.assert_only_self.ImplicitArgs": { + "full_name": "__wrappers__.assert_only_self.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.assert_only_self.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.assert_only_self.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.assert_only_self.__wrapped_func": { + "destination": "__main__.assert_only_self", + "type": "alias" + }, + "__wrappers__.assert_only_self_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.deploy_contract": { + "decorators": [ + "external" + ], + "pc": 175, + "type": "function" + }, + "__wrappers__.deploy_contract.Args": { + "full_name": "__wrappers__.deploy_contract.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract.ImplicitArgs": { + "full_name": "__wrappers__.deploy_contract.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.deploy_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.deploy_contract.__wrapped_func": { + "destination": "__main__.deploy_contract", + "type": "alias" + }, + "__wrappers__.deploy_contract_encode_return": { + "decorators": [], + "pc": 166, + "type": "function" + }, + "__wrappers__.deploy_contract_encode_return.Args": { + "full_name": "__wrappers__.deploy_contract_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.deploy_contract_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.deploy_contract_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.deploy_contract_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.deploy_contract_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.starknet.common.syscalls.call_contract.Args": { + "full_name": "starkware.starknet.common.syscalls.call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.call_contract.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 7, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.deploy": { + "decorators": [], + "pc": 12, + "type": "function" + }, + "starkware.starknet.common.syscalls.deploy.Args": { + "full_name": "starkware.starknet.common.syscalls.deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.deploy.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.deploy.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 20, + "value": "cast([fp + (-8)] + 9, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_caller_address": { + "decorators": [], + "pc": 24, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_caller_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.Return": { + "cairo_type": "(caller_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 1 + }, + "pc": 27, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_contract_address": { + "decorators": [], + "pc": 31, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_contract_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_contract_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 31, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 1 + }, + "pc": 34, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 31, + "value": "[cast(fp + (-3), felt**)]" + } + ] + } + } +} diff --git a/crates/papyrus_execution/resources/casm.json b/crates/papyrus_execution/resources/casm.json new file mode 100644 index 00000000000..df41e9fb8a5 --- /dev/null +++ b/crates/papyrus_execution/resources/casm.json @@ -0,0 +1,8776 @@ +{ + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "compiler_version": "2.0.0", + "bytecode": [ + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff9e26", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x93", + "0x4825800180007ffa", + "0x61da", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x9fb", + "0x20680017fff7ffe", + "0x7a", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0xa2e", + "0x20680017fff7ffe", + "0x66", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x43", + "0x1104800180018000", + "0x1549", + "0x482480017fff8000", + "0x1548", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fc7", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe07fff", + "0x10780017fff7fff", + "0x26", + "0x4824800180007fc7", + "0x0", + "0x400080007fe17fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fe37fff8000", + "0x48127ff17fff8000", + "0x1104800180018000", + "0xa27", + "0x482480017fbc8000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0xa76", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fde8000", + "0x1", + "0x48127fc27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0xa59", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fc57fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffb7a8", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xb0", + "0x4825800180007ffa", + "0x4858", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xa10", + "0x20680017fff7ffe", + "0x97", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x985", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x82", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0xa39", + "0x20680017fff7ffa", + "0x71", + "0x20680017fff7ffd", + "0x61", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3e", + "0x1104800180018000", + "0x1494", + "0x482480017fff8000", + "0x1493", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fef", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fec7fff", + "0x10780017fff7fff", + "0x21", + "0x4824800180007fef", + "0x0", + "0x400080007fed7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x1104800180018000", + "0xa52", + "0x482480017fd28000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fea8000", + "0x1", + "0x48127fea7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x9a9", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffb76c", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xa9", + "0x4825800180007ffa", + "0x4894", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x982", + "0x20680017fff7ffa", + "0x95", + "0x20680017fff7ffd", + "0x85", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x40137ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x976", + "0x20680017fff7ffa", + "0x73", + "0x20680017fff7ffd", + "0x63", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x40", + "0x1104800180018000", + "0x13d1", + "0x482480017fff8000", + "0x13d0", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fef", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fec7fff", + "0x10780017fff7fff", + "0x23", + "0x4824800180007fef", + "0x0", + "0x400080007fed7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x1104800180018000", + "0x9be", + "0x482480017fd08000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fea8000", + "0x1", + "0x48127fea7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x8e4", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffd666", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x7e", + "0x4825800180007ffa", + "0x299a", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x972", + "0x20680017fff7ffe", + "0x65", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x42", + "0x1104800180018000", + "0x1323", + "0x482480017fff8000", + "0x1322", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd6", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x25", + "0x4824800180007fd6", + "0x0", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0x97e", + "0x482480017fda8000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x851", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fd17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x834", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x48127fd47fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff5c4a", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x14b", + "0x4825800180007ffa", + "0xa3b6", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x778", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x132", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x770", + "0x20680017fff7ffe", + "0x11e", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x76a", + "0x20680017fff7ffe", + "0x10a", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x764", + "0x20680017fff7ffe", + "0xf6", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x75e", + "0x20680017fff7ffe", + "0xe2", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x758", + "0x20680017fff7ffe", + "0xce", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x752", + "0x20680017fff7ffe", + "0xba", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x74c", + "0x20680017fff7ffe", + "0xa6", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x746", + "0x20680017fff7ffe", + "0x92", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x740", + "0x20680017fff7ffe", + "0x7e", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x73a", + "0x20680017fff7ffe", + "0x6a", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x47", + "0x1104800180018000", + "0x1255", + "0x482480017fff8000", + "0x1254", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007f4f", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007f5d7fff", + "0x10780017fff7fff", + "0x2a", + "0x4824800180007f4f", + "0x0", + "0x400080007f5e7fff", + "0x482480017f5e8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x48127f5a7fff8000", + "0x48127f697fff8000", + "0x48127f777fff8000", + "0x48127f857fff8000", + "0x48127f937fff8000", + "0x48127fa17fff8000", + "0x48127faf7fff8000", + "0x48127fbd7fff8000", + "0x48127fcb7fff8000", + "0x48127fd97fff8000", + "0x48127fe77fff8000", + "0x1104800180018000", + "0x8d0", + "0x20680017fff7ffd", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017f5b8000", + "0x1", + "0x48127f4a7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x761", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127f5e7fff8000", + "0x48127f4d7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127f677fff8000", + "0x48127f567fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127f767fff8000", + "0x48127f657fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127f857fff8000", + "0x48127f747fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127f947fff8000", + "0x48127f837fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fa37fff8000", + "0x48127f927fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fb27fff8000", + "0x48127fa17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fc17fff8000", + "0x48127fb07fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fd07fff8000", + "0x48127fbf7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fdf7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffb7a8", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xb0", + "0x4825800180007ffa", + "0x4858", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x9a9", + "0x20680017fff7ffe", + "0x97", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x60f", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x82", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x6c3", + "0x20680017fff7ffa", + "0x71", + "0x20680017fff7ffd", + "0x61", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3e", + "0x1104800180018000", + "0x111e", + "0x482480017fff8000", + "0x111d", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fef", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fec7fff", + "0x10780017fff7fff", + "0x21", + "0x4824800180007fef", + "0x0", + "0x400080007fed7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x1104800180018000", + "0x9a3", + "0x482480017fd28000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fea8000", + "0x1", + "0x48127fea7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x633", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff8396", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xcb", + "0x4825800180007ffa", + "0x7c6a", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x8e5", + "0x20680017fff7ffe", + "0xb2", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x54b", + "0x20680017fff7ffe", + "0x9e", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x545", + "0x20680017fff7ffe", + "0x8a", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x53f", + "0x20680017fff7ffe", + "0x76", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x539", + "0x20680017fff7ffe", + "0x62", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3f", + "0x1104800180018000", + "0x1054", + "0x482480017fff8000", + "0x1053", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007f9a", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fb37fff", + "0x10780017fff7fff", + "0x22", + "0x4824800180007f9a", + "0x0", + "0x400080007fb47fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fb67fff8000", + "0x48127fc47fff8000", + "0x48127fd27fff8000", + "0x48127fe07fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x907", + "0x482480017f858000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fb18000", + "0x1", + "0x48127f957fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x568", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fb47fff8000", + "0x48127f987fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fbd7fff8000", + "0x48127fa17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fcc7fff8000", + "0x48127fb07fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fdb7fff8000", + "0x48127fbf7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffd986", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x79", + "0x4825800180007ffa", + "0x267a", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x806", + "0x20680017fff7ffe", + "0x60", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3d", + "0x1104800180018000", + "0xf8d", + "0x482480017fff8000", + "0xf8c", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd6", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x20", + "0x4824800180007fd6", + "0x0", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0x8b0", + "0x482480017fda8000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fd17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x4a3", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x48127fd47fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffc81a", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x9c", + "0x4825800180007ffa", + "0x37e6", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3e5", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x83", + "0x48127fff7fff8000", + "0x48127fee7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x40137ffa7fff8000", + "0x1104800180018000", + "0x498", + "0x20680017fff7ffa", + "0x72", + "0x20680017fff7ffd", + "0x62", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3f", + "0x1104800180018000", + "0xef3", + "0x482480017fff8000", + "0xef2", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fef", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fec7fff", + "0x10780017fff7fff", + "0x22", + "0x4824800180007fef", + "0x0", + "0x400080007fed7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x1104800180018000", + "0x842", + "0x482480017fd38000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fea8000", + "0x1", + "0x48127fea7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x407", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffff6d2", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x5d", + "0x4825800180007ffa", + "0x92e", + "0x400280007ff87fff", + "0x48297ffc80007ffd", + "0x482680017ff88000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x34", + "0x1104800180018000", + "0xe54", + "0x482480017fff8000", + "0xe53", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff4", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff47fff", + "0x10780017fff7fff", + "0x16", + "0x4824800180007ff4", + "0x0", + "0x400080007ff57fff", + "0x482480017ff58000", + "0x1", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x7d6", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff28000", + "0x1", + "0x480a7ff97fff8000", + "0x48127fee7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x373", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff57fff8000", + "0x480a7ff97fff8000", + "0x48127ff17fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffabf0", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xc7", + "0x4825800180007ffa", + "0x5410", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x653", + "0x20680017fff7ffe", + "0xae", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x2b9", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x99", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x36d", + "0x20680017fff7ffa", + "0x88", + "0x20680017fff7ffd", + "0x78", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x785", + "0x20680017fff7ffe", + "0x64", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x41", + "0x1104800180018000", + "0xdc2", + "0x482480017fff8000", + "0xdc1", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fdc", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fd97fff", + "0x10780017fff7fff", + "0x24", + "0x4824800180007fdc", + "0x0", + "0x400080007fda7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127fdc7fff8000", + "0x48127fdc7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x78a", + "0x482480017fbc8000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fd78000", + "0x1", + "0x48127fd77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x2d4", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fda7fff8000", + "0x48127fda7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe37fff8000", + "0x48127fe37fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff5d6c", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x64", + "0x4825800180007ffa", + "0xa294", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x3c", + "0x1104800180018000", + "0xd05", + "0x482480017fff8000", + "0xd04", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff4", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff47fff", + "0x10780017fff7fff", + "0x1f", + "0x4824800180007ff4", + "0x0", + "0x400080007ff57fff", + "0x482480017ff58000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x705", + "0x20680017fff7ffd", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff28000", + "0x1", + "0x48127fef7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x21c", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff57fff8000", + "0x48127ff27fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x86", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x16e", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x6d", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x166", + "0x20680017fff7ffe", + "0x59", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x36", + "0x1104800180018000", + "0xc81", + "0x482480017fff8000", + "0xc80", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd6", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe47fff", + "0x10780017fff7fff", + "0x19", + "0x4824800180007fd6", + "0x0", + "0x400080007fe57fff", + "0x48127fe47fff8000", + "0x48127ff37fff8000", + "0x1104800180018000", + "0x736", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x1b4", + "0x482480017fd88000", + "0x1", + "0x48127ff17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fe28000", + "0x1", + "0x48127fd17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x19e", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe57fff8000", + "0x48127fd47fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffd0f8", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x93", + "0x4825800180007ffa", + "0x2f08", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xd4", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x7a", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0xcc", + "0x20680017fff7ffe", + "0x66", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x43", + "0x1104800180018000", + "0xbe7", + "0x482480017fff8000", + "0xbe6", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd6", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe47fff", + "0x10780017fff7fff", + "0x26", + "0x4824800180007fd6", + "0x0", + "0x400080007fe57fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fe27fff8000", + "0x48127ff17fff8000", + "0x1104800180018000", + "0x69c", + "0x482480017fc28000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x114", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fe28000", + "0x1", + "0x48127fd17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0xf7", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe57fff8000", + "0x48127fd47fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x37", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x8", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x480080007ffa8000", + "0x208b7fff7fff7ffe", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffa", + "0x400280027ffb7ffe", + "0x400380037ffb7ffc", + "0x400380047ffb7ffd", + "0x480280067ffb8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffb8000", + "0x482680017ffb8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffb8000", + "0x482680017ffb8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffb8000", + "0x480280087ffb8000", + "0x1104800180018000", + "0x5cf", + "0x20680017fff7ffd", + "0x31", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400080007ff57fff", + "0x400080017ff57ff4", + "0x400080027ff57ffe", + "0x400180037ff57ffc", + "0x480080057ff58000", + "0x20680017fff7fff", + "0xc", + "0x480080047ff48000", + "0x482480017ff38000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080067ff08000", + "0x10780017fff7fff", + "0x9", + "0x480080047ff48000", + "0x482480017ff38000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480080067ff18000", + "0x480080077ff08000", + "0x1104800180018000", + "0x5bd", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xd", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffd7ffb", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff7a", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x26", + "0x40780017fff7fff", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x480080007ff68000", + "0x1104800180018000", + "0x54e", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff98000", + "0x480280097ff98000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0x575", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400280027ff97ffb", + "0x400280037ff97ffc", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xd", + "0x480280067ff98000", + "0x482680017ff98000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0x4bb", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x17", + "0x480a7ffb7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x521", + "0x20680017fff7ffe", + "0x9", + "0x48127ffd7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xe", + "0x480a7ffb7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574426c6f636b48617368", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xc", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x6", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x10780017fff7fff", + "0x9", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x1104800180018000", + "0x466", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff17fff8000", + "0x480a7ff27fff8000", + "0x1104800180018000", + "0x4fc", + "0x20680017fff7ffd", + "0x1ba", + "0x480080007fff8000", + "0x480080007fff8000", + "0x48287ff380007fff", + "0x480080047ffc8000", + "0x480080017ffb8000", + "0x480080027ffa8000", + "0x480080037ff98000", + "0x480080027ff98000", + "0x480080017ff88000", + "0x20680017fff7ff9", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x194", + "0x48287ff480007ffc", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x176", + "0x48287ff580007ff7", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x158", + "0x480080007ff08000", + "0x48287ff680007fff", + "0x480080077fee8000", + "0x480080017fed8000", + "0x480080027fec8000", + "0x480080037feb8000", + "0x480080047fea8000", + "0x480080057fe98000", + "0x480080067fe88000", + "0x20680017fff7ff8", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x132", + "0x48287ff780007ff7", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x114", + "0x48287ff880007ff4", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xf6", + "0x48307ff180007ff2", + "0x4824800180007fff", + "0x1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xd4", + "0x480a7ff07fff8000", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x4a8", + "0x20680017fff7ffd", + "0xc1", + "0x480080007fff8000", + "0x48307fff80007fde", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xa2", + "0x48287ff980007fdb", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x84", + "0x48287ffa80007fd1", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x66", + "0x48287ffb80007fbc", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x48", + "0x48287ffc80007fb9", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x2a", + "0x48287ffd80007fb2", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xe", + "0x40780017fff7fff", + "0x2", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x14", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1b", + "0x48127fe17fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fdf7fff8000", + "0x48127fdf7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x28", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2d", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x31", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x35", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x41", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x45", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x49", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x554e4558504543544544204552524f52", + "0x400080007ffe7fff", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x57", + "0x480a7ff07fff8000", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fa37fff8000", + "0x48127fa37fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc6b", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff98000", + "0x480280097ff98000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0x2ae", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ff9", + "0x400180017fff7ffb", + "0x480680017fff8000", + "0x2", + "0x400080027ffe7fff", + "0x482680017ffc8000", + "0x1", + "0x400080037ffd7fff", + "0x482680017ffd8000", + "0x1", + "0x400080047ffc7fff", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x5", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff87fff", + "0x400380017ff87ff7", + "0x400380027ff87ff9", + "0x400380037ff87ffa", + "0x400280047ff87ffd", + "0x400280057ff87ffe", + "0x480280077ff88000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff88000", + "0x482680017ff88000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff88000", + "0x480280097ff88000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff88000", + "0x482680017ff88000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff88000", + "0x480280097ff88000", + "0x1104800180018000", + "0x271", + "0x20680017fff7ffd", + "0x36", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ffc", + "0x400180017fff7ffd", + "0x48127fff7fff8000", + "0x482480017ffe8000", + "0x2", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400080007ff37fff", + "0x400080017ff37ff2", + "0x400180027ff37ff9", + "0x400180037ff37ffb", + "0x400080047ff37ffd", + "0x400080057ff37ffe", + "0x480080077ff38000", + "0x20680017fff7fff", + "0xb", + "0x480080067ff28000", + "0x482480017ff18000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480080087fef8000", + "0x480080097fee8000", + "0x10780017fff7fff", + "0x9", + "0x480080067ff28000", + "0x482480017ff18000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480080087fef8000", + "0x480080097fee8000", + "0x1104800180018000", + "0x24b", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf", + "0x48127fe77fff8000", + "0x48127fe77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5265706c616365436c617373", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x1104800180018000", + "0x18f", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x53656e644d657373616765546f4c31", + "0x400280007ffa7fff", + "0x400380017ffa7ff9", + "0x400380027ffa7ffb", + "0x400280037ffa7ffd", + "0x400280047ffa7ffe", + "0x480280067ffa8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x1104800180018000", + "0x15d", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48027ffd7ffc8000", + "0x48027ffe7ffc8000", + "0x48027fff7ffc8000", + "0x400280007ffc7ffd", + "0x482480017ffe8000", + "0x1", + "0x400280017ffc7fff", + "0x400280027ffc7ffe", + "0x484480017ffd8000", + "0x3", + "0x48307fff7ffb8000", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x3", + "0x480a7ffd7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x23f", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x15", + "0x480080007ffd8000", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48307ffb80007ffc", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff7", + "0x400380027ff87ff9", + "0x400380037ff87ffa", + "0x400280047ff87ffd", + "0x400280057ff87ffe", + "0x400380067ff87ffd", + "0x480280087ff88000", + "0x20680017fff7fff", + "0xc", + "0x480280077ff88000", + "0x482680017ff88000", + "0xc", + "0x480680017fff8000", + "0x0", + "0x480280097ff88000", + "0x4802800a7ff88000", + "0x4802800b7ff88000", + "0x10780017fff7fff", + "0xb", + "0x480280077ff88000", + "0x482680017ff88000", + "0xb", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480280097ff88000", + "0x4802800a7ff88000", + "0x1104800180018000", + "0x2a3", + "0x20680017fff7ffc", + "0xb", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x400080007ffd7ffe", + "0x400080017ffd7fff", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x2", + "0x1104800180018000", + "0x290", + "0x20680017fff7ffd", + "0x9b", + "0x4824800180007ffe", + "0x587f7cc3722e9654ea3963d5fe8c0748", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x7c", + "0x4824800180007ffb", + "0xa5963aa610cb75ba273817bce5f8c48f", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x5d", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x1", + "0x400080007ffe7fff", + "0x48127ffe7fff8000", + "0x482480017ffd8000", + "0x1", + "0x480680017fff8000", + "0x4b656363616b", + "0x400080007fef7fff", + "0x400080017fef7fee", + "0x400080027fef7ffd", + "0x400080037fef7ffe", + "0x480080057fef8000", + "0x20680017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206661696c", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x480080047feb8000", + "0x482480017fea8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fec7fff8000", + "0x480080067fed8000", + "0x480080077fec8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x298", + "0x480080047fd58000", + "0x482480017fd48000", + "0x8", + "0x20680017fff7ffb", + "0x29", + "0x4824800180007ffd", + "0x496e76616c696420696e707574206c656e677468", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xc", + "0x48127ff67fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e67206572726f72206d7367", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e6720686173682076616c7565", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e6720686173682076616c7565", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x482a7ffd7ffc8000", + "0x1104800180018000", + "0x24e", + "0x20680017fff7ffd", + "0xa", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x505", + "0x482480017fff8000", + "0x504", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff8", + "0x12a2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff77fff", + "0x10780017fff7fff", + "0x4c", + "0x4825800180007ff8", + "0x12a2", + "0x400280007ff77fff", + "0x482680017ff78000", + "0x1", + "0x20780017fff7ffd", + "0xd", + "0x48127fff7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff9b3", + "0x20680017fff7ffe", + "0x27", + "0x400280007ffc7fff", + "0x48127ff07fff8000", + "0x48127fee7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x4825800180007ffd", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd1", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff07fff8000", + "0x48127fee7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff78000", + "0x1", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x12", + "0x4825800180007ffd", + "0x10000000000000000", + "0x4844800180008002", + "0x8000000000000110000000000000000", + "0x4830800080017ffe", + "0x480280007ffc7fff", + "0x482480017ffe8000", + "0xefffffffffffffdeffffffffffffffff", + "0x480280017ffc7fff", + "0x400280027ffc7ffb", + "0x402480017fff7ffb", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x11", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x482680017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x400280017ffc7fff", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574457865637574696f6e496e666f", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x480280037ffd8000", + "0x20680017fff7fff", + "0xc", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280047ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x6", + "0x480680017fff8000", + "0x1", + "0x480280047ffd8000", + "0x480280057ffd8000", + "0x1104800180018000", + "0x19e", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffb80007ffc", + "0xa0680017fff8000", + "0x6", + "0x48317ffe80007ffd", + "0x400280007ffa7fff", + "0x10780017fff7fff", + "0x10", + "0x482680017ffd8000", + "0x1", + "0x48307fff80007ffd", + "0x400280007ffa7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffa8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x482a7ffd7ffb8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e646578206f7574206f6620626f756e6473", + "0x400080007ffe7fff", + "0x482680017ffa8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x4", + "0x10780017fff7fff", + "0xb2", + "0x48037ffd7ffc8002", + "0x48037ffe7ffc8003", + "0x48037fff7ffc8004", + "0x480380007ffa8000", + "0x4825800180018003", + "0x1", + "0x4828800080018000", + "0x480280017ffa8000", + "0x4846800180008000", + "0x3", + "0x48327fff80028000", + "0x400180027fff8004", + "0x400180017fff7ffd", + "0x400380007ffc8002", + "0x400380017ffc8003", + "0x4826800180048000", + "0x1", + "0x400280027ffc7fff", + "0x482680017ffa8000", + "0x2", + "0x480080007ffd8000", + "0x480a7ffd7fff8000", + "0x40337ffe80017ffd", + "0x1104800180018000", + "0xf", + "0x48307fff80007ffe", + "0x48317fff80008001", + "0x4844800180007fff", + "0x3", + "0x484480017fff8000", + "0xfd2", + "0x48127ff97fff8000", + "0x48327ffe7ffb8000", + "0x482680017ffc8000", + "0x3", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x482b7ffc80007ffd", + "0x40780017fff7fff", + "0x3", + "0x20780017fff8000", + "0x6", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x4845800180008000", + "0x3", + "0xa0780017fff8002", + "0x7", + "0x400380007ffb8001", + "0x402680017ffb7fff", + "0x1", + "0x10780017fff7fff", + "0x3", + "0x400a7ffb7fff7fff", + "0x480a7ffc7fff8000", + "0x4825800180007ffd", + "0x1", + "0x480a80017fff8000", + "0x48127ffb7fff8000", + "0x480a80037fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x4", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x480280007ff78002", + "0x4844800180018002", + "0x3", + "0x483280017ff88004", + "0x4800800280038004", + "0x482680017ff78004", + "0x1", + "0x4801800080017ffa", + "0x480380007ffc7ffa", + "0x480080017fff7ffd", + "0x480280017ffc7ffc", + "0x400680017fff7ffb", + "0x0", + "0x20680017fff7ffc", + "0xf", + "0x480080007fff8000", + "0x482480017fff8000", + "0x1", + "0x484480017fff8000", + "0x3", + "0x48307fff7ffa8001", + "0x4800800180007ffa", + "0x480080027fff8000", + "0x480180007ffe7ffa", + "0x402480017ff87fff", + "0x1", + "0x20680017fff7ffc", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x48317ffd80007ff9", + "0x400080007ffe7fff", + "0x48287ff780007ffe", + "0x400280027ffc7ffc", + "0x40337fff80017ffb", + "0x20780017fff8001", + "0x7", + "0x482480017ffd8000", + "0x1", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0xe", + "0x482680017ffa8000", + "0x1", + "0x48317fff80008000", + "0x400080017ffb7fff", + "0x482480017ffb8000", + "0x2", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x10780017fff7fff", + "0x32", + "0x4829800080007ffa", + "0x20680017fff7fff", + "0x4", + "0x402780017fff7fff", + "0x1", + "0x480080017ffc8000", + "0x480080027ffb8000", + "0x484480017fff8000", + "0x2aaaaaaaaaaaab05555555555555556", + "0x48307fff7ffd8000", + "0x480080037ff88000", + "0x480080047ff78000", + "0x484480017fff8000", + "0x4000000000000088000000000000001", + "0x48307fff7ffd8000", + "0x48307fff7ffb8000", + "0x48507ffe7ffa8000", + "0xa0680017fff8000", + "0xc", + "0x484680017ffa8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x402480017fff7ffc", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x4829800080007ffa", + "0x4826800180008000", + "0x1", + "0x40507fff7ffe7ffb", + "0x10780017fff7fff", + "0xf", + "0xa0680017fff8000", + "0xa", + "0x4846800180008000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x40327fff7ffa7ffa", + "0x40527fff7ffa7ffb", + "0x10780017fff7fff", + "0x5", + "0x480a80007fff7ffc", + "0x48297ffa80008000", + "0x40527fff7ffa7ffb", + "0x482480017fee8000", + "0x5", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x482680017ffc8000", + "0x3", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff98", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x48127ffa7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffa", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0xa1", + "0x20680017fff7ffb", + "0x41", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x110", + "0x20680017fff7ffd", + "0x31", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x4b656363616b", + "0x400280007ffb7fff", + "0x400280017ffb7ff9", + "0x400280027ffb7ffd", + "0x400280037ffb7ffe", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0xb", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x1104800180018000", + "0x163", + "0x20680017fff7ffd", + "0xa", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffebb", + "0x20680017fff7ffd", + "0x9", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080007ffc8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1275130f95dda36bcbb6e9d28796c1d7e10b6e9fd5ed083e0ede4b12f613528", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda6", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2a4", + "0x482480017fff8000", + "0x2a3", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff9", + "0x614e", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x59", + "0x4825800180007ff9", + "0x614e", + "0x400280007ff87fff", + "0x482680017ff88000", + "0x1", + "0x48297ffa80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffa8000", + "0x2", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x34", + "0x48127ff87fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480080007ffa8000", + "0x480080017ff98000", + "0x1104800180018000", + "0xc6", + "0x20680017fff7ffd", + "0x20", + "0x48127ffc7fff8000", + "0x48127f597fff8000", + "0x48127f5f7fff8000", + "0x48127f5f7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc8", + "0x20680017fff7ffb", + "0xb", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x48127f597fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x11", + "0x1104800180018000", + "0xa4", + "0x20680017fff7ffd", + "0x67", + "0x20680017fff7ffe", + "0x58", + "0x48297ffc80007ffd", + "0x480280007ffa8004", + "0x4824800180037fff", + "0x1", + "0x48307ffe7fff7ffc", + "0x480280017ffa7ffe", + "0x480280027ffa7fff", + "0x40507ffe7ff97ffd", + "0x40307fff7ffd7ffa", + "0x482680017ffa8000", + "0x3", + "0x480680017fff8000", + "0x11", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0xa0", + "0x20680017fff7ffd", + "0x3f", + "0x4824800180007fff", + "0x1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x2e", + "0x480680017fff8000", + "0x1", + "0x400280007ffd7fff", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x8f", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x1", + "0x20680017fff7ffb", + "0x19", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0xae", + "0x20680017fff7ffd", + "0x9", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x8000000000000001", + "0x400280007ffd7fff", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0xbf", + "0x20680017fff7ffd", + "0x1c", + "0x400280007ffb7fff", + "0x400280017ffb7ffe", + "0x48127ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xb7", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x2", + "0x20680017fff7ffb", + "0xb", + "0x400080007fff7ffd", + "0x400080017fff7ffc", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x482480017ffc8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4a", + "0x48127fb27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fb27fff8000", + "0x48127fb27fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xe8", + "0x20680017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffd80017ffc", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ffb7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x482480017ffc8000", + "0x100000000", + "0x480680017fff8000", + "0x7533325f737562204f766572666c6f77", + "0x1104800180018000", + "0xd7", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x14c", + "0x482480017fff8000", + "0x14b", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ffa", + "0x1612", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x44", + "0x4825800180007ffa", + "0x1612", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x4825800180007ffd", + "0x1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x2e", + "0x480680017fff8000", + "0x0", + "0x400280007ffc7fff", + "0x48127ffd7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb6", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x20680017fff7ffb", + "0x19", + "0x48127ffa7fff8000", + "0x48127fe37fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd5", + "0x20680017fff7ffd", + "0x9", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127fe37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x8000000000000000", + "0x400280007ffc7fff", + "0x48127ffd7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x10000000000000000", + "0x1104800180018000", + "0x79", + "0x20680017fff7ffd", + "0x44", + "0x20680017fff7ffe", + "0x34", + "0x480280007ffc8005", + "0x480280017ffc8005", + "0x4824800180047ffe", + "0x1", + "0x48307ffd7ffe7ffc", + "0x480280027ffc7ffd", + "0xa0680017fff7ffd", + "0x6", + "0x482480017ff97ffd", + "0xffffffffffffffff0000000000000000", + "0x10780017fff7fff", + "0x4", + "0x482480017fff7ffd", + "0xffffffffffffffff0000000000000000", + "0x400280037ffc7ffc", + "0x40507ffe7ff87ffd", + "0x40317fff7ffd7ffd", + "0x482680017ffc8000", + "0x4", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x6f", + "0x20680017fff7ffd", + "0x14", + "0x48127ffc7fff8000", + "0x48127feb7fff8000", + "0x1104800180018000", + "0x69", + "0x20680017fff7ffd", + "0x8", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fea7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x13", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2b", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2d", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fcf7fff8000", + "0x48127fcf7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x55", + "0x20680017fff7ffe", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x7533322069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0xa", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ffd", + "0x480680017fff8000", + "0x1", + "0x48127ffe7fff8000", + "0x482480017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x36", + "0x20680017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3d", + "0x20680017fff7ffe", + "0xb", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x2f", + "0x20680017fff7ffe", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753132382069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x4825800180007ffd", + "0x10000000000000000", + "0x400280007ffc7fff", + "0x10780017fff7fff", + "0xc", + "0x482680017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x400280007ffc7fff", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe" + ], + "hints": [ + [ + 0, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x61da" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 47, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -56 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 69, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 92, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 110, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 124, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 138, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 152, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 169, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x4858" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 228, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -16 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 268, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 286, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 300, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 322, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 336, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 350, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 367, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x4894" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 423, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -16 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 447, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 465, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 483, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 497, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 519, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 541, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 556, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x299a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 597, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -41 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 618, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 641, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 659, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 673, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 687, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 702, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xa3b6" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 803, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -176 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 834, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 852, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 870, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 884, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 898, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 912, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 926, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 940, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 954, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 968, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 982, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 996, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1010, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1024, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1038, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1055, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x4858" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1114, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -16 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1154, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1172, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1186, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1208, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1222, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1236, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1251, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x7c6a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1316, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -101 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1357, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1375, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1389, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1403, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1417, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1431, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1445, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1459, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1474, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x267a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1515, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -41 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1536, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1554, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1572, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1586, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1600, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1617, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x37e6" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1669, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -16 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1692, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1710, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1728, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1742, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1764, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1778, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1793, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x92e" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1828, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -11 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1846, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1857, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1876, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1891, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1909, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x5410" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1974, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -35 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1999, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2017, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2035, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2049, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2063, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2085, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2099, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2113, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2128, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xa294" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2163, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -11 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2183, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2201, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2219, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2233, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2248, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2295, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -41 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2311, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2327, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2345, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2359, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2373, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2387, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2402, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x2f08" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2449, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -41 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2471, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2494, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2512, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2526, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2540, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2554, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2575, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 2579, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 2589, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2671, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 2704, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -11 + } + } + } + } + ] + ], + [ + 2765, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 2769, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 2779, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2839, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2898, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 2947, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 3047, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3316, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3332, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3348, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3364, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3380, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3396, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3422, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3438, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3454, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3470, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3486, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3502, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3518, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3548, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 3552, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 3562, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3609, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 3646, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3670, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -8 + } + } + } + } + ] + ], + [ + 3693, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3708, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -13 + } + } + } + } + ] + ], + [ + 3759, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3809, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -6 + } + } + } + } + ] + ], + [ + 3850, + [ + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3934, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -8 + } + } + } + } + ] + ], + [ + 3976, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4028, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4042, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -17 + } + } + } + } + ] + ], + [ + 4045, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4097, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4119, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4133, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4211, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x12a2" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4294, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4326, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4330, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "scalar": { + "Immediate": "0x8000000000000110000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": 0 + }, + "y": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 4368, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 4408, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4428, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4449, + [ + { + "GetSegmentArenaIndex": { + "dict_end_ptr": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "dict_index": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 4490, + [ + { + "AllocSegment": { + "dst": { + "register": "FP", + "offset": 3 + } + } + } + ] + ], + [ + 4498, + [ + { + "InitSquashData": { + "dict_accesses": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "ptr_diff": { + "Deref": { + "register": "FP", + "offset": 0 + } + }, + "n_accesses": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "big_keys": { + "register": "FP", + "offset": 2 + }, + "first_key": { + "register": "FP", + "offset": 1 + } + } + } + ] + ], + [ + 4517, + [ + { + "GetCurrentAccessIndex": { + "range_check_ptr": { + "Deref": { + "register": "FP", + "offset": -9 + } + } + } + } + ] + ], + [ + 4530, + [ + { + "ShouldSkipSquashLoop": { + "should_skip_loop": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 4532, + [ + { + "GetCurrentAccessDelta": { + "index_delta_minus1": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4543, + [ + { + "ShouldContinueSquashLoop": { + "should_continue": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 4557, + [ + { + "GetNextDictKey": { + "next_key": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 4576, + [ + { + "AssertLeFindSmallArcs": { + "range_check_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "AP", + "offset": -4 + }, + "b": { + "Immediate": "0x1" + } + } + }, + "a": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "b": { + "Deref": { + "register": "FP", + "offset": 0 + } + } + } + } + ] + ], + [ + 4588, + [ + { + "AssertLeIsFirstArcExcluded": { + "skip_exclude_a_flag": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4600, + [ + { + "AssertLeIsSecondArcExcluded": { + "skip_exclude_b_minus_a": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4646, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4674, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 4761, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 4820, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x614e" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -7 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4916, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4943, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "quotient": { + "register": "AP", + "offset": 3 + }, + "remainder": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 5028, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5117, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 5164, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1612" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5239, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5261, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "quotient": { + "register": "AP", + "offset": 5 + }, + "remainder": { + "register": "AP", + "offset": 6 + } + } + } + ] + ], + [ + 5267, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": -3 + } + } + } + ] + ], + [ + 5313, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5346, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5367, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5407, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5444, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5455, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ] + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x3c118a68e16e12e97ed25cb4901c12f4d3162818669cc44c391d8049924c14", + "offset": 702, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b", + "offset": 1474, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0xf818e4530ec36b83dfe702489b4df537308c3b798b0cc120e32c2056d68b7d", + "offset": 2128, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x10d2fede95e3ec06a875a67219425c27c5bd734d57f1b221d729a2337b6b556", + "offset": 1793, + "builtins": [ + "range_check", + "segment_arena" + ] + }, + { + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "offset": 1907, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x23039bef544cff56442d9f61ae9b13cf9e36fcce009102c5b678aac93f37b36", + "offset": 556, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "offset": 167, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "offset": 365, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x2d7cf5d5a324a320f9f37804b1615a533fde487400b41af80f13f7ac5581325", + "offset": 1615, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50", + "offset": 1053, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331", + "offset": 1251, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97", + "offset": 0, + "builtins": [ + "range_check" + ] + } + ], + "L1_HANDLER": [ + { + "selector": "0x39edbbb129ad752107a94d40c3873cae369a46fd2fc578d075679aa67e85d12", + "offset": 2248, + "builtins": [ + "range_check" + ] + } + ], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "offset": 2402, + "builtins": [ + "range_check" + ] + } + ] + } +} diff --git a/crates/papyrus_execution/resources/deprecated_class.json b/crates/papyrus_execution/resources/deprecated_class.json new file mode 100644 index 00000000000..365d76b1f56 --- /dev/null +++ b/crates/papyrus_execution/resources/deprecated_class.json @@ -0,0 +1,5404 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + }, + { + "inputs": [], + "name": "without_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "with_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "return_result", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "x", + "type": "felt" + }, + { + "name": "y", + "type": "felt" + } + ], + "name": "bitwise_and", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "value", + "type": "felt" + } + ], + "name": "sqrt", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_storage_read_write", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_long_retdata", + "outputs": [ + { + "name": "a", + "type": "felt" + }, + { + "name": "b", + "type": "felt" + }, + { + "name": "c", + "type": "felt" + }, + { + "name": "d", + "type": "felt" + }, + { + "name": "e", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_library_call", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "lib_selector", + "type": "felt" + }, + { + "name": "nested_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_nested_library_call", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "function_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_call_contract", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "test_replace_class", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deploy_from_zero", + "type": "felt" + } + ], + "name": "test_deploy", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_storage_var", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "salt", + "type": "felt" + }, + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deployer_address", + "type": "felt" + } + ], + "name": "test_contract_address", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "foo", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "offset": 297, + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ], + "EXTERNAL": [ + { + "offset": 383, + "selector": "0xad451bd0dba3d8d97104e1bfc474f88605ccc7acbe1c846839a120fdf30d95" + }, + { + "offset": 645, + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b" + }, + { + "offset": 332, + "selector": "0xe7def693d16806ca2a2f398d8de5951344663ba77f340ed7a958da731872fc" + }, + { + "offset": 484, + "selector": "0x120c24672855cfe872cb35256ea85172417f2aada7a22c15908906dc5f3c69d" + }, + { + "offset": 407, + "selector": "0x137a07fa9c479e27114b8ae1fbf252f2065cf91a0d8615272e060a7ccf37309" + }, + { + "offset": 680, + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f" + }, + { + "offset": 799, + "selector": "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d" + }, + { + "offset": 615, + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c" + }, + { + "offset": 505, + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50" + }, + { + "offset": 731, + "selector": "0x36fa6de2810d05c3e1a0ebe23f60b9c2f4629bbead09e5a9704e1c5632630d5" + }, + { + "offset": 766, + "selector": "0x38215592552d97419658d30db8f189b242ec2056641de3dff8a7217745ec205" + }, + { + "offset": 316, + "selector": "0x382a967a31be13f23e23a5345f7a89b0362cc157d6fbe7564e6396a83cf4b4f" + }, + { + "offset": 359, + "selector": "0x39a1491f76903a16feed0a6433bec78de4c73194944e1118e226820ad479701" + }, + { + "offset": 577, + "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331" + }, + { + "offset": 442, + "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check", + "bitwise" + ], + "compiler_version": "0.11.1.1", + "data": [ + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x480280027ffb8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017ffe8000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff9", + "0x400380027ff87ffa", + "0x400380037ff87ffb", + "0x400380047ff87ffc", + "0x400380057ff87ffd", + "0x482680017ff88000", + "0x9", + "0x480280067ff88000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5265706c616365436c617373", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x3ffffffffffffffffffffffffffffff", + "0x480280017ffc8000", + "0x48307fff80007ffe", + "0x400280027ffc7fff", + "0x480280017ffc8000", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x480280007ffc8000", + "0x40317fff7ffe7ffd", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0x10", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48127ffe7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0xc", + "0x40780017fff7fff", + "0xa", + "0x480680017fff8000", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff", + "0x480a7ffc7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd8", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0xb", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff89", + "0x400780017fff8000", + "0x0", + "0x400780017fff8001", + "0x0", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480280007ffb8000", + "0x1104800180018000", + "0x2b", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff79", + "0x40137ffd7fff8000", + "0x480280017ffb8000", + "0x40297ffd7fff8001", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffb7fff8000", + "0x480280007ffc8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff66", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6a", + "0x40137ffd7fff8000", + "0x480280017ffc8000", + "0x402580017fff8001", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x27", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff4d", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffc", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffc8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x40337fff7ffb8000", + "0x480a7ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x48317ffd80008000", + "0x400080007ffd7ffe", + "0x480080007ffc8000", + "0x400080017ffc7fff", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x3", + "0x480080027ffa8000", + "0x20680017fff7ffb", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff8", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffa2", + "0x480a7ff77fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x535441524b4e45545f434f4e54524143545f41444452455353", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb6", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb3", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb0", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffc7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb9", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc2", + "0x480a7ff87fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff61", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x391a88f3badec8650b4d8356e18655269ee975e58e0060aa076396ce0b1dccb", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff03", + "0x480a7ffc7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff53", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff22", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1b", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff13", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400780017fff7ffd", + "0x19", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff2", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x480680017fff8000", + "0xf", + "0x400280027ffb7fff", + "0x482680017ffb8000", + "0x5", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280037ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff8000", + "0x9", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8e", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe83", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x48127ff67fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x2", + "0x480680017fff8000", + "0x3", + "0x480680017fff8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ff8", + "0x4003800180007ff9", + "0x4003800280007ffa", + "0x4003800380007ffb", + "0x4003800480007ffc", + "0x4826800180008000", + "0x5", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe8", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe23", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff7ffc", + "0x2", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x2", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde8", + "0x482480017fff8000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", + "0x40137fff7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x5", + "0x480a80007fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdee", + "0x48127ffd7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde7", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280037ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x4", + "0x480280037ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x480280037ffd8000", + "0x482680017ffd8000", + "0x4", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc3", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe3", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda9", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdbf", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd89", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff98000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x27", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe48", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe36", + "0x400680017fff7fff", + "0x27", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffea", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdea", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280017ffb8000", + "0x482480017ffe8000", + "0x1", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff78000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x480280007ffb8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "19": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.call_contract" + ], + "code": "syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": 0 + } + } + } + ], + "31": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.library_call" + ], + "code": "syscall_handler.library_call(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.library_call.syscall_ptr": 1 + } + } + } + ], + "44": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.deploy" + ], + "code": "syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.deploy.syscall_ptr": 2 + } + } + } + ], + "52": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 3 + } + } + } + ], + "61": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 4 + } + } + } + ], + "68": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.replace_class" + ], + "code": "syscall_handler.replace_class(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": 5 + } + } + } + ], + "71": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_250_bit" + ], + "code": "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_250_bit.high": 8, + "starkware.cairo.common.math.assert_250_bit.low": 7, + "starkware.cairo.common.math.assert_250_bit.value": 6 + } + } + } + ], + "86": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_small": 10 + } + } + } + ], + "104": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "ids.is_250 = 1 if ids.addr < 2**250 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_250": 11 + } + } + } + ], + "305": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.constructor" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 27, + "offset": 13 + }, + "reference_ids": {} + } + } + ], + "319": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.without_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 29, + "offset": 2 + }, + "reference_ids": {} + } + } + ], + "338": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.with_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 31, + "offset": 4 + }, + "reference_ids": {} + } + } + ], + "350": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.return_result_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 33, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "391": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.bitwise_and" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 36, + "offset": 8 + }, + "reference_ids": {} + } + } + ], + "403": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.sqrt" + ], + "code": "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)", + "flow_tracking_data": { + "ap_tracking": { + "group": 37, + "offset": 1 + }, + "reference_ids": { + "__main__.sqrt.root": 13, + "__main__.sqrt.value": 12 + } + } + } + ], + "414": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.sqrt" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 38, + "offset": 7 + }, + "reference_ids": {} + } + } + ], + "433": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_read_write_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 40, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "471": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_long_retdata_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 43, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "568": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_nested_library_call_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 48, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "652": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_replace_class" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 53, + "offset": 11 + }, + "reference_ids": {} + } + } + ], + "671": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_deploy_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 55, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "737": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_var" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 58, + "offset": 126 + }, + "reference_ids": {} + } + } + ], + "757": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_contract_address_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 61, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "802": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.foo" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 65, + "offset": 2 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "__main__.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 375, + "type": "function" + }, + "__main__.bitwise_and.Args": { + "full_name": "__main__.bitwise_and.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.bitwise_and.ImplicitArgs": { + "full_name": "__main__.bitwise_and.ImplicitArgs", + "members": { + "bitwise_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.bitwise_and.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.call_contract": { + "destination": "starkware.starknet.common.syscalls.call_contract", + "type": "alias" + }, + "__main__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 291, + "type": "function" + }, + "__main__.constructor.Args": { + "full_name": "__main__.constructor.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.constructor.ImplicitArgs": { + "full_name": "__main__.constructor.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.constructor.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.deploy": { + "destination": "starkware.starknet.common.syscalls.deploy", + "type": "alias" + }, + "__main__.foo": { + "decorators": [ + "external" + ], + "pc": 798, + "type": "function" + }, + "__main__.foo.Args": { + "full_name": "__main__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.ImplicitArgs": { + "full_name": "__main__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_contract_address": { + "destination": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address", + "type": "alias" + }, + "__main__.library_call": { + "destination": "starkware.starknet.common.syscalls.library_call", + "type": "alias" + }, + "__main__.number_map": { + "type": "namespace" + }, + "__main__.number_map.Args": { + "full_name": "__main__.number_map.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.number_map.ImplicitArgs": { + "full_name": "__main__.number_map.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.addr": { + "decorators": [], + "pc": 250, + "type": "function" + }, + "__main__.number_map.addr.Args": { + "full_name": "__main__.number_map.addr.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.addr.ImplicitArgs": { + "full_name": "__main__.number_map.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.number_map.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "__main__.number_map.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "__main__.number_map.read": { + "decorators": [], + "pc": 264, + "type": "function" + }, + "__main__.number_map.read.Args": { + "full_name": "__main__.number_map.read.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.read.ImplicitArgs": { + "full_name": "__main__.number_map.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "__main__.number_map.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.number_map.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.number_map.write": { + "decorators": [], + "pc": 278, + "type": "function" + }, + "__main__.number_map.write.Args": { + "full_name": "__main__.number_map.write.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.write.ImplicitArgs": { + "full_name": "__main__.number_map.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.replace_class": { + "destination": "starkware.starknet.common.syscalls.replace_class", + "type": "alias" + }, + "__main__.return_result": { + "decorators": [ + "external" + ], + "pc": 348, + "type": "function" + }, + "__main__.return_result.Args": { + "full_name": "__main__.return_result.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.return_result.ImplicitArgs": { + "full_name": "__main__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.return_result.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.sqrt": { + "decorators": [ + "external" + ], + "pc": 401, + "type": "function" + }, + "__main__.sqrt.Args": { + "full_name": "__main__.sqrt.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.ImplicitArgs": { + "full_name": "__main__.sqrt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.sqrt.root": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.root", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ], + "type": "reference" + }, + "__main__.sqrt.value": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.value", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 607, + "type": "function" + }, + "__main__.test_call_contract.Args": { + "full_name": "__main__.test_call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_call_contract.ImplicitArgs": { + "full_name": "__main__.test_call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 747, + "type": "function" + }, + "__main__.test_contract_address.Args": { + "full_name": "__main__.test_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_contract_address.ImplicitArgs": { + "full_name": "__main__.test_contract_address.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 662, + "type": "function" + }, + "__main__.test_deploy.Args": { + "full_name": "__main__.test_deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_deploy.ImplicitArgs": { + "full_name": "__main__.test_deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 497, + "type": "function" + }, + "__main__.test_library_call.Args": { + "full_name": "__main__.test_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_library_call.ImplicitArgs": { + "full_name": "__main__.test_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 460, + "type": "function" + }, + "__main__.test_long_retdata.Args": { + "full_name": "__main__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.ImplicitArgs": { + "full_name": "__main__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.Return": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "type": "type_definition" + }, + "__main__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 530, + "type": "function" + }, + "__main__.test_nested_library_call.Args": { + "full_name": "__main__.test_nested_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "lib_selector": { + "cairo_type": "felt", + "offset": 1 + }, + "nested_selector": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_nested_library_call.ImplicitArgs": { + "full_name": "__main__.test_nested_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_nested_library_call.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 640, + "type": "function" + }, + "__main__.test_replace_class.Args": { + "full_name": "__main__.test_replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.ImplicitArgs": { + "full_name": "__main__.test_replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 424, + "type": "function" + }, + "__main__.test_storage_read_write.Args": { + "full_name": "__main__.test_storage_read_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_storage_read_write.ImplicitArgs": { + "full_name": "__main__.test_storage_read_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_storage_read_write.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 712, + "type": "function" + }, + "__main__.test_storage_var.Args": { + "full_name": "__main__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_storage_var.ImplicitArgs": { + "full_name": "__main__.test_storage_var.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.test_storage_var.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.with_arg": { + "decorators": [ + "external" + ], + "pc": 329, + "type": "function" + }, + "__main__.with_arg.Args": { + "full_name": "__main__.with_arg.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.with_arg.ImplicitArgs": { + "full_name": "__main__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.with_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.without_arg": { + "decorators": [ + "external" + ], + "pc": 315, + "type": "function" + }, + "__main__.without_arg.Args": { + "full_name": "__main__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.ImplicitArgs": { + "full_name": "__main__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 383, + "type": "function" + }, + "__wrappers__.bitwise_and.Args": { + "full_name": "__wrappers__.bitwise_and.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.ImplicitArgs": { + "full_name": "__wrappers__.bitwise_and.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: starkware.cairo.common.cairo_builtins.BitwiseBuiltin*, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and.__wrapped_func": { + "destination": "__main__.bitwise_and", + "type": "alias" + }, + "__wrappers__.bitwise_and_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 297, + "type": "function" + }, + "__wrappers__.constructor.Args": { + "full_name": "__wrappers__.constructor.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.ImplicitArgs": { + "full_name": "__wrappers__.constructor.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.constructor.__wrapped_func": { + "destination": "__main__.constructor", + "type": "alias" + }, + "__wrappers__.constructor_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.foo": { + "decorators": [ + "external" + ], + "pc": 799, + "type": "function" + }, + "__wrappers__.foo.Args": { + "full_name": "__wrappers__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.ImplicitArgs": { + "full_name": "__wrappers__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.foo.__wrapped_func": { + "destination": "__main__.foo", + "type": "alias" + }, + "__wrappers__.foo_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.return_result": { + "decorators": [ + "external" + ], + "pc": 359, + "type": "function" + }, + "__wrappers__.return_result.Args": { + "full_name": "__wrappers__.return_result.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.ImplicitArgs": { + "full_name": "__wrappers__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.return_result.__wrapped_func": { + "destination": "__main__.return_result", + "type": "alias" + }, + "__wrappers__.return_result_encode_return": { + "decorators": [], + "pc": 350, + "type": "function" + }, + "__wrappers__.return_result_encode_return.Args": { + "full_name": "__wrappers__.return_result_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.return_result_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.return_result_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.sqrt": { + "decorators": [ + "external" + ], + "pc": 407, + "type": "function" + }, + "__wrappers__.sqrt.Args": { + "full_name": "__wrappers__.sqrt.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.ImplicitArgs": { + "full_name": "__wrappers__.sqrt.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.sqrt.__wrapped_func": { + "destination": "__main__.sqrt", + "type": "alias" + }, + "__wrappers__.sqrt_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 615, + "type": "function" + }, + "__wrappers__.test_call_contract.Args": { + "full_name": "__wrappers__.test_call_contract.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.ImplicitArgs": { + "full_name": "__wrappers__.test_call_contract.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_call_contract.__wrapped_func": { + "destination": "__main__.test_call_contract", + "type": "alias" + }, + "__wrappers__.test_call_contract_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 766, + "type": "function" + }, + "__wrappers__.test_contract_address.Args": { + "full_name": "__wrappers__.test_contract_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_contract_address.__wrapped_func": { + "destination": "__main__.test_contract_address", + "type": "alias" + }, + "__wrappers__.test_contract_address_encode_return": { + "decorators": [], + "pc": 757, + "type": "function" + }, + "__wrappers__.test_contract_address_encode_return.Args": { + "full_name": "__wrappers__.test_contract_address_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_contract_address_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 680, + "type": "function" + }, + "__wrappers__.test_deploy.Args": { + "full_name": "__wrappers__.test_deploy.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_deploy.__wrapped_func": { + "destination": "__main__.test_deploy", + "type": "alias" + }, + "__wrappers__.test_deploy_encode_return": { + "decorators": [], + "pc": 671, + "type": "function" + }, + "__wrappers__.test_deploy_encode_return.Args": { + "full_name": "__wrappers__.test_deploy_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_deploy_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 505, + "type": "function" + }, + "__wrappers__.test_library_call.Args": { + "full_name": "__wrappers__.test_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_library_call.__wrapped_func": { + "destination": "__main__.test_library_call", + "type": "alias" + }, + "__wrappers__.test_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 484, + "type": "function" + }, + "__wrappers__.test_long_retdata.Args": { + "full_name": "__wrappers__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_long_retdata.__wrapped_func": { + "destination": "__main__.test_long_retdata", + "type": "alias" + }, + "__wrappers__.test_long_retdata_encode_return": { + "decorators": [], + "pc": 471, + "type": "function" + }, + "__wrappers__.test_long_retdata_encode_return.Args": { + "full_name": "__wrappers__.test_long_retdata_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 5 + }, + "ret_value": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_long_retdata_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 577, + "type": "function" + }, + "__wrappers__.test_nested_library_call.Args": { + "full_name": "__wrappers__.test_nested_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_nested_library_call.__wrapped_func": { + "destination": "__main__.test_nested_library_call", + "type": "alias" + }, + "__wrappers__.test_nested_library_call_encode_return": { + "decorators": [], + "pc": 568, + "type": "function" + }, + "__wrappers__.test_nested_library_call_encode_return.Args": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_nested_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 645, + "type": "function" + }, + "__wrappers__.test_replace_class.Args": { + "full_name": "__wrappers__.test_replace_class.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.ImplicitArgs": { + "full_name": "__wrappers__.test_replace_class.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_replace_class.__wrapped_func": { + "destination": "__main__.test_replace_class", + "type": "alias" + }, + "__wrappers__.test_replace_class_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 442, + "type": "function" + }, + "__wrappers__.test_storage_read_write.Args": { + "full_name": "__wrappers__.test_storage_read_write.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_read_write.__wrapped_func": { + "destination": "__main__.test_storage_read_write", + "type": "alias" + }, + "__wrappers__.test_storage_read_write_encode_return": { + "decorators": [], + "pc": 433, + "type": "function" + }, + "__wrappers__.test_storage_read_write_encode_return.Args": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_storage_read_write_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 731, + "type": "function" + }, + "__wrappers__.test_storage_var.Args": { + "full_name": "__wrappers__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_var.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_var.__wrapped_func": { + "destination": "__main__.test_storage_var", + "type": "alias" + }, + "__wrappers__.test_storage_var_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.with_arg": { + "decorators": [ + "external" + ], + "pc": 332, + "type": "function" + }, + "__wrappers__.with_arg.Args": { + "full_name": "__wrappers__.with_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.ImplicitArgs": { + "full_name": "__wrappers__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.with_arg.__wrapped_func": { + "destination": "__main__.with_arg", + "type": "alias" + }, + "__wrappers__.with_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.without_arg": { + "decorators": [ + "external" + ], + "pc": 316, + "type": "function" + }, + "__wrappers__.without_arg.Args": { + "full_name": "__wrappers__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.ImplicitArgs": { + "full_name": "__wrappers__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.without_arg.__wrapped_func": { + "destination": "__main__.without_arg", + "type": "alias" + }, + "__wrappers__.without_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash.hash2": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.hash.hash2.Args": { + "full_name": "starkware.cairo.common.hash.hash2.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash.hash2.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash.hash2.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash_state.HashState": { + "full_name": "starkware.cairo.common.hash_state.HashState", + "members": { + "current_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "n_words": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash_felts": { + "decorators": [], + "pc": 208, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.Args", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 0 + }, + "length": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding": { + "decorators": [], + "pc": 183, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 1 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "initial_hash": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals", + "members": { + "cur_hash": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.hash_loop": { + "pc": 196, + "type": "label" + }, + "starkware.cairo.common.hash_state.hash_finalize": { + "decorators": [], + "pc": 177, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_finalize.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_finalize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_init": { + "decorators": [], + "pc": 124, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_init.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_init.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_init.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.Return": { + "cairo_type": "(hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_init.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update": { + "decorators": [], + "pc": 134, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_single": { + "decorators": [], + "pc": 150, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_single.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + }, + "item": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_single.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain": { + "decorators": [], + "pc": 166, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.math.assert_250_bit": { + "decorators": [ + "known_ap_change" + ], + "pc": 71, + "type": "function" + }, + "starkware.cairo.common.math.assert_250_bit.Args": { + "full_name": "starkware.cairo.common.math.assert_250_bit.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.HIGH_BOUND": { + "type": "const", + "value": 5316911983139663491615228241121378304 + }, + "starkware.cairo.common.math.assert_250_bit.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_250_bit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_250_bit.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND": { + "type": "const", + "value": 1809251394333065553493296640760748560207343510400633813116524750123642650624 + }, + "starkware.cairo.common.math.assert_250_bit.high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.high", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.low", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.value", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.registers.get_ap": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.registers.get_fp_and_pc": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap": { + "decorators": [ + "known_ap_change" + ], + "pc": 7, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Return": { + "cairo_type": "(ap_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc": { + "decorators": [], + "pc": 6, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Return": { + "cairo_type": "(fp_val: felt*, pc_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.storage.normalize_address": { + "decorators": [ + "known_ap_change" + ], + "pc": 84, + "type": "function" + }, + "starkware.starknet.common.storage.normalize_address.Args": { + "full_name": "starkware.starknet.common.storage.normalize_address.Args", + "members": { + "addr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.storage.normalize_address.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.normalize_address.addr": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.addr", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_250": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_250", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_small": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_small", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract": { + "decorators": [], + "pc": 12, + "type": "function" + }, + "starkware.starknet.common.syscalls.call_contract.Args": { + "full_name": "starkware.starknet.common.syscalls.call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.call_contract.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 1 + }, + "pc": 19, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.deploy": { + "decorators": [], + "pc": 36, + "type": "function" + }, + "starkware.starknet.common.syscalls.deploy.Args": { + "full_name": "starkware.starknet.common.syscalls.deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.deploy.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.deploy.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 1 + }, + "pc": 44, + "value": "cast([fp + (-8)] + 9, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.library_call": { + "decorators": [], + "pc": 24, + "type": "function" + }, + "starkware.starknet.common.syscalls.library_call.Args": { + "full_name": "starkware.starknet.common.syscalls.library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.library_call.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.library_call.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 1 + }, + "pc": 31, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.replace_class": { + "decorators": [], + "pc": 64, + "type": "function" + }, + "starkware.starknet.common.syscalls.replace_class.Args": { + "full_name": "starkware.starknet.common.syscalls.replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.replace_class.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 68, + "value": "cast([fp + (-4)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 48, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 1 + }, + "pc": 52, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 56, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 1 + }, + "pc": 61, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.core.os.contract_address.contract_address.CONTRACT_ADDRESS_PREFIX": { + "type": "const", + "value": 523065374597054866729014270389667305596563390979550329787219 + }, + "starkware.starknet.core.os.contract_address.contract_address.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address": { + "decorators": [], + "pc": 219, + "type": "function" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_finalize": { + "destination": "starkware.cairo.common.hash_state.hash_finalize", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_init": { + "destination": "starkware.cairo.common.hash_state.hash_init", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update": { + "destination": "starkware.cairo.common.hash_state.hash_update", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_single": { + "destination": "starkware.cairo.common.hash_state.hash_update_single", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_with_hashchain": { + "destination": "starkware.cairo.common.hash_state.hash_update_with_hashchain", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ] + } + } +} diff --git a/crates/papyrus_execution/resources/erc20_fee_contract_class.json b/crates/papyrus_execution/resources/erc20_fee_contract_class.json new file mode 100644 index 00000000000..72ac9b768ca --- /dev/null +++ b/crates/papyrus_execution/resources/erc20_fee_contract_class.json @@ -0,0 +1,9101 @@ +{ + "abi": [ + { + "members": [ + { + "name": "low", + "offset": 0, + "type": "felt" + }, + { + "name": "high", + "offset": 1, + "type": "felt" + } + ], + "name": "Uint256", + "size": 2, + "type": "struct" + }, + { + "data": [ + { + "name": "from_", + "type": "felt" + }, + { + "name": "to", + "type": "felt" + }, + { + "name": "value", + "type": "Uint256" + } + ], + "keys": [], + "name": "Transfer", + "type": "event" + }, + { + "data": [ + { + "name": "owner", + "type": "felt" + }, + { + "name": "spender", + "type": "felt" + }, + { + "name": "value", + "type": "Uint256" + } + ], + "keys": [], + "name": "Approval", + "type": "event" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "name", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "symbol", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "totalSupply", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "decimals", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "account", + "type": "felt" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "owner", + "type": "felt" + }, + { + "name": "spender", + "type": "felt" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permittedMinter", + "outputs": [ + { + "name": "minter", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "get_version", + "outputs": [ + { + "name": "version", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "get_identity", + "outputs": [ + { + "name": "identity", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "init_vector_len", + "type": "felt" + }, + { + "name": "init_vector", + "type": "felt*" + } + ], + "name": "initialize", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "sender", + "type": "felt" + }, + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "added_value", + "type": "Uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "subtracted_value", + "type": "Uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "permissionedMint", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "account", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "permissionedBurn", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": "0x65d", + "selector": "0x151e58b29179122a728eab07c8847e5baf5802379c5db3a7d57a8263a7bd1d" + }, + { + "offset": "0x574", + "selector": "0x41b033f4a31df8067c24d1e9b550a2ce75fd4a29e1147af9752174f0e6cb20" + }, + { + "offset": "0x2cb", + "selector": "0x4c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9" + }, + { + "offset": "0x4f1", + "selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463" + }, + { + "offset": "0x2ad", + "selector": "0x80aa9fdbfaf9615e4afc7f5f722e265daca5ccc655360fa5ccacf9c267936d" + }, + { + "offset": "0x524", + "selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e" + }, + { + "offset": "0x682", + "selector": "0xd63a78e4cd7fb4c41bc18d089154af78d400a5e837f270baea6cf8db18c8dd" + }, + { + "offset": "0x5e9", + "selector": "0x16cc063b8338363cf388ce7fe1df408bf10f16cd51635d392e21d852fafb683" + }, + { + "offset": "0x638", + "selector": "0x1aaf3e6107dd1349c81543ff4221a326814f77dadcc5810807b74f1a49ded4e" + }, + { + "offset": "0x30f", + "selector": "0x1e888a1026b19c8c0b57c72d63ed1737106aa10034105b980ba117bd0c29fe1" + }, + { + "offset": "0x28e", + "selector": "0x216b05c387bab9ac31918a3e61672f4618601f3c598a2f3f2710f37053e1ea4" + }, + { + "offset": "0x5a1", + "selector": "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c" + }, + { + "offset": "0x4bd", + "selector": "0x2a4bb4205277617b698a9a2950b938d0a236dd4619f82f05bec02bdbd245fab" + }, + { + "offset": "0x4d5", + "selector": "0x2c4943a27e820803a6ef49bb04b629950e2de615ab9ac0fb8baef037b168782" + }, + { + "offset": "0x2eb", + "selector": "0x2e4263afad30923c891518314c3c95dbe830a16874e8abc5777a9a20b54c76e" + }, + { + "offset": "0x442", + "selector": "0x358a2fe57368393087d3e6d24f1e04741c5bdc85e3e23790253e377f55c391e" + }, + { + "offset": "0x270", + "selector": "0x361458367e696363fbcc70777d07ebbd2394e89fd0adcaf147faccd1d294d60" + }, + { + "offset": "0x48d", + "selector": "0x3c0ba99f1a18bcdc81fcbcb6b4f15a9a6725f937075aed6fac107ffcb147068" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized" + ], + "end_pc": 1187, + "flow_tracking_data": { + "ap_tracking": { + "group": 79, + "offset": 28 + }, + "reference_ids": {} + }, + "name": "error_message", + "start_pc": 1185, + "value": "ALREADY_INITIALIZED" + }, + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.initialize" + ], + "end_pc": 1256, + "flow_tracking_data": { + "ap_tracking": { + "group": 87, + "offset": 60 + }, + "reference_ids": {} + }, + "name": "error_message", + "start_pc": 1254, + "value": "ILLEGAL_INIT_SIZE" + } + ], + "builtins": [ + "pedersen", + "range_check" + ], + "compiler_version": "0.10.3", + "data": [ + "0x40780017fff7fff", + "0x1", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x480280027ffb8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x4", + "0x400780017fff7ffd", + "0x1", + "0x208b7fff7fff7ffe", + "0x400380007ffc7ffd", + "0x482680017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x48297ffc80007ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x3ffffffffffffffffffffffffffffff", + "0x480280017ffc8000", + "0x48307fff80007ffe", + "0x400280027ffc7fff", + "0x480280017ffc8000", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x480280007ffc8000", + "0x40317fff7ffe7ffd", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x484480017fff8000", + "0x2aaaaaaaaaaaab05555555555555556", + "0x48307fff7ffd8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x484480017fff8000", + "0x4000000000000088000000000000001", + "0x48307fff7ffd8000", + "0xa0680017fff8000", + "0xe", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48287ffc80007fff", + "0x40307ffc7ff87fff", + "0x48297ffd80007ffc", + "0x482680017ffd8000", + "0x1", + "0x48507fff7ffe8000", + "0x40507ff97ff57fff", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xc", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48287ffd80007fff", + "0x48327fff7ffc8000", + "0x40307ffa7ff67fff", + "0x48527ffe7ffc8000", + "0x40507ff97ff57fff", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40317ffd7ff97ffd", + "0x48297ffc80007ffd", + "0x48527fff7ffc8000", + "0x40507ffb7ff77fff", + "0x40780017fff7fff", + "0x2", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0x10", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc0", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48127ffe7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffba", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0xc", + "0x40780017fff7fff", + "0xa", + "0x480680017fff8000", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff", + "0x480a7ffc7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffab", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0xb", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffa3", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x47657443616c6c657241646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x5", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xa", + "0x400380007ffc7ffd", + "0x40780017fff7fff", + "0x14", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xe", + "0x484680017ffd8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x400280007ffc7fff", + "0x40780017fff7fff", + "0x11", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x100000000000000000000000000000000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6f", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x48297ffc80007ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x404b800280028002", + "0x404b800380038003", + "0x482a7ffc7ffa8000", + "0x4846800180028000", + "0x100000000000000000000000000000000", + "0x40327fff80007ffe", + "0x482a7ffd7ffb8000", + "0x482880027fff8000", + "0x4846800180038000", + "0x100000000000000000000000000000000", + "0x40327fff80017ffe", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffd80007ffb", + "0x20680017fff7fff", + "0x9", + "0x480a7ff97fff8000", + "0x482680017ffa8000", + "0x1", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x482680017ffb8000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd3", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48307ffd80007ffe", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x480680017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x480a7ffb7fff8000", + "0x48287ffc80007ffd", + "0x48287ffd80007ffd", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbd", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffed7", + "0x40137fff7fff8000", + "0x480680017fff8000", + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x4002800080007fff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffed1", + "0x40137fff7fff8001", + "0x4003800080017ffa", + "0x4003800180017ffb", + "0x4003800280017ffc", + "0x4003800380017ffd", + "0x4826800180018000", + "0x4", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480a80007fff8000", + "0x4828800180007ffc", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff5b", + "0x480a7ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffebc", + "0x40137fff7fff8000", + "0x480680017fff8000", + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff", + "0x4002800080007fff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeb6", + "0x40137fff7fff8001", + "0x4003800080017ffa", + "0x4003800180017ffb", + "0x4003800280017ffc", + "0x4003800380017ffd", + "0x4826800180018000", + "0x4", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480a80007fff8000", + "0x4828800180007ffc", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff40", + "0x480a7ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x341c1bdfd89f69748aa00b5742b03adbffd79b8e80cab5c50d91cd8c2a79be1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff21", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1b", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0xb6ce5410fca59d078ee9b2a4371a9d684c530d697c64fbef0ae6d5e8f0ac72", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff03", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffefd", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1f0d4aa99431d246bac9b8e48c33e888245b15e9678f64f9bdfc8823dc8f979", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffee5", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffedf", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x110e2f729c9c2b988559994a3daccd838cf52faf88e18101373e67dd061455a", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec7", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec2", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffebb", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeb6", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x3a4e8ec16e258a799fe707996fd5d21d42b29adc1499a370edf7f809d8c458a", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe1f", + "0x480a7ffc7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe72", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe94", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8f", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdc", + "0x480a7ff87fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe87", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe82", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x3c87bf42ed4f01f11883bf54f43d91d2cbbd5fec26d1df9c74c57ae138800a4", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdeb", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde8", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe3b", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe5c", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe57", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd7", + "0x480a7ff77fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe4e", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe49", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0xff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc6", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff19", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff34", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff4f", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff00", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff00", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1e", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffee1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff12", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff25", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffce5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda0", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd9b", + "0x48127fe57fff8000", + "0x48127fe57fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec8", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe80", + "0x40137ffe7fff8000", + "0x40137fff7fff8001", + "0x48127ffd7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd88", + "0x40137ffd7fff8002", + "0x40137ffe7fff8003", + "0x400680017fff7fff", + "0x0", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x48127ffa7fff8000", + "0x480a80027fff8000", + "0x480a80037fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe7f", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdce", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffca6", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffca3", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd5e", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe7e", + "0x40137ffe7fff8000", + "0x40137fff7fff8001", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd7b", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc8d", + "0x48127ffc7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd95", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe78", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe61", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd3c", + "0x48127fe57fff8000", + "0x48127fe57fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe69", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd86", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc60", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc5d", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd18", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe81", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd81", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x0", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc3e", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcf9", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe19", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd18", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc2a", + "0x48127ffc7fff8000", + "0x48127fc97fff8000", + "0x48127fc97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd32", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe15", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdcd", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd24", + "0x48127fb37fff8000", + "0x48127fb37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdd5", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd24", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1390569bb0a3a722eb4228e8700301347da081211d5c2ded2db22ef389551ab", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc74", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc6e", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbe0", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdb", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc31", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbb1", + "0x40127ffd7fff7fe1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x2cd2687c06d341ffd0b635e3229e2ca36108201a2112da0d058d03b77eb5092", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc1f", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc19", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe5", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x400680017fff7fff", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc5", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4552433230", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc4", + "0x400780017fff7ffc", + "0x4", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd64", + "0x480280037ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff3c", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x482680017ffd8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb76", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe4c", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x3", + "0x480a7ff77fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb48", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a80007fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffce4", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbaa", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffabc", + "0x48127fc77fff8000", + "0x48127fc77fff8000", + "0x48127ffa7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe0b", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbbc", + "0x48127fb37fff8000", + "0x48127fb37fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a80007fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcd6", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x4", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x480280037ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbb", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffaf9", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe17", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb10", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffac6", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x48127ff77fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc62", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb01", + "0x40137ffd7fff8003", + "0x40137ffe7fff8004", + "0x400680017fff7fff", + "0x0", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x48127ffa7fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdcf", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc4", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffac8", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffa7e", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x48127ff77fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc1a", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb03", + "0x40137ffe7fff8003", + "0x40137fff7fff8004", + "0x48127ffd7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffad7", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff9e9", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffa7fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd80", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbd", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe01", + "0x40137ffd7fff8000", + "0x480a80007fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcc9", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddc", + "0x40137ffd7fff8000", + "0x480a80007fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd4b", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "0": [ + { + "accessible_scopes": [ + "starkware.cairo.common.alloc", + "starkware.cairo.common.alloc.alloc" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "9": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_not_zero" + ], + "code": "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'", + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_not_zero.value": 0 + } + } + } + ], + "14": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_nn" + ], + "code": "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_nn.a": 1 + } + } + } + ], + "32": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_250_bit" + ], + "code": "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_250_bit.high": 4, + "starkware.cairo.common.math.assert_250_bit.low": 3, + "starkware.cairo.common.math.assert_250_bit.value": 2 + } + } + } + ], + "45": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "import itertools\n\nfrom starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\na = ids.a % PRIME\nb = ids.b % PRIME\nassert a <= b, f'a = {a} is not less than or equal to b = {b}.'\n\n# Find an arc less than PRIME / 3, and another less than PRIME / 2.\nlengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)]\nlengths_and_indices.sort()\nassert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2\nexcluded = lengths_and_indices[2][1]\n\nmemory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (\n divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH))\nmemory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (\n divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_le_felt.a": 5, + "starkware.cairo.common.math.assert_le_felt.b": 6, + "starkware.cairo.common.math.assert_le_felt.range_check_ptr": 7 + } + } + } + ], + "55": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "memory[ap] = 1 if excluded != 0 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 8 + }, + "reference_ids": {} + } + } + ], + "69": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "memory[ap] = 1 if excluded != 1 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 9 + }, + "reference_ids": {} + } + } + ], + "81": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "assert excluded == 2", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 10 + }, + "reference_ids": {} + } + } + ], + "92": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 8, + "starkware.starknet.common.storage.normalize_address.is_small": 9 + } + } + } + ], + "110": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "ids.is_250 = 1 if ids.addr < 2**250 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 8, + "starkware.starknet.common.storage.normalize_address.is_250": 10 + } + } + } + ], + "133": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_caller_address" + ], + "code": "syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": 11 + } + } + } + ], + "141": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 12 + } + } + } + ], + "150": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 11, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 13 + } + } + } + ], + "160": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.emit_event" + ], + "code": "syscall_handler.emit_event(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 12, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.emit_event.syscall_ptr": 14 + } + } + } + ], + "163": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math_cmp", + "starkware.cairo.common.math_cmp.is_nn" + ], + "code": "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1", + "flow_tracking_data": { + "ap_tracking": { + "group": 13, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math_cmp.is_nn.a": 15 + } + } + } + ], + "173": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math_cmp", + "starkware.cairo.common.math_cmp.is_nn" + ], + "code": "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1", + "flow_tracking_data": { + "ap_tracking": { + "group": 13, + "offset": 1 + }, + "reference_ids": { + "starkware.cairo.common.math_cmp.is_nn.a": 15 + } + } + } + ], + "208": [ + { + "accessible_scopes": [ + "starkware.cairo.common.uint256", + "starkware.cairo.common.uint256.uint256_add" + ], + "code": "sum_low = ids.a.low + ids.b.low\nids.carry_low = 1 if sum_low >= ids.SHIFT else 0\nsum_high = ids.a.high + ids.b.high + ids.carry_low\nids.carry_high = 1 if sum_high >= ids.SHIFT else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 16, + "offset": 4 + }, + "reference_ids": { + "starkware.cairo.common.uint256.uint256_add.a": 16, + "starkware.cairo.common.uint256.uint256_add.b": 17, + "starkware.cairo.common.uint256.uint256_add.carry_high": 19, + "starkware.cairo.common.uint256.uint256_add.carry_low": 18 + } + } + } + ], + "615": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.name_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 44, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "645": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.symbol_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 47, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "675": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.totalSupply_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 50, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "706": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.decimals_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 53, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "737": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.balanceOf_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 56, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "773": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.allowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 59, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1081": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.permitted", + "blockifier.ERC20_without_some_syscalls.ERC20.permitted", + "__wrappers__", + "__wrappers__.permittedMinter_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 70, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1156": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "__wrappers__", + "__wrappers__.initialized_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 77, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1204": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_version_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 82, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1228": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_identity_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 85, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1283": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.initialize" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 88, + "offset": 185 + }, + "reference_ids": {} + } + } + ], + "1307": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.transfer_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 90, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1387": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.transferFrom_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 93, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1432": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.approve_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 96, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1504": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increaseAllowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 99, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1583": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.decreaseAllowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 102, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1640": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.permissionedMint" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 105, + "offset": 346 + }, + "reference_ids": {} + } + } + ], + "1677": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.permissionedBurn" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 107, + "offset": 494 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.CONTRACT_IDENTITY": { + "type": "const", + "value": 297732878896 + }, + "__main__.CONTRACT_VERSION": { + "type": "const", + "value": 1 + }, + "__main__.ERC20_allowances": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances", + "type": "alias" + }, + "__main__.ERC20_approve": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve", + "type": "alias" + }, + "__main__.ERC20_burn": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn", + "type": "alias" + }, + "__main__.ERC20_initializer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer", + "type": "alias" + }, + "__main__.ERC20_mint": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint", + "type": "alias" + }, + "__main__.ERC20_transfer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "__main__.Uint256": { + "destination": "starkware.cairo.common.uint256.Uint256", + "type": "alias" + }, + "__main__.allowance": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance", + "type": "alias" + }, + "__main__.approve": { + "decorators": [ + "external" + ], + "pc": 1417, + "type": "function" + }, + "__main__.approve.Args": { + "full_name": "__main__.approve.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "spender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.approve.ImplicitArgs": { + "full_name": "__main__.approve.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.approve.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "__main__.balanceOf": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf", + "type": "alias" + }, + "__main__.decimals": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals", + "type": "alias" + }, + "__main__.decreaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1533, + "type": "function" + }, + "__main__.decreaseAllowance.Args": { + "full_name": "__main__.decreaseAllowance.Args", + "members": { + "spender": { + "cairo_type": "felt", + "offset": 0 + }, + "subtracted_value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.decreaseAllowance.ImplicitArgs": { + "full_name": "__main__.decreaseAllowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.decreaseAllowance.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.decreaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 5 + }, + "__main__.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "__main__.get_identity": { + "decorators": [ + "view" + ], + "pc": 1225, + "type": "function" + }, + "__main__.get_identity.Args": { + "full_name": "__main__.get_identity.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_identity.ImplicitArgs": { + "full_name": "__main__.get_identity.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_identity.Return": { + "cairo_type": "(identity: felt)", + "type": "type_definition" + }, + "__main__.get_identity.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_version": { + "decorators": [ + "view" + ], + "pc": 1201, + "type": "function" + }, + "__main__.get_version.Args": { + "full_name": "__main__.get_version.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_version.ImplicitArgs": { + "full_name": "__main__.get_version.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_version.Return": { + "cairo_type": "(version: felt)", + "type": "type_definition" + }, + "__main__.get_version.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.increaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1461, + "type": "function" + }, + "__main__.increaseAllowance.Args": { + "full_name": "__main__.increaseAllowance.Args", + "members": { + "added_value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "spender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increaseAllowance.ImplicitArgs": { + "full_name": "__main__.increaseAllowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increaseAllowance.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.increaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 5 + }, + "__main__.initialize": { + "decorators": [ + "external" + ], + "pc": 1249, + "type": "function" + }, + "__main__.initialize.Args": { + "full_name": "__main__.initialize.Args", + "members": { + "init_vector": { + "cairo_type": "felt*", + "offset": 1 + }, + "init_vector_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.initialize.ImplicitArgs": { + "full_name": "__main__.initialize.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.initialize.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.initialize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.initialized": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized", + "type": "alias" + }, + "__main__.name": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name", + "type": "alias" + }, + "__main__.permissionedBurn": { + "decorators": [ + "external" + ], + "pc": 1649, + "type": "function" + }, + "__main__.permissionedBurn.Args": { + "full_name": "__main__.permissionedBurn.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedBurn.ImplicitArgs": { + "full_name": "__main__.permissionedBurn.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedBurn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.permissionedBurn.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.permissionedMint": { + "decorators": [ + "external" + ], + "pc": 1612, + "type": "function" + }, + "__main__.permissionedMint.Args": { + "full_name": "__main__.permissionedMint.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedMint.ImplicitArgs": { + "full_name": "__main__.permissionedMint.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedMint.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.permissionedMint.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.permittedMinter": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter", + "type": "alias" + }, + "__main__.permitted_initializer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer", + "type": "alias" + }, + "__main__.permitted_minter": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter", + "type": "alias" + }, + "__main__.permitted_minter_only": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only", + "type": "alias" + }, + "__main__.set_initialized": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized", + "type": "alias" + }, + "__main__.symbol": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol", + "type": "alias" + }, + "__main__.totalSupply": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply", + "type": "alias" + }, + "__main__.transfer": { + "decorators": [ + "external" + ], + "pc": 1292, + "type": "function" + }, + "__main__.transfer.Args": { + "full_name": "__main__.transfer.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transfer.ImplicitArgs": { + "full_name": "__main__.transfer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transfer.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.transferFrom": { + "decorators": [ + "external" + ], + "pc": 1336, + "type": "function" + }, + "__main__.transferFrom.Args": { + "full_name": "__main__.transferFrom.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "recipient": { + "cairo_type": "felt", + "offset": 1 + }, + "sender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.transferFrom.ImplicitArgs": { + "full_name": "__main__.transferFrom.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transferFrom.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.transferFrom.SIZEOF_LOCALS": { + "type": "const", + "value": 3 + }, + "__main__.uint256_add": { + "destination": "starkware.cairo.common.uint256.uint256_add", + "type": "alias" + }, + "__main__.uint256_check": { + "destination": "starkware.cairo.common.uint256.uint256_check", + "type": "alias" + }, + "__main__.uint256_le": { + "destination": "starkware.cairo.common.uint256.uint256_le", + "type": "alias" + }, + "__main__.uint256_sub": { + "destination": "starkware.cairo.common.uint256.uint256_sub", + "type": "alias" + }, + "__wrappers__.allowance": { + "decorators": [ + "view" + ], + "pc": 783, + "type": "function" + }, + "__wrappers__.allowance.Args": { + "full_name": "__wrappers__.allowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance.ImplicitArgs": { + "full_name": "__wrappers__.allowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.allowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.allowance.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance", + "type": "alias" + }, + "__wrappers__.allowance_encode_return": { + "decorators": [], + "pc": 773, + "type": "function" + }, + "__wrappers__.allowance_encode_return.Args": { + "full_name": "__wrappers__.allowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(remaining: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.allowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.allowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.allowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.allowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.approve": { + "decorators": [ + "external" + ], + "pc": 1441, + "type": "function" + }, + "__wrappers__.approve.Args": { + "full_name": "__wrappers__.approve.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve.ImplicitArgs": { + "full_name": "__wrappers__.approve.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.approve.__wrapped_func": { + "destination": "__main__.approve", + "type": "alias" + }, + "__wrappers__.approve_encode_return": { + "decorators": [], + "pc": 1432, + "type": "function" + }, + "__wrappers__.approve_encode_return.Args": { + "full_name": "__wrappers__.approve_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.approve_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.approve_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.approve_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.approve_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.balanceOf": { + "decorators": [ + "view" + ], + "pc": 747, + "type": "function" + }, + "__wrappers__.balanceOf.Args": { + "full_name": "__wrappers__.balanceOf.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf.ImplicitArgs": { + "full_name": "__wrappers__.balanceOf.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.balanceOf.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.balanceOf.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf", + "type": "alias" + }, + "__wrappers__.balanceOf_encode_return": { + "decorators": [], + "pc": 737, + "type": "function" + }, + "__wrappers__.balanceOf_encode_return.Args": { + "full_name": "__wrappers__.balanceOf_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.balanceOf_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.balanceOf_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.balanceOf_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.balanceOf_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.decimals": { + "decorators": [ + "view" + ], + "pc": 715, + "type": "function" + }, + "__wrappers__.decimals.Args": { + "full_name": "__wrappers__.decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals.ImplicitArgs": { + "full_name": "__wrappers__.decimals.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.decimals.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals", + "type": "alias" + }, + "__wrappers__.decimals_encode_return": { + "decorators": [], + "pc": 706, + "type": "function" + }, + "__wrappers__.decimals_encode_return.Args": { + "full_name": "__wrappers__.decimals_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(decimals: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.decimals_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.decimals_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.decimals_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.decimals_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.decreaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1592, + "type": "function" + }, + "__wrappers__.decreaseAllowance.Args": { + "full_name": "__wrappers__.decreaseAllowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance.ImplicitArgs": { + "full_name": "__wrappers__.decreaseAllowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.decreaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.decreaseAllowance.__wrapped_func": { + "destination": "__main__.decreaseAllowance", + "type": "alias" + }, + "__wrappers__.decreaseAllowance_encode_return": { + "decorators": [], + "pc": 1583, + "type": "function" + }, + "__wrappers__.decreaseAllowance_encode_return.Args": { + "full_name": "__wrappers__.decreaseAllowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.decreaseAllowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.decreaseAllowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.decreaseAllowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.decreaseAllowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.get_identity": { + "decorators": [ + "view" + ], + "pc": 1237, + "type": "function" + }, + "__wrappers__.get_identity.Args": { + "full_name": "__wrappers__.get_identity.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity.ImplicitArgs": { + "full_name": "__wrappers__.get_identity.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_identity.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_identity.__wrapped_func": { + "destination": "__main__.get_identity", + "type": "alias" + }, + "__wrappers__.get_identity_encode_return": { + "decorators": [], + "pc": 1228, + "type": "function" + }, + "__wrappers__.get_identity_encode_return.Args": { + "full_name": "__wrappers__.get_identity_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(identity: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_identity_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_identity_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_identity_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_identity_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.get_version": { + "decorators": [ + "view" + ], + "pc": 1213, + "type": "function" + }, + "__wrappers__.get_version.Args": { + "full_name": "__wrappers__.get_version.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version.ImplicitArgs": { + "full_name": "__wrappers__.get_version.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_version.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_version.__wrapped_func": { + "destination": "__main__.get_version", + "type": "alias" + }, + "__wrappers__.get_version_encode_return": { + "decorators": [], + "pc": 1204, + "type": "function" + }, + "__wrappers__.get_version_encode_return.Args": { + "full_name": "__wrappers__.get_version_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(version: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_version_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_version_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_version_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_version_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.increaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1513, + "type": "function" + }, + "__wrappers__.increaseAllowance.Args": { + "full_name": "__wrappers__.increaseAllowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance.ImplicitArgs": { + "full_name": "__wrappers__.increaseAllowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.increaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.increaseAllowance.__wrapped_func": { + "destination": "__main__.increaseAllowance", + "type": "alias" + }, + "__wrappers__.increaseAllowance_encode_return": { + "decorators": [], + "pc": 1504, + "type": "function" + }, + "__wrappers__.increaseAllowance_encode_return.Args": { + "full_name": "__wrappers__.increaseAllowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.increaseAllowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.increaseAllowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.increaseAllowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.increaseAllowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.initialize": { + "decorators": [ + "external" + ], + "pc": 1265, + "type": "function" + }, + "__wrappers__.initialize.Args": { + "full_name": "__wrappers__.initialize.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialize.ImplicitArgs": { + "full_name": "__wrappers__.initialize.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialize.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.initialize.__wrapped_func": { + "destination": "__main__.initialize", + "type": "alias" + }, + "__wrappers__.initialize_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.initialized": { + "decorators": [ + "view" + ], + "pc": 1165, + "type": "function" + }, + "__wrappers__.initialized.Args": { + "full_name": "__wrappers__.initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized.ImplicitArgs": { + "full_name": "__wrappers__.initialized.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.initialized.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized", + "type": "alias" + }, + "__wrappers__.initialized_encode_return": { + "decorators": [], + "pc": 1156, + "type": "function" + }, + "__wrappers__.initialized_encode_return.Args": { + "full_name": "__wrappers__.initialized_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(res: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.initialized_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.initialized_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialized_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.initialized_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.name": { + "decorators": [ + "view" + ], + "pc": 624, + "type": "function" + }, + "__wrappers__.name.Args": { + "full_name": "__wrappers__.name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name.ImplicitArgs": { + "full_name": "__wrappers__.name.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.name.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name", + "type": "alias" + }, + "__wrappers__.name_encode_return": { + "decorators": [], + "pc": 615, + "type": "function" + }, + "__wrappers__.name_encode_return.Args": { + "full_name": "__wrappers__.name_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(name: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.name_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.name_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.name_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.name_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permissionedBurn": { + "decorators": [ + "external" + ], + "pc": 1666, + "type": "function" + }, + "__wrappers__.permissionedBurn.Args": { + "full_name": "__wrappers__.permissionedBurn.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedBurn.ImplicitArgs": { + "full_name": "__wrappers__.permissionedBurn.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedBurn.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permissionedBurn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permissionedBurn.__wrapped_func": { + "destination": "__main__.permissionedBurn", + "type": "alias" + }, + "__wrappers__.permissionedBurn_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permissionedMint": { + "decorators": [ + "external" + ], + "pc": 1629, + "type": "function" + }, + "__wrappers__.permissionedMint.Args": { + "full_name": "__wrappers__.permissionedMint.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedMint.ImplicitArgs": { + "full_name": "__wrappers__.permissionedMint.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedMint.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permissionedMint.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permissionedMint.__wrapped_func": { + "destination": "__main__.permissionedMint", + "type": "alias" + }, + "__wrappers__.permissionedMint_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permittedMinter": { + "decorators": [ + "view" + ], + "pc": 1090, + "type": "function" + }, + "__wrappers__.permittedMinter.Args": { + "full_name": "__wrappers__.permittedMinter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter.ImplicitArgs": { + "full_name": "__wrappers__.permittedMinter.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permittedMinter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permittedMinter.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter", + "type": "alias" + }, + "__wrappers__.permittedMinter_encode_return": { + "decorators": [], + "pc": 1081, + "type": "function" + }, + "__wrappers__.permittedMinter_encode_return.Args": { + "full_name": "__wrappers__.permittedMinter_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(minter: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.permittedMinter_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.permittedMinter_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.permittedMinter_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.permittedMinter_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.symbol": { + "decorators": [ + "view" + ], + "pc": 654, + "type": "function" + }, + "__wrappers__.symbol.Args": { + "full_name": "__wrappers__.symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol.ImplicitArgs": { + "full_name": "__wrappers__.symbol.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.symbol.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol", + "type": "alias" + }, + "__wrappers__.symbol_encode_return": { + "decorators": [], + "pc": 645, + "type": "function" + }, + "__wrappers__.symbol_encode_return.Args": { + "full_name": "__wrappers__.symbol_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(symbol: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.symbol_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.symbol_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.symbol_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.symbol_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.totalSupply": { + "decorators": [ + "view" + ], + "pc": 685, + "type": "function" + }, + "__wrappers__.totalSupply.Args": { + "full_name": "__wrappers__.totalSupply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply.ImplicitArgs": { + "full_name": "__wrappers__.totalSupply.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.totalSupply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.totalSupply.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply", + "type": "alias" + }, + "__wrappers__.totalSupply_encode_return": { + "decorators": [], + "pc": 675, + "type": "function" + }, + "__wrappers__.totalSupply_encode_return.Args": { + "full_name": "__wrappers__.totalSupply_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(totalSupply: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.totalSupply_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.totalSupply_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.totalSupply_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.totalSupply_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.transfer": { + "decorators": [ + "external" + ], + "pc": 1316, + "type": "function" + }, + "__wrappers__.transfer.Args": { + "full_name": "__wrappers__.transfer.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer.ImplicitArgs": { + "full_name": "__wrappers__.transfer.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.transfer.__wrapped_func": { + "destination": "__main__.transfer", + "type": "alias" + }, + "__wrappers__.transferFrom": { + "decorators": [ + "external" + ], + "pc": 1396, + "type": "function" + }, + "__wrappers__.transferFrom.Args": { + "full_name": "__wrappers__.transferFrom.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom.ImplicitArgs": { + "full_name": "__wrappers__.transferFrom.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.transferFrom.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.transferFrom.__wrapped_func": { + "destination": "__main__.transferFrom", + "type": "alias" + }, + "__wrappers__.transferFrom_encode_return": { + "decorators": [], + "pc": 1387, + "type": "function" + }, + "__wrappers__.transferFrom_encode_return.Args": { + "full_name": "__wrappers__.transferFrom_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.transferFrom_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.transferFrom_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.transferFrom_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.transferFrom_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.transfer_encode_return": { + "decorators": [], + "pc": 1307, + "type": "function" + }, + "__wrappers__.transfer_encode_return.Args": { + "full_name": "__wrappers__.transfer_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.transfer_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.transfer_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.transfer_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.transfer_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.SELECTOR": { + "type": "const", + "value": 544914742286571513055574265148471203182105283038408585630116262969508767999 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.alloc": { + "destination": "starkware.cairo.common.alloc.alloc", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit": { + "decorators": [], + "pc": 323, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit_event": { + "destination": "starkware.starknet.common.syscalls.emit_event", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr": { + "decorators": [], + "pc": 533, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read": { + "decorators": [], + "pc": 550, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Return": { + "cairo_type": "(allowance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write": { + "decorators": [], + "pc": 571, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve": { + "decorators": [], + "pc": 937, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "caller": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr": { + "decorators": [], + "pc": 481, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read": { + "decorators": [], + "pc": 495, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Return": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write": { + "decorators": [], + "pc": 515, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn": { + "decorators": [], + "pc": 969, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr": { + "decorators": [], + "pc": 410, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read": { + "decorators": [], + "pc": 415, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Return": { + "cairo_type": "(decimals: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write": { + "decorators": [], + "pc": 428, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer": { + "decorators": [], + "pc": 590, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Args", + "members": { + "decimals": { + "cairo_type": "felt", + "offset": 2 + }, + "name": { + "cairo_type": "felt", + "offset": 0 + }, + "symbol": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint": { + "decorators": [], + "pc": 802, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.SIZEOF_LOCALS": { + "type": "const", + "value": 4 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr": { + "decorators": [], + "pc": 350, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read": { + "decorators": [], + "pc": 355, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Return": { + "cairo_type": "(name: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write": { + "decorators": [], + "pc": 368, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr": { + "decorators": [], + "pc": 380, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read": { + "decorators": [], + "pc": 385, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Return": { + "cairo_type": "(symbol: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write": { + "decorators": [], + "pc": 398, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr": { + "decorators": [], + "pc": 440, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read": { + "decorators": [], + "pc": 445, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Return": { + "cairo_type": "(total_supply: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write": { + "decorators": [], + "pc": 464, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Args", + "members": { + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer": { + "decorators": [], + "pc": 865, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "recipient": { + "cairo_type": "felt", + "offset": 1 + }, + "sender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.MAX_DECIMALS": { + "type": "const", + "value": 255 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.SignatureBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.SELECTOR": { + "type": "const", + "value": 271746229759260285552388728919865295615886751538523744128730118297934206697 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.alloc": { + "destination": "starkware.cairo.common.alloc.alloc", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit": { + "decorators": [], + "pc": 296, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Args", + "members": { + "from_": { + "cairo_type": "felt", + "offset": 0 + }, + "to": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit_event": { + "destination": "starkware.starknet.common.syscalls.emit_event", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Uint256": { + "destination": "starkware.cairo.common.uint256.Uint256", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance": { + "decorators": [ + "view" + ], + "pc": 765, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Return": { + "cairo_type": "(remaining: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.assert_nn_le": { + "destination": "starkware.cairo.common.math.assert_nn_le", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf": { + "decorators": [ + "view" + ], + "pc": 730, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Return": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals": { + "decorators": [ + "view" + ], + "pc": 700, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Return": { + "cairo_type": "(decimals: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name": { + "decorators": [ + "view" + ], + "pc": 609, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Return": { + "cairo_type": "(name: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol": { + "decorators": [ + "view" + ], + "pc": 639, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Return": { + "cairo_type": "(symbol: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply": { + "decorators": [ + "view" + ], + "pc": 669, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Return": { + "cairo_type": "(totalSupply: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_add": { + "destination": "starkware.cairo.common.uint256.uint256_add", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_check": { + "destination": "starkware.cairo.common.uint256.uint256_check", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_le": { + "destination": "starkware.cairo.common.uint256.uint256_le", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_sub": { + "destination": "starkware.cairo.common.uint256.uint256_sub", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter": { + "decorators": [ + "view" + ], + "pc": 1075, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Return": { + "cairo_type": "(minter: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer": { + "decorators": [], + "pc": 1065, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Args", + "members": { + "minter_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr": { + "decorators": [], + "pc": 1035, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read": { + "decorators": [], + "pc": 1040, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write": { + "decorators": [], + "pc": 1053, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only": { + "decorators": [], + "pc": 1105, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr": { + "decorators": [], + "pc": 1120, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read": { + "decorators": [], + "pc": 1125, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write": { + "decorators": [], + "pc": 1138, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized": { + "decorators": [ + "view" + ], + "pc": 1150, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized": { + "decorators": [], + "pc": 1180, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized": { + "decorators": [], + "pc": 1191, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.alloc.alloc": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.alloc.alloc.Args": { + "full_name": "starkware.cairo.common.alloc.alloc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.ImplicitArgs": { + "full_name": "starkware.cairo.common.alloc.alloc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.Return": { + "cairo_type": "(ptr: felt*)", + "type": "type_definition" + }, + "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bitwise.ALL_ONES": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719234 + }, + "starkware.cairo.common.bitwise.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash.hash2": { + "decorators": [], + "pc": 3, + "type": "function" + }, + "starkware.cairo.common.hash.hash2.Args": { + "full_name": "starkware.cairo.common.hash.hash2.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash.hash2.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash.hash2.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.math.assert_250_bit": { + "decorators": [ + "known_ap_change" + ], + "pc": 32, + "type": "function" + }, + "starkware.cairo.common.math.assert_250_bit.Args": { + "full_name": "starkware.cairo.common.math.assert_250_bit.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.HIGH_BOUND": { + "type": "const", + "value": 5316911983139663491615228241121378304 + }, + "starkware.cairo.common.math.assert_250_bit.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_250_bit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_250_bit.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND": { + "type": "const", + "value": 1809251394333065553493296640760748560207343510400633813116524750123642650624 + }, + "starkware.cairo.common.math.assert_250_bit.high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.high", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)] + 1, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.low", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)], felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.value", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le": { + "decorators": [], + "pc": 18, + "type": "function" + }, + "starkware.cairo.common.math.assert_le.Args": { + "full_name": "starkware.cairo.common.math.assert_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_le_felt": { + "decorators": [ + "known_ap_change" + ], + "pc": 45, + "type": "function" + }, + "starkware.cairo.common.math.assert_le_felt.Args": { + "full_name": "starkware.cairo.common.math.assert_le_felt.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le_felt.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_le_felt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH": { + "type": "const", + "value": 5316911983139663648412552867652567041 + }, + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH": { + "type": "const", + "value": 3544607988759775765608368578435044694 + }, + "starkware.cairo.common.math.assert_le_felt.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_le_felt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_le_felt.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.a", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-4), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.b": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.b", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.range_check_ptr": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-5), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 8 + }, + "pc": 55, + "value": "cast([fp + (-5)] + 4, felt)" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.skip_exclude_a": { + "pc": 69, + "type": "label" + }, + "starkware.cairo.common.math.assert_le_felt.skip_exclude_b_minus_a": { + "pc": 81, + "type": "label" + }, + "starkware.cairo.common.math.assert_nn": { + "decorators": [], + "pc": 14, + "type": "function" + }, + "starkware.cairo.common.math.assert_nn.Args": { + "full_name": "starkware.cairo.common.math.assert_nn.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_nn.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_nn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_nn.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_nn.a", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 14, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_nn_le": { + "decorators": [], + "pc": 23, + "type": "function" + }, + "starkware.cairo.common.math.assert_nn_le.Args": { + "full_name": "starkware.cairo.common.math.assert_nn_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_nn_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn_le.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_nn_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_not_zero": { + "decorators": [], + "pc": 9, + "type": "function" + }, + "starkware.cairo.common.math.assert_not_zero.Args": { + "full_name": "starkware.cairo.common.math.assert_not_zero.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_not_zero.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_not_zero.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.math.assert_not_zero.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_not_zero.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_not_zero.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_not_zero.value", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 9, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math_cmp.RC_BOUND": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math_cmp.assert_le_felt": { + "destination": "starkware.cairo.common.math.assert_le_felt", + "type": "alias" + }, + "starkware.cairo.common.math_cmp.assert_lt_felt": { + "destination": "starkware.cairo.common.math.assert_lt_felt", + "type": "alias" + }, + "starkware.cairo.common.math_cmp.is_le": { + "decorators": [ + "known_ap_change" + ], + "pc": 196, + "type": "function" + }, + "starkware.cairo.common.math_cmp.is_le.Args": { + "full_name": "starkware.cairo.common.math_cmp.is_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math_cmp.is_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_le.Return": { + "cairo_type": "felt", + "type": "type_definition" + }, + "starkware.cairo.common.math_cmp.is_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math_cmp.is_nn": { + "decorators": [ + "known_ap_change" + ], + "pc": 163, + "type": "function" + }, + "starkware.cairo.common.math_cmp.is_nn.Args": { + "full_name": "starkware.cairo.common.math_cmp.is_nn.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_nn.ImplicitArgs": { + "full_name": "starkware.cairo.common.math_cmp.is_nn.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_nn.Return": { + "cairo_type": "felt", + "type": "type_definition" + }, + "starkware.cairo.common.math_cmp.is_nn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math_cmp.is_nn.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math_cmp.is_nn.a", + "references": [ + { + "ap_tracking_data": { + "group": 13, + "offset": 0 + }, + "pc": 163, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math_cmp.is_nn.need_felt_comparison": { + "pc": 187, + "type": "label" + }, + "starkware.cairo.common.math_cmp.is_nn.out_of_range": { + "pc": 173, + "type": "label" + }, + "starkware.cairo.common.pow.assert_le": { + "destination": "starkware.cairo.common.math.assert_le", + "type": "alias" + }, + "starkware.cairo.common.pow.get_ap": { + "destination": "starkware.cairo.common.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.pow.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.registers.get_ap": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.registers.get_fp_and_pc": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.uint256.ALL_ONES": { + "type": "const", + "value": 340282366920938463463374607431768211455 + }, + "starkware.cairo.common.uint256.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "starkware.cairo.common.uint256.HALF_SHIFT": { + "type": "const", + "value": 18446744073709551616 + }, + "starkware.cairo.common.uint256.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.uint256.Uint256": { + "full_name": "starkware.cairo.common.uint256.Uint256", + "members": { + "high": { + "cairo_type": "felt", + "offset": 1 + }, + "low": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.assert_in_range": { + "destination": "starkware.cairo.common.math.assert_in_range", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_le": { + "destination": "starkware.cairo.common.math.assert_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_nn_le": { + "destination": "starkware.cairo.common.math.assert_nn_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_and": { + "destination": "starkware.cairo.common.bitwise.bitwise_and", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_or": { + "destination": "starkware.cairo.common.bitwise.bitwise_or", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_xor": { + "destination": "starkware.cairo.common.bitwise.bitwise_xor", + "type": "alias" + }, + "starkware.cairo.common.uint256.get_ap": { + "destination": "starkware.cairo.common.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.uint256.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.uint256.is_le": { + "destination": "starkware.cairo.common.math_cmp.is_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.pow": { + "destination": "starkware.cairo.common.pow.pow", + "type": "alias" + }, + "starkware.cairo.common.uint256.uint256_add": { + "decorators": [], + "pc": 206, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_add.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_add.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_add.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_add.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_add.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256, carry: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_add.SIZEOF_LOCALS": { + "type": "const", + "value": 4 + }, + "starkware.cairo.common.uint256.uint256_add.a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "full_name": "starkware.cairo.common.uint256.uint256_add.a", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-6), starkware.cairo.common.uint256.Uint256*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "full_name": "starkware.cairo.common.uint256.uint256_add.b", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-4), starkware.cairo.common.uint256.Uint256*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.carry_high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.uint256.uint256_add.carry_high", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 3, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.carry_low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.uint256.uint256_add.carry_low", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 2, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_check": { + "decorators": [], + "pc": 201, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_check.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_check.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_check.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_check.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_check.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_check.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_le": { + "decorators": [], + "pc": 245, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_le.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_le.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_le.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_lt": { + "decorators": [], + "pc": 228, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_lt.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_lt.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_lt.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_lt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_lt.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_lt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_neg": { + "decorators": [], + "pc": 265, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_neg.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_neg.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_neg.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_neg.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_neg.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_neg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_not": { + "decorators": [], + "pc": 257, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_not.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_not.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_not.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_not.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_not.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_not.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_sub": { + "decorators": [], + "pc": 280, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_sub.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_sub.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_sub.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_sub.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_sub.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_sub.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.storage.normalize_address": { + "decorators": [ + "known_ap_change" + ], + "pc": 90, + "type": "function" + }, + "starkware.starknet.common.storage.normalize_address.Args": { + "full_name": "starkware.starknet.common.storage.normalize_address.Args", + "members": { + "addr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.storage.normalize_address.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.normalize_address.addr": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.addr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 90, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_250": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_250", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 110, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_small": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_small", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 92, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event": { + "decorators": [], + "pc": 153, + "type": "function" + }, + "starkware.starknet.common.syscalls.emit_event.Args": { + "full_name": "starkware.starknet.common.syscalls.emit_event.Args", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 3 + }, + "data_len": { + "cairo_type": "felt", + "offset": 2 + }, + "keys": { + "cairo_type": "felt*", + "offset": 1 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.emit_event.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.emit_event.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.emit_event.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.emit_event.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 12, + "offset": 0 + }, + "pc": 153, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 12, + "offset": 1 + }, + "pc": 160, + "value": "cast([fp + (-7)] + 5, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_caller_address": { + "decorators": [], + "pc": 130, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_caller_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.Return": { + "cairo_type": "(caller_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 130, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 1 + }, + "pc": 133, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 137, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 137, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 141, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 145, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 11, + "offset": 0 + }, + "pc": 145, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 11, + "offset": 1 + }, + "pc": 150, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 9, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 14, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)] + 1, felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-5), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 90, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 92, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 110, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 130, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 137, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 11, + "offset": 0 + }, + "pc": 145, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 12, + "offset": 0 + }, + "pc": 153, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 13, + "offset": 0 + }, + "pc": 163, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-6), starkware.cairo.common.uint256.Uint256*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-4), starkware.cairo.common.uint256.Uint256*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 3, felt*)]" + } + ] + } + } +} diff --git a/crates/papyrus_execution/resources/versioned_constants_13_0.json b/crates/papyrus_execution/resources/versioned_constants_13_0.json new file mode 100644 index 00000000000..da35da1279b --- /dev/null +++ b/crates/papyrus_execution/resources/versioned_constants_13_0.json @@ -0,0 +1,532 @@ +{ + "gateway": { + "max_calldata_length": 4000, + "max_contract_bytecode_size": 61440 + }, + "invoke_tx_max_n_steps": 3000000, + "max_recursion_depth": 50, + "os_constants": { + "block_hash_contract_address": 1, + "call_contract_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "constructor_entry_point_selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "default_entry_point_selector": 0, + "deploy_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 200, + "syscall_base_gas_cost": 1 + }, + "emit_event_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "entry_point_gas_cost": { + "entry_point_initial_budget": 1, + "step_gas_cost": 500 + }, + "entry_point_initial_budget": { + "step_gas_cost": 100 + }, + "entry_point_type_constructor": 2, + "entry_point_type_external": 0, + "entry_point_type_l1_handler": 1, + "error_block_number_out_of_range": "Block number out of range", + "error_invalid_argument": "Invalid argument", + "error_invalid_input_len": "Invalid input length", + "error_out_of_gas": "Out of gas", + "execute_entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "fee_transfer_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 100 + }, + "get_block_hash_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "get_execution_info_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "initial_gas_cost": { + "step_gas_cost": 100000000 + }, + "keccak_gas_cost": { + "syscall_base_gas_cost": 1 + }, + "keccak_round_cost_gas_cost": 180000, + "l1_gas": "L1_GAS", + "l1_gas_index": 0, + "l1_handler_version": 0, + "l2_gas": "L2_GAS", + "l2_gas_index": 1, + "library_call_gas_cost": { + "call_contract_gas_cost": 1 + }, + "memory_hole_gas_cost": 10, + "nop_entry_point_offset": -1, + "range_check_gas_cost": 70, + "replace_class_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "secp256k1_add_gas_cost": { + "range_check_gas_cost": 29, + "step_gas_cost": 406 + }, + "secp256k1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 30, + "step_gas_cost": 391 + }, + "secp256k1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 239 + }, + "secp256k1_mul_gas_cost": { + "range_check_gas_cost": 7045, + "step_gas_cost": 76401 + }, + "secp256k1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 35, + "step_gas_cost": 475 + }, + "secp256r1_add_gas_cost": { + "range_check_gas_cost": 57, + "step_gas_cost": 589 + }, + "secp256r1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 44, + "step_gas_cost": 510 + }, + "secp256r1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 241 + }, + "secp256r1_mul_gas_cost": { + "range_check_gas_cost": 13961, + "step_gas_cost": 125240 + }, + "secp256r1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 49, + "step_gas_cost": 594 + }, + "send_message_to_l1_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "sha256_process_block_gas_cost": { + "range_check_gas_cost": 0, + "step_gas_cost": 0, + "syscall_base_gas_cost": 0 + }, + "sierra_array_len_bound": 4294967296, + "step_gas_cost": 100, + "storage_read_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "storage_write_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "stored_block_hash_buffer": 10, + "syscall_base_gas_cost": { + "step_gas_cost": 100 + }, + "transaction_gas_cost": { + "entry_point_gas_cost": 2, + "fee_transfer_gas_cost": 1, + "step_gas_cost": 100 + }, + "transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "validate_declare_entry_point_selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "validate_entry_point_selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "validated": "VALID" + }, + "os_resources": { + "compute_os_kzg_commitment_info": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "execute_syscalls": { + "CallContract": { + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0, + "n_steps": 691 + }, + "DelegateCall": { + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0, + "n_steps": 713 + }, + "DelegateL1Handler": { + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0, + "n_steps": 692 + }, + "Deploy": { + "builtin_instance_counter": { + "pedersen_builtin": 7, + "range_check_builtin": 18 + }, + "n_memory_holes": 0, + "n_steps": 944 + }, + "EmitEvent": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 19 + }, + "GetBlockHash": { + "builtin_instance_counter": { + "range_check_builtin": 2 + }, + "n_memory_holes": 0, + "n_steps": 74 + }, + "GetBlockNumber": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 40 + }, + "GetBlockTimestamp": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 38 + }, + "GetCallerAddress": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 32 + }, + "GetContractAddress": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 36 + }, + "GetExecutionInfo": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 29 + }, + "GetSequencerAddress": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 34 + }, + "GetTxInfo": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 29 + }, + "GetTxSignature": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 44 + }, + "Keccak": { + "builtin_instance_counter": { + "bitwise_builtin": 6, + "keccak_builtin": 1, + "range_check_builtin": 56 + }, + "n_memory_holes": 0, + "n_steps": 381 + }, + "LibraryCall": { + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0, + "n_steps": 680 + }, + "LibraryCallL1Handler": { + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0, + "n_steps": 659 + }, + "ReplaceClass": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 73 + }, + "Secp256k1Add": { + "builtin_instance_counter": { + "range_check_builtin": 29 + }, + "n_memory_holes": 0, + "n_steps": 406 + }, + "Secp256k1GetPointFromX": { + "builtin_instance_counter": { + "range_check_builtin": 30 + }, + "n_memory_holes": 20, + "n_steps": 391 + }, + "Secp256k1GetXy": { + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 40, + "n_steps": 239 + }, + "Secp256k1Mul": { + "builtin_instance_counter": { + "range_check_builtin": 7045 + }, + "n_memory_holes": 0, + "n_steps": 76401 + }, + "Secp256k1New": { + "builtin_instance_counter": { + "range_check_builtin": 35 + }, + "n_memory_holes": 40, + "n_steps": 475 + }, + "Secp256r1Add": { + "builtin_instance_counter": { + "range_check_builtin": 57 + }, + "n_memory_holes": 0, + "n_steps": 589 + }, + "Secp256r1GetPointFromX": { + "builtin_instance_counter": { + "range_check_builtin": 44 + }, + "n_memory_holes": 20, + "n_steps": 510 + }, + "Secp256r1GetXy": { + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 40, + "n_steps": 241 + }, + "Secp256r1Mul": { + "builtin_instance_counter": { + "range_check_builtin": 13961 + }, + "n_memory_holes": 0, + "n_steps": 125240 + }, + "Secp256r1New": { + "builtin_instance_counter": { + "range_check_builtin": 49 + }, + "n_memory_holes": 40, + "n_steps": 594 + }, + "SendMessageToL1": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 84 + }, + "Sha256ProcessBlock": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "StorageRead": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 44 + }, + "StorageWrite": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 46 + } + }, + "execute_txs_inner": { + "Declare": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 15, + "range_check_builtin": 63 + }, + "n_memory_holes": 0, + "n_steps": 2711 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 15, + "range_check_builtin": 63 + }, + "n_memory_holes": 0, + "n_steps": 2711 + } + } + }, + "DeployAccount": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 23, + "range_check_builtin": 83 + }, + "n_memory_holes": 0, + "n_steps": 3628 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 23, + "range_check_builtin": 83 + }, + "n_memory_holes": 0, + "n_steps": 3628 + } + } + }, + "InvokeFunction": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 16, + "range_check_builtin": 80 + }, + "n_memory_holes": 0, + "n_steps": 3382 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 16, + "range_check_builtin": 80 + }, + "n_memory_holes": 0, + "n_steps": 3382 + } + } + }, + "L1Handler": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 17 + }, + "n_memory_holes": 0, + "n_steps": 1069 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 17 + }, + "n_memory_holes": 0, + "n_steps": 1069 + } + } + } + } + }, + "validate_max_n_steps": 1000000, + "vm_resource_fee_cost": { + "bitwise_builtin": [ + 32, + 100 + ], + "ec_op_builtin": [ + 512, + 100 + ], + "ecdsa_builtin": [ + 1024, + 100 + ], + "keccak_builtin": [ + 1024, + 100 + ], + "n_steps": [ + 5, + 1000 + ], + "output_builtin": [ + 0, + 1 + ], + "pedersen_builtin": [ + 16, + 100 + ], + "poseidon_builtin": [ + 16, + 100 + ], + "range_check_builtin": [ + 8, + 100 + ] + } +} diff --git a/crates/papyrus_execution/resources/versioned_constants_13_1.json b/crates/papyrus_execution/resources/versioned_constants_13_1.json new file mode 100644 index 00000000000..cad391a7816 --- /dev/null +++ b/crates/papyrus_execution/resources/versioned_constants_13_1.json @@ -0,0 +1,587 @@ +{ + "gateway": { + "max_calldata_length": 4000, + "max_contract_bytecode_size": 81920 + }, + "invoke_tx_max_n_steps": 4000000, + "l2_resource_gas_costs": { + "event_key_factor": [ + 2, + 1 + ], + "gas_per_code_byte": [ + 875, + 1000 + ], + "gas_per_data_felt": [ + 128, + 1000 + ] + }, + "max_recursion_depth": 50, + "os_constants": { + "block_hash_contract_address": 1, + "call_contract_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "constructor_entry_point_selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "default_entry_point_selector": 0, + "deploy_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 200, + "syscall_base_gas_cost": 1 + }, + "emit_event_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "entry_point_gas_cost": { + "entry_point_initial_budget": 1, + "step_gas_cost": 500 + }, + "entry_point_initial_budget": { + "step_gas_cost": 100 + }, + "entry_point_type_constructor": 2, + "entry_point_type_external": 0, + "entry_point_type_l1_handler": 1, + "error_block_number_out_of_range": "Block number out of range", + "error_invalid_argument": "Invalid argument", + "error_invalid_input_len": "Invalid input length", + "error_out_of_gas": "Out of gas", + "execute_entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "fee_transfer_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 100 + }, + "get_block_hash_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "get_execution_info_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "initial_gas_cost": { + "step_gas_cost": 100000000 + }, + "keccak_gas_cost": { + "syscall_base_gas_cost": 1 + }, + "keccak_round_cost_gas_cost": 180000, + "l1_gas": "L1_GAS", + "l1_gas_index": 0, + "l1_handler_version": 0, + "l2_gas": "L2_GAS", + "l2_gas_index": 1, + "library_call_gas_cost": { + "call_contract_gas_cost": 1 + }, + "memory_hole_gas_cost": 10, + "nop_entry_point_offset": -1, + "range_check_gas_cost": 70, + "replace_class_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "secp256k1_add_gas_cost": { + "range_check_gas_cost": 29, + "step_gas_cost": 406 + }, + "secp256k1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 30, + "step_gas_cost": 391 + }, + "secp256k1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 239 + }, + "secp256k1_mul_gas_cost": { + "memory_hole_gas_cost": 2, + "range_check_gas_cost": 7045, + "step_gas_cost": 76501 + }, + "secp256k1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 35, + "step_gas_cost": 475 + }, + "secp256r1_add_gas_cost": { + "range_check_gas_cost": 57, + "step_gas_cost": 589 + }, + "secp256r1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 44, + "step_gas_cost": 510 + }, + "secp256r1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 241 + }, + "secp256r1_mul_gas_cost": { + "memory_hole_gas_cost": 2, + "range_check_gas_cost": 13961, + "step_gas_cost": 125340 + }, + "secp256r1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 49, + "step_gas_cost": 594 + }, + "send_message_to_l1_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "sha256_process_block_gas_cost": { + "range_check_gas_cost": 0, + "step_gas_cost": 0, + "syscall_base_gas_cost": 0 + }, + "sierra_array_len_bound": 4294967296, + "step_gas_cost": 100, + "storage_read_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "storage_write_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "stored_block_hash_buffer": 10, + "syscall_base_gas_cost": { + "step_gas_cost": 100 + }, + "transaction_gas_cost": { + "entry_point_gas_cost": 2, + "fee_transfer_gas_cost": 1, + "step_gas_cost": 100 + }, + "transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "validate_declare_entry_point_selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "validate_entry_point_selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "validate_rounding_consts": { + "validate_block_number_rounding": 100, + "validate_timestamp_rounding": 3600 + }, + "validated": "VALID" + }, + "os_resources": { + "compute_os_kzg_commitment_info": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "execute_syscalls": { + "CallContract": { + "builtin_instance_counter": { + "range_check_builtin": 20 + }, + "n_memory_holes": 0, + "n_steps": 760 + }, + "DelegateCall": { + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0, + "n_steps": 713 + }, + "DelegateL1Handler": { + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0, + "n_steps": 692 + }, + "Deploy": { + "builtin_instance_counter": { + "pedersen_builtin": 7, + "range_check_builtin": 19 + }, + "n_memory_holes": 0, + "n_steps": 1012 + }, + "EmitEvent": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 61 + }, + "GetBlockHash": { + "builtin_instance_counter": { + "range_check_builtin": 2 + }, + "n_memory_holes": 0, + "n_steps": 104 + }, + "GetBlockNumber": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 40 + }, + "GetBlockTimestamp": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 38 + }, + "GetCallerAddress": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 64 + }, + "GetContractAddress": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 64 + }, + "GetExecutionInfo": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 64 + }, + "GetSequencerAddress": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 34 + }, + "GetTxInfo": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 64 + }, + "GetTxSignature": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 44 + }, + "Keccak": { + "builtin_instance_counter": { + "bitwise_builtin": 6, + "keccak_builtin": 1, + "range_check_builtin": 56 + }, + "n_memory_holes": 0, + "n_steps": 381 + }, + "LibraryCall": { + "builtin_instance_counter": { + "range_check_builtin": 20 + }, + "n_memory_holes": 0, + "n_steps": 751 + }, + "LibraryCallL1Handler": { + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0, + "n_steps": 659 + }, + "ReplaceClass": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 98 + }, + "Secp256k1Add": { + "builtin_instance_counter": { + "range_check_builtin": 29 + }, + "n_memory_holes": 0, + "n_steps": 408 + }, + "Secp256k1GetPointFromX": { + "builtin_instance_counter": { + "range_check_builtin": 30 + }, + "n_memory_holes": 0, + "n_steps": 393 + }, + "Secp256k1GetXy": { + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0, + "n_steps": 205 + }, + "Secp256k1Mul": { + "builtin_instance_counter": { + "range_check_builtin": 7045 + }, + "n_memory_holes": 0, + "n_steps": 76503 + }, + "Secp256k1New": { + "builtin_instance_counter": { + "range_check_builtin": 35 + }, + "n_memory_holes": 0, + "n_steps": 459 + }, + "Secp256r1Add": { + "builtin_instance_counter": { + "range_check_builtin": 57 + }, + "n_memory_holes": 0, + "n_steps": 591 + }, + "Secp256r1GetPointFromX": { + "builtin_instance_counter": { + "range_check_builtin": 44 + }, + "n_memory_holes": 0, + "n_steps": 512 + }, + "Secp256r1GetXy": { + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0, + "n_steps": 207 + }, + "Secp256r1Mul": { + "builtin_instance_counter": { + "range_check_builtin": 13961 + }, + "n_memory_holes": 0, + "n_steps": 125342 + }, + "Secp256r1New": { + "builtin_instance_counter": { + "range_check_builtin": 49 + }, + "n_memory_holes": 0, + "n_steps": 578 + }, + "SendMessageToL1": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 139 + }, + "Sha256ProcessBlock": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "StorageRead": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 87 + }, + "StorageWrite": { + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 89 + } + }, + "execute_txs_inner": { + "Declare": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 16, + "range_check_builtin": 63 + }, + "n_memory_holes": 0, + "n_steps": 2839 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": {}, + "n_memory_holes": 0, + "n_steps": 0 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 16, + "range_check_builtin": 63 + }, + "n_memory_holes": 0, + "n_steps": 2839 + } + } + }, + "DeployAccount": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 2 + }, + "n_memory_holes": 0, + "n_steps": 21 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 23, + "range_check_builtin": 83 + }, + "n_memory_holes": 0, + "n_steps": 3792 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 2 + }, + "n_memory_holes": 0, + "n_steps": 21 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 23, + "range_check_builtin": 83 + }, + "n_memory_holes": 0, + "n_steps": 3792 + } + } + }, + "InvokeFunction": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 8 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 14, + "range_check_builtin": 80 + }, + "n_memory_holes": 0, + "n_steps": 3546 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 8 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 14, + "range_check_builtin": 80 + }, + "n_memory_holes": 0, + "n_steps": 3546 + } + } + }, + "L1Handler": { + "deprecated_resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 13 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 17 + }, + "n_memory_holes": 0, + "n_steps": 1146 + } + }, + "resources": { + "calldata_factor": { + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0, + "n_steps": 13 + }, + "constant": { + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 17 + }, + "n_memory_holes": 0, + "n_steps": 1146 + } + } + } + } + }, + "tx_event_limits": { + "max_data_length": 300, + "max_keys_length": 50, + "max_n_emitted_events": 1000 + }, + "validate_max_n_steps": 1000000, + "vm_resource_fee_cost": { + "bitwise_builtin": [ + 16, + 100 + ], + "ec_op_builtin": [ + 256, + 100 + ], + "ecdsa_builtin": [ + 512, + 100 + ], + "keccak_builtin": [ + 512, + 100 + ], + "n_steps": [ + 25, + 10000 + ], + "output_builtin": [ + 0, + 1 + ], + "pedersen_builtin": [ + 8, + 100 + ], + "poseidon_builtin": [ + 8, + 100 + ], + "range_check_builtin": [ + 4, + 100 + ] + } +} diff --git a/crates/papyrus_execution/src/execution_test.rs b/crates/papyrus_execution/src/execution_test.rs new file mode 100644 index 00000000000..4862e02ff0b --- /dev/null +++ b/crates/papyrus_execution/src/execution_test.rs @@ -0,0 +1,859 @@ +// TODO(shahak): Add a test for executing when there's a missing casm that's not required and when +// there's a missing casm that is required. +use std::sync::Arc; + +use assert_matches::assert_matches; +use blockifier::abi::abi_utils::get_storage_var_address; +use blockifier::execution::call_info::Retdata; +use blockifier::execution::errors::ConstructorEntryPointExecutionError; +use blockifier::execution::stack_trace::gen_transaction_execution_error_trace; +use blockifier::transaction::errors::TransactionExecutionError as BlockifierTransactionExecutionError; +use indexmap::indexmap; +use papyrus_storage::test_utils::get_test_storage; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockNumber, StarknetVersion}; +use starknet_api::core::{ + ChainId, + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + Nonce, + PatriciaKey, +}; +use starknet_api::state::{StateNumber, ThinStateDiff}; +use starknet_api::transaction::{Calldata, Fee}; +use starknet_api::{calldata, class_hash, contract_address, felt, patricia_key}; +use starknet_types_core::felt::Felt; + +use crate::execution_utils::selector_from_name; +use crate::objects::{ + DeclareTransactionTrace, + DeployAccountTransactionTrace, + FeeEstimation, + FunctionInvocationResult, + InvokeTransactionTrace, + PriceUnit, + TransactionSimulationOutput, + TransactionTrace, +}; +use crate::test_utils::{ + execute_simulate_transactions, + prepare_storage, + TxsScenarioBuilder, + ACCOUNT_ADDRESS, + ACCOUNT_CLASS_HASH, + ACCOUNT_INITIAL_BALANCE, + CHAIN_ID, + CONTRACT_ADDRESS, + DEPRECATED_CONTRACT_ADDRESS, + GAS_PRICE, + NEW_ACCOUNT_ADDRESS, + SEQUENCER_ADDRESS, + TEST_ERC20_CONTRACT_ADDRESS, +}; +use crate::testing_instances::get_test_execution_config; +use crate::{ + estimate_fee, + execute_call, + get_versioned_constants, + ExecutableTransactionInput, + ExecutionError, + FeeEstimationResult, + RevertedTransaction, +}; + +// Test calling entry points of a deprecated class. +#[test] +fn execute_call_cairo0() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let chain_id = ChainId::Other(CHAIN_ID.to_string()); + + // Test that the entry point can be called without arguments. + + let retdata = execute_call( + storage_reader.clone(), + None, + &chain_id, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(0), + &DEPRECATED_CONTRACT_ADDRESS, + selector_from_name("without_arg"), + Calldata::default(), + &get_test_execution_config(), + true, + ) + .unwrap() + .retdata; + assert_eq!(retdata, Retdata::default()); + + // Test that the entry point can be called with arguments. + let retdata = execute_call( + storage_reader.clone(), + None, + &chain_id, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(0), + &DEPRECATED_CONTRACT_ADDRESS, + selector_from_name("with_arg"), + Calldata(Arc::new(vec![Felt::from(25u128)])), + &get_test_execution_config(), + true, + ) + .unwrap() + .retdata; + assert_eq!(retdata, Retdata::default()); + + // Test that the entry point can return a result. + let retdata = execute_call( + storage_reader.clone(), + None, + &chain_id, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(0), + &DEPRECATED_CONTRACT_ADDRESS, + selector_from_name("return_result"), + Calldata(Arc::new(vec![Felt::from(123u128)])), + &get_test_execution_config(), + true, + ) + .unwrap() + .retdata; + assert_eq!(retdata, Retdata(vec![Felt::from(123u128)])); + + // Test that the entry point can read and write to the contract storage. + let retdata = execute_call( + storage_reader, + None, + &chain_id, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(0), + &DEPRECATED_CONTRACT_ADDRESS, + selector_from_name("test_storage_read_write"), + Calldata(Arc::new(vec![Felt::from(123u128), Felt::from(456u128)])), + &get_test_execution_config(), + true, + ) + .unwrap() + .retdata; + assert_eq!(retdata, Retdata(vec![Felt::from(456u128)])); +} + +// Test calling entry points of a cairo 1 class. +#[test] +fn execute_call_cairo1() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let key = felt!(1234_u16); + let value = felt!(18_u8); + let calldata = calldata![key, value]; + + // Test that the entry point can read and write to the contract storage. + let retdata = execute_call( + storage_reader, + None, + &CHAIN_ID, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(0), + &CONTRACT_ADDRESS, + selector_from_name("test_storage_read_write"), + calldata, + &get_test_execution_config(), + true, + ) + .unwrap() + .retdata; + + assert_eq!(retdata, Retdata(vec![value])); +} + +// TODO(yair): Compare to the expected fee instead of asserting that it is not zero (all +// estimate_fee tests). +#[test] +fn estimate_fee_invoke() { + let tx = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .collect(); + let fees = estimate_fees(tx).expect("Fee estimation should succeed."); + for fee in fees { + assert_ne!(fee.overall_fee, Fee(0)); + assert_eq!(fee.gas_price, GAS_PRICE.price_in_wei); + } +} + +#[test] +fn estimate_fee_declare_deprecated_class() { + let tx = TxsScenarioBuilder::default().declare_deprecated_class(*ACCOUNT_ADDRESS).collect(); + + let fees = estimate_fees(tx).expect("Fee estimation should succeed."); + for fee in fees { + assert_ne!(fee.overall_fee, Fee(0)); + assert_eq!(fee.gas_price, GAS_PRICE.price_in_wei); + } +} + +#[test] +fn estimate_fee_declare_class() { + let tx = TxsScenarioBuilder::default().declare_class(*ACCOUNT_ADDRESS).collect(); + + let fees = estimate_fees(tx).expect("Fee estimation should succeed."); + for fee in fees { + assert_ne!(fee.overall_fee, Fee(0)); + assert_eq!(fee.gas_price, GAS_PRICE.price_in_wei); + } +} + +#[test] +fn estimate_fee_deploy_account() { + let tx = TxsScenarioBuilder::default().deploy_account().collect(); + + let fees = estimate_fees(tx).expect("Fee estimation should succeed."); + for fee in fees { + assert_ne!(fee.overall_fee, Fee(0)); + assert_eq!(fee.gas_price, GAS_PRICE.price_in_wei); + } +} + +#[test] +fn estimate_fee_combination() { + let txs = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .declare_class(*ACCOUNT_ADDRESS) + .declare_deprecated_class(*ACCOUNT_ADDRESS) + .deploy_account() + .collect(); + + let fees = estimate_fees(txs).expect("Fee estimation should succeed."); + for fee in fees { + assert_ne!(fee.overall_fee, Fee(0)); + assert_eq!(fee.gas_price, GAS_PRICE.price_in_wei); + } +} + +#[test] +fn estimate_fee_reverted() { + let non_existing_contract = contract_address!("0x987"); + let txs = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .invoke_deprecated(*ACCOUNT_ADDRESS, non_existing_contract, None, false) + .collect(); + + let failed_estimation = estimate_fees(txs).expect_err("Fee estimation should fail."); + assert_matches!(failed_estimation, RevertedTransaction { index: 1, revert_reason: _ }) +} + +fn estimate_fees(txs: Vec) -> FeeEstimationResult { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + estimate_fee( + txs, + &CHAIN_ID, + storage_reader, + None, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(1), + &get_test_execution_config(), + false, + // TODO(yair): Add test for blob fee estimation. + true, + ) + .unwrap() +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} + +#[test] +fn simulate_invoke() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let tx = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .collect(); + let exec_only_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, false); + let validate_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, true); + let charge_fee_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, true, false); + let charge_fee_validate_results = + execute_simulate_transactions(storage_reader, None, tx, None, true, true); + + for (exec_only, (validate, (charge_fee, charge_fee_validate))) in exec_only_results.iter().zip( + validate_results + .iter() + .zip(charge_fee_results.iter().zip(charge_fee_validate_results.iter())), + ) { + let TransactionTrace::Invoke(exec_only_trace) = &exec_only.transaction_trace else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + assert_matches!( + exec_only_trace, + InvokeTransactionTrace { + validate_invocation: None, + execute_invocation: FunctionInvocationResult::Ok(_), + fee_transfer_invocation: None, + } + ); + + let TransactionTrace::Invoke(validate_trace) = &validate.transaction_trace else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + assert_matches!( + validate_trace, + InvokeTransactionTrace { + validate_invocation: Some(_), + execute_invocation: FunctionInvocationResult::Ok(_), + fee_transfer_invocation: None, + } + ); + + let TransactionTrace::Invoke(charge_fee_trace) = &charge_fee.transaction_trace else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + assert_matches!( + charge_fee_trace, + InvokeTransactionTrace { + validate_invocation: None, + execute_invocation: FunctionInvocationResult::Ok(_), + fee_transfer_invocation: Some(_), + } + ); + assert_eq!(charge_fee.fee_estimation.gas_price, GAS_PRICE.price_in_wei); + + assert_eq!(exec_only_trace.execute_invocation, charge_fee_trace.execute_invocation); + + let TransactionTrace::Invoke(charge_fee_validate_trace) = + &charge_fee_validate.transaction_trace + else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + assert_matches!( + charge_fee_validate_trace, + InvokeTransactionTrace { + validate_invocation: Some(_), + execute_invocation: FunctionInvocationResult::Ok(_), + fee_transfer_invocation: Some(_), + } + ); + + // TODO(yair): Compare the trace to an expected trace. + } +} + +#[test] +fn simulate_declare_deprecated() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let tx = TxsScenarioBuilder::default().declare_deprecated_class(*ACCOUNT_ADDRESS).collect(); + let exec_only_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, false); + let validate_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, true); + let charge_fee_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, true, false); + let charge_fee_validate_results = + execute_simulate_transactions(storage_reader, None, tx, None, true, true); + + for (exec_only, (validate, (charge_fee, charge_fee_validate))) in exec_only_results.iter().zip( + validate_results + .iter() + .zip(charge_fee_results.iter().zip(charge_fee_validate_results.iter())), + ) { + let TransactionTrace::Declare(exec_only_trace) = &exec_only.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + exec_only_trace, + DeclareTransactionTrace { validate_invocation: None, fee_transfer_invocation: None } + ); + + let TransactionTrace::Declare(validate_trace) = &validate.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + validate_trace, + DeclareTransactionTrace { validate_invocation: Some(_), fee_transfer_invocation: None } + ); + + let TransactionTrace::Declare(charge_fee_trace) = &charge_fee.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + charge_fee_trace, + DeclareTransactionTrace { validate_invocation: None, fee_transfer_invocation: Some(_) } + ); + + let TransactionTrace::Declare(charge_fee_validate_trace) = + &charge_fee_validate.transaction_trace + else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + charge_fee_validate_trace, + DeclareTransactionTrace { + validate_invocation: Some(_), + fee_transfer_invocation: Some(_), + } + ); + + // TODO(yair): Compare the trace to an expected trace. + } +} + +#[test] +fn simulate_declare() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let tx = TxsScenarioBuilder::default().declare_class(*ACCOUNT_ADDRESS).collect(); + let exec_only_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, false); + let validate_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, true); + let charge_fee_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, true, false); + let charge_fee_validate_results = + execute_simulate_transactions(storage_reader, None, tx, None, true, true); + + for (exec_only, (validate, (charge_fee, charge_fee_validate))) in exec_only_results.iter().zip( + validate_results + .iter() + .zip(charge_fee_results.iter().zip(charge_fee_validate_results.iter())), + ) { + let TransactionTrace::Declare(exec_only_trace) = &exec_only.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + exec_only_trace, + DeclareTransactionTrace { validate_invocation: None, fee_transfer_invocation: None } + ); + + let TransactionTrace::Declare(validate_trace) = &validate.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + validate_trace, + DeclareTransactionTrace { validate_invocation: Some(_), fee_transfer_invocation: None } + ); + + let TransactionTrace::Declare(charge_fee_trace) = &charge_fee.transaction_trace else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + charge_fee_trace, + DeclareTransactionTrace { validate_invocation: None, fee_transfer_invocation: Some(_) } + ); + + let TransactionTrace::Declare(charge_fee_validate_trace) = + &charge_fee_validate.transaction_trace + else { + panic!("Wrong trace type, expected DeclareTransactionTrace.") + }; + assert_matches!( + charge_fee_validate_trace, + DeclareTransactionTrace { + validate_invocation: Some(_), + fee_transfer_invocation: Some(_), + } + ); + + // TODO(yair): Compare the trace to an expected trace. + } +} + +#[test] +fn simulate_deploy_account() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let tx = TxsScenarioBuilder::default().deploy_account().collect(); + let exec_only_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, false); + let validate_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, false, true); + let charge_fee_results = + execute_simulate_transactions(storage_reader.clone(), None, tx.clone(), None, true, false); + let charge_fee_validate_results = + execute_simulate_transactions(storage_reader, None, tx, None, true, true); + + for (exec_only, (validate, (charge_fee, charge_fee_validate))) in exec_only_results.iter().zip( + validate_results + .iter() + .zip(charge_fee_results.iter().zip(charge_fee_validate_results.iter())), + ) { + let TransactionTrace::DeployAccount(exec_only_trace) = &exec_only.transaction_trace else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + assert_matches!( + exec_only_trace, + DeployAccountTransactionTrace { + validate_invocation: None, + fee_transfer_invocation: None, + constructor_invocation: _, + } + ); + + let TransactionTrace::DeployAccount(validate_trace) = &validate.transaction_trace else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + assert_matches!( + validate_trace, + DeployAccountTransactionTrace { + validate_invocation: Some(_), + fee_transfer_invocation: None, + constructor_invocation: _ + } + ); + + let TransactionTrace::DeployAccount(charge_fee_trace) = &charge_fee.transaction_trace + else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + assert_matches!( + charge_fee_trace, + DeployAccountTransactionTrace { + validate_invocation: None, + fee_transfer_invocation: Some(_), + constructor_invocation: _ + } + ); + + let TransactionTrace::DeployAccount(charge_fee_validate_trace) = + &charge_fee_validate.transaction_trace + else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + assert_matches!( + charge_fee_validate_trace, + DeployAccountTransactionTrace { + validate_invocation: Some(_), + fee_transfer_invocation: Some(_), + constructor_invocation: _ + } + ); + + // TODO(yair): Compare the trace to an expected trace. + } +} + +#[test] +fn simulate_invoke_from_new_account() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + let txs = TxsScenarioBuilder::default() + // Invoke contract from a newly deployed account. + .deploy_account() + .invoke_deprecated( + *NEW_ACCOUNT_ADDRESS, + *DEPRECATED_CONTRACT_ADDRESS, + // the deploy account make the next nonce be 1. + Some(Nonce(felt!(1_u128))), + false, + ) + // TODO(yair): Find out how to deploy another contract to test calling a new contract. + .collect(); + + let mut result = execute_simulate_transactions(storage_reader, None, txs, None, false, false); + assert_eq!(result.len(), 2); + + let Some(TransactionSimulationOutput { + transaction_trace: TransactionTrace::Invoke(invoke_trace), + .. + }) = result.pop() + else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + let Some(TransactionSimulationOutput { + transaction_trace: TransactionTrace::DeployAccount(deploy_account_trace), + .. + }) = result.pop() + else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + + assert_eq!( + deploy_account_trace.constructor_invocation.function_call.contract_address, + *NEW_ACCOUNT_ADDRESS + ); + + // Check that the invoke transaction succeeded. + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); +} + +#[test] +fn simulate_invoke_from_new_account_validate_and_charge() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + // Taken from the trace of the deploy account transaction. + let new_account_address = ContractAddress(patricia_key!( + "0x0153ade9ef510502c4f3b879c049dcc3ad5866706cae665f0d9df9b01e794fdb" + )); + let txs = TxsScenarioBuilder::default() + // Invoke contract from a newly deployed account. + .deploy_account() + .invoke_deprecated( + new_account_address, + *DEPRECATED_CONTRACT_ADDRESS, + // the deploy account make the next nonce be 1. + Some(Nonce(felt!(1_u128))), + false, + ) + // TODO(yair): Find out how to deploy another contract to test calling a new contract. + .collect(); + + let mut result = execute_simulate_transactions(storage_reader, None, txs, None, true, true); + assert_eq!(result.len(), 2); + + let Some(TransactionSimulationOutput { + transaction_trace: TransactionTrace::Invoke(invoke_trace), + fee_estimation: FeeEstimation { overall_fee: invoke_fee_estimation, unit: invoke_unit, .. }, + .. + }) = result.pop() + else { + panic!("Wrong trace type, expected InvokeTransactionTrace.") + }; + let Some(TransactionSimulationOutput { + transaction_trace: TransactionTrace::DeployAccount(deploy_account_trace), + fee_estimation: FeeEstimation { overall_fee: deploy_fee_estimation, unit: deploy_unit, .. }, + .. + }) = result.pop() + else { + panic!("Wrong trace type, expected DeployAccountTransactionTrace.") + }; + + assert_eq!( + deploy_account_trace.constructor_invocation.function_call.contract_address, + new_account_address + ); + + // Check that the invoke transaction succeeded. + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + + // Check that the fee was charged. + assert_ne!(deploy_fee_estimation, Fee(0)); + assert_eq!(invoke_unit, PriceUnit::Wei); + assert_matches!(deploy_account_trace.fee_transfer_invocation, Some(_)); + assert_ne!(invoke_fee_estimation, Fee(0)); + assert_eq!(deploy_unit, PriceUnit::Wei); + assert_matches!(invoke_trace.fee_transfer_invocation, Some(_)); +} + +#[test] +// TODO: Fix this test. +#[ignore] +fn induced_state_diff() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + let sequencer_balance_key = + get_storage_var_address("ERC20_balances", &[*SEQUENCER_ADDRESS.0.key()]); + + // TODO(yair): Add a reverted transaction. + let tx = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .declare_class(*ACCOUNT_ADDRESS) + .declare_deprecated_class(*ACCOUNT_ADDRESS) + .deploy_account() + .collect(); + let simulation_results = + execute_simulate_transactions(storage_reader, None, tx, None, true, true); + // This is the value TxsScenarioBuilder uses for the first declared class hash. + let mut next_declared_class_hash = 100_u128; + let mut account_balance: u128 = ACCOUNT_INITIAL_BALANCE.to_biguint().try_into().unwrap(); + let mut sequencer_balance = 0_u128; + + account_balance -= simulation_results[0].fee_estimation.overall_fee.0; + sequencer_balance += simulation_results[0].fee_estimation.overall_fee.0; + let expected_invoke_deprecated = ThinStateDiff { + nonces: indexmap! {*ACCOUNT_ADDRESS => Nonce(felt!(1_u128))}, + deployed_contracts: indexmap! {}, + storage_diffs: indexmap! { + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!{ + account_balance_key => felt!(account_balance), + sequencer_balance_key => felt!(sequencer_balance), + }, + }, + declared_classes: indexmap! {}, + deprecated_declared_classes: vec![], + replaced_classes: indexmap! {}, + }; + assert_eq!(simulation_results[0].induced_state_diff, expected_invoke_deprecated); + + account_balance -= simulation_results[1].fee_estimation.overall_fee.0; + sequencer_balance += simulation_results[1].fee_estimation.overall_fee.0; + let expected_declare_class = ThinStateDiff { + nonces: indexmap! {*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))}, + declared_classes: indexmap! {class_hash!(next_declared_class_hash) => CompiledClassHash::default()}, + storage_diffs: indexmap! { + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!{ + account_balance_key => felt!(account_balance), + sequencer_balance_key => felt!(sequencer_balance), + }, + }, + deployed_contracts: indexmap! {}, + deprecated_declared_classes: vec![], + replaced_classes: indexmap! {}, + }; + assert_eq!(simulation_results[1].induced_state_diff, expected_declare_class); + next_declared_class_hash += 1; + + account_balance -= simulation_results[2].fee_estimation.overall_fee.0; + sequencer_balance += simulation_results[2].fee_estimation.overall_fee.0; + let expected_declare_deprecated_class = ThinStateDiff { + nonces: indexmap! {*ACCOUNT_ADDRESS => Nonce(felt!(3_u128))}, + deprecated_declared_classes: vec![class_hash!(next_declared_class_hash)], + storage_diffs: indexmap! { + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!{ + account_balance_key => felt!(account_balance), + sequencer_balance_key => felt!(sequencer_balance), + }, + }, + declared_classes: indexmap! {}, + deployed_contracts: indexmap! {}, + replaced_classes: indexmap! {}, + }; + assert_eq!(simulation_results[2].induced_state_diff, expected_declare_deprecated_class); + + let new_account_balance_key = + get_storage_var_address("ERC20_balances", &[*NEW_ACCOUNT_ADDRESS.0.key()]); + let mut new_account_balance: u128 = ACCOUNT_INITIAL_BALANCE.to_biguint().try_into().unwrap(); + new_account_balance -= simulation_results[3].fee_estimation.overall_fee.0; + + sequencer_balance += simulation_results[3].fee_estimation.overall_fee.0; + let expected_deploy_account = ThinStateDiff { + nonces: indexmap! {*NEW_ACCOUNT_ADDRESS => Nonce(felt!(1_u128))}, + deprecated_declared_classes: vec![], + storage_diffs: indexmap! { + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!{ + new_account_balance_key => felt!(new_account_balance), + sequencer_balance_key => felt!(sequencer_balance), + }, + }, + declared_classes: indexmap! {}, + deployed_contracts: indexmap! {*NEW_ACCOUNT_ADDRESS => *ACCOUNT_CLASS_HASH}, + replaced_classes: indexmap! {}, + }; + assert_eq!(simulation_results[3].induced_state_diff, expected_deploy_account); +} + +#[test] +fn simulate_with_query_bit_outputs_same_as_no_query_bit() { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + prepare_storage(storage_writer); + + // A tx with only_query=true. + let tx = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, true) + .collect(); + + let res_only_query = + execute_simulate_transactions(storage_reader.clone(), None, tx, None, false, false); + + // A tx with only_query=false. + let tx = TxsScenarioBuilder::default() + .invoke_deprecated(*ACCOUNT_ADDRESS, *DEPRECATED_CONTRACT_ADDRESS, None, false) + .collect(); + + let res_regular = + execute_simulate_transactions(storage_reader.clone(), None, tx, None, false, false); + + assert_eq!(res_only_query, res_regular); +} + +// Test that we provide the correct messages for different blockifier error variants. +// TODO(yair): remove once blockifier arranges the errors. +#[test] +fn blockifier_error_mapping() { + let child = blockifier::execution::errors::EntryPointExecutionError::RecursionDepthExceeded; + let storage_address = contract_address!("0x123"); + let class_hash = class_hash!("0x321"); + let expected = format!( + "Contract constructor execution has failed:\n0: Error in the contract class constructor \ + (contract address: {:#064x}, class hash: {:#064x}, selector: UNKNOWN):\n{child}\n", + storage_address.0.key(), + class_hash.0 + ); + + let blockifier_err = BlockifierTransactionExecutionError::ContractConstructorExecutionFailed( + ConstructorEntryPointExecutionError::ExecutionError { + error: child, + class_hash, + contract_address: storage_address, + constructor_selector: None, + }, + ); + let err = ExecutionError::from((0, blockifier_err)); + let ExecutionError::TransactionExecutionError { transaction_index, execution_error } = err + else { + panic!("unexpected variant") + }; + assert_eq!(execution_error, expected); + assert_eq!(transaction_index, 0); + + let child = blockifier::execution::errors::EntryPointExecutionError::RecursionDepthExceeded; + let selector = EntryPointSelector(felt!("0x111")); + let blockifier_err = BlockifierTransactionExecutionError::ExecutionError { + error: child, + class_hash, + storage_address, + selector, + }; + let expected = format!( + "Transaction execution has failed:\n{}", + // TODO: consider adding ErrorStack display instead. + String::from(gen_transaction_execution_error_trace(&blockifier_err)) + ); + let err = ExecutionError::from((0, blockifier_err)); + let ExecutionError::TransactionExecutionError { transaction_index, execution_error } = err + else { + panic!("unexpected variant") + }; + assert_eq!(execution_error, expected); + assert_eq!(transaction_index, 0); + + let child = blockifier::execution::errors::EntryPointExecutionError::RecursionDepthExceeded; + let blockifier_err = BlockifierTransactionExecutionError::ValidateTransactionError { + error: child, + class_hash, + storage_address, + selector, + }; + let expected = format!( + "Transaction validation has failed:\n{}", + String::from(gen_transaction_execution_error_trace(&blockifier_err)) + ); + let err = ExecutionError::from((0, blockifier_err)); + let ExecutionError::TransactionExecutionError { transaction_index, execution_error } = err + else { + panic!("unexpected variant") + }; + assert_eq!(execution_error, expected); + assert_eq!(transaction_index, 0); +} + +// Test that we retrieve the correct versioned constants. +#[test] +fn test_get_versioned_constants() { + let starknet_version_13_0 = StarknetVersion("0.13.0".to_string()); + let starknet_version_13_1 = StarknetVersion("0.13.1".to_string()); + let versioned_constants = get_versioned_constants(Some(&starknet_version_13_0)).unwrap(); + assert_eq!(versioned_constants.invoke_tx_max_n_steps, 3_000_000); + let versioned_constants = get_versioned_constants(Some(&starknet_version_13_1)).unwrap(); + assert_eq!(versioned_constants.invoke_tx_max_n_steps, 4_000_000); +} diff --git a/crates/papyrus_execution/src/execution_utils.rs b/crates/papyrus_execution/src/execution_utils.rs new file mode 100644 index 00000000000..928728acabf --- /dev/null +++ b/crates/papyrus_execution/src/execution_utils.rs @@ -0,0 +1,218 @@ +//! Utilities for executing contracts and transactions. +use std::fs::File; +use std::path::PathBuf; + +// Expose the tool for creating entry point selectors from function names. +pub use blockifier::abi::abi_utils::selector_from_name; +use blockifier::execution::contract_class::{ + ContractClass as BlockifierContractClass, + ContractClassV0, + ContractClassV1, +}; +use blockifier::state::cached_state::{CachedState, CommitmentStateDiff, MutRefState}; +use blockifier::state::state_api::StateReader; +use blockifier::transaction::objects::TransactionExecutionInfo; +use cairo_vm::types::errors::program_errors::ProgramError; +use indexmap::IndexMap; +use papyrus_common::state::{DeployedContract, ReplacedClass, StorageEntry}; +use papyrus_storage::compiled_class::CasmStorageReader; +use papyrus_storage::db::{TransactionKind, RO}; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageError, StorageResult, StorageTxn}; +use starknet_api::core::{ClassHash, ContractAddress, Nonce}; +use starknet_api::state::{StateNumber, StorageKey, ThinStateDiff}; +use starknet_types_core::felt::Felt; +use thiserror::Error; + +use crate::objects::TransactionTrace; +use crate::state_reader::ExecutionStateReader; +use crate::{ + BlockifierError, + ExecutableTransactionInput, + ExecutionConfig, + ExecutionError, + ExecutionResult, +}; + +// An error that can occur during the use of the execution utils. +#[derive(Debug, Error)] +pub(crate) enum ExecutionUtilsError { + #[error(transparent)] + ProgramError(#[from] ProgramError), + #[error(transparent)] + StorageError(#[from] StorageError), + #[error("Casm table not fully synced")] + CasmTableNotSynced, +} + +/// Returns the execution config from the config file. +impl TryFrom for ExecutionConfig { + type Error = ExecutionError; + + fn try_from(execution_config_file: PathBuf) -> Result { + let file = File::open(execution_config_file).map_err(ExecutionError::ConfigFileError)?; + serde_json::from_reader(file).map_err(ExecutionError::ConfigSerdeError) + } +} + +pub(crate) fn get_contract_class( + txn: &StorageTxn<'_, RO>, + class_hash: &ClassHash, + state_number: StateNumber, +) -> Result, ExecutionUtilsError> { + match txn.get_state_reader()?.get_class_definition_block_number(class_hash)? { + Some(block_number) if state_number.is_before(block_number) => return Ok(None), + Some(_block_number) => { + let Some(casm) = txn.get_casm(class_hash)? else { + return Err(ExecutionUtilsError::CasmTableNotSynced); + }; + return Ok(Some(BlockifierContractClass::V1( + ContractClassV1::try_from(casm).map_err(ExecutionUtilsError::ProgramError)?, + ))); + } + None => {} + }; + + let Some(deprecated_class) = + txn.get_state_reader()?.get_deprecated_class_definition_at(state_number, class_hash)? + else { + return Ok(None); + }; + Ok(Some(BlockifierContractClass::V0( + ContractClassV0::try_from(deprecated_class).map_err(ExecutionUtilsError::ProgramError)?, + ))) +} + +/// Given an ExecutableTransactionInput, returns a function that will convert the corresponding +/// TransactionExecutionInfo into the right TransactionTrace variant. +pub fn get_trace_constructor( + tx: &ExecutableTransactionInput, +) -> fn(TransactionExecutionInfo) -> ExecutionResult { + match tx { + ExecutableTransactionInput::Invoke(..) => { + |execution_info| Ok(TransactionTrace::Invoke(execution_info.try_into()?)) + } + ExecutableTransactionInput::DeclareV0(..) => { + |execution_info| Ok(TransactionTrace::Declare(execution_info.try_into()?)) + } + ExecutableTransactionInput::DeclareV1(..) => { + |execution_info| Ok(TransactionTrace::Declare(execution_info.try_into()?)) + } + ExecutableTransactionInput::DeclareV2(..) => { + |execution_info| Ok(TransactionTrace::Declare(execution_info.try_into()?)) + } + ExecutableTransactionInput::DeclareV3(..) => { + |execution_info| Ok(TransactionTrace::Declare(execution_info.try_into()?)) + } + ExecutableTransactionInput::DeployAccount(..) => { + |execution_info| Ok(TransactionTrace::DeployAccount(execution_info.try_into()?)) + } + ExecutableTransactionInput::L1Handler(..) => { + |execution_info| Ok(TransactionTrace::L1Handler(execution_info.try_into()?)) + } + } +} + +/// Returns the state diff induced by a single transaction. If the transaction +/// is a deprecated Declare, the user is required to pass the class hash of the deprecated class as +/// it is not provided by the blockifier API. +pub fn induced_state_diff( + transactional_state: &mut CachedState>>, + deprecated_declared_class_hash: Option, +) -> ExecutionResult { + let blockifier_state_diff = CommitmentStateDiff::from(transactional_state.to_state_diff()?); + // Determine which contracts were deployed and which were replaced by comparing their + // previous class hash (default value suggests it didn't exist before). + let mut deployed_contracts = IndexMap::new(); + let mut replaced_classes = IndexMap::new(); + let default_class_hash = ClassHash::default(); + for (address, class_hash) in blockifier_state_diff.address_to_class_hash.iter() { + let prev_class_hash = + transactional_state.state.get_class_hash_at(*address).map_err(BlockifierError::new)?; + if prev_class_hash == default_class_hash { + deployed_contracts.insert(*address, *class_hash); + } else { + replaced_classes.insert(*address, *class_hash); + } + } + Ok(ThinStateDiff { + deployed_contracts, + storage_diffs: blockifier_state_diff.storage_updates, + declared_classes: blockifier_state_diff.class_hash_to_compiled_class_hash, + deprecated_declared_classes: deprecated_declared_class_hash + .map_or_else(Vec::new, |class_hash| vec![class_hash]), + nonces: blockifier_state_diff.address_to_nonce, + replaced_classes, + }) +} + +/// Get the storage at the given contract and key in the given state. If there's a given pending +/// storage diffs, apply them on top of the given state. +// TODO(shahak) If the structure of storage diffs changes, remove this function and move its code +// into papyrus_rpc. +pub fn get_storage_at( + txn: &StorageTxn<'_, Mode>, + state_number: StateNumber, + pending_storage_diffs: Option<&IndexMap>>, + contract_address: ContractAddress, + key: StorageKey, +) -> StorageResult { + if let Some(pending_storage_diffs) = pending_storage_diffs { + if let Some(storage_entries) = pending_storage_diffs.get(&contract_address) { + if let Some(StorageEntry { key: _, value }) = storage_entries + .iter() + .find(|StorageEntry { key: other_key, value: _ }| key == *other_key) + { + return Ok(*value); + } + } + } + txn.get_state_reader()?.get_storage_at(state_number, &contract_address, &key) +} + +/// Get the nonce at the given contract in the given state. If there's a given pending nonces +/// update, apply them on top of the given state. +pub fn get_nonce_at( + txn: &StorageTxn<'_, Mode>, + state_number: StateNumber, + pending_nonces: Option<&IndexMap>, + contract_address: ContractAddress, +) -> StorageResult> { + if let Some(pending_nonces) = pending_nonces { + if let Some(nonce) = pending_nonces.get(&contract_address) { + return Ok(Some(*nonce)); + } + } + + txn.get_state_reader()?.get_nonce_at(state_number, &contract_address) +} + +/// Get the class hash of the contract at the given address, if it exists. If there's a given +/// pending deployed contracts, search in them as well. +pub fn get_class_hash_at( + txn: &StorageTxn<'_, Mode>, + state_number: StateNumber, + pending_deployed_contracts_and_replaced_classes: Option<( + &Vec, + &Vec, + )>, + contract_address: ContractAddress, +) -> StorageResult> { + if let Some((pending_deployed_contracts, pending_replaced_classes)) = + pending_deployed_contracts_and_replaced_classes + { + // Searching first in the replaced classes because if the contract was deployed and + // replaced, the replaced class is the contract's class. + for ReplacedClass { address, class_hash } in pending_replaced_classes { + if *address == contract_address { + return Ok(Some(*class_hash)); + } + } + for DeployedContract { address, class_hash } in pending_deployed_contracts { + if *address == contract_address { + return Ok(Some(*class_hash)); + } + } + } + txn.get_state_reader()?.get_class_hash_at(state_number, &contract_address) +} diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs new file mode 100644 index 00000000000..46536125d48 --- /dev/null +++ b/crates/papyrus_execution/src/lib.rs @@ -0,0 +1,931 @@ +#![warn(missing_docs)] +//! Functionality for executing Starknet transactions and contract entry points. +//! +//! In this module, we use the term "state_number" to refer to the state of the storage at the +//! execution, and "block_context_block_number" to refer to the block in which the transactions +//! should run. For example, if you want to simulate transactions at the beginning of block 10, you +//! should use state_number = 10 and block_context_block_number = 10. If you want to simulate +//! transactions at the end of block 10, you should use state_number = 11 and +//! block_context_block_number = 10. +//! See documentation of [StateNumber] for more details. +#[cfg(test)] +mod execution_test; +pub mod execution_utils; +mod state_reader; + +#[cfg(test)] +mod test_utils; +#[cfg(any(feature = "testing", test))] +pub mod testing_instances; + +pub mod objects; +use std::cell::Cell; +use std::collections::BTreeMap; +use std::num::NonZeroU128; +use std::path::Path; +use std::sync::Arc; + +use blockifier::blockifier::block::{pre_process_block, BlockInfo, BlockNumberHashPair, GasPrices}; +use blockifier::bouncer::BouncerConfig; +use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses, TransactionContext}; +use blockifier::execution::call_info::CallExecution; +use blockifier::execution::contract_class::{ClassInfo, ContractClass as BlockifierContractClass}; +use blockifier::execution::entry_point::{ + CallEntryPoint, + CallType as BlockifierCallType, + EntryPointExecutionContext, +}; +use blockifier::state::cached_state::CachedState; +use blockifier::transaction::errors::TransactionExecutionError as BlockifierTransactionExecutionError; +use blockifier::transaction::objects::{ + DeprecatedTransactionInfo, + TransactionExecutionInfo, + TransactionInfo, +}; +use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction; +use blockifier::transaction::transactions::ExecutableTransaction; +use blockifier::versioned_constants::VersionedConstants; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use cairo_vm::types::builtin_name::BuiltinName; +use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use execution_utils::{get_trace_constructor, induced_state_diff}; +use objects::{PriceUnit, TransactionSimulationOutput}; +use once_cell::sync::Lazy; +use papyrus_common::transaction_hash::get_transaction_hash; +use papyrus_common::TransactionOptions; +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageError, StorageReader}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockNumber, StarknetVersion}; +use starknet_api::core::{ChainId, ClassHash, ContractAddress, EntryPointSelector, PatriciaKey}; +use starknet_api::data_availability::L1DataAvailabilityMode; +// TODO: merge multiple EntryPointType structs in SN_API into one. +use starknet_api::deprecated_contract_class::{ + ContractClass as DeprecatedContractClass, + EntryPointType, +}; +use starknet_api::state::{StateNumber, ThinStateDiff}; +use starknet_api::transaction::{ + Calldata, + DeclareTransaction, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeclareTransactionV3, + DeployAccountTransaction, + Fee, + InvokeTransaction, + L1HandlerTransaction, + Transaction, + TransactionHash, + TransactionVersion, +}; +use starknet_api::{contract_address, felt, patricia_key, StarknetApiError}; +use state_reader::ExecutionStateReader; +use tracing::trace; + +use crate::objects::{tx_execution_output_to_fee_estimation, FeeEstimation, PendingData}; + +const STARKNET_VERSION_O_13_0: &str = "0.13.0"; +const STARKNET_VERSION_O_13_1: &str = "0.13.1"; +const STRK_FEE_CONTRACT_ADDRESS: &str = + "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"; +const ETH_FEE_CONTRACT_ADDRESS: &str = + "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +const INITIAL_GAS_COST: u64 = 10000000000; + +/// Result type for execution functions. +pub type ExecutionResult = Result; + +static VERSIONED_CONSTANTS_13_0: Lazy = Lazy::new(|| { + VersionedConstants::try_from(Path::new("./resources/versioned_constants_13_0.json")) + .expect("Versioned constants JSON file is malformed") +}); +static VERSIONED_CONSTANTS_13_1: Lazy = Lazy::new(|| { + VersionedConstants::try_from(Path::new("./resources/versioned_constants_13_1.json")) + .expect("Versioned constants JSON file is malformed") +}); + +#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)] +/// Parameters that are needed for execution. +pub struct ExecutionConfig { + /// The strk address to receive fees + pub strk_fee_contract_address: ContractAddress, + /// The eth address to receive fees + pub eth_fee_contract_address: ContractAddress, + /// The initial gas cost for a transaction + pub initial_gas_cost: u64, +} + +impl Default for ExecutionConfig { + fn default() -> Self { + ExecutionConfig { + strk_fee_contract_address: contract_address!(STRK_FEE_CONTRACT_ADDRESS), + eth_fee_contract_address: contract_address!(ETH_FEE_CONTRACT_ADDRESS), + initial_gas_cost: INITIAL_GAS_COST, + } + } +} + +impl SerializeConfig for ExecutionConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "strk_fee_contract_address", + &self.strk_fee_contract_address, + "The strk fee token address to receive fees", + ParamPrivacyInput::Public, + ), + ser_param( + "eth_fee_contract_address", + &self.eth_fee_contract_address, + "The eth fee token address to receive fees", + ParamPrivacyInput::Public, + ), + ser_param( + "initial_gas_cost", + &self.initial_gas_cost, + "The initial gas cost for a transaction", + ParamPrivacyInput::Public, + ), + ]) + } +} + +#[allow(missing_docs)] +/// The error type for the execution module. +#[derive(thiserror::Error, Debug)] +pub enum ExecutionError { + #[error("Bad declare tx: {tx:?}. error: {err:?}")] + BadDeclareTransaction { + tx: DeclareTransaction, + #[source] + err: blockifier::execution::errors::ContractClassError, + }, + #[error("Execution config file does not contain a configuration for all blocks")] + ConfigContentError, + #[error(transparent)] + ConfigFileError(#[from] std::io::Error), + #[error(transparent)] + ConfigSerdeError(#[from] serde_json::Error), + #[error(transparent)] + ContractError(#[from] BlockifierError), + #[error( + "The contract at address {contract_address:?} is not found at state number \ + {state_number:?}." + )] + ContractNotFound { contract_address: ContractAddress, state_number: StateNumber }, + #[error("Gas consumed should fit into u64")] + GasConsumedOutOfRange, + #[error("Missing class hash in call info")] + MissingClassHash, + #[error("Missing compiled class with hash {class_hash} (The CASM table isn't synced)")] + MissingCompiledClass { class_hash: ClassHash }, + #[error(transparent)] + StateError(#[from] blockifier::state::errors::StateError), + #[error(transparent)] + StorageError(#[from] StorageError), + #[error(transparent)] + TransactionFeeError(#[from] blockifier::transaction::errors::TransactionFeeError), + #[error( + "Execution failed at transaction {transaction_index:?} with error: {execution_error:?}" + )] + TransactionExecutionError { transaction_index: usize, execution_error: String }, + #[error("Failed to calculate transaction hash.")] + TransactionHashCalculationFailed(StarknetApiError), + #[error("Unknown builtin name: {builtin_name}")] + UnknownBuiltin { builtin_name: BuiltinName }, +} + +/// Whether the only-query bit of the transaction version is on. +pub type OnlyQuery = bool; + +/// Gathers all the possible errors that can be returned from the blockifier. +type BlockifierError = anyhow::Error; + +/// Executes a StarkNet call and returns the execution result. +#[allow(clippy::too_many_arguments)] +pub fn execute_call( + storage_reader: StorageReader, + maybe_pending_data: Option, + chain_id: &ChainId, + state_number: StateNumber, + block_context_number: BlockNumber, + contract_address: &ContractAddress, + entry_point_selector: EntryPointSelector, + calldata: Calldata, + execution_config: &ExecutionConfig, + override_kzg_da_to_false: bool, +) -> ExecutionResult { + verify_contract_exists( + *contract_address, + &storage_reader, + state_number, + maybe_pending_data.as_ref(), + )?; + + let call_entry_point = CallEntryPoint { + class_hash: None, + code_address: Some(*contract_address), + entry_point_type: EntryPointType::External, + entry_point_selector, + calldata, + storage_address: *contract_address, + caller_address: ContractAddress::default(), + call_type: BlockifierCallType::Call, + // TODO(yair): check if this is the correct value. + initial_gas: execution_config.initial_gas_cost, + }; + + let mut cached_state = CachedState::new(ExecutionStateReader { + storage_reader: storage_reader.clone(), + state_number, + maybe_pending_data: maybe_pending_data.clone(), + missing_compiled_class: Cell::new(None), + }); + + let block_context = create_block_context( + &mut cached_state, + block_context_number, + chain_id.clone(), + &storage_reader, + maybe_pending_data.as_ref(), + execution_config, + override_kzg_da_to_false, + )?; + + let mut context = EntryPointExecutionContext::new_invoke( + // TODO(yair): fix when supporting v3 transactions + Arc::new(TransactionContext { + block_context, + tx_info: TransactionInfo::Deprecated(DeprecatedTransactionInfo::default()), + }), + true, // limit_steps_by_resources + ) + .map_err(|err| ExecutionError::ContractError(err.into()))?; + + let res = call_entry_point + .execute(&mut cached_state, &mut ExecutionResources::default(), &mut context) + .map_err(|error| { + if let Some(class_hash) = cached_state.state.missing_compiled_class.get() { + ExecutionError::MissingCompiledClass { class_hash } + } else { + ExecutionError::ContractError(error.into()) + } + })?; + + Ok(res.execution) +} + +fn verify_contract_exists( + contract_address: ContractAddress, + storage_reader: &StorageReader, + state_number: StateNumber, + maybe_pending_data: Option<&PendingData>, +) -> ExecutionResult<()> { + execution_utils::get_class_hash_at( + &storage_reader.begin_ro_txn()?, + state_number, + maybe_pending_data.map(|pending_state_diff| { + (&pending_state_diff.deployed_contracts, &pending_state_diff.replaced_classes) + }), + contract_address, + )? + .ok_or(ExecutionError::ContractNotFound { contract_address, state_number })?; + Ok(()) +} + +fn create_block_context( + cached_state: &mut CachedState, + block_context_number: BlockNumber, + chain_id: ChainId, + storage_reader: &StorageReader, + maybe_pending_data: Option<&PendingData>, + execution_config: &ExecutionConfig, + // TODO(shahak): Remove this once we stop supporting rpc v0.6. + override_kzg_da_to_false: bool, +) -> ExecutionResult { + let ( + block_number, + block_timestamp, + l1_gas_price, + l1_data_gas_price, + sequencer_address, + l1_da_mode, + ) = match maybe_pending_data { + Some(pending_data) => ( + block_context_number.unchecked_next(), + pending_data.timestamp, + pending_data.l1_gas_price, + pending_data.l1_data_gas_price, + pending_data.sequencer, + pending_data.l1_da_mode, + ), + None => { + let header = storage_reader + .begin_ro_txn()? + .get_block_header(block_context_number)? + .expect("Should have block header."); + ( + header.block_number, + header.timestamp, + header.l1_gas_price, + header.l1_data_gas_price, + header.sequencer, + header.l1_da_mode, + ) + } + }; + let ten_blocks_ago = get_10_blocks_ago(&block_context_number, cached_state)?; + + let use_kzg_da = if override_kzg_da_to_false { + false + } else { + match l1_da_mode { + L1DataAvailabilityMode::Calldata => false, + L1DataAvailabilityMode::Blob => true, + } + }; + + let block_info = BlockInfo { + block_timestamp, + sequencer_address: sequencer_address.0, + use_kzg_da, + block_number, + // TODO(yair): What to do about blocks pre 0.13.1 where the data gas price were 0? + gas_prices: GasPrices { + eth_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_wei.0) + .unwrap_or(NonZeroU128::MIN), + strk_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_fri.0) + .unwrap_or(NonZeroU128::MIN), + eth_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_wei.0) + .unwrap_or(NonZeroU128::MIN), + strk_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_fri.0) + .unwrap_or(NonZeroU128::MIN), + }, + }; + let chain_info = ChainInfo { + chain_id, + fee_token_addresses: FeeTokenAddresses { + strk_fee_token_address: execution_config.strk_fee_contract_address, + eth_fee_token_address: execution_config.eth_fee_contract_address, + }, + }; + let starknet_version: Option = + storage_reader.begin_ro_txn()?.get_starknet_version(block_number)?; + let versioned_constants: &VersionedConstants = + get_versioned_constants(starknet_version.as_ref())?; + + let block_context = BlockContext::new( + block_info, + chain_info, + versioned_constants.clone(), + BouncerConfig::max(), + ); + let next_block_number = block_context.block_info().block_number; + + pre_process_block(cached_state, ten_blocks_ago, next_block_number)?; + Ok(block_context) +} + +/// The size of the json string representing the abi of a class or deprecated class. +pub type AbiSize = usize; + +/// The size of the sierra program. +pub type SierraSize = usize; + +const DEPRECATED_CONTRACT_SIERRA_SIZE: SierraSize = 0; + +/// The transaction input to be executed. +// TODO(yair): This should use broadcasted transactions instead of regular transactions, but the +// blockifier expects regular transactions. Consider changing the blockifier to use broadcasted txs. +#[allow(missing_docs)] +#[derive(Clone, Debug)] +pub enum ExecutableTransactionInput { + Invoke(InvokeTransaction, OnlyQuery), + // todo(yair): Do we need to support V0? + DeclareV0(DeclareTransactionV0V1, DeprecatedContractClass, AbiSize, OnlyQuery), + DeclareV1(DeclareTransactionV0V1, DeprecatedContractClass, AbiSize, OnlyQuery), + DeclareV2(DeclareTransactionV2, CasmContractClass, SierraSize, AbiSize, OnlyQuery), + DeclareV3(DeclareTransactionV3, CasmContractClass, SierraSize, AbiSize, OnlyQuery), + DeployAccount(DeployAccountTransaction, OnlyQuery), + L1Handler(L1HandlerTransaction, Fee, OnlyQuery), +} + +impl ExecutableTransactionInput { + fn calc_tx_hash(self, chain_id: &ChainId) -> ExecutionResult<(Self, TransactionHash)> { + match self.apply_on_transaction(|tx, only_query| { + get_transaction_hash(tx, chain_id, &TransactionOptions { only_query }) + }) { + (original_tx, Ok(tx_hash)) => Ok((original_tx, tx_hash)), + (_, Err(err)) => Err(ExecutionError::TransactionHashCalculationFailed(err)), + } + } + + /// Applies a non consuming function on the transaction as if it was of type [Transaction] of + /// StarknetAPI and returns the result without cloning the original transaction. + // TODO(yair): Refactor this. + fn apply_on_transaction(self, func: F) -> (Self, T) + where + F: Fn(&Transaction, OnlyQuery) -> T, + { + match self { + ExecutableTransactionInput::Invoke(tx, only_query) => { + let as_transaction = Transaction::Invoke(tx); + let res = func(&as_transaction, only_query); + let Transaction::Invoke(tx) = as_transaction else { + unreachable!("Should be invoke transaction.") + }; + (Self::Invoke(tx, only_query), res) + } + ExecutableTransactionInput::DeclareV0(tx, class, abi_length, only_query) => { + let as_transaction = Transaction::Declare(DeclareTransaction::V0(tx)); + let res = func(&as_transaction, only_query); + let Transaction::Declare(DeclareTransaction::V0(tx)) = as_transaction else { + unreachable!("Should be declare v0 transaction.") + }; + (Self::DeclareV0(tx, class, abi_length, only_query), res) + } + ExecutableTransactionInput::DeclareV1(tx, class, abi_length, only_query) => { + let as_transaction = Transaction::Declare(DeclareTransaction::V1(tx)); + let res = func(&as_transaction, only_query); + let Transaction::Declare(DeclareTransaction::V1(tx)) = as_transaction else { + unreachable!("Should be declare v1 transaction.") + }; + (Self::DeclareV1(tx, class, abi_length, only_query), res) + } + ExecutableTransactionInput::DeclareV2( + tx, + class, + sierra_program_length, + abi_length, + only_query, + ) => { + let as_transaction = Transaction::Declare(DeclareTransaction::V2(tx)); + let res = func(&as_transaction, only_query); + let Transaction::Declare(DeclareTransaction::V2(tx)) = as_transaction else { + unreachable!("Should be declare v2 transaction.") + }; + (Self::DeclareV2(tx, class, sierra_program_length, abi_length, only_query), res) + } + ExecutableTransactionInput::DeclareV3( + tx, + class, + sierra_program_length, + abi_length, + only_query, + ) => { + let as_transaction = Transaction::Declare(DeclareTransaction::V3(tx)); + let res = func(&as_transaction, only_query); + let Transaction::Declare(DeclareTransaction::V3(tx)) = as_transaction else { + unreachable!("Should be declare v3 transaction.") + }; + (Self::DeclareV3(tx, class, sierra_program_length, abi_length, only_query), res) + } + ExecutableTransactionInput::DeployAccount(tx, only_query) => { + let as_transaction = Transaction::DeployAccount(tx); + let res = func(&as_transaction, only_query); + let Transaction::DeployAccount(tx) = as_transaction else { + unreachable!("Should be deploy account transaction.") + }; + (Self::DeployAccount(tx, only_query), res) + } + ExecutableTransactionInput::L1Handler(tx, fee, only_query) => { + let as_transaction = Transaction::L1Handler(tx); + let res = func(&as_transaction, only_query); + let Transaction::L1Handler(tx) = as_transaction else { + unreachable!("Should be L1 handler transaction.") + }; + (Self::L1Handler(tx, fee, only_query), res) + } + } + } + + /// Returns the transaction version. + pub fn transaction_version(&self) -> TransactionVersion { + match self { + ExecutableTransactionInput::Invoke(tx, ..) => tx.version(), + ExecutableTransactionInput::DeclareV0(..) => TransactionVersion::ZERO, + ExecutableTransactionInput::DeclareV1(..) => TransactionVersion::ONE, + ExecutableTransactionInput::DeclareV2(..) => TransactionVersion::TWO, + ExecutableTransactionInput::DeclareV3(..) => TransactionVersion::THREE, + ExecutableTransactionInput::DeployAccount(tx, ..) => tx.version(), + ExecutableTransactionInput::L1Handler(tx, ..) => tx.version, + } + } +} + +/// Calculates the transaction hashes for a series of transactions without cloning the transactions. +fn calc_tx_hashes( + txs: Vec, + chain_id: &ChainId, +) -> ExecutionResult<(Vec, Vec)> { + Ok(txs + .into_iter() + .map(|tx| tx.calc_tx_hash(chain_id)) + .collect::, _>>()? + .into_iter() + .unzip()) +} + +/// Output for fee estimation when a transaction reverted. +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +pub struct RevertedTransaction { + /// The index of the reverted transaction. + pub index: usize, + /// The revert reason. + pub revert_reason: String, +} + +/// Valid output for fee estimation for a series of transactions can be either a list of fees or the +/// index and revert reason of the first reverted transaction. +pub type FeeEstimationResult = Result, RevertedTransaction>; + +/// Returns the fee estimation for a series of transactions. +#[allow(clippy::too_many_arguments)] +pub fn estimate_fee( + txs: Vec, + chain_id: &ChainId, + storage_reader: StorageReader, + maybe_pending_data: Option, + state_number: StateNumber, + block_context_block_number: BlockNumber, + execution_config: &ExecutionConfig, + validate: bool, + override_kzg_da_to_false: bool, +) -> ExecutionResult { + let (txs_execution_info, block_context) = execute_transactions( + txs, + None, + chain_id, + storage_reader, + maybe_pending_data, + state_number, + block_context_block_number, + execution_config, + false, + validate, + override_kzg_da_to_false, + )?; + let mut result = Vec::new(); + for (index, tx_execution_output) in txs_execution_info.into_iter().enumerate() { + // If the transaction reverted, fail the entire estimation. + if let Some(revert_reason) = tx_execution_output.execution_info.revert_error { + return Ok(Err(RevertedTransaction { index, revert_reason })); + } else { + result + .push(tx_execution_output_to_fee_estimation(&tx_execution_output, &block_context)?); + } + } + Ok(Ok(result)) +} + +struct TransactionExecutionOutput { + execution_info: TransactionExecutionInfo, + induced_state_diff: ThinStateDiff, + price_unit: PriceUnit, +} + +// Executes a series of transactions and returns the execution results. +// TODO(yair): Return structs instead of tuples. +#[allow(clippy::too_many_arguments)] +fn execute_transactions( + txs: Vec, + tx_hashes: Option>, + chain_id: &ChainId, + storage_reader: StorageReader, + maybe_pending_data: Option, + state_number: StateNumber, + block_context_block_number: BlockNumber, + execution_config: &ExecutionConfig, + charge_fee: bool, + validate: bool, + override_kzg_da_to_false: bool, +) -> ExecutionResult<(Vec, BlockContext)> { + // The starknet state will be from right before the block in which the transactions should run. + let mut cached_state = CachedState::new(ExecutionStateReader { + storage_reader: storage_reader.clone(), + state_number, + maybe_pending_data: maybe_pending_data.clone(), + missing_compiled_class: Cell::new(None), + }); + + let block_context = create_block_context( + &mut cached_state, + block_context_block_number, + chain_id.clone(), + &storage_reader, + maybe_pending_data.as_ref(), + execution_config, + override_kzg_da_to_false, + )?; + + let (txs, tx_hashes) = match tx_hashes { + Some(tx_hashes) => (txs, tx_hashes), + None => { + let tx_hashes = calc_tx_hashes(txs, chain_id)?; + trace!("Calculated tx hashes: {:?}", tx_hashes); + tx_hashes + } + }; + + let mut res = vec![]; + for (transaction_index, (tx, tx_hash)) in txs.into_iter().zip(tx_hashes.into_iter()).enumerate() + { + let transaction_version = tx.transaction_version(); + // TODO: consider supporting match instead. + let price_unit = if transaction_version == TransactionVersion::ZERO + || transaction_version == TransactionVersion::ONE + || transaction_version == TransactionVersion::TWO + { + PriceUnit::Wei + } else { + PriceUnit::Fri + }; + let mut transactional_state = CachedState::create_transactional(&mut cached_state); + let deprecated_declared_class_hash = match &tx { + ExecutableTransactionInput::DeclareV0( + DeclareTransactionV0V1 { class_hash, .. }, + _, + _, + _, + ) => Some(*class_hash), + ExecutableTransactionInput::DeclareV1( + DeclareTransactionV0V1 { class_hash, .. }, + _, + _, + _, + ) => Some(*class_hash), + _ => None, + }; + let blockifier_tx = to_blockifier_tx(tx, tx_hash, transaction_index)?; + let tx_execution_info_result = + blockifier_tx.execute(&mut transactional_state, &block_context, charge_fee, validate); + let state_diff = + induced_state_diff(&mut transactional_state, deprecated_declared_class_hash)?; + transactional_state.commit(); + let execution_info = tx_execution_info_result.map_err(|error| { + if let Some(class_hash) = cached_state.state.missing_compiled_class.get() { + ExecutionError::MissingCompiledClass { class_hash } + } else { + ExecutionError::from((transaction_index, error)) + } + })?; + res.push(TransactionExecutionOutput { + execution_info, + induced_state_diff: state_diff, + price_unit, + }); + } + + Ok((res, block_context)) +} + +/// Converts a transaction index and [BlockifierTransactionExecutionError] to an [ExecutionError]. +// TODO(yair): Remove once blockifier arranges the errors hierarchy. +impl From<(usize, BlockifierTransactionExecutionError)> for ExecutionError { + fn from(transaction_index_and_error: (usize, BlockifierTransactionExecutionError)) -> Self { + let (transaction_index, error) = transaction_index_and_error; + Self::TransactionExecutionError { transaction_index, execution_error: error.to_string() } + } +} + +fn get_10_blocks_ago( + block_number: &BlockNumber, + cached_state: &CachedState, +) -> ExecutionResult> { + if block_number.0 < 10 { + return Ok(None); + } + let block_min_10 = BlockNumber(block_number.0 - 10); + let Some(header_10_blocks_ago) = + cached_state.state.storage_reader.begin_ro_txn()?.get_block_header(block_min_10)? + else { + return Ok(None); + }; + Ok(Some(BlockNumberHashPair { + number: header_10_blocks_ago.block_number, + hash: header_10_blocks_ago.block_hash, + })) +} + +fn to_blockifier_tx( + tx: ExecutableTransactionInput, + tx_hash: TransactionHash, + transaction_index: usize, +) -> ExecutionResult { + // TODO(yair): support only_query version bit (enable in the RPC v0.6 and use the correct + // value). + match tx { + ExecutableTransactionInput::Invoke(invoke_tx, only_query) => { + BlockifierTransaction::from_api( + Transaction::Invoke(invoke_tx), + tx_hash, + None, + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + + ExecutableTransactionInput::DeployAccount(deploy_acc_tx, only_query) => { + BlockifierTransaction::from_api( + Transaction::DeployAccount(deploy_acc_tx), + tx_hash, + None, + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + + ExecutableTransactionInput::DeclareV0( + declare_tx, + deprecated_class, + abi_length, + only_query, + ) => { + let class_v0 = BlockifierContractClass::V0(deprecated_class.try_into().map_err( + |e: cairo_vm::types::errors::program_errors::ProgramError| { + ExecutionError::TransactionExecutionError { + transaction_index, + execution_error: e.to_string(), + } + }, + )?); + let class_info = ClassInfo::new(&class_v0, DEPRECATED_CONTRACT_SIERRA_SIZE, abi_length) + .map_err(|err| ExecutionError::BadDeclareTransaction { + tx: DeclareTransaction::V0(declare_tx.clone()), + err, + })?; + BlockifierTransaction::from_api( + Transaction::Declare(DeclareTransaction::V0(declare_tx)), + tx_hash, + Some(class_info), + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + ExecutableTransactionInput::DeclareV1( + declare_tx, + deprecated_class, + abi_length, + only_query, + ) => { + let class_v0 = BlockifierContractClass::V0( + deprecated_class.try_into().map_err(BlockifierError::new)?, + ); + let class_info = ClassInfo::new(&class_v0, DEPRECATED_CONTRACT_SIERRA_SIZE, abi_length) + .map_err(|err| ExecutionError::BadDeclareTransaction { + tx: DeclareTransaction::V1(declare_tx.clone()), + err, + })?; + BlockifierTransaction::from_api( + Transaction::Declare(DeclareTransaction::V1(declare_tx)), + tx_hash, + Some(class_info), + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + ExecutableTransactionInput::DeclareV2( + declare_tx, + compiled_class, + sierra_program_length, + abi_length, + only_query, + ) => { + let class_v1 = BlockifierContractClass::V1( + compiled_class.try_into().map_err(BlockifierError::new)?, + ); + let class_info = + ClassInfo::new(&class_v1, sierra_program_length, abi_length).map_err(|err| { + ExecutionError::BadDeclareTransaction { + tx: DeclareTransaction::V2(declare_tx.clone()), + err, + } + })?; + BlockifierTransaction::from_api( + Transaction::Declare(DeclareTransaction::V2(declare_tx)), + tx_hash, + Some(class_info), + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + ExecutableTransactionInput::DeclareV3( + declare_tx, + compiled_class, + sierra_program_length, + abi_length, + only_query, + ) => { + let class_v1 = BlockifierContractClass::V1( + compiled_class.try_into().map_err(BlockifierError::new)?, + ); + let class_info = + ClassInfo::new(&class_v1, sierra_program_length, abi_length).map_err(|err| { + ExecutionError::BadDeclareTransaction { + tx: DeclareTransaction::V3(declare_tx.clone()), + err, + } + })?; + BlockifierTransaction::from_api( + Transaction::Declare(DeclareTransaction::V3(declare_tx)), + tx_hash, + Some(class_info), + None, + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + ExecutableTransactionInput::L1Handler(l1_handler_tx, paid_fee, only_query) => { + BlockifierTransaction::from_api( + Transaction::L1Handler(l1_handler_tx), + tx_hash, + None, + Some(paid_fee), + None, + only_query, + ) + .map_err(|err| ExecutionError::from((transaction_index, err))) + } + } +} + +// TODO(dan): add 0_13_1_1 support +fn get_versioned_constants( + starknet_version: Option<&StarknetVersion>, +) -> ExecutionResult<&'static VersionedConstants> { + let versioned_constants = match starknet_version { + Some(starknet_version) => match starknet_version { + StarknetVersion(version) if version == STARKNET_VERSION_O_13_0 => { + &VERSIONED_CONSTANTS_13_0 + } + StarknetVersion(version) if version == STARKNET_VERSION_O_13_1 => { + &VERSIONED_CONSTANTS_13_1 + } + _ => VersionedConstants::latest_constants(), + }, + None => VersionedConstants::latest_constants(), + }; + Ok(versioned_constants) +} + +/// Simulates a series of transactions and returns the transaction traces and the fee estimations. +// TODO(yair): Return structs instead of tuples. +#[allow(clippy::too_many_arguments)] +pub fn simulate_transactions( + txs: Vec, + tx_hashes: Option>, + chain_id: &ChainId, + storage_reader: StorageReader, + maybe_pending_data: Option, + state_number: StateNumber, + block_context_block_number: BlockNumber, + execution_config: &ExecutionConfig, + charge_fee: bool, + validate: bool, + override_kzg_da_to_false: bool, +) -> ExecutionResult> { + let trace_constructors = txs.iter().map(get_trace_constructor).collect::>(); + let (execution_results, block_context) = execute_transactions( + txs, + tx_hashes, + chain_id, + storage_reader, + maybe_pending_data, + state_number, + block_context_block_number, + execution_config, + charge_fee, + validate, + override_kzg_da_to_false, + )?; + execution_results + .into_iter() + .zip(trace_constructors) + .map(|(tx_execution_output, trace_constructor)| { + let fee_estimation = + tx_execution_output_to_fee_estimation(&tx_execution_output, &block_context)?; + match trace_constructor(tx_execution_output.execution_info) { + Ok(transaction_trace) => Ok(TransactionSimulationOutput { + transaction_trace, + induced_state_diff: tx_execution_output.induced_state_diff, + fee_estimation, + }), + Err(e) => Err(e), + } + }) + .collect() +} diff --git a/crates/papyrus_execution/src/objects.rs b/crates/papyrus_execution/src/objects.rs new file mode 100644 index 00000000000..96d2e627a8c --- /dev/null +++ b/crates/papyrus_execution/src/objects.rs @@ -0,0 +1,532 @@ +//! Execution objects. +use std::collections::HashMap; + +use blockifier::context::BlockContext; +use blockifier::execution::call_info::{ + CallInfo, + OrderedEvent as BlockifierOrderedEvent, + OrderedL2ToL1Message as BlockifierOrderedL2ToL1Message, + Retdata as BlockifierRetdata, +}; +use blockifier::execution::entry_point::CallType as BlockifierCallType; +use blockifier::transaction::objects::{GasVector, TransactionExecutionInfo}; +use cairo_vm::types::builtin_name::BuiltinName; +use cairo_vm::vm::runners::cairo_runner::ExecutionResources as VmExecutionResources; +use indexmap::IndexMap; +use itertools::Itertools; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_common::state::{ + DeclaredClassHashEntry, + DeployedContract, + ReplacedClass, + StorageEntry, +}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockTimestamp, GasPrice, GasPricePerToken}; +use starknet_api::core::{ + ClassHash, + ContractAddress, + EntryPointSelector, + Nonce, + SequencerContractAddress, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::deprecated_contract_class::EntryPointType; +use starknet_api::state::ThinStateDiff; +use starknet_api::transaction::{ + Builtin, + Calldata, + EventContent, + ExecutionResources, + Fee, + GasVector as StarknetApiGasVector, + MessageToL1, +}; +use starknet_types_core::felt::Felt; + +use crate::{ExecutionError, ExecutionResult, TransactionExecutionOutput}; + +// TODO(yair): Move types to starknet_api. + +/// The output of simulating a transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct TransactionSimulationOutput { + /// The execution trace of the transaction. + pub transaction_trace: TransactionTrace, + /// The state diff induced by the transaction. + pub induced_state_diff: ThinStateDiff, + /// The details of the fees charged by the transaction. + pub fee_estimation: FeeEstimation, +} + +/// The execution trace of a transaction. +#[allow(missing_docs)] +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum TransactionTrace { + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionTrace), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionTrace), + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionTrace), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionTrace), +} + +/// The execution trace of an Invoke transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct InvokeTransactionTrace { + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __validate__ call. + pub validate_invocation: Option, + /// The trace of the __execute__ call or the reason in case of reverted transaction. + pub execute_invocation: FunctionInvocationResult, + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __fee_transfer__ call. + pub fee_transfer_invocation: Option, +} + +/// Output for successful fee estimation. +// TODO(shahak): We assume that this struct has the same deserialization as the RPC specs v0.7. +// Consider duplicating this struct inside the RPC crate. +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +pub struct FeeEstimation { + /// Gas consumed by this transaction. This includes gas for DA in calldata mode. + pub gas_consumed: Felt, + /// The gas price for execution and calldata DA. + pub gas_price: GasPrice, + /// Gas consumed by DA in blob mode. + pub data_gas_consumed: Felt, + /// The gas price for DA blob. + pub data_gas_price: GasPrice, + /// The total amount of fee. This is equal to: + /// gas_consumed * gas_price + data_gas_consumed * data_gas_price. + pub overall_fee: Fee, + /// The unit in which the fee was paid (Wei/Fri). + pub unit: PriceUnit, +} + +/// The reason for a reverted transaction. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[allow(missing_docs)] +pub enum RevertReason { + #[serde(rename = "revert_reason")] + RevertReason(String), +} + +impl TryFrom for InvokeTransactionTrace { + type Error = ExecutionError; + fn try_from(transaction_execution_info: TransactionExecutionInfo) -> ExecutionResult { + let execute_invocation = match transaction_execution_info.revert_error { + Some(revert_error) => { + FunctionInvocationResult::Err(RevertReason::RevertReason(revert_error)) + } + None => FunctionInvocationResult::Ok( + ( + transaction_execution_info + .execute_call_info + .expect("Invoke transaction execution should contain execute_call_info."), + transaction_execution_info.transaction_receipt.da_gas, + ) + .try_into()?, + ), + }; + + Ok(Self { + validate_invocation: match transaction_execution_info.validate_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + execute_invocation, + fee_transfer_invocation: match transaction_execution_info.fee_transfer_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + }) + } +} + +pub(crate) fn tx_execution_output_to_fee_estimation( + tx_execution_output: &TransactionExecutionOutput, + block_context: &BlockContext, +) -> ExecutionResult { + let gas_prices = &block_context.block_info().gas_prices; + let (gas_price, data_gas_price) = match tx_execution_output.price_unit { + PriceUnit::Wei => ( + GasPrice(gas_prices.eth_l1_gas_price.get()), + GasPrice(gas_prices.eth_l1_data_gas_price.get()), + ), + PriceUnit::Fri => ( + GasPrice(gas_prices.strk_l1_gas_price.get()), + GasPrice(gas_prices.strk_l1_data_gas_price.get()), + ), + }; + + let gas_vector = tx_execution_output.execution_info.transaction_receipt.gas; + + Ok(FeeEstimation { + gas_consumed: gas_vector.l1_gas.into(), + gas_price, + data_gas_consumed: gas_vector.l1_data_gas.into(), + data_gas_price, + overall_fee: tx_execution_output.execution_info.transaction_receipt.fee, + unit: tx_execution_output.price_unit, + }) +} + +/// The execution trace of a Declare transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeclareTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, +} + +impl TryFrom for DeclareTransactionTrace { + type Error = ExecutionError; + fn try_from(transaction_execution_info: TransactionExecutionInfo) -> ExecutionResult { + Ok(Self { + validate_invocation: match transaction_execution_info.validate_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + fee_transfer_invocation: match transaction_execution_info.fee_transfer_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + }) + } +} + +/// The execution trace of a DeployAccount transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeployAccountTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __constructor__ call. + pub constructor_invocation: FunctionInvocation, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, +} + +impl TryFrom for DeployAccountTransactionTrace { + type Error = ExecutionError; + fn try_from(transaction_execution_info: TransactionExecutionInfo) -> ExecutionResult { + Ok(Self { + validate_invocation: match transaction_execution_info.validate_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + constructor_invocation: ( + transaction_execution_info.execute_call_info.expect( + "Deploy account execution should contain execute_call_info (the constructor \ + call info).", + ), + transaction_execution_info.transaction_receipt.da_gas, + ) + .try_into()?, + fee_transfer_invocation: match transaction_execution_info.fee_transfer_call_info { + None => None, + Some(call_info) => Some( + (call_info, transaction_execution_info.transaction_receipt.da_gas) + .try_into()?, + ), + }, + }) + } +} + +/// The execution trace of an L1Handler transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct L1HandlerTransactionTrace { + /// The trace of the funcion call. + pub function_invocation: FunctionInvocation, +} + +impl TryFrom for L1HandlerTransactionTrace { + type Error = ExecutionError; + fn try_from(transaction_execution_info: TransactionExecutionInfo) -> ExecutionResult { + Ok(Self { + function_invocation: ( + transaction_execution_info + .execute_call_info + .expect("L1Handler execution should contain execute_call_info."), + transaction_execution_info.transaction_receipt.da_gas, + ) + .try_into()?, + }) + } +} + +/// Wether the function invocation succeeded or reverted. +// Not using `Result` because it is not being serialized according to the spec. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[allow(missing_docs)] +#[serde(untagged)] +pub enum FunctionInvocationResult { + Ok(FunctionInvocation), + Err(RevertReason), +} + +/// The execution trace of a function call. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct FunctionInvocation { + #[serde(flatten)] + /// The details of the function call. + pub function_call: FunctionCall, + /// The address of the invoking contract. 0 for the root invocation. + pub caller_address: ContractAddress, + /// The hash of the class being called. + pub class_hash: ClassHash, + /// The type of the entry point being called. + pub entry_point_type: EntryPointType, + /// library call or regular call. + pub call_type: CallType, + /// The value returned from the function invocation. + pub result: Retdata, + /// The calls made by this invocation. + pub calls: Vec, + /// The events emitted in this invocation. + pub events: Vec, + /// The messages sent by this invocation to L1. + pub messages: Vec, + /// The VM execution resources used by this invocation. + pub execution_resources: ExecutionResources, +} + +impl TryFrom<(CallInfo, GasVector)> for FunctionInvocation { + type Error = ExecutionError; + fn try_from((call_info, gas_vector): (CallInfo, GasVector)) -> ExecutionResult { + Ok(Self { + function_call: FunctionCall { + contract_address: call_info.call.storage_address, + entry_point_selector: call_info.call.entry_point_selector, + calldata: call_info.call.calldata, + }, + caller_address: call_info.call.caller_address, + class_hash: call_info.call.class_hash.ok_or(ExecutionError::MissingClassHash)?, /* TODO: fix this. */ + entry_point_type: call_info.call.entry_point_type, + call_type: call_info.call.call_type.into(), + result: call_info.execution.retdata.into(), + calls: call_info + .inner_calls + .into_iter() + .map(|call_info| (call_info, gas_vector)) + .map(Self::try_from) + .collect::>()?, + events: call_info + .execution + .events + .into_iter() + .sorted_by_key(|ordered_event| ordered_event.order) + .map(OrderedEvent::from) + .collect(), + messages: call_info + .execution + .l2_to_l1_messages + .into_iter() + .sorted_by_key(|ordered_message| ordered_message.order) + .map(|ordered_message| { + // TODO(yair): write a test that verifies that the from_address is correct. + OrderedL2ToL1Message::from(ordered_message, call_info.call.storage_address) + }) + .collect(), + execution_resources: vm_resources_to_execution_resources( + call_info.resources, + gas_vector, + )?, + }) + } +} + +// Can't implement `TryFrom` because both types are from external crates. +fn vm_resources_to_execution_resources( + vm_resources: VmExecutionResources, + GasVector { l1_gas, l1_data_gas }: GasVector, +) -> ExecutionResult { + let mut builtin_instance_counter = HashMap::new(); + for (builtin_name, count) in vm_resources.builtin_instance_counter { + if count == 0 { + continue; + } + let count: u64 = count as u64; + match builtin_name { + BuiltinName::output => continue, + BuiltinName::pedersen => builtin_instance_counter.insert(Builtin::Pedersen, count), + BuiltinName::range_check => builtin_instance_counter.insert(Builtin::RangeCheck, count), + BuiltinName::ecdsa => builtin_instance_counter.insert(Builtin::Ecdsa, count), + BuiltinName::bitwise => builtin_instance_counter.insert(Builtin::Bitwise, count), + BuiltinName::ec_op => builtin_instance_counter.insert(Builtin::EcOp, count), + BuiltinName::keccak => builtin_instance_counter.insert(Builtin::Keccak, count), + BuiltinName::poseidon => builtin_instance_counter.insert(Builtin::Poseidon, count), + BuiltinName::segment_arena => { + builtin_instance_counter.insert(Builtin::SegmentArena, count) + } + // TODO: what about the following? + // BuiltinName::range_check96 => todo!(), + // BuiltinName::add_mod => todo!(), + // BuiltinName::mul_mod => todo!(), + _ => { + return Err(ExecutionError::UnknownBuiltin { builtin_name }); + } + }; + } + Ok(ExecutionResources { + steps: vm_resources.n_steps as u64, + builtin_instance_counter, + memory_holes: vm_resources.n_memory_holes as u64, + da_gas_consumed: StarknetApiGasVector { + l1_gas: l1_gas.try_into().map_err(|_| ExecutionError::GasConsumedOutOfRange)?, + l1_data_gas: l1_data_gas + .try_into() + .map_err(|_| ExecutionError::GasConsumedOutOfRange)?, + }, + gas_consumed: StarknetApiGasVector::default(), + }) +} + +/// library call or regular call. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[allow(missing_docs)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum CallType { + Call, + LibraryCall, +} + +impl From for CallType { + fn from(call_type: BlockifierCallType) -> Self { + match call_type { + BlockifierCallType::Call => CallType::Call, + BlockifierCallType::Delegate => CallType::LibraryCall, + } + } +} + +/// The return data of a function call. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct Retdata(pub Vec); + +impl From for Retdata { + fn from(retdata: BlockifierRetdata) -> Self { + Self(retdata.0) + } +} + +/// An event emitted by a contract. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct OrderedEvent { + /// The order of the event in the transaction. + pub order: usize, + #[serde(flatten)] + /// The event. + pub event: EventContent, +} + +impl From for OrderedEvent { + fn from(ordered_event: BlockifierOrderedEvent) -> Self { + Self { order: ordered_event.order, event: ordered_event.event } + } +} + +/// A message sent from L2 to L1. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct OrderedL2ToL1Message { + /// The order of the message in the transaction. + pub order: usize, + #[serde(flatten)] + /// The message. + pub message: MessageToL1, +} + +impl OrderedL2ToL1Message { + /// Constructs a new `OrderedL2ToL1Message`. + pub fn from( + blockifier_message: BlockifierOrderedL2ToL1Message, + from_address: ContractAddress, + ) -> Self { + Self { + order: blockifier_message.order, + message: MessageToL1 { + from_address, + to_address: blockifier_message.message.to_address, + payload: blockifier_message.message.payload, + }, + } + } +} + +/// The details of a function call. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct FunctionCall { + /// The address of the contract being called. + pub contract_address: ContractAddress, + /// The selector of the entry point being called. + pub entry_point_selector: EntryPointSelector, + /// The calldata of the function call. + pub calldata: Calldata, +} + +/// A state diff for the pending block. +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct PendingData { + // TODO(shahak): Consider indexing by address and key. + /// All the contract storages that were changed in the pending block. + pub storage_diffs: IndexMap>, + /// All the contracts that were deployed in the pending block. + pub deployed_contracts: Vec, + /// All the classes that were declared in the pending block. + pub declared_classes: Vec, + /// All the deprecated classes that were declared in the pending block. + pub old_declared_contracts: Vec, + /// All the nonces that were changed in the pending block. + pub nonces: IndexMap, + /// All the classes that were declared in the pending block. + pub replaced_classes: Vec, + /// The timestamp of the pending block. + pub timestamp: BlockTimestamp, + /// The gas price of the pending block. + pub l1_gas_price: GasPricePerToken, + /// The data price of the pending block. + pub l1_data_gas_price: GasPricePerToken, + /// The data availability mode of the pending block. + pub l1_da_mode: L1DataAvailabilityMode, + /// The sequencer address of the pending block. + pub sequencer: SequencerContractAddress, + /// The classes and casms that were declared in the pending block. + pub classes: PendingClasses, +} + +/// The unit of the fee. +#[derive( + Debug, Default, Clone, Copy, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord, +)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum PriceUnit { + /// Wei. + #[default] + Wei, + /// Fri. + Fri, +} diff --git a/crates/papyrus_execution/src/state_reader.rs b/crates/papyrus_execution/src/state_reader.rs new file mode 100644 index 00000000000..a15df3c3c83 --- /dev/null +++ b/crates/papyrus_execution/src/state_reader.rs @@ -0,0 +1,161 @@ +#[cfg(test)] +#[path = "state_reader_test.rs"] +mod state_reader_test; + +use std::cell::Cell; + +use blockifier::execution::contract_class::{ + ContractClass as BlockifierContractClass, + ContractClassV0, + ContractClassV1, +}; +use blockifier::state::errors::StateError; +use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult}; +use papyrus_common::pending_classes::{ApiContractClass, PendingClassesTrait}; +use papyrus_common::state::DeclaredClassHashEntry; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageError, StorageReader}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::{StateNumber, StorageKey}; +use starknet_types_core::felt::Felt; + +use crate::execution_utils; +use crate::execution_utils::{get_contract_class, ExecutionUtilsError}; +use crate::objects::PendingData; + +/// A view into the state at a specific state number. +pub struct ExecutionStateReader { + pub storage_reader: StorageReader, + pub state_number: StateNumber, + pub maybe_pending_data: Option, + // We want to return a custom error when missing a compiled class, but we need to return + // Blockifier's error, so we store the missing class's hash in case of error. + pub missing_compiled_class: Cell>, +} + +impl BlockifierStateReader for ExecutionStateReader { + fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + ) -> StateResult { + execution_utils::get_storage_at( + &self.storage_reader.begin_ro_txn().map_err(storage_err_to_state_err)?, + self.state_number, + self.maybe_pending_data.as_ref().map(|pending_data| &pending_data.storage_diffs), + contract_address, + key, + ) + .map_err(storage_err_to_state_err) + } + + // Returns the default value if the contract address is not found. + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { + Ok(execution_utils::get_nonce_at( + &self.storage_reader.begin_ro_txn().map_err(storage_err_to_state_err)?, + self.state_number, + self.maybe_pending_data.as_ref().map(|pending_data| &pending_data.nonces), + contract_address, + ) + .map_err(storage_err_to_state_err)? + .unwrap_or_default()) + } + + // Returns the default value if the contract address is not found. + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { + Ok(execution_utils::get_class_hash_at( + &self.storage_reader.begin_ro_txn().map_err(storage_err_to_state_err)?, + self.state_number, + self.maybe_pending_data.as_ref().map(|pending_data| { + (&pending_data.deployed_contracts, &pending_data.replaced_classes) + }), + contract_address, + ) + .map_err(storage_err_to_state_err)? + .unwrap_or_default()) + } + + fn get_compiled_contract_class( + &self, + class_hash: ClassHash, + ) -> StateResult { + if let Some(pending_casm) = self + .maybe_pending_data + .as_ref() + .and_then(|pending_data| pending_data.classes.get_compiled_class(class_hash)) + { + return Ok(BlockifierContractClass::V1( + ContractClassV1::try_from(pending_casm).map_err(StateError::ProgramError)?, + )); + } + if let Some(ApiContractClass::DeprecatedContractClass(pending_deprecated_class)) = self + .maybe_pending_data + .as_ref() + .and_then(|pending_data| pending_data.classes.get_class(class_hash)) + { + return Ok(BlockifierContractClass::V0( + ContractClassV0::try_from(pending_deprecated_class) + .map_err(StateError::ProgramError)?, + )); + } + match get_contract_class( + &self.storage_reader.begin_ro_txn().map_err(storage_err_to_state_err)?, + &class_hash, + self.state_number, + ) { + Ok(Some(contract_class)) => Ok(contract_class), + Ok(None) => Err(StateError::UndeclaredClassHash(class_hash)), + Err(ExecutionUtilsError::CasmTableNotSynced) => { + self.missing_compiled_class.set(Some(class_hash)); + Err(StateError::StateReadError("Casm table not fully synced".to_string())) + } + Err(ExecutionUtilsError::ProgramError(err)) => Err(StateError::ProgramError(err)), + Err(ExecutionUtilsError::StorageError(err)) => Err(storage_err_to_state_err(err)), + } + } + + fn get_compiled_class_hash(&self, class_hash: ClassHash) -> StateResult { + if let Some(pending_data) = &self.maybe_pending_data { + for DeclaredClassHashEntry { class_hash: other_class_hash, compiled_class_hash } in + &pending_data.declared_classes + { + if class_hash == *other_class_hash { + return Ok(*compiled_class_hash); + } + } + } + let block_number = self + .storage_reader + .begin_ro_txn() + .map_err(storage_err_to_state_err)? + .get_state_reader() + .map_err(storage_err_to_state_err)? + .get_class_definition_block_number(&class_hash) + .map_err(storage_err_to_state_err)? + .ok_or(StateError::UndeclaredClassHash(class_hash))?; + + let state_diff = self + .storage_reader + .begin_ro_txn() + .map_err(storage_err_to_state_err)? + .get_state_diff(block_number) + .map_err(storage_err_to_state_err)? + .ok_or(StateError::StateReadError(format!( + "Inner storage error. Missing state diff at block {block_number}." + )))?; + + let compiled_class_hash = state_diff.declared_classes.get(&class_hash).ok_or( + StateError::StateReadError(format!( + "Inner storage error. Missing class declaration at block {block_number}, class \ + {class_hash}." + )), + )?; + + Ok(*compiled_class_hash) + } +} + +// Converts a storage error to the error type of the state reader. +fn storage_err_to_state_err(err: StorageError) -> StateError { + StateError::StateReadError(err.to_string()) +} diff --git a/crates/papyrus_execution/src/state_reader_test.rs b/crates/papyrus_execution/src/state_reader_test.rs new file mode 100644 index 00000000000..332eec48c91 --- /dev/null +++ b/crates/papyrus_execution/src/state_reader_test.rs @@ -0,0 +1,260 @@ +use std::cell::Cell; + +use assert_matches::assert_matches; +use blockifier::execution::contract_class::{ + ContractClass as BlockifierContractClass, + ContractClassV0, + ContractClassV1, +}; +use blockifier::state::errors::StateError; +use blockifier::state::state_api::StateReader; +use cairo_lang_utils::bigint::BigUintAsHex; +use indexmap::indexmap; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses, PendingClassesTrait}; +use papyrus_common::state::{ + DeclaredClassHashEntry, + DeployedContract, + ReplacedClass, + StorageEntry, +}; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use starknet_api::block::{BlockBody, BlockHash, BlockHeader, BlockNumber}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass, StateNumber, StorageKey, ThinStateDiff}; +use starknet_api::{felt, patricia_key}; +use starknet_types_core::felt::Felt; + +use crate::objects::PendingData; +use crate::state_reader::ExecutionStateReader; +use crate::test_utils::{get_test_casm, get_test_deprecated_contract_class}; + +const CONTRACT_ADDRESS: &str = "0x2"; +const DEPRECATED_CONTRACT_ADDRESS: &str = "0x1"; + +#[test] +fn read_state() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + + let class_hash0 = ClassHash(2u128.into()); + let address0 = ContractAddress(patricia_key!(CONTRACT_ADDRESS)); + let storage_key0 = StorageKey(patricia_key!("0x0")); + let storage_value0 = felt!(777_u128); + let storage_value1 = felt!(888_u128); + // The class is not used in the execution, so it can be default. + let class0 = ContractClass::default(); + let casm0 = get_test_casm(); + let blockifier_casm0 = + BlockifierContractClass::V1(ContractClassV1::try_from(casm0.clone()).unwrap()); + let compiled_class_hash0 = CompiledClassHash(StarkHash::default()); + + let class_hash1 = ClassHash(1u128.into()); + let class1 = get_test_deprecated_contract_class(); + let address1 = ContractAddress(patricia_key!(DEPRECATED_CONTRACT_ADDRESS)); + let nonce0 = Nonce(felt!(1_u128)); + + let address2 = ContractAddress(patricia_key!("0x123")); + let storage_value2 = felt!(999_u128); + let class_hash2 = ClassHash(1234u128.into()); + let compiled_class_hash2 = CompiledClassHash(StarkHash::TWO); + let mut casm1 = get_test_casm(); + casm1.bytecode[0] = BigUintAsHex { value: 12345u32.into() }; + let blockifier_casm1 = + BlockifierContractClass::V1(ContractClassV1::try_from(casm1.clone()).unwrap()); + let nonce1 = Nonce(felt!(2_u128)); + let class_hash3 = ClassHash(567_u128.into()); + let class_hash4 = ClassHash(89_u128.into()); + let class_hash5 = ClassHash(98765_u128.into()); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(0), &[], &[]) + .unwrap() + .append_header( + BlockNumber(1), + &BlockHeader { + block_hash: BlockHash(felt!(1_u128)), + block_number: BlockNumber(1), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(1), BlockBody::default()) + .unwrap() + .append_state_diff( + BlockNumber(1), + ThinStateDiff { + deployed_contracts: indexmap!( + address0 => class_hash0, + address1 => class_hash1, + ), + storage_diffs: indexmap!( + address0 => indexmap!( + storage_key0 => storage_value0, + ), + ), + declared_classes: indexmap!( + class_hash0 => compiled_class_hash0, + class_hash5 => compiled_class_hash0, + ), + deprecated_declared_classes: vec![class_hash1], + nonces: indexmap!( + address0 => nonce0, + address1 => Nonce::default(), + ), + replaced_classes: indexmap!(), + }, + ) + .unwrap() + .append_classes( + BlockNumber(1), + &[(class_hash0, &class0), (class_hash5, &class0)], + &[(class_hash1, &class1)], + ) + .unwrap() + .append_casm(&class_hash0, &casm0) + .unwrap() + .append_header( + BlockNumber(2), + &BlockHeader { + block_hash: BlockHash(felt!(2_u128)), + block_number: BlockNumber(2), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(2), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(2), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(2), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + let state_number0 = StateNumber::unchecked_right_after_block(BlockNumber(0)); + let state_reader0 = ExecutionStateReader { + storage_reader: storage_reader.clone(), + state_number: state_number0, + maybe_pending_data: None, + missing_compiled_class: Cell::new(None), + }; + let storage_after_block_0 = state_reader0.get_storage_at(address0, storage_key0).unwrap(); + assert_eq!(storage_after_block_0, Felt::default()); + let nonce_after_block_0 = state_reader0.get_nonce_at(address0).unwrap(); + assert_eq!(nonce_after_block_0, Nonce::default()); + let class_hash_after_block_0 = state_reader0.get_class_hash_at(address0).unwrap(); + assert_eq!(class_hash_after_block_0, ClassHash::default()); + let compiled_contract_class_after_block_0 = + state_reader0.get_compiled_contract_class(class_hash0); + assert_matches!( + compiled_contract_class_after_block_0, Err(StateError::UndeclaredClassHash(class_hash)) + if class_hash == class_hash0 + ); + assert_eq!(state_reader0.get_compiled_class_hash(class_hash0).unwrap(), compiled_class_hash0); + + let state_number1 = StateNumber::unchecked_right_after_block(BlockNumber(1)); + let state_reader1 = ExecutionStateReader { + storage_reader: storage_reader.clone(), + state_number: state_number1, + maybe_pending_data: None, + missing_compiled_class: Cell::new(None), + }; + let storage_after_block_1 = state_reader1.get_storage_at(address0, storage_key0).unwrap(); + assert_eq!(storage_after_block_1, storage_value0); + let nonce_after_block_1 = state_reader1.get_nonce_at(address0).unwrap(); + assert_eq!(nonce_after_block_1, nonce0); + let class_hash_after_block_1 = state_reader1.get_class_hash_at(address0).unwrap(); + assert_eq!(class_hash_after_block_1, class_hash0); + let compiled_contract_class_after_block_1 = + state_reader1.get_compiled_contract_class(class_hash0).unwrap(); + assert_eq!(compiled_contract_class_after_block_1, blockifier_casm0); + + // Test that if we try to get a casm and it's missing, that an error is returned and the field + // `missing_compiled_class` is set to its hash + state_reader1.get_compiled_contract_class(class_hash5).unwrap_err(); + assert_eq!(state_reader1.missing_compiled_class.get().unwrap(), class_hash5); + + let state_number2 = StateNumber::unchecked_right_after_block(BlockNumber(2)); + let mut state_reader2 = ExecutionStateReader { + storage_reader, + state_number: state_number2, + maybe_pending_data: None, + missing_compiled_class: Cell::new(None), + }; + let nonce_after_block_2 = state_reader2.get_nonce_at(address0).unwrap(); + assert_eq!(nonce_after_block_2, nonce0); + + // Test pending state diff + let mut pending_classes = PendingClasses::default(); + pending_classes.add_compiled_class(class_hash2, casm1); + pending_classes.add_class(class_hash3, ApiContractClass::ContractClass(class0)); + pending_classes + .add_class(class_hash4, ApiContractClass::DeprecatedContractClass(class1.clone())); + state_reader2.maybe_pending_data = Some(PendingData { + storage_diffs: indexmap!( + address0 => vec![StorageEntry{key: storage_key0, value: storage_value1}], + address2 => vec![StorageEntry{key: storage_key0, value: storage_value2}], + ), + deployed_contracts: vec![DeployedContract { address: address2, class_hash: class_hash2 }], + declared_classes: vec![DeclaredClassHashEntry { + class_hash: class_hash2, + compiled_class_hash: compiled_class_hash2, + }], + nonces: indexmap!( + address2 => nonce1, + ), + classes: pending_classes, + ..Default::default() + }); + + assert_eq!(state_reader2.get_storage_at(address0, storage_key0).unwrap(), storage_value1); + assert_eq!(state_reader2.get_storage_at(address2, storage_key0).unwrap(), storage_value2); + assert_eq!(state_reader2.get_class_hash_at(address0).unwrap(), class_hash0); + assert_eq!(state_reader2.get_class_hash_at(address2).unwrap(), class_hash2); + assert_eq!(state_reader2.get_compiled_class_hash(class_hash0).unwrap(), compiled_class_hash0); + assert_eq!(state_reader2.get_compiled_class_hash(class_hash2).unwrap(), compiled_class_hash2); + assert_eq!(state_reader2.get_nonce_at(address0).unwrap(), nonce0); + assert_eq!(state_reader2.get_nonce_at(address2).unwrap(), nonce1); + assert_eq!(state_reader2.get_compiled_contract_class(class_hash0).unwrap(), blockifier_casm0); + assert_eq!(state_reader2.get_compiled_contract_class(class_hash2).unwrap(), blockifier_casm1); + // Test that if we only got the class without the casm then an error is returned. + state_reader2.get_compiled_contract_class(class_hash3).unwrap_err(); + // Test that if the class is deprecated it is returned. + assert_eq!( + state_reader2.get_compiled_contract_class(class_hash4).unwrap(), + BlockifierContractClass::V0(ContractClassV0::try_from(class1).unwrap()) + ); + + // Test get_class_hash_at when the class is replaced. + if let Some(pending_data) = &mut state_reader2.maybe_pending_data { + pending_data.replaced_classes = vec![ + ReplacedClass { address: address0, class_hash: class_hash3 }, + ReplacedClass { address: address2, class_hash: class_hash3 }, + ]; + } + assert_eq!(state_reader2.get_class_hash_at(address0).unwrap(), class_hash3); + assert_eq!(state_reader2.get_class_hash_at(address2).unwrap(), class_hash3); +} + +// Make sure we have the arbitrary precision feature of serde_json. +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_execution/src/test_utils.rs b/crates/papyrus_execution/src/test_utils.rs new file mode 100644 index 00000000000..7ce4ec2fc7e --- /dev/null +++ b/crates/papyrus_execution/src/test_utils.rs @@ -0,0 +1,350 @@ +use std::collections::HashMap; + +use blockifier::abi::abi_utils::get_storage_var_address; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::indexmap; +use lazy_static::lazy_static; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::{StorageReader, StorageWriter}; +use serde::de::DeserializeOwned; +use starknet_api::block::{ + BlockBody, + BlockHash, + BlockHeader, + BlockNumber, + BlockTimestamp, + GasPrice, + GasPricePerToken, +}; +use starknet_api::core::{ + ChainId, + ClassHash, + CompiledClassHash, + ContractAddress, + Nonce, + PatriciaKey, + SequencerContractAddress, +}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::{ContractClass, StateNumber, ThinStateDiff}; +use starknet_api::transaction::{ + Calldata, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeployAccountTransaction, + DeployAccountTransactionV1, + Fee, + InvokeTransaction, + InvokeTransactionV1, + TransactionHash, +}; +use starknet_api::{calldata, class_hash, contract_address, felt, patricia_key}; +use starknet_types_core::felt::Felt; +use test_utils::read_json_file; + +use crate::execution_utils::selector_from_name; +use crate::objects::{PendingData, TransactionSimulationOutput}; +use crate::testing_instances::get_test_execution_config; +use crate::{simulate_transactions, ExecutableTransactionInput, OnlyQuery, SierraSize}; + +lazy_static! { + pub static ref CHAIN_ID: ChainId = ChainId::Other(String::from("TEST_CHAIN_ID")); + pub static ref GAS_PRICE: GasPricePerToken = GasPricePerToken{ + price_in_wei: GasPrice(100 * u128::pow(10, 9)), + // TODO(yair): add value and tests. + price_in_fri: GasPrice::default(), + }; + pub static ref MAX_FEE: Fee = Fee(1000000 * GAS_PRICE.price_in_wei.0); + pub static ref BLOCK_TIMESTAMP: BlockTimestamp = BlockTimestamp(1234); + pub static ref SEQUENCER_ADDRESS: SequencerContractAddress = + SequencerContractAddress(contract_address!("0xa")); + pub static ref DEPRECATED_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1"); + pub static ref CONTRACT_ADDRESS: ContractAddress = contract_address!("0x2"); + pub static ref ACCOUNT_CLASS_HASH: ClassHash = class_hash!("0x333"); + pub static ref ACCOUNT_ADDRESS: ContractAddress = contract_address!("0x444"); + // Taken from the trace of the deploy account transaction. + pub static ref NEW_ACCOUNT_ADDRESS: ContractAddress = + contract_address!("0x0153ade9ef510502c4f3b879c049dcc3ad5866706cae665f0d9df9b01e794fdb"); + pub static ref TEST_ERC20_CONTRACT_CLASS_HASH: ClassHash = class_hash!("0x1010"); + pub static ref TEST_ERC20_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1001"); + pub static ref ACCOUNT_INITIAL_BALANCE: Felt = felt!(2 * MAX_FEE.0); +} + +// Sierra size must be > 0. +const DUMMY_SIERRA_SIZE: SierraSize = 1; + +fn get_test_instance(path_in_resource_dir: &str) -> T { + serde_json::from_value(read_json_file(path_in_resource_dir)).unwrap() +} + +// A deprecated class for testing, taken from get_deprecated_contract_class of Blockifier. +pub fn get_test_deprecated_contract_class() -> DeprecatedContractClass { + get_test_instance("deprecated_class.json") +} +pub fn get_test_casm() -> CasmContractClass { + get_test_instance("casm.json") +} +pub fn get_test_erc20_fee_contract_class() -> DeprecatedContractClass { + get_test_instance("erc20_fee_contract_class.json") +} +// An account class for testing. +pub fn get_test_account_class() -> DeprecatedContractClass { + get_test_instance("account_class.json") +} + +pub fn prepare_storage(mut storage_writer: StorageWriter) { + let class_hash0 = class_hash!("0x2"); + let class_hash1 = class_hash!("0x1"); + + let minter_var_address = get_storage_var_address("permitted_minter", &[]); + + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + let new_account_balance_key = + get_storage_var_address("ERC20_balances", &[*NEW_ACCOUNT_ADDRESS.0.key()]); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff( + BlockNumber(0), + ThinStateDiff { + deployed_contracts: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => *TEST_ERC20_CONTRACT_CLASS_HASH, + *CONTRACT_ADDRESS => class_hash0, + *DEPRECATED_CONTRACT_ADDRESS => class_hash1, + *ACCOUNT_ADDRESS => *ACCOUNT_CLASS_HASH, + ), + storage_diffs: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!( + // Give the accounts some balance. + account_balance_key => *ACCOUNT_INITIAL_BALANCE, + new_account_balance_key => *ACCOUNT_INITIAL_BALANCE, + // Give the first account mint permission (what is this?). + minter_var_address => *ACCOUNT_ADDRESS.0.key() + ), + ), + declared_classes: indexmap!( + // The class is not used in the execution, so it can be default. + class_hash0 => CompiledClassHash::default() + ), + deprecated_declared_classes: vec![ + *TEST_ERC20_CONTRACT_CLASS_HASH, + class_hash1, + *ACCOUNT_CLASS_HASH, + ], + nonces: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => Nonce::default(), + *CONTRACT_ADDRESS => Nonce::default(), + *DEPRECATED_CONTRACT_ADDRESS => Nonce::default(), + *ACCOUNT_ADDRESS => Nonce::default(), + ), + replaced_classes: indexmap!(), + }, + ) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash0, &ContractClass::default())], + &[ + (*TEST_ERC20_CONTRACT_CLASS_HASH, &get_test_erc20_fee_contract_class()), + (class_hash1, &get_test_deprecated_contract_class()), + (*ACCOUNT_CLASS_HASH, &get_test_account_class()), + ], + ) + .unwrap() + .append_casm(&class_hash0, &get_test_casm()) + .unwrap() + .append_header( + BlockNumber(1), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!(1_u128)), + parent_hash: BlockHash(felt!(0_u128)), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(1), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(1), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(1), &[], &[]) + .unwrap() + .commit() + .unwrap(); +} + +pub fn execute_simulate_transactions( + storage_reader: StorageReader, + maybe_pending_data: Option, + txs: Vec, + tx_hashes: Option>, + charge_fee: bool, + validate: bool, +) -> Vec { + let chain_id = ChainId::Other(CHAIN_ID.to_string()); + + simulate_transactions( + txs, + tx_hashes, + &chain_id, + storage_reader, + maybe_pending_data, + StateNumber::unchecked_right_after_block(BlockNumber(0)), + BlockNumber(1), + &get_test_execution_config(), + charge_fee, + validate, + // TODO: Consider testing without overriding DA (It's already tested in the RPC) + true, + ) + .unwrap() +} + +// Creates transactions for testing while resolving nonces and class hashes uniqueness. +pub struct TxsScenarioBuilder { + // Each transaction by the same sender needs a unique nonce. + sender_to_nonce: HashMap, + // Each declare class needs a unique class hash. + next_class_hash: u128, + // the result. + txs: Vec, +} + +impl Default for TxsScenarioBuilder { + fn default() -> Self { + Self { sender_to_nonce: HashMap::new(), next_class_hash: 100_u128, txs: Vec::new() } + } +} + +impl TxsScenarioBuilder { + pub fn collect(&self) -> Vec { + self.txs.clone() + } + + pub fn invoke_deprecated( + mut self, + sender_address: ContractAddress, + contract_address: ContractAddress, + nonce: Option, + only_query: OnlyQuery, + ) -> Self { + let calldata = calldata![ + *contract_address.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ]; + let nonce = match nonce { + None => self.next_nonce(sender_address), + Some(nonce) => { + let override_next_nonce: u128 = + u64::try_from(nonce.0.to_biguint()).expect("Nonce should fit in u64.").into(); + self.sender_to_nonce.insert(sender_address, override_next_nonce + 1); + nonce + } + }; + let tx = ExecutableTransactionInput::Invoke( + InvokeTransaction::V1(InvokeTransactionV1 { + calldata, + max_fee: *MAX_FEE, + sender_address, + nonce, + ..Default::default() + }), + only_query, + ); + self.txs.push(tx); + self + } + + pub fn declare_deprecated_class(mut self, sender_address: ContractAddress) -> Self { + let tx = ExecutableTransactionInput::DeclareV1( + DeclareTransactionV0V1 { + max_fee: *MAX_FEE, + sender_address, + nonce: self.next_nonce(sender_address), + class_hash: self.next_class_hash(), + ..Default::default() + }, + get_test_deprecated_contract_class(), + 0, + false, + ); + self.txs.push(tx); + self + } + + pub fn declare_class(mut self, sender_address: ContractAddress) -> TxsScenarioBuilder { + let tx = ExecutableTransactionInput::DeclareV2( + DeclareTransactionV2 { + max_fee: *MAX_FEE, + sender_address, + nonce: self.next_nonce(sender_address), + class_hash: self.next_class_hash(), + ..Default::default() + }, + get_test_casm(), + DUMMY_SIERRA_SIZE, + 0, + false, + ); + self.txs.push(tx); + self + } + + pub fn deploy_account(mut self) -> TxsScenarioBuilder { + let tx = ExecutableTransactionInput::DeployAccount( + DeployAccountTransaction::V1(DeployAccountTransactionV1 { + max_fee: *MAX_FEE, + nonce: Nonce(felt!(0_u128)), + class_hash: *ACCOUNT_CLASS_HASH, + ..Default::default() + }), + false, + ); + self.txs.push(tx); + self + } + + // TODO(yair): add l1 handler transaction. + + fn next_nonce(&mut self, sender_address: ContractAddress) -> Nonce { + match self.sender_to_nonce.get_mut(&sender_address) { + Some(current) => { + let res = Nonce(felt!(*current)); + *current += 1; + res + } + None => { + self.sender_to_nonce.insert(sender_address, 1); + Nonce(felt!(0_u128)) + } + } + } + + fn next_class_hash(&mut self) -> ClassHash { + let class_hash = ClassHash(self.next_class_hash.into()); + self.next_class_hash += 1; + class_hash + } +} diff --git a/crates/papyrus_execution/src/testing_instances.rs b/crates/papyrus_execution/src/testing_instances.rs new file mode 100644 index 00000000000..389806de1f4 --- /dev/null +++ b/crates/papyrus_execution/src/testing_instances.rs @@ -0,0 +1,121 @@ +#![allow(clippy::unwrap_used)] +//! Utilities for generating testing instances of the execution objects. + +/// Returns the storage key of a storage variable. +pub use blockifier::abi::abi_utils::get_storage_var_address; +use starknet_api::block::GasPrice; +use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, PatriciaKey}; +use starknet_api::deprecated_contract_class::EntryPointType; +use starknet_api::transaction::{Calldata, EventContent, ExecutionResources, Fee, MessageToL1}; +use starknet_api::{contract_address, felt, patricia_key}; +use starknet_types_core::felt::Felt; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, GetTestInstance}; + +use crate::objects::{ + CallType, + DeclareTransactionTrace, + DeployAccountTransactionTrace, + FeeEstimation, + FunctionCall, + FunctionInvocation, + FunctionInvocationResult, + InvokeTransactionTrace, + L1HandlerTransactionTrace, + OrderedEvent, + OrderedL2ToL1Message, + PriceUnit, + Retdata, + RevertReason, + TransactionTrace, +}; +use crate::ExecutionConfig; + +/// Creates ExecutionConfig for tests. +pub fn get_test_execution_config() -> ExecutionConfig { + ExecutionConfig { + strk_fee_contract_address: contract_address!("0x1001"), + eth_fee_contract_address: contract_address!("0x1001"), + initial_gas_cost: 10_u64.pow(10), + } +} + +auto_impl_get_test_instance! { + pub enum TransactionTrace { + Invoke(InvokeTransactionTrace) = 0, + Declare(DeclareTransactionTrace) = 1, + DeployAccount(DeployAccountTransactionTrace) = 2, + } + + pub struct InvokeTransactionTrace { + pub validate_invocation: Option, + pub execute_invocation: FunctionInvocationResult, + pub fee_transfer_invocation: Option, + } + pub struct DeclareTransactionTrace { + pub validate_invocation: Option, + pub fee_transfer_invocation: Option, + } + pub struct DeployAccountTransactionTrace { + pub validate_invocation: Option, + pub constructor_invocation: FunctionInvocation, + pub fee_transfer_invocation: Option, + } + pub struct L1HandlerTransactionTrace { + pub function_invocation: FunctionInvocation, + } + pub struct FeeEstimation { + pub gas_consumed: Felt, + pub gas_price: GasPrice, + pub data_gas_consumed: Felt, + pub data_gas_price: GasPrice, + pub overall_fee: Fee, + pub unit: PriceUnit, + } + pub enum FunctionInvocationResult { + Ok(FunctionInvocation) = 0, + Err(RevertReason) = 1, + } + pub enum CallType { + Call = 0, + LibraryCall = 1, + } + pub struct Retdata(pub Vec); + pub struct OrderedEvent { + pub order: usize, + pub event: EventContent, + } + pub struct OrderedL2ToL1Message { + pub order: usize, + pub message: MessageToL1, + } + pub struct FunctionCall { + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub enum PriceUnit { + Wei = 0, + Fri = 1, + } + + pub enum RevertReason { + RevertReason(String) = 0, + } +} + +impl GetTestInstance for FunctionInvocation { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self { + function_call: FunctionCall::get_test_instance(rng), + caller_address: ContractAddress::get_test_instance(rng), + class_hash: ClassHash::get_test_instance(rng), + entry_point_type: EntryPointType::get_test_instance(rng), + call_type: CallType::get_test_instance(rng), + result: Retdata::get_test_instance(rng), + calls: Vec::new(), + events: Vec::::get_test_instance(rng), + messages: Vec::::get_test_instance(rng), + execution_resources: ExecutionResources::get_test_instance(rng), + } + } +} diff --git a/crates/papyrus_load_test/Cargo.toml b/crates/papyrus_load_test/Cargo.toml new file mode 100644 index 00000000000..d3a0d5781f6 --- /dev/null +++ b/crates/papyrus_load_test/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "papyrus_load_test" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[features] +compare_endpoints = [] + +[dependencies] +anyhow.workspace = true +assert_matches.workspace = true +goose = "0.17.0" +once_cell.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"]} +tokio.workspace = true +rand.workspace = true +reqwest.workspace = true + +[dev-dependencies] +lazy_static.workspace = true +pretty_assertions.workspace = true \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_hash.txt b/crates/papyrus_load_test/resources/block_hash.txt new file mode 100644 index 00000000000..c0737373c89 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_hash.txt @@ -0,0 +1,16 @@ +0x50cc7487c659bb461eecbcce444e16d0a63949f10ab707c01739348d357eb3b +0xe3ac13fe4fc1b57c37ba79c002d4fdeb4da52b65ce6e3e90287b268e23ca36 +0x7400983bce6b2d145288f4f4d063a97eaeb74a4e66df37b0a914be04ae82533 +0x325a488ea0f8f19033a068236f7be85f6407898cf86b8453d9b7e58dac2b93 +0x531a714a8d334b26a3a8cd7a305c6a13aee28fe49d597b94bdae6ae0902cc82 +0x8e18bbaa65430cc80f7d0f79673e42141bd02641b92b6c29a41ae082d2df46 +0x2ab4d8425b4c8ddb5ee208869a86251c24808c22d0e3a8c1374c6451e4d5848 +0x7ed9936155e122ff0a923e8bd90e5bb430b36736aa476e41d66daf6c65a3f67 +0x3ade30d2f978b7eac4b2914cc7740e427ecd5f823f61cf0fc97232e3c7308e4 +0x5eb4ceda5580a61615ed63aa7669e0cd9a0d9da2afa3c02ce1c95d644893750 +0x13ee14b206daada8414d32f3bd6d3551c50e872f22a8a80e6e43f99963c3f0 +0x780a870d472bebfdbcf88340c2c913b284dc4e7f5c4ec087c1058b79b3943c1 +0x41c086729ade767e912c5a5094d1077b2f5897ac9fd49faf70f985cbb42ade7 +0x75798af95e54deccd36bf9b0501835238aba28c87f7a78c48d24f8ea64ab03b +0x10be8bf72c16b04fe38091ca62597a49c25007f71f6e26fbce9cfcddccb110a +0x5b5171481eb73a39fdac4ea429b430dfb644bd2e77416fbf943a8e6cd499e92 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_hash_and_class_hash.txt b/crates/papyrus_load_test/resources/block_hash_and_class_hash.txt new file mode 100644 index 00000000000..c82f2ab0ae0 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_hash_and_class_hash.txt @@ -0,0 +1,4 @@ +0x250e3dcb9aeeef2eccb747e4a9a1801f84f006ae7b9480f36eda56688bd7f02 0x2c3348ad109f7f3967df6494b3c48741d61675d9a7915b265aa7101a631dc33 +0x4b0aca0925d1f462ddbb8dd4ce1a547c4990b129f60a04a40ebba89d98fe9f4 0x2cdf5ac65a41b135969dcefa9d52799a48994d4d3aee24732b78580a9fa7c63 +0x60e6b537c2e06a0f9ff95edc2ed0b85b9c1baba3358e6b1f82f6a195ab9bd2b 0x31da92cf5f54bcb81b447e219e2b791b23f3052d12b6c9abd04ff2e5626576 +0x82b644434a29232783d7f4ba4bc0189cc53f598b381ab23cfb3570a63747bf 0x60924bf85cdd22c7e24cf8b6ac45a9a6b753671dfd0da07aae5d6b3c65a05e2 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_hash_and_contract_address.txt b/crates/papyrus_load_test/resources/block_hash_and_contract_address.txt new file mode 100644 index 00000000000..a8d43c4c0d7 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_hash_and_contract_address.txt @@ -0,0 +1,16 @@ +0x4d0d4d0ffbf386c0dea8d6274538ffd4e5540d14c197d57005ed4deb4cb34f7 0x883bb1e472fda0d2b35363a187cdaf4be7e13006a61926844895cd2d4fd9f3 +0x2df2103ec4e68c73c2e6a78157587b5f9d59c484c761a6213961434b784e9de 0x179e955aa746eee3b076a57147e84519a0f8fb73a8ab68447efb16c722dedba +0x3948772844fcf2f983fa9db1d231a301b5882fbf4562fc13c9bfa6f08004d4 0x548f5e61191f6785a780ceccb8065c8f37e08302c0321a4d89695865cc161cc +0x47f5619903fb637e7cffbf167d8d42a0b8803f02b314b0de4ee3550d3809b47 0x68b221074399e0cd9f8f742528194aeb72510af2c60a987b1e01fa605a0e3ac +0x5acc639be7638ea3ea3e7b040c8e4649cf70fcad13ef23b914d708e33f225e8 0x1556c3c836d7417f481b01260d0452e839b67460e5e4ce9d15e835f0ff1b4ca +0x612b214df4ff5c30b7c7b57f30ab91a636dc790ac8ed9c352fb41fea7951de4 0x2c15c7c40324247ff92aa0285b540378d34fb2cb4d47ee3e1fd4b0a3416b15d +0x114f581e913add809ad070737778b9775df029cc2264dd6d40cf8efee7a8e76 0x3eca9181d4d3240e1306151a8a0847cefa178992d2b3e507c276ce9d4d5f922 +0x1be9303cfa9fdf42a7998dbfb19db35fa7f2a0f241f0bb75ee01eae9b2fd7be 0x5b66d6fb6250fe390b958bd7c7d4eb52949121b80457d18ac8d7562c2ddb02c +0x5ea101db8a859bc39663245cf9d7a461c6506eea674fadd33c69b64ad0aa024 0x49a61e196581dc2794361c003f5f8b171360f42e3647aaf4afd17fb197a1f86 +0xce7eceb52e1be2d70a23333130b1ed27da1bc4ee433a3edff3d1a2c0ae4bf7 0x62f179888fc9c925d97899671cd9cf0cd22b4dce7034a96ad9b51987ba85e01 +0x71e8ff6dc163d7499b36a9eb0c8dbd2734c3150e7d98646ecc636c7d26a5b3f 0x237dfe5d2fa0beb1e4562b50f6c5c46e0de0a9fe8e069d062d1739e946ff667 +0x5ea4738b2db51b9f3173f5ee5b67f3d2a0c9b5a687940192cdefa7636923221 0x670dd476479fbf80a70b1c248f729078c9f2424c3e961914ad1cdf53493e51c +0x756acaa67f4ebc9e5aca5e61645314345dcdc7fa70c604de6bfa5a7408e8a65 0x1cb19a745e4327ee7c58b8084e62c09b8bb6f832e598130964f58d88a46eaea +0x494a752614399bfc6b3c32af1d30d596934e32943966ca4ad4a9460d4e8fc9f 0x4f2155895c6ff42ef65657ae7f16927e3fdececfca092e61d6b326b32b84dab +0x47fefa9cdbd45acd1f44555c91b0718f8564429e76b0ebd050b5092c584f243 0x14c24023bc6d99a8a8cd0aca9808012be3875b359a5c63ace6c74c491fbb13c +0x1316efe8a1b08b108e5a4bef3f8ff11efe54d7569f976c4064374bfeb7bc43e 0x9290679542ab67ab72075aec55aa0a71cbe1118bc3f81188daa91881aa1135 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_hash_and_transaction_index.txt b/crates/papyrus_load_test/resources/block_hash_and_transaction_index.txt new file mode 100644 index 00000000000..f21064347e1 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_hash_and_transaction_index.txt @@ -0,0 +1,4 @@ +0x1287175bd9d1d31c96d3bac5dfbeaf9683c46de9e61d95f3adfcdb6346e37f 13 +0x345e8d21d51f1828ce12a6ec511f175b2e4882eb3608b757105f9d805fe14f1 0 +0x4811b14890edb55b66dace2f0d414d0904cdbaf4e6309467b05161e5fd97f80 19 +0x770fbc9d9129be2fc03f6217bdac47a17205b544cad7b17ea146fda51a5a8c0 8 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_number.txt b/crates/papyrus_load_test/resources/block_number.txt new file mode 100644 index 00000000000..b66835c7100 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_number.txt @@ -0,0 +1,16 @@ +45 +551 +438 +613 +824 +932 +864 +619 +936 +628 +135 +735 +919 +886 +493 +514 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_number_and_class_hash.txt b/crates/papyrus_load_test/resources/block_number_and_class_hash.txt new file mode 100644 index 00000000000..1fa77f7e189 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_number_and_class_hash.txt @@ -0,0 +1,4 @@ +443 0x60924bf85cdd22c7e24cf8b6ac45a9a6b753671dfd0da07aae5d6b3c65a05e2 +593 0x2f09c8cc7698d6a220b929b525efd5b3622a7658e9a9e4c8a52d5ed995d6fe +378 0x2f09c8cc7698d6a220b929b525efd5b3622a7658e9a9e4c8a52d5ed995d6fe +894 0x60924bf85cdd22c7e24cf8b6ac45a9a6b753671dfd0da07aae5d6b3c65a05e2 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_number_and_contract_address.txt b/crates/papyrus_load_test/resources/block_number_and_contract_address.txt new file mode 100644 index 00000000000..c17ac45c5c0 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_number_and_contract_address.txt @@ -0,0 +1,16 @@ +879 0x43e4a5d24a2d288770660cf8e9bca74cfa1a2b4ba384740b459373f6fca3e8f +866 0x5266348d23dcac076f851cd0b9aa7dd6b09079b85f0ab7a252cce205d7f51a3 +719 0xba9c760880f1974d128226c87beb8eaf15f018f4b5aec29a26ad51cd6e46a9 +795 0x5a1c72d04a6bb4614ba1ad5408e455702a997c291c651776e228e16d05c96c0 +1000 0x6d6eb6998c7246f1eeff40cbc745bf29fffe02183d2f8d5ac29997b90aeb59c +978 0x1cec1956af92d5927daeddd10021bbe73486480cf1cb4367a4ac93ccfd3936d +669 0x1a4ba37a9de049942c908708ab5b819306b8a05cc154237d0553c8b056512ea +482 0x57b973bf2eb26ebb28af5d6184b4a044b24a8dcbf724feb95782c4d1aef1ca9 +994 0x78bf67540c717eaa6128498b93a7fcfa321978d81e2f6cc0c9e9bfeed14905e +816 0xf666b9fdb9c2d30eb68f8ebba52772e55b4fa4f5861073ce1d2ad4dbeddf88 +910 0x66f49bfd83f0a20e8db0ec8a88c9f85056f8ab955812b1c9b25103a99154676 +899 0x39da87f18785601c06d4758267fd7cda5e7149d05fc6180487083dac480329b +966 0x2f8af5755bf6d8b1ebf1e80fd72f1f2ab261490068f9e4df2c5dcb2ba12014e +912 0x220dc9a8c51fa39cd018b61efd44ddc07dcee03ab1b1580b667dff71ae3b817 +999 0x5c0eaeb122d9cded0cde25615e2e5074bdc73907cbebbbd9e45b58804cf34b5 +834 0x16db2e69b75c3ead471528ab7d8013ca5f1e400efa46b77c66b9a09b04dc010 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_number_and_transaction_index.txt b/crates/papyrus_load_test/resources/block_number_and_transaction_index.txt new file mode 100644 index 00000000000..f1d6a315811 --- /dev/null +++ b/crates/papyrus_load_test/resources/block_number_and_transaction_index.txt @@ -0,0 +1,4 @@ +839 59 +157 7 +789 2 +735 7 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/block_range_and_contract_address.txt b/crates/papyrus_load_test/resources/block_range_and_contract_address.txt new file mode 100644 index 00000000000..8943305d75b --- /dev/null +++ b/crates/papyrus_load_test/resources/block_range_and_contract_address.txt @@ -0,0 +1,8 @@ +892 945 0x4c2bbb563ddf976ecd65425a4dcd1daeef34ea9d83e045e86a43ca2fc0e47ae +816 962 0x244768a8b9815d8e28fbbee458bceedb477cf568a0dfc8942f2f2a1df6e61b +989 994 0x77b4b06e0c4268f0928e1351a589f4663daae4cf23520b17953f1eba8c33798 +864 871 0x6641e5e4ca97de0500868f01d312fdb0b1c77ee458ec76c569d54f24e2e5965 +719 822 0x14e24fcd6372761a1aa8527daf50dea06054915a566f669f45f7a23125f182 +481 977 0x3e21f4224a46678d1aed0348e5c12b2f60f09ca7b5f624fdba046cfdbdca6c8 +879 904 0x5e4042477edd3802286495d2123244ea7adbd7c98417efaf518d568457a3680 +868 950 0x669dc8b9a6a7ade51bf6d017f2789abe495a7cff3369486d2f49093b64f385 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/last_block_number.txt b/crates/papyrus_load_test/resources/last_block_number.txt new file mode 100644 index 00000000000..6c2993e08a6 --- /dev/null +++ b/crates/papyrus_load_test/resources/last_block_number.txt @@ -0,0 +1 @@ +57344 \ No newline at end of file diff --git a/crates/papyrus_load_test/resources/transaction_hash.txt b/crates/papyrus_load_test/resources/transaction_hash.txt new file mode 100644 index 00000000000..b219db7aa5b --- /dev/null +++ b/crates/papyrus_load_test/resources/transaction_hash.txt @@ -0,0 +1,8 @@ +0x7b82ad0b8fdd98104418f0266ce5bccf80e49d0c6532b66859f7b697df37aca +0x28d3f07fe130ef7fcd3a0c1735e2648e9f114b84a78f67b2cf65e8864052df +0x67261c6cfa9abecf3193c4af39d9bac4096418d311f115ddd5a37f520bfc439 +0x257b14d3d1d7d3b76661a980f27467ddc408d4f7bd631da5a464d7dd08fdd0a +0x3ac1eb17fb193380f1f4c4474c713bc25cf108376d12305ebf1f10a80f5a0fe +0x27dec180e3d4143eae91458c9df45a34ab7d00a5438a7f64a92c3d2300e6353 +0x375e740b4c427c3b8e4cb3a56aed8504627f408831c717a86ed6eb7b55228c6 +0x3bc4a25fbf98f628614fd118e1c3233a97e48673d4b3e5d988a529696617e05 \ No newline at end of file diff --git a/crates/papyrus_load_test/src/compare_endpoints.rs b/crates/papyrus_load_test/src/compare_endpoints.rs new file mode 100644 index 00000000000..e3968e2f8a5 --- /dev/null +++ b/crates/papyrus_load_test/src/compare_endpoints.rs @@ -0,0 +1,212 @@ +use std::env::var; +use std::fs::{create_dir, remove_dir_all, File}; +use std::io::Write; +use std::path::Path; + +use reqwest::Client; +use serde_json::Value as jsonVal; + +use crate::create_request; +use crate::transactions::create_requests_vector_from_file; + +// TODO(dvir): consider using logging instead of printing. +// TODO(dvir): consider add tests for this. +// TODO(dvir): consider adding also test for endpoints without any parameters. + +lazy_static::lazy_static! { + // The URL of the first node. + static ref ALPHA_NODE_URL: String = var("ALPHA_NODE_URL").unwrap(); + // The URL of the second node. + static ref BETA_NODE_URL: String = var("BETA_NODE_URL").unwrap(); + + // The path to the results directory. + static ref RESULT_PATH: String = var("RESULT_PATH").unwrap_or("./results".to_string()); + // The name of the file to write to the request with different results. + static ref REQUEST_FILE_NAME: String = var("REQUEST_FILE_NAME").unwrap_or("requests.txt".to_string()); + // The name of the file to write to the response of the alpha node. + static ref ALPHA_RESPONSE_FILE_NAME: String = var("ALPHA_RESPONSE_FILE_NAME").unwrap_or("alpha_response.txt".to_string()); + // The name of the file to write to the response of the beta node. + static ref BETA_RESPONSE_FILE_NAME: String = var("BETA_RESPONSE_FILE_NAME").unwrap_or("beta_response.txt".to_string()); +} + +// Maximum number of retries when sending a request. +const MAX_RETRIES: usize = 3; + +// TODO(dvir): remove the order_arrays fix where we want to check also the order. +// Creates the tests for comparing different endpoints. +create_compare_endpoints_test! { + get_block_with_transaction_hashes_by_number, "block_number.txt", &[order_arrays]; + get_block_with_transaction_hashes_by_hash, "block_hash.txt", &[order_arrays]; + get_block_with_full_transactions_by_number, "block_number.txt", &[order_arrays]; + get_block_with_full_transactions_by_hash, "block_hash.txt", &[order_arrays]; + get_block_with_full_transactions_and_receipts_by_number, "block_number.txt", &[order_arrays]; + get_block_with_full_transactions_and_receipts_by_hash, "block_hash.txt", &[order_arrays]; + get_block_transaction_count_by_number, "block_number.txt", &[order_arrays]; + get_block_transaction_count_by_hash, "block_hash.txt", &[order_arrays]; + get_state_update_by_number, "block_number.txt", &[order_arrays]; + get_state_update_by_hash, "block_hash.txt", &[order_arrays]; + get_transaction_by_block_id_and_index_by_number, "block_number_and_transaction_index.txt", &[order_arrays]; + get_transaction_by_block_id_and_index_by_hash, "block_hash_and_transaction_index.txt", &[order_arrays]; + get_transaction_by_hash, "transaction_hash.txt", &[order_arrays]; + get_transaction_receipt, "transaction_hash.txt", &[order_arrays]; + get_class_at_by_number, "block_number_and_contract_address.txt", &[order_arrays]; + get_class_at_by_hash, "block_hash_and_contract_address.txt", &[order_arrays]; + get_class_hash_at_by_number, "block_number_and_contract_address.txt", &[order_arrays]; + get_class_hash_at_by_hash, "block_hash_and_contract_address.txt", &[order_arrays]; + get_nonce_by_number, "block_number_and_contract_address.txt", &[order_arrays]; + get_nonce_by_hash, "block_hash_and_contract_address.txt", &[order_arrays]; + get_storage_at_by_number, "block_number_and_contract_address.txt", &[order_arrays]; + get_storage_at_by_hash, "block_hash_and_contract_address.txt", &[order_arrays]; + get_class_by_number, "block_number_and_class_hash.txt", &[order_arrays]; + get_class_by_hash, "block_hash_and_class_hash.txt", &[order_arrays]; + // The continuation_token format is not specified in the spec. + get_events_with_address, "block_range_and_contract_address.txt", &[order_arrays, |val| remove_all_fields(val, "continuation_token")]; + get_events_without_address, "block_range_and_contract_address.txt", &[order_arrays, |val| remove_all_fields(val, "continuation_token")]; + trace_transaction, "transaction_hash.txt", &[order_arrays]; + trace_block_transactions_by_number, "block_number.txt", &[order_arrays]; + trace_block_transactions_by_hash, "block_hash.txt", &[order_arrays]; +} + +// TODO(dvir): consider making the requests concurrent. +// Compares the result of the requests for the endpoint after performing the fixes on the returned +// responses. +async fn compare(requests: Vec, endpoint: &str, fixes: &[fn(&mut jsonVal)]) -> bool { + // This variable is used to check if all the responses are the same. + let mut everything_is_the_same = true; + + // Remove the current endpoint results if exists. + let result_path = Path::new(&*RESULT_PATH); + let endpoint_path = result_path.join(endpoint); + if endpoint_path.exists() { + remove_dir_all(&endpoint_path).unwrap(); + } + + let client = Client::new(); + for (idx, request) in requests.iter().enumerate() { + if idx % 10 == 0 { + println!("{endpoint} iteration: {idx}"); + } + + let Some(mut alpha_response) = send(&client, &ALPHA_NODE_URL, request).await else { + // TODO(dvir): consider formatting this nicer. + println!( + "Failed to send request: {request} to URL: {} skipping this request.", + *ALPHA_NODE_URL + ); + continue; + }; + let Some(mut beta_response) = send(&client, &BETA_NODE_URL, request).await else { + println!( + "Failed to send request {request} to {}, skipping this request.", + *BETA_NODE_URL + ); + continue; + }; + + for fix in fixes { + fix(&mut alpha_response); + fix(&mut beta_response); + } + + if alpha_response != beta_response { + println!( + "Different responses for method: {} with parameters: {}", + request["method"], request["params"] + ); + + if everything_is_the_same { + everything_is_the_same = false; + create_dir(&endpoint_path).unwrap(); + } + + // TODO(dvir): consider changing the directory name. + // The path for the current request. + let param_path = endpoint_path.join(request["params"].to_string()); + create_dir(¶m_path).unwrap(); + + let mut file = File::create(param_path.join(&*REQUEST_FILE_NAME)).unwrap(); + file.write_all(format!("{:#?}", request).as_bytes()).unwrap(); + + let mut file = File::create(param_path.join(&*ALPHA_RESPONSE_FILE_NAME)).unwrap(); + file.write_all(format!("{:#?}", alpha_response).as_bytes()).unwrap(); + + let mut file = File::create(param_path.join(&*BETA_RESPONSE_FILE_NAME)).unwrap(); + file.write_all(format!("{:#?}", beta_response).as_bytes()).unwrap(); + } + } + + println!("Finished comparing {endpoint}."); + everything_is_the_same +} + +// Given [Name, "Path", &[fix1, fix2, ...];] writes the following test: +// #[tokio::test] +// async fn Name() { +// let requests = create_requests_vector("Path", create_request::Name); +// assert!(compare(requests, Name, &[fix1, fix2, ...]).await); +// } +macro_rules! create_compare_endpoints_test { + () => {}; + ($name:ident, $file_name:literal, $fixes:expr; $($rest:tt)*) => { + #[tokio::test] + async fn $name (){ + let requests = create_requests_vector_from_file($file_name, create_request::$name); + assert!(compare(requests, stringify!($name), $fixes).await); + } + create_compare_endpoints_test!($($rest)*); + }; +} +pub(crate) use create_compare_endpoints_test; + +// Sends the request to the url and returns the response. If the request fails, retries up to +// MAX_RETRIES times. +async fn send(client: &Client, url: &str, req: &jsonVal) -> Option { + let builder = client.post(url).json(req); + for _ in 0..MAX_RETRIES { + let Ok(res) = builder.try_clone().unwrap().send().await else { + continue; + }; + let Ok(res) = res.json().await else { + continue; + }; + return Some(res); + } + None +} + +// Removes all fields with name 'field_name'. +fn remove_all_fields(val: &mut jsonVal, field_name: &str) { + match val { + jsonVal::Array(vec) => { + for entry in vec { + remove_all_fields(entry, field_name); + } + } + jsonVal::Object(map) => { + map.remove(field_name); + for (_key, val) in map { + remove_all_fields(val, field_name); + } + } + _ => {} + } +} + +// Orders all the arrays in val by their string representation. +// Useful to compare two json object that are the same but with different order. +fn order_arrays(val: &mut jsonVal) { + match val { + jsonVal::Array(vec) => { + for entry in vec.iter_mut() { + order_arrays(entry); + } + vec.sort_by_key(|val| val.to_string()); + } + jsonVal::Object(map) => { + for (_key, val) in map { + order_arrays(val); + } + } + _ => {} + } +} diff --git a/crates/papyrus_load_test/src/create_files.rs b/crates/papyrus_load_test/src/create_files.rs new file mode 100644 index 00000000000..4880a600922 --- /dev/null +++ b/crates/papyrus_load_test/src/create_files.rs @@ -0,0 +1,442 @@ +use std::fs::File; +use std::future::Future; +use std::io::Write; + +use once_cell::sync::OnceCell; +use rand::Rng; +use reqwest::{Client, Url}; +use serde_json::Value as jsonVal; + +use crate::{ + get_last_block_number, + get_random_block_number, + path_in_resources, + GET_BLOCK_TRANSACTION_COUNT_BY_HASH_WEIGHT, + GET_BLOCK_TRANSACTION_COUNT_BY_NUMBER_WEIGHT, + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_HASH_WEIGHT, + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_NUMBER_WEIGHT, + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_HASH_WEIGHT, + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_NUMBER_WEIGHT, + GET_CLASS_AT_BY_HASH_WEIGHT, + GET_CLASS_AT_BY_NUMBER_WEIGHT, + GET_CLASS_BY_HASH_WEIGHT, + GET_CLASS_BY_NUMBER_WEIGHT, + GET_CLASS_HASH_AT_BY_HASH_WEIGHT, + GET_CLASS_HASH_AT_BY_NUMBER_WEIGHT, + GET_EVENTS_WITHOUT_ADDRESS_WEIGHT, + GET_EVENTS_WITH_ADDRESS_WEIGHT, + GET_NONCE_BY_HASH_WEIGHT, + GET_NONCE_BY_NUMBER_WEIGHT, + GET_STATE_UPDATE_BY_HASH_WEIGHT, + GET_STATE_UPDATE_BY_NUMBER_WEIGHT, + GET_STORAGE_AT_BY_HASH_WEIGHT, + GET_STORAGE_AT_BY_NUMBER_WEIGHT, + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_HASH_WEIGHT, + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_NUMBER_WEIGHT, + GET_TRANSACTION_BY_HASH_WEIGHT, + GET_TRANSACTION_RECEIPT_WEIGHT, +}; + +// The limit on the storage size for request arguments. +const STORAGE_SIZE_IN_BYTES: usize = 7000; +// Average size of arguments to a request. +const AVERAGE_ARGS_SIZE_IN_BYTES: usize = 70; +// The number of arguments to requests we can save with the given storage size limit. +const ARGS_COUNT: usize = STORAGE_SIZE_IN_BYTES / AVERAGE_ARGS_SIZE_IN_BYTES; + +// Returns the number of arguments given a weight. +const fn get_args_count(weight: usize) -> usize { + weight * ARGS_COUNT / WEIGHT_SUM +} + +// The weight of each file. The weight is the sum of the request weights which use the file content +// as arguments. +const BLOCK_NUMBER_WEIGHT: usize = GET_BLOCK_WITH_TRANSACTION_HASHES_BY_NUMBER_WEIGHT + + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_NUMBER_WEIGHT + + GET_BLOCK_TRANSACTION_COUNT_BY_NUMBER_WEIGHT + + GET_STATE_UPDATE_BY_NUMBER_WEIGHT; +const BLOCK_HASH_WEIGHT: usize = GET_BLOCK_WITH_TRANSACTION_HASHES_BY_HASH_WEIGHT + + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_HASH_WEIGHT + + GET_BLOCK_TRANSACTION_COUNT_BY_HASH_WEIGHT + + GET_STATE_UPDATE_BY_HASH_WEIGHT; +const BLOCK_NUMBER_AND_TRANSACTION_INDEX_WEIGHT: usize = + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_NUMBER_WEIGHT; +const BLOCK_HASH_AND_TRANSACTION_INDEX_WEIGHT: usize = + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_HASH_WEIGHT; +const TRANSACTION_HASH_WEIGHT: usize = + GET_TRANSACTION_BY_HASH_WEIGHT + GET_TRANSACTION_RECEIPT_WEIGHT; +const BLOCK_NUMBER_AND_CONTRACT_ADDRESS_WEIGHT: usize = GET_CLASS_AT_BY_NUMBER_WEIGHT + + GET_CLASS_HASH_AT_BY_NUMBER_WEIGHT + + GET_NONCE_BY_NUMBER_WEIGHT + + GET_STORAGE_AT_BY_NUMBER_WEIGHT; +const BLOCK_HASH_AND_CONTRACT_ADDRESS_WEIGHT: usize = GET_CLASS_AT_BY_HASH_WEIGHT + + GET_CLASS_HASH_AT_BY_HASH_WEIGHT + + GET_NONCE_BY_HASH_WEIGHT + + GET_STORAGE_AT_BY_HASH_WEIGHT; +const BLOCK_NUMBER_AND_CLASS_HASH_WEIGHT: usize = GET_CLASS_BY_NUMBER_WEIGHT; +const BLOCK_HASH_AND_CLASS_HASH_WEIGHT: usize = GET_CLASS_BY_HASH_WEIGHT; +const BLOCK_RANGE_AND_CONTRACT_ADDRESS_WEIGHT: usize = + GET_EVENTS_WITH_ADDRESS_WEIGHT + GET_EVENTS_WITHOUT_ADDRESS_WEIGHT; + +// The sum of the file’s weights. +const WEIGHT_SUM: usize = BLOCK_NUMBER_WEIGHT + + BLOCK_HASH_WEIGHT + + BLOCK_NUMBER_AND_TRANSACTION_INDEX_WEIGHT + + BLOCK_HASH_AND_TRANSACTION_INDEX_WEIGHT + + TRANSACTION_HASH_WEIGHT + + BLOCK_NUMBER_AND_CONTRACT_ADDRESS_WEIGHT + + BLOCK_HASH_AND_CONTRACT_ADDRESS_WEIGHT + + BLOCK_NUMBER_AND_CLASS_HASH_WEIGHT + + BLOCK_HASH_AND_CLASS_HASH_WEIGHT + + BLOCK_RANGE_AND_CONTRACT_ADDRESS_WEIGHT; + +// The number of arguments to write in a file. +const BLOCK_NUMBER_COUNT: usize = get_args_count(BLOCK_NUMBER_WEIGHT); +const BLOCK_HASH_COUNT: usize = get_args_count(BLOCK_HASH_WEIGHT); +const BLOCK_NUMBER_AND_TRANSACTION_INDEX_COUNT: usize = + get_args_count(BLOCK_NUMBER_AND_TRANSACTION_INDEX_WEIGHT); +const BLOCK_HASH_AND_TRANSACTION_INDEX_COUNT: usize = + get_args_count(BLOCK_HASH_AND_TRANSACTION_INDEX_WEIGHT); +const TRANSACTION_HASH_COUNT: usize = get_args_count(TRANSACTION_HASH_WEIGHT); +const BLOCK_NUMBER_AND_CONTRACT_ADDRESS_COUNT: usize = + get_args_count(BLOCK_NUMBER_AND_CONTRACT_ADDRESS_WEIGHT); +const BLOCK_HASH_AND_CONTRACT_ADDRESS_COUNT: usize = + get_args_count(BLOCK_HASH_AND_CONTRACT_ADDRESS_WEIGHT); +const BLOCK_NUMBER_AND_CLASS_HASH_COUNT: usize = get_args_count(BLOCK_NUMBER_AND_CLASS_HASH_WEIGHT); +const BLOCK_HASH_AND_CLASS_HASH_COUNT: usize = get_args_count(BLOCK_HASH_AND_CLASS_HASH_WEIGHT); +const BLOCK_RANGE_AND_CONTRACT_ADDRESS_COUNT: usize = + get_args_count(BLOCK_RANGE_AND_CONTRACT_ADDRESS_WEIGHT); + +static URL: OnceCell = OnceCell::new(); + +// Creates the files to run the load test. +pub async fn create_files(url_str: &str) { + URL.set(Url::parse(url_str).unwrap()).unwrap(); + last_block_number().await; + + let block_number = + tokio::spawn(create_file("block_number.txt", BLOCK_NUMBER_COUNT, get_block_number_args)); + let block_hash = + tokio::spawn(create_file("block_hash.txt", BLOCK_HASH_COUNT, get_block_hash_args)); + + let transaction_hash = tokio::spawn(create_file( + "transaction_hash.txt", + TRANSACTION_HASH_COUNT, + get_transaction_hash_args, + )); + + let block_hash_and_transaction_index = tokio::spawn(create_file( + "block_hash_and_transaction_index.txt", + BLOCK_HASH_AND_TRANSACTION_INDEX_COUNT, + get_block_hash_and_transaction_index_args, + )); + + let block_number_and_transaction_index = tokio::spawn(create_file( + "block_number_and_transaction_index.txt", + BLOCK_NUMBER_AND_TRANSACTION_INDEX_COUNT, + get_block_number_and_transaction_index_args, + )); + + let block_number_and_contract_address = tokio::spawn(create_file( + "block_number_and_contract_address.txt", + BLOCK_NUMBER_AND_CONTRACT_ADDRESS_COUNT, + get_block_number_and_contract_address_args, + )); + + let block_hash_and_contract_address = tokio::spawn(create_file( + "block_hash_and_contract_address.txt", + BLOCK_HASH_AND_CONTRACT_ADDRESS_COUNT, + get_block_hash_and_contract_address_args, + )); + + let block_number_and_class_hash = tokio::spawn(create_file( + "block_number_and_class_hash.txt", + BLOCK_NUMBER_AND_CLASS_HASH_COUNT, + get_block_number_and_class_hash_args, + )); + + let block_hash_and_class_hash = tokio::spawn(create_file( + "block_hash_and_class_hash.txt", + BLOCK_HASH_AND_CLASS_HASH_COUNT, + get_block_hash_and_class_hash_args, + )); + + let block_range_and_contract_address = tokio::spawn(create_file( + "block_range_and_contract_address.txt", + BLOCK_RANGE_AND_CONTRACT_ADDRESS_COUNT, + get_block_range_and_contract_address_args, + )); + + tokio::try_join!( + block_number, + block_hash, + transaction_hash, + block_hash_and_transaction_index, + block_number_and_transaction_index, + block_number_and_contract_address, + block_hash_and_contract_address, + block_number_and_class_hash, + block_hash_and_class_hash, + block_range_and_contract_address, + ) + .unwrap(); +} + +// Write to a file lines with parameters to requests. +// - file_name: the file to write to. +// - params_set_count: the number of lines with parameters to write to the file. +// - get_params: a function that returns a vector with parameters to a request. The use of Fn is to +// enable closure, and the reason get_args is async is that creating the parameters is IO bound. +pub async fn create_file(file_name: &str, param_set_count: usize, get_params: impl Fn() -> Fut) +where + Fut: Future>, +{ + let mut to_write = String::new(); + for _ in 0..param_set_count { + for arg in get_params().await { + to_write.push_str(&arg); + to_write.push(' '); + } + to_write.pop().unwrap(); + to_write.push('\n'); + } + // Remove the last '\n'. + to_write.pop(); + let mut file = File::create(path_in_resources(file_name)) + .unwrap_or_else(|err| panic!("Create file \"{file_name}\" failed.: {err}")); + file.write_all(to_write.as_bytes()).unwrap(); +} + +pub async fn get_block_with_tx_hashes(block_number: u64) -> jsonVal { + let params = format!("{{ \"block_number\": {block_number} }}"); + send_request("starknet_getBlockWithTxHashes", ¶ms).await +} + +// Creates the file last_block_number.txt. Write to the file the last block number for the load +// test. +async fn last_block_number() { + let last_block_number = &send_request("starknet_blockNumber", "").await["result"]; + let mut file = File::create(path_in_resources("last_block_number.txt")).unwrap(); + file.write_all(last_block_number.to_string().as_bytes()).unwrap(); +} + +// Returns a vector with a random block number. +pub async fn get_block_number_args() -> Vec { + vec![get_random_block_number().to_string()] +} + +pub async fn get_block_hash_by_block_number(block_number: u64) -> String { + let response = &get_block_with_tx_hashes(block_number).await["result"]["block_hash"]; + let block_hash = match response { + jsonVal::String(block_hash) => block_hash, + _ => unreachable!(), + }; + block_hash.to_string() +} + +// Returns a vector with a random block hash. +pub async fn get_block_hash_args() -> Vec { + let block_number = get_random_block_number(); + let block_hash = get_block_hash_by_block_number(block_number).await; + vec![block_hash] +} + +// Returns a vector with a random transaction hash. +pub async fn get_transaction_hash_args() -> Vec { + let block_number = get_random_block_number(); + let response = &get_block_with_tx_hashes(block_number).await["result"]["transactions"]; + let trans_list = match response { + jsonVal::Array(transactions) => transactions, + _ => unreachable!("The gateway returns the transaction hashes as a vector."), + }; + let trans_index = rand::thread_rng().gen_range(0..trans_list.len()); + let trans_hash = match &trans_list[trans_index] { + jsonVal::String(trans_hash) => trans_hash, + _ => unreachable!("The gateway transaction hash as a String."), + }; + vec![trans_hash.to_string()] +} + +// Given block number returns the number of transactions in this block. +pub async fn get_transaction_count_by_block_number(block_number: u64) -> u64 { + let params = format!("{{ \"block_number\": {block_number} }}"); + let response = &send_request("starknet_getBlockTransactionCount", ¶ms).await["result"]; + let trans_count = match response { + jsonVal::Number(count) => count, + _ => unreachable!(), + }; + trans_count.as_u64().unwrap() +} + +// Returns a vector with a random block hash and transaction index in this block. +pub async fn get_block_hash_and_transaction_index_args() -> Vec { + let block_number = get_random_block_number(); + let block_hash = get_block_hash_by_block_number(block_number).await; + let trans_count = get_transaction_count_by_block_number(block_number).await; + let random_index = rand::thread_rng().gen_range(0..trans_count); + vec![block_hash, random_index.to_string()] +} + +// Returns a vector with a random block number and transaction index in this block. +pub async fn get_block_number_and_transaction_index_args() -> Vec { + let block_number = get_random_block_number(); + let trans_count = get_transaction_count_by_block_number(block_number).await; + let random_index = rand::thread_rng().gen_range(0..trans_count); + vec![block_number.to_string(), random_index.to_string()] +} + +// Returns a vector with a random block number and contract address of a contract which was deployed +// before the block. +pub async fn get_block_number_and_contract_address_args() -> Vec { + let (block_number, contract_address) = get_random_block_number_and_contract_address().await; + // A block number which in it the contract was already deployed. + let after_block_number = rand::thread_rng().gen_range(block_number..=get_last_block_number()); + vec![after_block_number.to_string(), contract_address] +} + +// Returns a vector with a random block hash and contract address of a contract which was deployed +// before the block. +pub async fn get_block_hash_and_contract_address_args() -> Vec { + let (block_number, contract_address) = get_random_block_number_and_contract_address().await; + // A block number which in it the contract was already deployed. + let after_block_number = rand::thread_rng().gen_range(block_number..=get_last_block_number()); + let after_block_hash = get_block_hash_by_block_number(after_block_number).await; + vec![after_block_hash, contract_address] +} + +// Returns a vector with a random block number and contract address of a contract which was deployed +// in this block. +pub async fn get_random_block_number_and_contract_address() -> (u64, String) { + loop { + let block_number = get_random_block_number(); + let contract_address = get_random_contract_address_deployed_in_block(block_number).await; + if let Some(contract_address) = contract_address { + return (block_number, contract_address); + } + } +} + +// Given a block number return a random contract address which was deployed in this block. +// Returns Option because it is possible that no contracts were deployed in the given block. +pub async fn get_random_contract_address_deployed_in_block(block_number: u64) -> Option { + let params = format!("{{ \"block_number\": {block_number} }}"); + let response = &send_request("starknet_getStateUpdate", ¶ms).await["result"]["state_diff"] + ["deployed_contracts"]; + let contract_list = match response { + jsonVal::Array(contract_list) => contract_list, + _ => unreachable!("The gateway returns the deployed contracts as a vector."), + }; + // In case no contracts was deployed in the block. + if contract_list.is_empty() { + return None; + } + let random_index = rand::thread_rng().gen_range(0..contract_list.len()); + let contract_address = match &contract_list[random_index] { + jsonVal::Object(contract_list) => &contract_list["address"], + _ => unreachable!( + "The gateway returns a deployed contracts as a mapping from address to contract \ + address." + ), + }; + let contract_address = match contract_address { + jsonVal::String(contract_address) => contract_address, + _ => unreachable!("The gateway returns a deployed contracts address as a String."), + }; + Some(contract_address.to_string()) +} + +// Returns a vector with a random block number and class hash of a class which was declared +// before the block. +pub async fn get_block_number_and_class_hash_args() -> Vec { + let (block_number, class_hash) = get_random_block_number_and_class_hash().await; + // A block number which in it the class was already declared. + let after_block_number = rand::thread_rng().gen_range(block_number..=get_last_block_number()); + vec![after_block_number.to_string(), class_hash] +} + +// Returns a vector with a random block hash and class hash of a class which was declared +// before the block. +pub async fn get_block_hash_and_class_hash_args() -> Vec { + let (block_number, class_hash) = get_random_block_number_and_class_hash().await; + // A block number which in it the class was already declared. + let after_block_number = rand::thread_rng().gen_range(block_number..=get_last_block_number()); + let after_block_hash = get_block_hash_by_block_number(after_block_number).await; + vec![after_block_hash, class_hash] +} + +// Returns a vector with a random block number and class hash of a class which was declared +// in this block. +pub async fn get_random_block_number_and_class_hash() -> (u64, String) { + loop { + let block_number = get_random_block_number(); + let class_hash = get_random_class_hash_declared_in_block(block_number).await; + if let Some(class_hash) = class_hash { + return (block_number, class_hash); + } + } +} + +// Given a block number return a random class hash which was declared in this block. +// Returns Option because it is possible that no classes were declared in the given block. +pub async fn get_random_class_hash_declared_in_block(block_number: u64) -> Option { + let params = format!("{{ \"block_number\": {block_number} }}"); + let mut declared_classes = Vec::::new(); + // Cairo 1 classes. + let classes = &mut send_request("starknet_getStateUpdate", ¶ms).await["result"] + ["state_diff"]["declared_classes"] + .take(); + // Cairo 1 declared classes returns as a couple of "class_hash" and "compiled_class_hash". + let mut classes = classes + .as_array_mut() + .unwrap() + .iter() + .map(|two_hashes| two_hashes["class_hash"].clone()) + .collect(); + declared_classes.append(&mut classes); + // Cairo 0 classes. + let classes = &mut send_request("starknet_getStateUpdate", ¶ms).await["result"] + ["state_diff"]["deprecated_declared_classes"] + .take(); + declared_classes.append(classes.as_array_mut().unwrap()); + + if declared_classes.is_empty() { + return None; + } + let random_index = rand::thread_rng().gen_range(0..declared_classes.len()); + let class_hash = declared_classes[random_index].as_str().unwrap().to_string(); + Some(class_hash) +} + +// Returns a vector with a block range (from_block_number, to_block_number) and contract address of +// a contract that was already deployed in this range. +pub async fn get_block_range_and_contract_address_args() -> Vec { + let (block_number, contract_address) = get_random_block_number_and_contract_address().await; + let from_block = rand::thread_rng().gen_range(block_number..=get_last_block_number()); + let to_block = rand::thread_rng().gen_range(from_block..=get_last_block_number()); + vec![from_block.to_string(), to_block.to_string(), contract_address] +} + +pub async fn send_request(method: &str, params: &str) -> serde_json::Value { + send_request_inner(method, params, URL.get().unwrap()).await +} + +// Sends a request with method and params to the url. The request will send multiple times until a +// good answer is received. +pub async fn send_request_inner(method: &str, params: &str, url: &Url) -> serde_json::Value { + let builder = Client::new() + .post(url.clone()) + .header("Content-Type", "application/json") + .body(format!(r#"{{"jsonrpc":"2.0","id":"1","method":"{method}","params":[{params}]}}"#)); + + loop { + let Ok(res) = builder.try_clone().unwrap().send().await else { + println!("Failed to send request. Retrying..."); + continue; + }; + let Ok(res) = res.text().await else { + println!("Failed to get response text. Retrying..."); + continue; + }; + return serde_json::from_str(&res).unwrap(); + } +} diff --git a/crates/papyrus_load_test/src/create_request.rs b/crates/papyrus_load_test/src/create_request.rs new file mode 100644 index 00000000000..8040ddac24c --- /dev/null +++ b/crates/papyrus_load_test/src/create_request.rs @@ -0,0 +1,238 @@ +use std::str::SplitWhitespace; + +use serde_json::{json, Value as jsonVal}; + +use crate::jsonrpc_request; + +// TODO(dvir): consider adding more variations to get_events requests. +// Chunk size for get_events requests. +const CHUNK_SIZE: usize = 100; +pub fn get_events_with_address(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let from_block = arg_iter.next_u64(); + let to_block = arg_iter.next_u64(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getEvents", + json!([{"from_block":{"block_number": from_block}, "to_block":{"block_number": to_block}, + "chunk_size": CHUNK_SIZE, "address": contract_address, "keys": []}]), + ) +} + +pub fn get_events_without_address(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let from_block = arg_iter.next_u64(); + let to_block = arg_iter.next_u64(); + jsonrpc_request( + "starknet_getEvents", + json!([{"from_block":{"block_number": from_block}, "to_block":{"block_number": to_block}, + "chunk_size": CHUNK_SIZE, "keys": []}]), + ) +} + +pub fn get_class_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let class_hash = arg_iter.next_str(); + jsonrpc_request("starknet_getClass", json!([{ "block_number": block_number }, class_hash])) +} + +pub fn get_class_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let class_hash = arg_iter.next_str(); + jsonrpc_request("starknet_getClass", json!([{ "block_hash": block_hash }, class_hash])) +} + +pub fn get_storage_at_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getStorageAt", + json!([contract_address, "0x0", { "block_number": block_number }]), + ) +} + +pub fn get_storage_at_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getStorageAt", + json!([contract_address, "0x0", { "block_hash": block_hash }]), + ) +} + +pub fn get_nonce_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getNonce", + json!([{ "block_number": block_number }, contract_address]), + ) +} + +pub fn get_nonce_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let contract_address = arg_iter.next_str(); + jsonrpc_request("starknet_getNonce", json!([{ "block_hash": block_hash }, contract_address])) +} + +pub fn get_class_hash_at_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getClassHashAt", + json!([{ "block_number": block_number }, contract_address]), + ) +} + +pub fn get_class_hash_at_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getClassHashAt", + json!([{ "block_hash": block_hash }, contract_address]), + ) +} + +pub fn get_class_at_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let contract_address = arg_iter.next_str(); + jsonrpc_request( + "starknet_getClassAt", + json!([{ "block_number": block_number }, contract_address]), + ) +} + +pub fn get_class_at_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let contract_address = arg_iter.next_str(); + jsonrpc_request("starknet_getClassAt", json!([{ "block_hash": block_hash }, contract_address])) +} + +pub fn get_transaction_by_block_id_and_index_by_hash(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_hash = arg_iter.next_str(); + let transaction_index = arg_iter.next_u64(); + jsonrpc_request( + "starknet_getTransactionByBlockIdAndIndex", + json!([{ "block_hash": block_hash }, transaction_index]), + ) +} + +pub fn get_transaction_by_block_id_and_index_by_number(args: &str) -> jsonVal { + let mut arg_iter = ArgsIter::new(args); + let block_number = arg_iter.next_u64(); + let transaction_index = arg_iter.next_u64(); + jsonrpc_request( + "starknet_getTransactionByBlockIdAndIndex", + json!([{ "block_number": block_number }, transaction_index]), + ) +} + +pub fn get_block_with_transaction_hashes_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_getBlockWithTxHashes", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn get_block_with_transaction_hashes_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getBlockWithTxHashes", json!([{ "block_hash": block_hash }])) +} + +pub fn get_block_with_full_transactions_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_getBlockWithTxs", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn get_block_with_full_transactions_and_receipts_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getBlockWithReceipts", json!([{ "block_hash": block_hash }])) +} + +pub fn get_block_with_full_transactions_and_receipts_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_getBlockWithReceipts", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn get_block_with_full_transactions_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getBlockWithTxs", json!([{ "block_hash": block_hash }])) +} + +pub fn get_block_transaction_count_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_getBlockTransactionCount", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn get_block_transaction_count_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getBlockTransactionCount", json!([{ "block_hash": block_hash }])) +} + +pub fn get_state_update_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_getStateUpdate", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn get_state_update_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getStateUpdate", json!([{ "block_hash": block_hash }])) +} + +pub fn get_transaction_by_hash(transaction_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getTransactionByHash", json!([transaction_hash])) +} + +pub fn get_transaction_receipt(transaction_hash: &str) -> jsonVal { + jsonrpc_request("starknet_getTransactionReceipt", json!([transaction_hash])) +} + +pub fn trace_transaction(transaction_hash: &str) -> jsonVal { + jsonrpc_request("starknet_traceTransaction", json!([transaction_hash])) +} + +pub fn trace_block_transactions_by_number(block_number: &str) -> jsonVal { + jsonrpc_request( + "starknet_traceBlockTransactions", + json!([{ "block_number": block_number.parse::().unwrap() }]), + ) +} + +pub fn trace_block_transactions_by_hash(block_hash: &str) -> jsonVal { + jsonrpc_request("starknet_traceBlockTransactions", json!([{ "block_hash": block_hash }])) +} + +// This struct is for iterating over the args string. +struct ArgsIter<'a> { + iter: SplitWhitespace<'a>, +} + +impl<'a> ArgsIter<'a> { + fn new(args: &'a str) -> Self { + ArgsIter { iter: args.split_whitespace() } + } + + // Returns the next argument as &str. + fn next_str(&mut self) -> String { + self.iter.next().unwrap().to_string() + } + + // Returns the next argument as u64. + fn next_u64(&mut self) -> u64 { + self.iter.next().unwrap().parse::().unwrap() + } +} diff --git a/crates/papyrus_load_test/src/lib.rs b/crates/papyrus_load_test/src/lib.rs new file mode 100644 index 00000000000..bdc031a2a3c --- /dev/null +++ b/crates/papyrus_load_test/src/lib.rs @@ -0,0 +1,115 @@ +#![allow(clippy::unwrap_used)] +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +#[cfg(feature = "compare_endpoints")] +#[cfg(test)] +mod compare_endpoints; +pub mod create_files; +pub mod create_request; +#[cfg(test)] +mod precision_test; +pub mod scenarios; +pub mod transactions; + +use std::{env, fs}; + +use goose::goose::{GooseUser, TransactionError}; +use once_cell::sync::{Lazy, OnceCell}; +use rand::Rng; +use serde::Deserialize; +use serde_json::{json, Value as jsonVal}; + +type PostResult = Result>; + +pub async fn post_jsonrpc_request(user: &mut GooseUser, request: &jsonVal) -> PostResult { + let version_id = &*RPC_VERSION_ID; + let response = user + .post_json(&format!("/rpc/{version_id}"), request) + .await? + .response + .map_err(|e| Box::new(e.into()))?; + // The purpose of this struct and the line afterward is to report on failed requests. + // The "response.json::" deserialize the body of response to + // TransactionReceiptResponse. If the response is an error, the result field doesn't exist in + // the body, the deserialization will fail, and the function will return an error. + #[derive(Deserialize)] + struct TransactionReceiptResponse { + result: jsonVal, + } + let response = + response.json::().await.map_err(|e| Box::new(e.into()))?; + Ok(response.result) +} + +pub fn jsonrpc_request(method: &str, params: jsonVal) -> jsonVal { + json!({ + "jsonrpc": "2.0", + "id": "0", + "method": method, + "params": params, + }) +} + +static LAST_BLOCK_NUMBER: OnceCell = OnceCell::new(); +// Returns the last block number for which this load test is relevant. +pub fn get_last_block_number() -> u64 { + *LAST_BLOCK_NUMBER.get_or_init(|| { + fs::read_to_string(path_in_resources("last_block_number.txt")) + .unwrap() + .parse::() + .unwrap() + }) +} + +// Returns a random block from zero to the last block for which this load test is relevant. +pub fn get_random_block_number() -> u64 { + let last_block = get_last_block_number(); + let mut rng = rand::thread_rng(); + rng.gen_range(0..=last_block) +} + +// Returns the path to the file_name inside the resources folder in payprus_loadtest module. +pub fn path_in_resources(file_name: &str) -> String { + env::var("CARGO_MANIFEST_DIR").unwrap() + "/resources/" + file_name +} + +// TODO(dvir): update those number with real statics after the node will be in production. +// Weight for each request to the node. +const BLOCK_HASH_AND_NUMBER_WEIGHT: usize = 10; +const BLOCK_NUMBER_WEIGHT: usize = 10; +const CHAIN_ID_WEIGHT: usize = 10; +const GET_BLOCK_TRANSACTION_COUNT_BY_HASH_WEIGHT: usize = 10; +const GET_BLOCK_TRANSACTION_COUNT_BY_NUMBER_WEIGHT: usize = 10; +const GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_HASH_WEIGHT: usize = 10; +const GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_NUMBER_WEIGHT: usize = 10; +const GET_BLOCK_WITH_TRANSACTION_HASHES_BY_HASH_WEIGHT: usize = 10; +const GET_BLOCK_WITH_TRANSACTION_HASHES_BY_NUMBER_WEIGHT: usize = 10; +const GET_CLASS_AT_BY_HASH_WEIGHT: usize = 10; +const GET_CLASS_AT_BY_NUMBER_WEIGHT: usize = 10; +const GET_CLASS_BY_HASH_WEIGHT: usize = 10; +const GET_CLASS_BY_NUMBER_WEIGHT: usize = 10; +const GET_CLASS_HASH_AT_BY_HASH_WEIGHT: usize = 10; +const GET_CLASS_HASH_AT_BY_NUMBER_WEIGHT: usize = 10; +const GET_EVENTS_WITHOUT_ADDRESS_WEIGHT: usize = 10; +const GET_EVENTS_WITH_ADDRESS_WEIGHT: usize = 10; +const GET_NONCE_BY_HASH_WEIGHT: usize = 10; +const GET_NONCE_BY_NUMBER_WEIGHT: usize = 10; +const GET_STATE_UPDATE_BY_HASH_WEIGHT: usize = 10; +const GET_STATE_UPDATE_BY_NUMBER_WEIGHT: usize = 10; +const GET_STORAGE_AT_BY_HASH_WEIGHT: usize = 10; +const GET_STORAGE_AT_BY_NUMBER_WEIGHT: usize = 10; +const GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_HASH_WEIGHT: usize = 10; +const GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_NUMBER_WEIGHT: usize = 10; +const GET_TRANSACTION_BY_HASH_WEIGHT: usize = 10; +const GET_TRANSACTION_RECEIPT_WEIGHT: usize = 10; +const SYNCING_WEIGHT: usize = 10; +const TRACE_BLOCK_TRANSACTIONS_BY_HASH_WEIGHT: usize = 10; +const TRACE_BLOCK_TRANSACTIONS_BY_NUMBER_WEIGHT: usize = 10; +const TRACE_TRANSACTION_WEIGHT: usize = 10; + +static RPC_VERSION_ID: Lazy = Lazy::new(|| match std::env::var("VERSION_ID") { + Ok(version_id) => version_id, + Err(_) => unreachable!("VERSION_ID environment variable is not set"), +}); diff --git a/crates/papyrus_load_test/src/main.rs b/crates/papyrus_load_test/src/main.rs new file mode 100644 index 00000000000..8375cd8efc1 --- /dev/null +++ b/crates/papyrus_load_test/src/main.rs @@ -0,0 +1,70 @@ +// This code is inspired by the pathfinder load test. +// first set the env variable VERSION_ID to the version of the node you want to test. +// To run this load test, run locally a node and then run: +// cargo run -r -p papyrus_load_test -- -t 5m -H http://127.0.0.1:8080 --scenarios=generalrequestv004 +// To see all the available scenarios run: +// cargo run -r -p papyrus_load_test -- --scenarios-list +// To create the files of requests run: +// cargo run -r -p papyrus_load_test -- --create_files http://127.0.0.1:8080/rpc/V0_7 +// For more options run: +// cargo run -r -p papyrus_load_test -- --help + +use std::env; +use std::fs::File; + +use assert_matches::assert_matches; +use goose::{util, GooseAttack}; +use papyrus_load_test::create_files::create_files; +use papyrus_load_test::scenarios; +use serde::Serialize; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let args: Vec = env::args().collect(); + assert_matches!(std::env::var("VERSION_ID"), Ok(_)); + if args.len() > 1 && args[1].eq("--create_files") { + create_files(&args[2]).await; + return Ok(()); + } + + let metrics = GooseAttack::initialize()? + // The choice between versions must be also in the environment variable VERSION_ID. + // TODO(dvir): Add scenarios for v0_5 and v0_6. + .register_scenario(scenarios::general_request_v0_4()) + .execute() + .await?; + + // The OUTPUT_FILE env is expected to be a valid path in the os. + // If exists, aggregated results will be written to that path in the following json format: + // [ + // { + // "name": , + // "unit": "Milliseconds", + // "value": , + // }, + // ] + if let Ok(path) = env::var("OUTPUT_FILE") { + let file = File::create(path)?; + let mut performance: Vec = vec![]; + for (name, data) in metrics.requests { + let raw_data = data.raw_data; + let median = util::median( + &raw_data.times, + raw_data.counter, + raw_data.minimum_time, + raw_data.maximum_time, + ); + performance.push(Entry { name, unit: "Milliseconds".to_string(), value: median }); + } + serde_json::to_writer(file, &performance)? + } + + Ok(()) +} + +#[derive(Debug, Clone, Default, Serialize)] +pub struct Entry { + name: String, + unit: String, // "Milliseconds" + value: usize, +} diff --git a/crates/papyrus_load_test/src/precision_test.rs b/crates/papyrus_load_test/src/precision_test.rs new file mode 100644 index 00000000000..18138b3f646 --- /dev/null +++ b/crates/papyrus_load_test/src/precision_test.rs @@ -0,0 +1,10 @@ +use pretty_assertions::assert_eq; + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_load_test/src/scenarios.rs b/crates/papyrus_load_test/src/scenarios.rs new file mode 100644 index 00000000000..61b7df4f9c7 --- /dev/null +++ b/crates/papyrus_load_test/src/scenarios.rs @@ -0,0 +1,110 @@ +use goose::goose::Scenario; + +use crate::{ + transactions as txs, + BLOCK_HASH_AND_NUMBER_WEIGHT, + BLOCK_NUMBER_WEIGHT, + CHAIN_ID_WEIGHT, + GET_BLOCK_TRANSACTION_COUNT_BY_HASH_WEIGHT, + GET_BLOCK_TRANSACTION_COUNT_BY_NUMBER_WEIGHT, + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_HASH_WEIGHT, + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_NUMBER_WEIGHT, + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_HASH_WEIGHT, + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_NUMBER_WEIGHT, + GET_CLASS_AT_BY_HASH_WEIGHT, + GET_CLASS_AT_BY_NUMBER_WEIGHT, + GET_CLASS_BY_HASH_WEIGHT, + GET_CLASS_BY_NUMBER_WEIGHT, + GET_CLASS_HASH_AT_BY_HASH_WEIGHT, + GET_CLASS_HASH_AT_BY_NUMBER_WEIGHT, + GET_EVENTS_WITHOUT_ADDRESS_WEIGHT, + GET_EVENTS_WITH_ADDRESS_WEIGHT, + GET_NONCE_BY_HASH_WEIGHT, + GET_NONCE_BY_NUMBER_WEIGHT, + GET_STATE_UPDATE_BY_HASH_WEIGHT, + GET_STATE_UPDATE_BY_NUMBER_WEIGHT, + GET_STORAGE_AT_BY_HASH_WEIGHT, + GET_STORAGE_AT_BY_NUMBER_WEIGHT, + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_HASH_WEIGHT, + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_NUMBER_WEIGHT, + GET_TRANSACTION_BY_HASH_WEIGHT, + GET_TRANSACTION_RECEIPT_WEIGHT, + SYNCING_WEIGHT, + TRACE_BLOCK_TRANSACTIONS_BY_HASH_WEIGHT, + TRACE_BLOCK_TRANSACTIONS_BY_NUMBER_WEIGHT, + TRACE_TRANSACTION_WEIGHT, +}; + +// TODO(dvir): add also traceTransaction, simulateTransactions, estimateFee and call endpoints. +pub fn general_request_v0_4() -> Scenario { + let mut scenario = Scenario::new("general_request_v0_4"); + // This is the scenario name to run from the command line. + // This name must be alphanumeric, so instead of letting Goose do the conversion from the + // scenario name for us, we give it the name we want. + scenario.machine_name = "generalrequestv04".to_string(); + + let trans_and_weights = vec![ + (txs::block_hash_and_number(), BLOCK_HASH_AND_NUMBER_WEIGHT), + (txs::block_number(), BLOCK_NUMBER_WEIGHT), + (txs::chain_id(), CHAIN_ID_WEIGHT), + (txs::get_block_transaction_count_by_hash(), GET_BLOCK_TRANSACTION_COUNT_BY_HASH_WEIGHT), + ( + txs::get_block_transaction_count_by_number(), + GET_BLOCK_TRANSACTION_COUNT_BY_NUMBER_WEIGHT, + ), + ( + txs::get_block_with_full_transactions_by_hash(), + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_HASH_WEIGHT, + ), + ( + txs::get_block_with_full_transactions_by_number(), + GET_BLOCK_WITH_FULL_TRANSACTIONS_BY_NUMBER_WEIGHT, + ), + ( + txs::get_block_with_transaction_hashes_by_hash(), + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_HASH_WEIGHT, + ), + ( + txs::get_block_with_transaction_hashes_by_number(), + GET_BLOCK_WITH_TRANSACTION_HASHES_BY_NUMBER_WEIGHT, + ), + (txs::get_class_at_by_hash(), GET_CLASS_AT_BY_HASH_WEIGHT), + (txs::get_class_at_by_number(), GET_CLASS_AT_BY_NUMBER_WEIGHT), + (txs::get_class_by_hash(), GET_CLASS_BY_HASH_WEIGHT), + (txs::get_class_by_number(), GET_CLASS_BY_NUMBER_WEIGHT), + (txs::get_class_hash_at_by_hash(), GET_CLASS_HASH_AT_BY_HASH_WEIGHT), + (txs::get_class_hash_at_by_number(), GET_CLASS_HASH_AT_BY_NUMBER_WEIGHT), + (txs::get_events_without_address(), GET_EVENTS_WITHOUT_ADDRESS_WEIGHT), + (txs::get_events_with_address(), GET_EVENTS_WITH_ADDRESS_WEIGHT), + (txs::get_nonce_by_hash(), GET_NONCE_BY_HASH_WEIGHT), + (txs::get_nonce_by_number(), GET_NONCE_BY_NUMBER_WEIGHT), + (txs::get_state_update_by_hash(), GET_STATE_UPDATE_BY_HASH_WEIGHT), + (txs::get_state_update_by_number(), GET_STATE_UPDATE_BY_NUMBER_WEIGHT), + (txs::get_storage_at_by_hash(), GET_STORAGE_AT_BY_HASH_WEIGHT), + (txs::get_storage_at_by_number(), GET_STORAGE_AT_BY_NUMBER_WEIGHT), + ( + txs::get_transaction_by_block_id_and_index_by_hash(), + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_HASH_WEIGHT, + ), + ( + txs::get_transaction_by_block_id_and_index_by_number(), + GET_TRANSACTION_BY_BLOCK_ID_AND_INDEX_BY_NUMBER_WEIGHT, + ), + (txs::get_transaction_by_hash(), GET_TRANSACTION_BY_HASH_WEIGHT), + (txs::get_transaction_receipt(), GET_TRANSACTION_RECEIPT_WEIGHT), + (txs::syncing(), SYNCING_WEIGHT), + ]; + for (transaction, weight) in trans_and_weights.into_iter() { + scenario = scenario.register_transaction(transaction.set_weight(weight).unwrap()); + } + + let new_trans_and_weights = vec![ + (txs::trace_block_transactions_by_hash(), TRACE_BLOCK_TRANSACTIONS_BY_HASH_WEIGHT), + (txs::trace_block_transactions_by_number(), TRACE_BLOCK_TRANSACTIONS_BY_NUMBER_WEIGHT), + (txs::trace_transaction(), TRACE_TRANSACTION_WEIGHT), + ]; + for (transaction, weight) in new_trans_and_weights.into_iter() { + scenario = scenario.register_transaction(transaction.set_weight(weight).unwrap()); + } + scenario +} diff --git a/crates/papyrus_load_test/src/transactions.rs b/crates/papyrus_load_test/src/transactions.rs new file mode 100644 index 00000000000..f98d2d40940 --- /dev/null +++ b/crates/papyrus_load_test/src/transactions.rs @@ -0,0 +1,119 @@ +use std::fs::File; +use std::io::prelude::*; +use std::io::BufReader; +use std::sync::Arc; + +use goose::goose::{Transaction, TransactionFunction}; +use rand::Rng; +use serde_json::{json, Value as jsonVal}; + +use crate::{create_request, jsonrpc_request, path_in_resources, post_jsonrpc_request}; + +create_get_transaction_function_with_requests_from_file! { + get_block_with_transaction_hashes_by_number, "block_number.txt"; + get_block_with_transaction_hashes_by_hash, "block_hash.txt"; + get_block_with_full_transactions_by_number, "block_number.txt"; + get_block_with_full_transactions_by_hash, "block_hash.txt"; + get_block_with_full_transactions_and_receipts_by_number, "block_number.txt"; + get_block_with_full_transactions_and_receipts_by_hash, "block_hash.txt"; + get_block_transaction_count_by_number, "block_number.txt"; + get_block_transaction_count_by_hash, "block_hash.txt"; + get_state_update_by_number, "block_number.txt"; + get_state_update_by_hash, "block_hash.txt"; + get_transaction_by_block_id_and_index_by_number, "block_number_and_transaction_index.txt"; + get_transaction_by_block_id_and_index_by_hash, "block_hash_and_transaction_index.txt"; + get_transaction_by_hash, "transaction_hash.txt"; + get_transaction_receipt, "transaction_hash.txt"; + get_class_at_by_number, "block_number_and_contract_address.txt"; + get_class_at_by_hash, "block_hash_and_contract_address.txt"; + get_class_hash_at_by_number, "block_number_and_contract_address.txt"; + get_class_hash_at_by_hash, "block_hash_and_contract_address.txt"; + get_nonce_by_number, "block_number_and_contract_address.txt"; + get_nonce_by_hash, "block_hash_and_contract_address.txt"; + get_storage_at_by_number, "block_number_and_contract_address.txt"; + get_storage_at_by_hash, "block_hash_and_contract_address.txt"; + get_class_by_number, "block_number_and_class_hash.txt"; + get_class_by_hash, "block_hash_and_class_hash.txt"; + get_events_with_address, "block_range_and_contract_address.txt"; + get_events_without_address, "block_range_and_contract_address.txt"; + trace_transaction, "transaction_hash.txt"; + trace_block_transactions_by_number, "block_number.txt"; + trace_block_transactions_by_hash, "block_hash.txt"; +} + +pub fn block_number() -> Transaction { + transaction_with_constant_request("blockNumber", "block_number") +} + +pub fn block_hash_and_number() -> Transaction { + transaction_with_constant_request("blockHashAndNumber", "block_hash_and_number") +} + +pub fn chain_id() -> Transaction { + transaction_with_constant_request("chainId", "chain_id") +} + +pub fn syncing() -> Transaction { + transaction_with_constant_request("syncing", "syncing") +} + +fn transaction_with_constant_request(method_name: &str, transaction_name: &str) -> Transaction { + let method = String::from("starknet_") + method_name; + let request = jsonrpc_request(&method, json!([])); + let func: TransactionFunction = Arc::new(move |user| { + let request = request.clone(); + Box::pin(async move { + post_jsonrpc_request(user, &request).await?; + + Ok(()) + }) + }); + Transaction::new(func).set_name(transaction_name) +} + +// Returns a Transaction that each call choose a random request from the requests vector +// and sends it to the node. +fn random_request_transaction(requests: Vec) -> Transaction { + let func: TransactionFunction = Arc::new(move |user| { + let index: usize = rand::thread_rng().gen_range(0..requests.len()); + let req = requests[index].clone(); + Box::pin(async move { + post_jsonrpc_request(user, &req).await?; + + Ok(()) + }) + }); + Transaction::new(func) +} + +// Given file_name reads the file line by line and, for each line, creates request to the node using +// convert_to_request function. Returns a vector with all the requests were created from the file. +pub(crate) fn create_requests_vector_from_file( + file_name: &str, + convert_to_request: fn(&str) -> jsonVal, +) -> Vec { + let file = File::open(path_in_resources(file_name)).unwrap(); + let reader = BufReader::new(file); + let mut requests = Vec::::new(); + for line in reader.lines() { + requests.push(convert_to_request(&line.unwrap())); + } + requests +} + +// Given [Name, "Path";] write the function: +// pub fn Name() -> Transaction { +// let requests = create_requests_vector("Path", create_request::Name); +// random_request_transaction(requests).set_name(Name) +// } +macro_rules! create_get_transaction_function_with_requests_from_file { + () => {}; + ($name:tt, $file_name:literal; $($rest:tt)*) => { + pub fn $name() -> Transaction { + let requests = create_requests_vector_from_file($file_name, create_request::$name); + random_request_transaction(requests).set_name(stringify!($name)) + } + create_get_transaction_function_with_requests_from_file!($($rest)*); + }; +} +pub(crate) use create_get_transaction_function_with_requests_from_file; diff --git a/crates/papyrus_monitoring_gateway/Cargo.toml b/crates/papyrus_monitoring_gateway/Cargo.toml new file mode 100644 index 00000000000..ee6684649b5 --- /dev/null +++ b/crates/papyrus_monitoring_gateway/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "papyrus_monitoring_gateway" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[dependencies] +axum.workspace = true +hyper = { workspace = true, features = ["full"] } +metrics-exporter-prometheus = { version = "0.12.1" } +metrics-process = { version = "1.0.11" } +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +rand.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +starknet_client = { path = "../starknet_client" } +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tracing.workspace = true +validator = { workspace = true, features = ["derive"] } + +[dev-dependencies] +http-body = { version = "0.4.5" } +metrics.workspace = true +papyrus_storage = { path = "../papyrus_storage", features = ["testing"] } +pretty_assertions.workspace = true +starknet_client = { path = "../starknet_client", features = ["testing"] } +tower = { workspace = true, features = ["util"] } diff --git a/crates/papyrus_monitoring_gateway/src/gateway_test.rs b/crates/papyrus_monitoring_gateway/src/gateway_test.rs new file mode 100644 index 00000000000..8c1dc4487e2 --- /dev/null +++ b/crates/papyrus_monitoring_gateway/src/gateway_test.rs @@ -0,0 +1,241 @@ +use std::net::{SocketAddr, TcpListener}; +use std::sync::Arc; + +use axum::body::Body; +use axum::http::{Request, StatusCode}; +use axum::response::Response; +use axum::Router; +use http_body::combinators::UnsyncBoxBody; +use metrics::{absolute_counter, describe_counter, register_counter}; +use metrics_exporter_prometheus::PrometheusBuilder; +use papyrus_storage::{table_names, test_utils}; +use pretty_assertions::assert_eq; +use serde_json::{json, Value}; +use starknet_client::reader::MockStarknetReader; +use starknet_client::writer::MockStarknetWriter; +use tower::ServiceExt; + +use crate::{app, is_ready, MONITORING_PREFIX}; + +const TEST_CONFIG_PRESENTATION: &str = "full_general_config_presentation"; +const PUBLIC_TEST_CONFIG_PRESENTATION: &str = "public_general_config_presentation"; +const SECRET: &str = "abcd"; +const TEST_VERSION: &str = "1.2.3-dev"; +const TEST_PEER_ID: &str = "peer_id"; + +// TODO(dan): consider using a proper fixture. +fn setup_app() -> Router { + let ((storage_reader, _), _temp_dir) = test_utils::get_test_storage(); + app( + String::from("https://default_url"), + storage_reader, + TEST_VERSION, + serde_json::to_value(TEST_CONFIG_PRESENTATION).unwrap(), + serde_json::to_value(PUBLIC_TEST_CONFIG_PRESENTATION).unwrap(), + SECRET.to_string(), + None, + TEST_PEER_ID.to_string(), + ) +} + +async fn request_app( + app: Router, + method: &str, +) -> Response> { + app.oneshot( + Request::builder() + .uri(format!("/{MONITORING_PREFIX}/{method}").as_str()) + .body(Body::empty()) + .unwrap(), + ) + .await + .unwrap() +} + +#[tokio::test] +async fn db_stats() { + let app = setup_app(); + let response = request_app(app, "dbTablesStats").await; + + assert_eq!(response.status(), StatusCode::OK); + + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body).unwrap(); + assert!(!body["db_stats"].is_null()); + for &name in table_names() { + assert!( + body["tables_stats"].get(name).is_some(), + "{name} is not found in returned DB statistics." + ) + } +} + +#[tokio::test] +async fn mmap_files_stats() { + let app = setup_app(); + let response = request_app(app, "mmapFilesStats").await; + + assert_eq!(response.status(), StatusCode::OK); + + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body).unwrap(); + assert!(!body["thin_state_diff"].is_null()); + assert!(!body["contract_class"].is_null()); + assert!(!body["casm"].is_null()); + assert!(!body["deprecated_contract_class"].is_null()); +} + +#[tokio::test] +async fn version() { + let app = setup_app(); + let response = request_app(app, "nodeVersion").await; + + assert_eq!(response.status(), StatusCode::OK); + + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + assert_eq!(&body[..], TEST_VERSION.as_bytes()); +} + +async fn validate_response(request: &str, expected_response: &str) { + let app = setup_app(); + let response = request_app(app, request).await; + + assert_eq!(response.status(), StatusCode::OK); + + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body).unwrap(); + assert_eq!(body, json!(expected_response)); +} + +#[tokio::test] +async fn public_node_config() { + validate_response("nodeConfig", PUBLIC_TEST_CONFIG_PRESENTATION).await; +} + +#[tokio::test] +async fn node_config_valid_secret() { + validate_response(format!("nodeConfigFull/{SECRET}").as_str(), TEST_CONFIG_PRESENTATION).await; +} + +#[tokio::test] +async fn node_config_invalid_secret() { + let app = setup_app(); + let response = request_app(app, "nodeConfigFull/zzz".to_string().as_str()).await; + + assert_eq!(response.status(), StatusCode::FORBIDDEN); +} + +#[tokio::test] +async fn alive() { + let app = setup_app(); + let response = request_app(app, "alive").await; + + assert_eq!(response.status(), StatusCode::OK); +} + +#[tokio::test] +async fn peer_id() { + let app = setup_app(); + let response = request_app(app, "peer_id").await; + + assert_eq!(response.status(), StatusCode::OK); + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + assert_eq!(body, TEST_PEER_ID); +} + +#[tokio::test] +async fn ready() { + let mut gateway_client_mock = MockStarknetWriter::new(); + let mut feeder_gateway_client_mock = MockStarknetReader::new(); + + gateway_client_mock.expect_is_alive().times(1).returning(|| true); + feeder_gateway_client_mock.expect_is_alive().times(1).returning(|| true); + + let response: String = + is_ready(Arc::new(gateway_client_mock), Arc::new(feeder_gateway_client_mock)).await; + assert_eq!(response, StatusCode::OK.to_string()); +} + +#[tokio::test] +async fn without_metrics() { + let app = setup_app(); + let response = request_app(app, "metrics").await; + + assert_eq!(response.status(), StatusCode::METHOD_NOT_ALLOWED); + let body_bytes = hyper::body::to_bytes(response.into_body()).await.unwrap(); + assert!(body_bytes.is_empty()); +} + +#[tokio::test] +async fn with_metrics() { + // Creates an app with prometheus handle. + let ((storage_reader, _), _temp_dir) = test_utils::get_test_storage(); + let prometheus_handle = PrometheusBuilder::new().install_recorder().unwrap(); + let app = app( + String::from("https://default_url"), + storage_reader, + TEST_VERSION, + serde_json::Value::default(), + serde_json::Value::default(), + String::new(), + Some(prometheus_handle), + TEST_PEER_ID.to_string(), + ); + + // Register a metric. + let metric_name = "metric_name"; + let metric_help = "metric_help"; + let metric_value = 8224; + register_counter!(metric_name); + describe_counter!(metric_name, metric_help); + absolute_counter!(metric_name, metric_value); + + let response = request_app(app, "metrics").await; + + assert_eq!(response.status(), StatusCode::OK); + + let body_bytes = hyper::body::to_bytes(response.into_body()).await.unwrap(); + let body_string = String::from_utf8(body_bytes.to_vec()).unwrap(); + let expected_prefix = format!( + "# HELP {metric_name} {metric_help}\n# TYPE {metric_name} counter\n{metric_name} \ + {metric_value}\n\n" + ); + assert!(body_string.starts_with(&expected_prefix)); +} + +#[tokio::test] +async fn run_server() { + let listener = TcpListener::bind("0.0.0.0:0".parse::().unwrap()).unwrap(); + let addr = listener.local_addr().unwrap(); + + tokio::spawn(async move { + axum::Server::from_tcp(listener) + .unwrap() + .serve(setup_app().into_make_service()) + .await + .unwrap(); + }); + + let client = hyper::Client::new(); + + let response = client + .request( + Request::builder() + .uri(format!("http://{addr}/{MONITORING_PREFIX}/nodeVersion")) + .body(Body::empty()) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::OK); +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_monitoring_gateway/src/lib.rs b/crates/papyrus_monitoring_gateway/src/lib.rs new file mode 100644 index 00000000000..823b2044f2c --- /dev/null +++ b/crates/papyrus_monitoring_gateway/src/lib.rs @@ -0,0 +1,343 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +#[cfg(test)] +mod gateway_test; + +use std::collections::{BTreeMap, HashMap}; +use std::fmt::Display; +use std::net::SocketAddr; +use std::str::FromStr; +use std::sync::Arc; + +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use axum::routing::get; +use axum::{Json, Router}; +use metrics_exporter_prometheus::{BuildError, PrometheusBuilder, PrometheusHandle}; +use metrics_process::Collector; +use papyrus_config::converters::{deserialize_optional_map, serialize_optional_map}; +use papyrus_config::dumping::{ser_generated_param, ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializationType, SerializedParam}; +use papyrus_storage::mmap_file::MMapFileStats; +use papyrus_storage::{DbStats, StorageError, StorageReader}; +use rand::distributions::Alphanumeric; +use rand::{thread_rng, Rng}; +use serde::{Deserialize, Serialize}; +use starknet_client::reader::{StarknetFeederGatewayClient, StarknetReader}; +use starknet_client::writer::{StarknetGatewayClient, StarknetWriter}; +use starknet_client::RetryConfig; +use tracing::{debug, info, instrument}; +use validator::Validate; + +const MONITORING_PREFIX: &str = "monitoring"; +const PROCESS_METRICS_PREFIX: &str = "papyrus_"; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Validate)] +pub struct MonitoringGatewayConfig { + pub server_address: String, + pub collect_metrics: bool, + #[serde(deserialize_with = "deserialize_optional_map")] + pub metric_labels: Option>, + #[validate(length(min = 1))] + #[serde(default = "random_secret")] + pub present_full_config_secret: String, + pub starknet_url: String, +} + +fn random_secret() -> String { + let secret = thread_rng().sample_iter(&Alphanumeric).take(10).map(char::from).collect(); + info!("The randomly generated config presentation secret is: {}", secret); + secret +} + +impl Default for MonitoringGatewayConfig { + fn default() -> Self { + MonitoringGatewayConfig { + server_address: String::from("0.0.0.0:8081"), + collect_metrics: false, + metric_labels: None, + // A constant value for testing purposes. + present_full_config_secret: String::from("qwerty"), + starknet_url: String::from("https://alpha-mainnet.starknet.io/"), + } + } +} + +impl SerializeConfig for MonitoringGatewayConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "server_address", + &self.server_address, + "node's monitoring server.", + ParamPrivacyInput::Public, + ), + ser_param( + "collect_metrics", + &self.collect_metrics, + "If true, collect and return metrics in the monitoring gateway.", + ParamPrivacyInput::Public, + ), + ser_param( + "metric_labels", + &serialize_optional_map(&self.metric_labels), + "'label1:value1 label2:value2 ...' additional labels for metrics.", + ParamPrivacyInput::Public, + ), + ser_generated_param( + "present_full_config_secret", + SerializationType::String, + "A secret for presenting the full general config.", + ParamPrivacyInput::Private, + ), + ser_param( + "starknet_url", + &self.starknet_url, + "The URL of a centralized Starknet gateway.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl Display for MonitoringGatewayConfig { + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:?}") + } +} + +pub struct MonitoringServer { + config: MonitoringGatewayConfig, + // Nested Json presentation of all the parameters in the node config. + full_general_config_presentation: serde_json::Value, + // Nested Json presentation of the public parameters in the node config. + public_general_config_presentation: serde_json::Value, + storage_reader: StorageReader, + version: &'static str, + prometheus_handle: Option, + own_peer_id: String, +} + +impl MonitoringServer { + pub fn new( + config: MonitoringGatewayConfig, + full_general_config_presentation: serde_json::Value, + public_general_config_presentation: serde_json::Value, + storage_reader: StorageReader, + version: &'static str, + own_peer_id: String, + ) -> Result { + let prometheus_handle = if config.collect_metrics { + let mut builder = PrometheusBuilder::new(); + if let Some(metric_labels) = &config.metric_labels { + for (label, value) in metric_labels { + builder = builder.add_global_label(label, value); + } + } + Some(builder.install_recorder()?) + } else { + None + }; + Ok(MonitoringServer { + config, + storage_reader, + full_general_config_presentation, + public_general_config_presentation, + version, + prometheus_handle, + own_peer_id, + }) + } + + /// Spawns a monitoring server. + pub async fn spawn_server(self) -> tokio::task::JoinHandle> { + tokio::spawn(async move { self.run_server().await }) + } + + #[instrument( + skip(self), + fields( + version = %self.version, + config = %self.config, + full_general_config_presentation = %self.full_general_config_presentation, + public_general_config_presentation = %self.public_general_config_presentation, + present_full_config_secret = %self.config.present_full_config_secret), + level = "debug")] + async fn run_server(&self) -> std::result::Result<(), hyper::Error> { + let server_address = SocketAddr::from_str(&self.config.server_address) + .expect("Configuration value for monitor server address should be valid"); + let app = app( + self.config.starknet_url.clone(), + self.storage_reader.clone(), + self.version, + self.full_general_config_presentation.clone(), + self.public_general_config_presentation.clone(), + self.config.present_full_config_secret.clone(), + self.prometheus_handle.clone(), + self.own_peer_id.clone(), + ); + debug!("Starting monitoring gateway."); + axum::Server::bind(&server_address).serve(app.into_make_service()).await + } +} + +#[allow(clippy::too_many_arguments)] +fn app( + starknet_url: String, + storage_reader: StorageReader, + version: &'static str, + full_general_config_presentation: serde_json::Value, + public_general_config_presentation: serde_json::Value, + present_full_config_secret: String, + prometheus_handle: Option, + own_peer_id: String, +) -> Router { + let is_ready_retry_config = + RetryConfig { retry_base_millis: 50, retry_max_delay_millis: 1000, max_retries: 0 }; + let starknet_feeder_client = Arc::new( + StarknetFeederGatewayClient::new( + starknet_url.as_str(), + None, + version, + is_ready_retry_config, + ) + .expect("Failed creating Starknet feeder client."), + ); + let starknet_client = Arc::new( + StarknetGatewayClient::new(starknet_url.as_str(), version, is_ready_retry_config) + .expect("Failed creating Starknet client."), + ); + + let db_tables_stats_reader = storage_reader.clone(); + let mmap_files_stats_reader = storage_reader.clone(); + + Router::new() + .route( + format!("/{MONITORING_PREFIX}/dbTablesStats").as_str(), + get(move || db_tables_stats(db_tables_stats_reader)), + ) + .route( + format!("/{MONITORING_PREFIX}/mmapFilesStats").as_str(), + get(move || mmap_files_stats(mmap_files_stats_reader)), + ) + .route( + format!("/{MONITORING_PREFIX}/nodeConfig").as_str(), + get(move || node_config(public_general_config_presentation)), + ) + .route( + // The "*secret" captures the end of the path and stores it in "secret". + format!("/{MONITORING_PREFIX}/nodeConfigFull/*secret").as_str(), + get(move |secret| { + node_config_by_secret( + full_general_config_presentation, + secret, + present_full_config_secret, + ) + }), + ) + .route( + format!("/{MONITORING_PREFIX}/nodeVersion").as_str(), + get(move || node_version(version)), + ) + .route( + format!("/{MONITORING_PREFIX}/alive").as_str(), + get(move || async { StatusCode::OK.to_string() }), + ) + .route( + format!("/{MONITORING_PREFIX}/metrics").as_str(), + get(move || metrics(prometheus_handle)), + ) + .route( + format!("/{MONITORING_PREFIX}/ready").as_str(), + get(move || is_ready(starknet_client, starknet_feeder_client)), + ) + .route(format!("/{MONITORING_PREFIX}/peer_id").as_str(), get(move || async { own_peer_id })) +} + +async fn is_ready( + starknet_client: Arc, + starknet_feeder_client: Arc, +) -> String { + let response = starknet_feeder_client.is_alive().await; + assert!(response); + + let response = starknet_client.is_alive().await; + assert!(response); + + StatusCode::OK.to_string() +} + +/// Returns DB statistics. +#[instrument(skip(storage_reader), level = "debug", ret)] +async fn db_tables_stats(storage_reader: StorageReader) -> Result, ServerError> { + Ok(storage_reader.db_tables_stats()?.into()) +} + +#[instrument(skip(storage_reader), level = "debug", ret)] +async fn mmap_files_stats( + storage_reader: StorageReader, +) -> Result>, ServerError> { + Ok(storage_reader.mmap_files_stats().into()) +} + +/// Returns the node config. +#[instrument(level = "debug", ret)] +async fn node_config( + full_general_config_presentation: serde_json::Value, +) -> axum::Json { + full_general_config_presentation.into() +} + +/// Returns the node config. +#[instrument(level = "debug", ret)] +async fn node_config_by_secret( + full_general_config_presentation: serde_json::Value, + given_secret: Path, + expected_secret: String, +) -> Result, StatusCode> { + if given_secret.to_string() == expected_secret { + Ok(node_config(full_general_config_presentation).await) + } else { + Err(StatusCode::FORBIDDEN) + } +} + +/// Returns prometheus metrics. +/// In case the node doesn’t collect metrics returns an empty response with status code 405: method +/// not allowed. +#[instrument(level = "debug", ret, skip(prometheus_handle))] +async fn metrics(prometheus_handle: Option) -> Response { + match prometheus_handle { + Some(handle) => { + Collector::default().prefix(PROCESS_METRICS_PREFIX).collect(); + handle.render().into_response() + } + None => StatusCode::METHOD_NOT_ALLOWED.into_response(), + } +} + +/// Returns the node version. +#[instrument(level = "debug", ret)] +async fn node_version(version: &'static str) -> String { + version.to_string() +} + +#[derive(thiserror::Error, Debug)] +enum ServerError { + #[error(transparent)] + StorageError(#[from] StorageError), +} + +impl IntoResponse for ServerError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + // TODO(dan): consider using a generic error message instead. + ServerError::StorageError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), + }; + (status, error_message).into_response() + } +} diff --git a/crates/papyrus_network/Cargo.toml b/crates/papyrus_network/Cargo.toml new file mode 100644 index 00000000000..d0aabc1d506 --- /dev/null +++ b/crates/papyrus_network/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "papyrus_network" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[features] +testing = [] + +[[bin]] +name = "streamed_bytes_benchmark" +required-features = ["clap"] +path = "src/bin/streamed_bytes_benchmark.rs" + +[dependencies] +async-stream.workspace = true +bytes.workspace = true +defaultmap.workspace = true +derive_more.workspace = true +futures.workspace = true +lazy_static.workspace = true +libp2p = { workspace = true, features = [ + "gossipsub", + "identify", + "kad", + "macros", + "noise", + "quic", + "tcp", + "tokio", + "yamux", + "serde", +] } +metrics.workspace = true +replace_with.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +serde = { workspace = true, features = ["derive"] } +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tracing.workspace = true +unsigned-varint = { workspace = true, features = ["std"] } +validator = { workspace = true, features = ["derive"] } + +# Binaries dependencies +clap = { workspace = true, optional = true, features = ["derive"] } + + +[dev-dependencies] +assert_matches.workspace = true +deadqueue = { workspace = true, features = ["unlimited"] } +libp2p-swarm-test.workspace = true +mockall.workspace = true +pretty_assertions.workspace = true +tokio = { workspace = true, features = ["full", "sync", "test-util"] } +tokio-stream.workspace = true +void.workspace = true diff --git a/crates/papyrus_network/src/bin/streamed_bytes_benchmark.rs b/crates/papyrus_network/src/bin/streamed_bytes_benchmark.rs new file mode 100644 index 00000000000..21f3fa8daba --- /dev/null +++ b/crates/papyrus_network/src/bin/streamed_bytes_benchmark.rs @@ -0,0 +1,331 @@ +use std::collections::HashMap; +use std::time::{Duration, Instant}; + +use clap::Parser; +use futures::StreamExt; +use libp2p::swarm::SwarmEvent; +use libp2p::{PeerId, StreamProtocol, Swarm}; +use papyrus_network::bin_utils::{build_swarm, dial}; +use papyrus_network::sqmr::behaviour::{Behaviour, Event, ExternalEvent, SessionError}; +use papyrus_network::sqmr::{Bytes, Config, InboundSessionId, OutboundSessionId, SessionId}; + +const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/papyrus/bench/1"); +const CONST_BYTE: u8 = 1; + +fn pretty_size(mut size: f64) -> String { + for term in ["B", "KB", "MB", "GB"] { + if size < 1024.0 { + return format!("{:.2} {}", size, term); + } + size /= 1024.0; + } + format!("{:.2} TB", size) +} + +fn encode_inbound_session_metadata(num_messages: usize, message_size: usize) -> Bytes { + let mut result = num_messages.to_be_bytes().to_vec(); + result.extend_from_slice(&message_size.to_be_bytes()); + result +} + +fn decode_inbound_session_metadata(mut bytes: Bytes) -> (usize, usize) { + let second_bytes = bytes.split_off(8); + ( + usize::from_be_bytes( + bytes.try_into().expect("Failed converting a vec of size 8 to [u8; 8]"), + ), + usize::from_be_bytes( + second_bytes + .try_into() + .expect("Called decode_inbound_session_metadata on Vec of size not 16"), + ), + ) +} + +/// A node that benchmarks the throughput of messages sent/received. +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Address this node listens on for incoming connections. + #[arg(short, long)] + listen_address: String, + + /// Address this node attempts to dial to. + #[arg(short, long)] + dial_address: Option, + + /// Amount of expected inbound sessions. + #[arg(short = 'i', long)] + num_expected_inbound_sessions: usize, + + /// Amount of expected peers to connect to this peer (dial or listener). + #[arg(short = 'c', long)] + num_expected_connections: usize, + + /// Number of queries to send for each node that we connect to (whether we dialed to it or it + /// dialed to us). + #[arg(short = 'q', long, default_value_t)] + num_queries_per_connection: u64, + + /// Number of messages to send for each inbound session. + #[arg(short = 'm', long, default_value_t)] + num_messages_per_session: usize, + + /// Size (in bytes) of each message to send for inbound sessions. + #[arg(short = 's', long, default_value_t)] + message_size: usize, + + /// Amount of time (in seconds) to wait until closing an unactive connection. + #[arg(short = 't', long, default_value_t = 10)] + idle_connection_timeout: u64, +} + +fn create_outbound_sessions_if_all_peers_connected( + swarm: &mut Swarm, + peer_id: PeerId, + outbound_session_measurements: &mut HashMap, + peers_pending_outbound_session: &mut Vec, + args: &Args, +) { + peers_pending_outbound_session.push(peer_id); + if peers_pending_outbound_session.len() >= args.num_expected_connections { + for peer_id in peers_pending_outbound_session { + for _ in 0..args.num_queries_per_connection { + let outbound_session_id = + swarm.behaviour_mut().send_query(vec![], *peer_id, PROTOCOL_NAME).expect( + "There's no connection to a peer immediately after we got a \ + ConnectionEstablished event", + ); + outbound_session_measurements + .insert(outbound_session_id, OutboundSessionMeasurement::new()); + } + } + } +} + +fn send_response_to_inbound_sessions( + swarm: &mut Swarm, + inbound_session_to_messages: &mut HashMap>>, + args: &Args, +) { + for inbound_session_id in inbound_session_to_messages.keys() { + swarm + .behaviour_mut() + .send_response( + encode_inbound_session_metadata(args.num_messages_per_session, args.message_size), + *inbound_session_id, + ) + .unwrap_or_else(|_| { + panic!("Inbound session {} dissappeared unexpectedly", inbound_session_id) + }); + } + while !inbound_session_to_messages.is_empty() { + inbound_session_to_messages.retain(|inbound_session_id, messages| match messages.pop() { + Some(message) => { + swarm.behaviour_mut().send_response(message, *inbound_session_id).unwrap_or_else( + |_| panic!("Inbound session {} dissappeared unexpectedly", inbound_session_id), + ); + + true + } + None => { + swarm.behaviour_mut().close_inbound_session(*inbound_session_id).unwrap_or_else( + |_| panic!("Inbound session {} dissappeared unexpectedly", inbound_session_id), + ); + false + } + }) + } +} + +// TODO(shahak) extract to other file. +struct OutboundSessionMeasurement { + start_time: Instant, + first_message_time: Option, + num_messages: Option, + message_size: Option, +} + +impl OutboundSessionMeasurement { + pub fn print(&self) { + let Some(first_message_time) = self.first_message_time else { + println!( + "An outbound session finished with no messages, skipping time measurements +display" + ); + return; + }; + let messages_elapsed = first_message_time.elapsed(); + let elapsed = self.start_time.elapsed(); + let num_messages = self.num_messages.expect( + "OutboundSessionMeasurement's first_message_time field was set while the num_messages \ + field wasn't set", + ); + let message_size = self.message_size.expect( + "OutboundSessionMeasurement's first_message_time field was set while the message_size \ + field wasn't set", + ); + println!("########## Outbound session finished ##########"); + println!( + "Session had {} messages of size {}. In total {}", + num_messages, + pretty_size(message_size as f64), + pretty_size((message_size * num_messages) as f64), + ); + println!("Session took {:.3} seconds", elapsed.as_secs_f64()); + println!("Message sending took {:.3} seconds", messages_elapsed.as_secs_f64()); + println!("---- Total session statistics ----"); + println!("{:.2} messages/second", num_messages as f64 / elapsed.as_secs_f64()); + println!( + "{}/second", + pretty_size((message_size * num_messages) as f64 / elapsed.as_secs_f64()) + ); + println!("---- Message sending statistics ----"); + println!("{:.2} messages/second", num_messages as f64 / messages_elapsed.as_secs_f64()); + println!( + "{}/second", + pretty_size((message_size * num_messages) as f64 / messages_elapsed.as_secs_f64()) + ); + } + + pub fn new() -> Self { + Self { + start_time: Instant::now(), + first_message_time: None, + num_messages: None, + message_size: None, + } + } + pub fn report_first_message(&mut self, response: Bytes) { + self.first_message_time = Some(Instant::now()); + let (num_messages, message_size) = decode_inbound_session_metadata(response); + self.num_messages = Some(num_messages); + self.message_size = Some(message_size); + } +} + +fn dial_if_requested(swarm: &mut Swarm, args: &Args) { + if let Some(dial_address) = args.dial_address.as_ref() { + dial(swarm, dial_address); + } +} + +#[tokio::main] +async fn main() { + let args = Args::parse(); + + // TODO: add secret key to the args and replace None with it. + let mut swarm = build_swarm( + vec![args.listen_address.clone()], + Duration::from_secs(args.idle_connection_timeout), + None, + |_| { + let mut behaviour = + Behaviour::new(Config { session_timeout: Duration::from_secs(3600) }); + behaviour.add_new_supported_inbound_protocol(PROTOCOL_NAME); + behaviour + }, + ); + let mut outbound_session_measurements = HashMap::new(); + let mut inbound_session_to_messages = HashMap::new(); + let mut connected_in_the_past = false; + + let mut preprepared_messages = (0..args.num_expected_inbound_sessions) + .map(|_| { + (0..args.num_messages_per_session) + .map(|_| vec![CONST_BYTE; args.message_size]) + .collect::>() + }) + .collect::>(); + + let mut peers_pending_outbound_session = Vec::new(); + println!("Preprepared messages for sending"); + + dial_if_requested(&mut swarm, &args); + + while let Some(event) = swarm.next().await { + match event { + SwarmEvent::ConnectionEstablished { peer_id, .. } => { + println!("Connected to a peer!"); + connected_in_the_past = true; + create_outbound_sessions_if_all_peers_connected( + &mut swarm, + peer_id, + &mut outbound_session_measurements, + &mut peers_pending_outbound_session, + &args, + ); + } + SwarmEvent::Behaviour(Event::External(ExternalEvent::NewInboundSession { + inbound_session_id, + .. + })) => { + inbound_session_to_messages.insert( + inbound_session_id, + preprepared_messages + .pop() + .expect("There are more inbound sessions than expected"), + ); + if preprepared_messages.is_empty() { + send_response_to_inbound_sessions( + &mut swarm, + &mut inbound_session_to_messages, + &args, + ); + } + } + SwarmEvent::Behaviour(Event::External( + ExternalEvent::SessionFinishedSuccessfully { + session_id: SessionId::OutboundSessionId(outbound_session_id), + }, + )) => { + outbound_session_measurements[&outbound_session_id].print(); + } + SwarmEvent::Behaviour(Event::External(ExternalEvent::ReceivedResponse { + outbound_session_id, + response, + peer_id: _, + })) => { + if response[0] != CONST_BYTE { + outbound_session_measurements + .get_mut(&outbound_session_id) + .expect("Received response on non-existing outbound session") + .report_first_message(response); + } + } + SwarmEvent::OutgoingConnectionError { .. } => { + dial_if_requested(&mut swarm, &args); + } + SwarmEvent::Behaviour(Event::External(ExternalEvent::SessionFailed { + session_id, + error: SessionError::ConnectionClosed, + })) => { + println!( + "Session {:?} failed on ConnectionClosed. Try to increase \ + idle_connection_timeout", + session_id + ); + } + SwarmEvent::Behaviour(Event::External(ExternalEvent::SessionFailed { + session_id, + error: SessionError::IOError(io_error), + })) => { + println!("Session {:?} failed on {}", session_id, io_error.kind()); + } + SwarmEvent::Behaviour(Event::External( + ExternalEvent::SessionFinishedSuccessfully { + session_id: SessionId::InboundSessionId(_), + }, + )) + | SwarmEvent::NewListenAddr { .. } + | SwarmEvent::IncomingConnection { .. } + | SwarmEvent::ConnectionClosed { .. } => {} + _ => { + panic!("Unexpected event {:?}", event); + } + } + if connected_in_the_past && swarm.network_info().num_peers() == 0 { + break; + } + } +} diff --git a/crates/papyrus_network/src/bin_utils/mod.rs b/crates/papyrus_network/src/bin_utils/mod.rs new file mode 100644 index 00000000000..1025b72d0d3 --- /dev/null +++ b/crates/papyrus_network/src/bin_utils/mod.rs @@ -0,0 +1,57 @@ +use std::str::FromStr; +use std::time::Duration; + +use libp2p::identity::Keypair; +use libp2p::swarm::dial_opts::DialOpts; +use libp2p::swarm::NetworkBehaviour; +use libp2p::{noise, yamux, Multiaddr, Swarm, SwarmBuilder}; +use tracing::debug; + +pub fn build_swarm( + listen_addresses: Vec, + idle_connection_timeout: Duration, + secret_key: Option>, + behaviour: impl Fn(Keypair) -> Behaviour, +) -> Swarm +where +{ + let listen_addresses = listen_addresses.iter().map(|listen_address| { + Multiaddr::from_str(listen_address) + .unwrap_or_else(|_| panic!("Unable to parse address {}", listen_address)) + }); + debug!("Creating swarm with listen addresses: {:?}", listen_addresses); + + let key_pair = match secret_key { + Some(secret_key) => { + Keypair::ed25519_from_bytes(secret_key).expect("Error while parsing secret key") + } + None => Keypair::generate_ed25519(), + }; + let mut swarm = SwarmBuilder::with_existing_identity(key_pair) + .with_tokio() + .with_tcp(Default::default(), noise::Config::new, yamux::Config::default) + .expect("Error building TCP transport") + // TODO: quic transpot does not work (failure appears in the command line when running in debug mode) + // .with_quic() + .with_behaviour(|key| behaviour(key.clone())) + .expect("Error while building the swarm") + .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(idle_connection_timeout)) + .build(); + for listen_address in listen_addresses { + swarm + .listen_on(listen_address.clone()) + .unwrap_or_else(|_| panic!("Error while binding to {}", listen_address)); + } + swarm +} + +pub fn dial(swarm: &mut Swarm, dial_address_str: &str) +where + Behaviour: NetworkBehaviour, +{ + let dial_address = Multiaddr::from_str(dial_address_str) + .unwrap_or_else(|_| panic!("Unable to parse address {}", dial_address_str)); + swarm + .dial(DialOpts::unknown_peer_id().address(dial_address).build()) + .unwrap_or_else(|_| panic!("Error while dialing {}", dial_address_str)); +} diff --git a/crates/papyrus_network/src/discovery/discovery_test.rs b/crates/papyrus_network/src/discovery/discovery_test.rs new file mode 100644 index 00000000000..d6149771ee4 --- /dev/null +++ b/crates/papyrus_network/src/discovery/discovery_test.rs @@ -0,0 +1,315 @@ +// TODO(shahak): add flow test + +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::time::Duration; + +use assert_matches::assert_matches; +use futures::future::pending; +use futures::{FutureExt, Stream, StreamExt}; +use libp2p::core::{ConnectedPoint, Endpoint}; +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::{ + ConnectionClosed, + ConnectionId, + DialError, + DialFailure, + FromSwarm, + NetworkBehaviour, + ToSwarm, +}; +use libp2p::{Multiaddr, PeerId}; +use tokio::select; +use tokio::sync::Mutex; +use tokio::time::timeout; +use void::Void; + +use super::kad_impl::KadToOtherBehaviourEvent; +use super::{Behaviour, ToOtherBehaviourEvent, DIAL_SLEEP}; +use crate::mixed_behaviour::BridgedBehaviour; +use crate::test_utils::next_on_mutex_stream; +use crate::{mixed_behaviour, peer_manager}; + +const TIMEOUT: Duration = Duration::from_secs(1); +const SLEEP_DURATION: Duration = Duration::from_millis(10); + +impl Unpin for Behaviour {} + +impl Stream for Behaviour { + type Item = ToSwarm; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match Pin::into_inner(self).poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(Some(event)), + } + } +} + +// In case we have a bug when we return pending and then return an event. +const TIMES_TO_CHECK_FOR_PENDING_EVENT: usize = 5; + +fn assert_no_event(behaviour: &mut Behaviour) { + for _ in 0..TIMES_TO_CHECK_FOR_PENDING_EVENT { + assert!(behaviour.next().now_or_never().is_none()); + } +} + +#[tokio::test] +async fn discovery_outputs_dial_request_on_start_without_query() { + let bootstrap_peer_id = PeerId::random(); + let bootstrap_peer_address = Multiaddr::empty(); + + let mut behaviour = Behaviour::new(bootstrap_peer_id, bootstrap_peer_address); + + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::Dial{opts} if opts.get_peer_id() == Some(bootstrap_peer_id) + ); + + assert_no_event(&mut behaviour); +} + +#[tokio::test] +async fn discovery_redials_on_dial_failure() { + const EPSILON_SLEEP: Duration = Duration::from_millis(10); + + let bootstrap_peer_id = PeerId::random(); + let bootstrap_peer_address = Multiaddr::empty(); + + let mut behaviour = Behaviour::new(bootstrap_peer_id, bootstrap_peer_address); + + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::Dial{opts} if opts.get_peer_id() == Some(bootstrap_peer_id) + ); + + behaviour.on_swarm_event(FromSwarm::DialFailure(DialFailure { + peer_id: Some(bootstrap_peer_id), + error: &DialError::Aborted, + connection_id: ConnectionId::new_unchecked(0), + })); + + // Check that there are no events until we sleep for enough time. + tokio::time::pause(); + tokio::time::advance(DIAL_SLEEP - EPSILON_SLEEP).await; + assert_no_event(&mut behaviour); + + // Sleep and check for event. + tokio::time::advance(EPSILON_SLEEP).await; + tokio::time::resume(); + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::Dial{opts} if opts.get_peer_id() == Some(bootstrap_peer_id) + ); +} + +#[tokio::test] +async fn discovery_redials_when_all_connections_closed() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + // Consume the initial query event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + behaviour.on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id: behaviour.bootstrap_peer_id(), + connection_id: ConnectionId::new_unchecked(0), + endpoint: &ConnectedPoint::Dialer { + address: behaviour.bootstrap_peer_address().clone(), + role_override: Endpoint::Dialer, + }, + remaining_established: 0, + })); + + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::Dial{opts} if opts.get_peer_id() == Some(behaviour.bootstrap_peer_id()) + ); +} + +#[tokio::test] +async fn discovery_doesnt_redial_when_one_connection_closes() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + // Consume the initial query event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + behaviour.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id: behaviour.bootstrap_peer_id(), + connection_id: ConnectionId::new_unchecked(1), + endpoint: &ConnectedPoint::Dialer { + address: behaviour.bootstrap_peer_address().clone(), + role_override: Endpoint::Dialer, + }, + failed_addresses: &[], + other_established: 1, + })); + + behaviour.on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id: behaviour.bootstrap_peer_id(), + connection_id: ConnectionId::new_unchecked(0), + endpoint: &ConnectedPoint::Dialer { + address: behaviour.bootstrap_peer_address().clone(), + role_override: Endpoint::Dialer, + }, + remaining_established: 1, + })); + + assert_no_event(&mut behaviour); +} + +async fn create_behaviour_and_connect_to_bootstrap_node() -> Behaviour { + let bootstrap_peer_id = PeerId::random(); + let bootstrap_peer_address = Multiaddr::empty(); + + let mut behaviour = Behaviour::new(bootstrap_peer_id, bootstrap_peer_address.clone()); + + // Consume the dial event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + behaviour.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id: bootstrap_peer_id, + connection_id: ConnectionId::new_unchecked(0), + endpoint: &ConnectedPoint::Dialer { + address: bootstrap_peer_address.clone(), + role_override: Endpoint::Dialer, + }, + failed_addresses: &[], + other_established: 0, + })); + + // Consume the event to add the bootstrap node to kademlia. + // TODO(shahak): Consider extracting the validation to a separate test. + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::FoundListenAddresses { + peer_id, + listen_addresses, + } + ) if peer_id == bootstrap_peer_id && listen_addresses == vec![bootstrap_peer_address] + ); + + behaviour +} + +#[tokio::test] +async fn discovery_outputs_single_query_after_connecting() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::RequestKadQuery(_peer_id)) + ); + + assert_no_event(&mut behaviour); +} + +#[tokio::test] +async fn discovery_doesnt_output_queries_while_paused() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::PauseDiscovery, + )); + assert_no_event(&mut behaviour); + + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::ResumeDiscovery, + )); + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::RequestKadQuery(_peer_id)) + ); +} + +#[tokio::test] +async fn discovery_outputs_single_query_on_query_finished() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + // Consume the initial query event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::Kad( + KadToOtherBehaviourEvent::KadQueryFinished, + )); + let event = timeout(TIMEOUT, behaviour.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::RequestKadQuery(_peer_id)) + ); +} + +#[tokio::test] +async fn discovery_doesnt_output_queries_if_query_finished_while_paused() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + // Consume the initial query event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::PauseDiscovery, + )); + assert_no_event(&mut behaviour); + + // Simulate that the query has finished. + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::Kad( + KadToOtherBehaviourEvent::KadQueryFinished, + )); + assert_no_event(&mut behaviour); +} + +#[tokio::test] +async fn discovery_awakes_on_resume() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + behaviour.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::PauseDiscovery, + )); + + // There should be an event once we resume because discovery has just started. + + let mutex = Mutex::new(behaviour); + + select! { + _ = async { + tokio::time::sleep(SLEEP_DURATION).await; + mutex.lock().await.on_other_behaviour_event( + &mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::ResumeDiscovery, + ) + ); + timeout(TIMEOUT, pending::<()>()).await.unwrap(); + } => {}, + maybe_event = next_on_mutex_stream(&mutex) => assert!(maybe_event.is_some()), + } +} + +#[tokio::test] +async fn discovery_awakes_on_query_finished() { + let mut behaviour = create_behaviour_and_connect_to_bootstrap_node().await; + + // Consume the initial query event. + timeout(TIMEOUT, behaviour.next()).await.unwrap(); + + let mutex = Mutex::new(behaviour); + + select! { + _ = async { + tokio::time::sleep(SLEEP_DURATION).await; + mutex.lock().await.on_other_behaviour_event( + &mixed_behaviour::ToOtherBehaviourEvent::Kad( + KadToOtherBehaviourEvent::KadQueryFinished, + ) + ); + timeout(TIMEOUT, pending::<()>()).await.unwrap(); + } => {}, + maybe_event = next_on_mutex_stream(&mutex) => assert!(maybe_event.is_some()), + } +} diff --git a/crates/papyrus_network/src/discovery/flow_test.rs b/crates/papyrus_network/src/discovery/flow_test.rs new file mode 100644 index 00000000000..43f01ca7c1f --- /dev/null +++ b/crates/papyrus_network/src/discovery/flow_test.rs @@ -0,0 +1,101 @@ +use std::collections::HashSet; +use std::iter; + +use futures::StreamExt; +use libp2p::core::multiaddr::Protocol; +use libp2p::identity::Keypair; +use libp2p::kad::store::MemoryStore; +use libp2p::swarm::behaviour::toggle::Toggle; +use libp2p::swarm::{NetworkBehaviour, SwarmEvent}; +use libp2p::{identify, kad, Multiaddr, Swarm}; +use libp2p_swarm_test::SwarmExt; + +use super::Behaviour; +use crate::mixed_behaviour; +use crate::mixed_behaviour::{BridgedBehaviour, MixedBehaviour}; +use crate::utils::StreamHashMap; + +#[derive(NetworkBehaviour)] +struct DiscoveryMixedBehaviour { + pub identify: identify::Behaviour, + pub kademlia: kad::Behaviour, + pub discovery: Toggle, +} + +impl DiscoveryMixedBehaviour { + pub fn new(key: Keypair, bootstrap_peer_multiaddr: Option) -> Self { + let mixed_behaviour = + MixedBehaviour::new(key, bootstrap_peer_multiaddr, Default::default()); + Self { + identify: mixed_behaviour.identify, + kademlia: mixed_behaviour.kademlia, + discovery: mixed_behaviour.discovery, + } + } +} + +#[tokio::test] +async fn all_nodes_have_same_bootstrap_peer() { + const NUM_NODES: usize = 2; + + let mut bootstrap_swarm = + Swarm::new_ephemeral(|keypair| DiscoveryMixedBehaviour::new(keypair, None)); + bootstrap_swarm.listen().with_memory_addr_external().await; + + let bootstrap_peer_id = *bootstrap_swarm.local_peer_id(); + let bootstrap_peer_multiaddr = bootstrap_swarm + .external_addresses() + .next() + .unwrap() + .clone() + .with_p2p(bootstrap_peer_id) + .unwrap(); + + let swarms = (0..NUM_NODES).map(|_| { + Swarm::new_ephemeral(|keypair| { + DiscoveryMixedBehaviour::new(keypair, Some(bootstrap_peer_multiaddr.clone())) + }) + }); + let mut swarms_stream = StreamHashMap::new( + iter::once(bootstrap_swarm) + .chain(swarms) + .map(|swarm| (*swarm.local_peer_id(), swarm)) + .collect(), + ); + for swarm in swarms_stream.values_mut() { + // Can't use libp2p's listen function since it assumes no other events are emitted. + swarm.listen_on(Protocol::Memory(0).into()).unwrap(); + } + + let mut connected_peers = HashSet::new(); + + while connected_peers.len() < NUM_NODES * (NUM_NODES - 1) { + let (peer_id, event) = swarms_stream.next().await.unwrap(); + + let mixed_event: mixed_behaviour::Event = match event { + SwarmEvent::Behaviour(DiscoveryMixedBehaviourEvent::Discovery(event)) => event.into(), + SwarmEvent::Behaviour(DiscoveryMixedBehaviourEvent::Kademlia(event)) => event.into(), + SwarmEvent::Behaviour(DiscoveryMixedBehaviourEvent::Identify(event)) => event.into(), + SwarmEvent::ConnectionEstablished { peer_id: other_peer_id, .. } => { + if peer_id != bootstrap_peer_id && bootstrap_peer_id != other_peer_id { + connected_peers.insert((peer_id, other_peer_id)); + } + continue; + } + _ => continue, + }; + + let mixed_behaviour::Event::ToOtherBehaviourEvent(event) = mixed_event else { + continue; + }; + if let mixed_behaviour::ToOtherBehaviourEvent::NoOp = event { + continue; + }; + let behaviour_ref = swarms_stream.get_mut(&peer_id).unwrap().behaviour_mut(); + behaviour_ref.identify.on_other_behaviour_event(&event); + behaviour_ref.kademlia.on_other_behaviour_event(&event); + if let Some(discovery) = behaviour_ref.discovery.as_mut() { + discovery.on_other_behaviour_event(&event); + } + } +} diff --git a/crates/papyrus_network/src/discovery/identify_impl.rs b/crates/papyrus_network/src/discovery/identify_impl.rs new file mode 100644 index 00000000000..85b342382b1 --- /dev/null +++ b/crates/papyrus_network/src/discovery/identify_impl.rs @@ -0,0 +1,36 @@ +use libp2p::{identify, Multiaddr, PeerId}; + +use crate::mixed_behaviour; +use crate::mixed_behaviour::BridgedBehaviour; + +pub const IDENTIFY_PROTOCOL_VERSION: &str = "/staknet/identify/0.1.0-rc.0"; + +#[derive(Debug)] +pub enum IdentifyToOtherBehaviourEvent { + FoundListenAddresses { peer_id: PeerId, listen_addresses: Vec }, +} + +impl From for mixed_behaviour::Event { + fn from(event: identify::Event) -> Self { + match event { + identify::Event::Received { peer_id, info } => { + mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::Identify( + IdentifyToOtherBehaviourEvent::FoundListenAddresses { + peer_id, + listen_addresses: info.listen_addrs, + }, + ), + ) + } + // TODO(shahak): Consider logging error events. + _ => mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::NoOp, + ), + } + } +} + +impl BridgedBehaviour for identify::Behaviour { + fn on_other_behaviour_event(&mut self, _event: &mixed_behaviour::ToOtherBehaviourEvent) {} +} diff --git a/crates/papyrus_network/src/discovery/kad_impl.rs b/crates/papyrus_network/src/discovery/kad_impl.rs new file mode 100644 index 00000000000..cfdd0bd9455 --- /dev/null +++ b/crates/papyrus_network/src/discovery/kad_impl.rs @@ -0,0 +1,58 @@ +use libp2p::kad; +use tracing::error; + +use super::identify_impl::IdentifyToOtherBehaviourEvent; +use crate::mixed_behaviour; +use crate::mixed_behaviour::BridgedBehaviour; + +#[derive(Debug)] +pub enum KadToOtherBehaviourEvent { + KadQueryFinished, +} + +impl From for mixed_behaviour::Event { + fn from(event: kad::Event) -> Self { + match event { + kad::Event::OutboundQueryProgressed { + id: _, + result: kad::QueryResult::GetClosestPeers(result), + .. + } => { + if let Err(err) = result { + error!("Kademlia query failed on {err:?}"); + } + mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::Kad( + KadToOtherBehaviourEvent::KadQueryFinished, + ), + ) + } + _ => mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::NoOp, + ), + } + } +} + +impl BridgedBehaviour for kad::Behaviour { + fn on_other_behaviour_event(&mut self, event: &mixed_behaviour::ToOtherBehaviourEvent) { + match event { + mixed_behaviour::ToOtherBehaviourEvent::Discovery( + super::ToOtherBehaviourEvent::RequestKadQuery(peer_id), + ) => { + self.get_closest_peers(*peer_id); + } + mixed_behaviour::ToOtherBehaviourEvent::Identify( + IdentifyToOtherBehaviourEvent::FoundListenAddresses { peer_id, listen_addresses }, + ) + | mixed_behaviour::ToOtherBehaviourEvent::Discovery( + super::ToOtherBehaviourEvent::FoundListenAddresses { peer_id, listen_addresses }, + ) => { + for address in listen_addresses { + self.add_address(peer_id, address.clone()); + } + } + _ => {} + } + } +} diff --git a/crates/papyrus_network/src/discovery/mod.rs b/crates/papyrus_network/src/discovery/mod.rs new file mode 100644 index 00000000000..48ac5c2b8c5 --- /dev/null +++ b/crates/papyrus_network/src/discovery/mod.rs @@ -0,0 +1,235 @@ +#[cfg(test)] +mod discovery_test; +#[cfg(test)] +mod flow_test; +pub mod identify_impl; +pub mod kad_impl; + +use std::task::{ready, Context, Poll, Waker}; +use std::time::Duration; + +use futures::future::BoxFuture; +use futures::{pin_mut, Future, FutureExt}; +use kad_impl::KadToOtherBehaviourEvent; +use libp2p::core::Endpoint; +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::dial_opts::{DialOpts, PeerCondition}; +use libp2p::swarm::{ + dummy, + AddressChange, + ConnectionClosed, + ConnectionDenied, + ConnectionHandler, + ConnectionId, + DialFailure, + FromSwarm, + NetworkBehaviour, + ToSwarm, +}; +use libp2p::{Multiaddr, PeerId}; + +use crate::mixed_behaviour::BridgedBehaviour; +use crate::{mixed_behaviour, peer_manager}; + +// TODO(shahak): Consider adding to config. +const DIAL_SLEEP: Duration = Duration::from_secs(5); + +pub struct Behaviour { + is_paused: bool, + // TODO(shahak): Consider running several queries in parallel + is_query_running: bool, + bootstrap_peer_address: Multiaddr, + bootstrap_peer_id: PeerId, + is_dialing_to_bootstrap_peer: bool, + // This needs to be boxed to allow polling it from a &mut. + sleep_future_for_dialing_bootstrap_peer: Option>, + is_connected_to_bootstrap_peer: bool, + is_bootstrap_in_kad_routing_table: bool, + wakers: Vec, +} + +#[derive(Debug)] +pub enum ToOtherBehaviourEvent { + RequestKadQuery(PeerId), + FoundListenAddresses { peer_id: PeerId, listen_addresses: Vec }, +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = ToOtherBehaviourEvent; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result { + Ok(dummy::ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _addr: &Multiaddr, + _role_override: Endpoint, + ) -> Result { + Ok(dummy::ConnectionHandler) + } + + fn on_swarm_event(&mut self, event: FromSwarm<'_>) { + match event { + FromSwarm::DialFailure(DialFailure { peer_id: Some(peer_id), .. }) + if peer_id == self.bootstrap_peer_id => + { + self.is_dialing_to_bootstrap_peer = false; + // For the case that the reason for failure is consistent (e.g the bootstrap peer + // is down), we sleep before redialing + // TODO(shahak): Consider increasing the time after each failure, the same way we + // do in starknet client. + self.sleep_future_for_dialing_bootstrap_peer = + Some(tokio::time::sleep(DIAL_SLEEP).boxed()); + } + FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id, .. }) + if peer_id == self.bootstrap_peer_id => + { + self.is_connected_to_bootstrap_peer = true; + self.is_dialing_to_bootstrap_peer = false; + } + FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + remaining_established, + .. + }) if peer_id == self.bootstrap_peer_id && remaining_established == 0 => { + self.is_connected_to_bootstrap_peer = false; + self.is_dialing_to_bootstrap_peer = false; + } + FromSwarm::AddressChange(AddressChange { peer_id, .. }) + if peer_id == self.bootstrap_peer_id => + { + todo!(); + } + _ => {} + } + } + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + _event: ::ToBehaviour, + ) { + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll::FromBehaviour>> + { + if !self.is_dialing_to_bootstrap_peer && !self.is_connected_to_bootstrap_peer { + if let Some(sleep_future) = &mut self.sleep_future_for_dialing_bootstrap_peer { + pin_mut!(sleep_future); + ready!(sleep_future.poll(cx)); + } + self.is_dialing_to_bootstrap_peer = true; + self.sleep_future_for_dialing_bootstrap_peer = None; + return Poll::Ready(ToSwarm::Dial { + opts: DialOpts::peer_id(self.bootstrap_peer_id) + .addresses(vec![self.bootstrap_peer_address.clone()]) + // The peer manager might also be dialing to the bootstrap node. + .condition(PeerCondition::DisconnectedAndNotDialing) + .build(), + }); + } + + // If we're not connected to any node, then each Kademlia query we make will automatically + // return without any peers. Running queries in that mode will add unnecessary overload to + // the swarm. + if !self.is_connected_to_bootstrap_peer { + return Poll::Pending; + } + if !self.is_bootstrap_in_kad_routing_table { + self.is_bootstrap_in_kad_routing_table = true; + return Poll::Ready(ToSwarm::GenerateEvent( + ToOtherBehaviourEvent::FoundListenAddresses { + peer_id: self.bootstrap_peer_id, + listen_addresses: vec![self.bootstrap_peer_address.clone()], + }, + )); + } + + if !self.is_paused && !self.is_query_running { + self.is_query_running = true; + Poll::Ready(ToSwarm::GenerateEvent(ToOtherBehaviourEvent::RequestKadQuery( + libp2p::identity::PeerId::random(), + ))) + } else { + self.wakers.push(cx.waker().clone()); + Poll::Pending + } + } +} + +impl Behaviour { + // TODO(shahak): Add support to discovery from multiple bootstrap nodes. + // TODO(shahak): Add support to multiple addresses for bootstrap node. + pub fn new(bootstrap_peer_id: PeerId, bootstrap_peer_address: Multiaddr) -> Self { + Self { + is_paused: false, + is_query_running: false, + bootstrap_peer_id, + bootstrap_peer_address, + is_dialing_to_bootstrap_peer: false, + sleep_future_for_dialing_bootstrap_peer: None, + is_connected_to_bootstrap_peer: false, + is_bootstrap_in_kad_routing_table: false, + wakers: Vec::new(), + } + } + + #[cfg(test)] + pub fn bootstrap_peer_id(&self) -> PeerId { + self.bootstrap_peer_id + } + + #[cfg(test)] + pub fn bootstrap_peer_address(&self) -> &Multiaddr { + &self.bootstrap_peer_address + } +} + +impl From for mixed_behaviour::Event { + fn from(event: ToOtherBehaviourEvent) -> Self { + mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::Discovery(event), + ) + } +} + +impl BridgedBehaviour for Behaviour { + fn on_other_behaviour_event(&mut self, event: &mixed_behaviour::ToOtherBehaviourEvent) { + match event { + mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::PauseDiscovery, + ) => self.is_paused = true, + mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::ResumeDiscovery, + ) => { + for waker in self.wakers.drain(..) { + waker.wake(); + } + self.is_paused = false; + } + mixed_behaviour::ToOtherBehaviourEvent::Kad( + KadToOtherBehaviourEvent::KadQueryFinished, + ) => { + for waker in self.wakers.drain(..) { + waker.wake(); + } + self.is_query_running = false; + } + _ => {} + } + } +} diff --git a/crates/papyrus_network/src/e2e_broadcast_test.rs b/crates/papyrus_network/src/e2e_broadcast_test.rs new file mode 100644 index 00000000000..e3ac20fec52 --- /dev/null +++ b/crates/papyrus_network/src/e2e_broadcast_test.rs @@ -0,0 +1,121 @@ +use std::time::Duration; + +use futures::{FutureExt, SinkExt, StreamExt}; +use libp2p::core::multiaddr::Protocol; +use libp2p::swarm::SwarmEvent; +use libp2p::{Multiaddr, Swarm}; +use libp2p_swarm_test::SwarmExt; + +use crate::gossipsub_impl::Topic; +use crate::mixed_behaviour::MixedBehaviour; +use crate::network_manager::GenericNetworkManager; +use crate::sqmr; +use crate::sqmr::Bytes; + +const TIMEOUT: Duration = Duration::from_secs(1); + +async fn create_swarm(bootstrap_peer_multiaddr: Option) -> Swarm { + let mut swarm = Swarm::new_ephemeral(|keypair| { + MixedBehaviour::new(keypair.clone(), bootstrap_peer_multiaddr, sqmr::Config::default()) + }); + // Not using SwarmExt::listen because it panics if the swarm emits other events + let expected_listener_id = swarm.listen_on(Protocol::Memory(0).into()).unwrap(); + let address = swarm + .wait(|event| match event { + SwarmEvent::NewListenAddr { listener_id, address } + if expected_listener_id == listener_id => + { + Some(address) + } + _ => None, + }) + .await; + swarm.add_external_address(address); + + swarm +} + +fn create_network_manager( + swarm: Swarm, +) -> GenericNetworkManager> { + GenericNetworkManager::generic_new(swarm) +} + +const BUFFER_SIZE: usize = 100; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Number(pub u8); + +#[derive(Debug)] +struct EmptyBytesError; + +impl TryFrom for Number { + type Error = EmptyBytesError; + + fn try_from(bytes: Bytes) -> Result { + bytes.first().map(|x| Number(*x)).ok_or(EmptyBytesError) + } +} + +impl From for Bytes { + fn from(num: Number) -> Self { + vec![num.0] + } +} + +#[tokio::test] +async fn broadcast_subscriber_end_to_end_test() { + let topic1 = Topic::new("TOPIC1"); + let topic2 = Topic::new("TOPIC2"); + let bootstrap_swarm = create_swarm(None).await; + let bootstrap_peer_multiaddr = bootstrap_swarm.external_addresses().next().unwrap().clone(); + let bootstrap_peer_multiaddr = + bootstrap_peer_multiaddr.with_p2p(*bootstrap_swarm.local_peer_id()).unwrap(); + let bootstrap_network_manager = create_network_manager(bootstrap_swarm); + let mut network_manager1 = + create_network_manager(create_swarm(Some(bootstrap_peer_multiaddr.clone())).await); + let mut network_manager2 = + create_network_manager(create_swarm(Some(bootstrap_peer_multiaddr)).await); + + let mut subscriber_channels1_1 = + network_manager1.register_broadcast_topic::(topic1.clone(), BUFFER_SIZE).unwrap(); + let mut subscriber_channels1_2 = + network_manager1.register_broadcast_topic::(topic2.clone(), BUFFER_SIZE).unwrap(); + + let subscriber_channels2_1 = + network_manager2.register_broadcast_topic::(topic1.clone(), BUFFER_SIZE).unwrap(); + + let subscriber_channels2_2 = + network_manager2.register_broadcast_topic::(topic2.clone(), BUFFER_SIZE).unwrap(); + + tokio::select! { + _ = network_manager1.run() => panic!("network manager ended"), + _ = network_manager2.run() => panic!("network manager ended"), + _ = bootstrap_network_manager.run() => panic!("network manager ended"), + result = tokio::time::timeout( + TIMEOUT, async move { + // TODO(shahak): Remove this sleep once we fix the bug of broadcasting while there + // are no peers. + tokio::time::sleep(Duration::from_millis(100)).await; + let number1 = Number(1); + let number2 = Number(2); + let mut broadcasted_messages_receiver2_1 = + subscriber_channels2_1.broadcasted_messages_receiver; + let mut broadcasted_messages_receiver2_2 = + subscriber_channels2_2.broadcasted_messages_receiver; + subscriber_channels1_1.messages_to_broadcast_sender.send(number1).await.unwrap(); + subscriber_channels1_2.messages_to_broadcast_sender.send(number2).await.unwrap(); + let (received_number1, _report_callback) = + broadcasted_messages_receiver2_1.next().await.unwrap(); + let (received_number2, _report_callback) = + broadcasted_messages_receiver2_2.next().await.unwrap(); + assert_eq!(received_number1.unwrap(), number1); + assert_eq!(received_number2.unwrap(), number2); + assert!(broadcasted_messages_receiver2_1.next().now_or_never().is_none()); + assert!(broadcasted_messages_receiver2_2.next().now_or_never().is_none()); + } + ) => { + result.unwrap() + } + } +} diff --git a/crates/papyrus_network/src/gossipsub_impl.rs b/crates/papyrus_network/src/gossipsub_impl.rs new file mode 100644 index 00000000000..f2d4327ff36 --- /dev/null +++ b/crates/papyrus_network/src/gossipsub_impl.rs @@ -0,0 +1,53 @@ +use libp2p::gossipsub::TopicHash; +use libp2p::{gossipsub, PeerId}; +use tracing::error; + +use crate::mixed_behaviour; +use crate::mixed_behaviour::BridgedBehaviour; +use crate::sqmr::Bytes; + +#[cfg(test)] +pub type Topic = gossipsub::IdentTopic; +#[cfg(not(test))] +pub type Topic = gossipsub::Sha256Topic; + +#[derive(Debug)] +pub enum ExternalEvent { + #[allow(dead_code)] + Received { originated_peer_id: PeerId, message: Bytes, topic_hash: TopicHash }, +} + +impl From for mixed_behaviour::Event { + fn from(event: gossipsub::Event) -> Self { + match event { + gossipsub::Event::Message { + message: gossipsub::Message { data, topic, source, .. }, + .. + } => { + let Some(originated_peer_id) = source else { + error!( + "Received a message from gossipsub without source even though we've \ + configured it to reject such messages" + ); + return mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::NoOp, + ); + }; + mixed_behaviour::Event::ExternalEvent(mixed_behaviour::ExternalEvent::GossipSub( + ExternalEvent::Received { + originated_peer_id, + message: data, + topic_hash: topic, + }, + )) + } + _ => mixed_behaviour::Event::ToOtherBehaviourEvent( + mixed_behaviour::ToOtherBehaviourEvent::NoOp, + ), + } + } +} + +impl BridgedBehaviour for gossipsub::Behaviour { + fn on_other_behaviour_event(&mut self, _event: &mixed_behaviour::ToOtherBehaviourEvent) {} +} diff --git a/crates/papyrus_network/src/lib.rs b/crates/papyrus_network/src/lib.rs new file mode 100644 index 00000000000..819588b3b47 --- /dev/null +++ b/crates/papyrus_network/src/lib.rs @@ -0,0 +1,106 @@ +/// This crate is responsible for sending messages to a given peer and responding to them according +/// to the [`Starknet p2p specs`] +/// +/// [`Starknet p2p specs`]: https://github.com/starknet-io/starknet-p2p-specs/ +pub mod bin_utils; +mod discovery; +#[cfg(test)] +mod e2e_broadcast_test; +pub mod gossipsub_impl; +pub mod mixed_behaviour; +pub mod network_manager; +mod peer_manager; +pub mod sqmr; +#[cfg(test)] +mod test_utils; +mod utils; + +use std::collections::BTreeMap; +use std::time::Duration; + +use libp2p::Multiaddr; +use papyrus_config::converters::{ + deserialize_optional_vec_u8, + deserialize_seconds_to_duration, + serialize_optional_vec_u8, +}; +use papyrus_config::dumping::{ser_optional_param, ser_param, SerializeConfig}; +use papyrus_config::validators::validate_vec_u256; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use validator::Validate; + +// TODO: add peer manager config to the network config +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Validate)] +pub struct NetworkConfig { + pub tcp_port: u16, + pub quic_port: u16, + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub session_timeout: Duration, + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub idle_connection_timeout: Duration, + pub bootstrap_peer_multiaddr: Option, + #[validate(custom = "validate_vec_u256")] + #[serde(deserialize_with = "deserialize_optional_vec_u8")] + pub(crate) secret_key: Option>, +} + +impl SerializeConfig for NetworkConfig { + fn dump(&self) -> BTreeMap { + let mut config = BTreeMap::from_iter([ + ser_param( + "tcp_port", + &self.tcp_port, + "The port that the node listens on for incoming tcp connections.", + ParamPrivacyInput::Public, + ), + ser_param( + "quic_port", + &self.quic_port, + "The port that the node listens on for incoming quic connections.", + ParamPrivacyInput::Public, + ), + ser_param( + "session_timeout", + &self.session_timeout.as_secs(), + "Maximal time in seconds that each session can take before failing on timeout.", + ParamPrivacyInput::Public, + ), + ser_param( + "idle_connection_timeout", + &self.idle_connection_timeout.as_secs(), + "Amount of time in seconds that a connection with no active sessions will stay \ + alive.", + ParamPrivacyInput::Public, + ), + ]); + config.extend(ser_optional_param( + &self.bootstrap_peer_multiaddr, + Multiaddr::empty(), + "bootstrap_peer_multiaddr", + "The multiaddress of the peer node. It should include the peer's id. For more info: https://docs.libp2p.io/concepts/fundamentals/peers/", + ParamPrivacyInput::Public, + )); + config.extend([ser_param( + "secret_key", + &serialize_optional_vec_u8(&self.secret_key), + "The secret key used for building the peer id. If it's an empty string a random one \ + will be used.", + ParamPrivacyInput::Private, + )]); + config + } +} + +impl Default for NetworkConfig { + fn default() -> Self { + Self { + tcp_port: 10000, + quic_port: 10001, + session_timeout: Duration::from_secs(120), + idle_connection_timeout: Duration::from_secs(120), + bootstrap_peer_multiaddr: None, + secret_key: None, + } + } +} diff --git a/crates/papyrus_network/src/mixed_behaviour.rs b/crates/papyrus_network/src/mixed_behaviour.rs new file mode 100644 index 00000000000..79aa7622e89 --- /dev/null +++ b/crates/papyrus_network/src/mixed_behaviour.rs @@ -0,0 +1,99 @@ +// TODO(shahak): Erase main_behaviour and make this a separate module. + +use libp2p::identity::Keypair; +use libp2p::kad::store::MemoryStore; +use libp2p::swarm::behaviour::toggle::Toggle; +use libp2p::swarm::dial_opts::DialOpts; +use libp2p::swarm::NetworkBehaviour; +use libp2p::{gossipsub, identify, kad, Multiaddr, PeerId}; + +use crate::discovery::identify_impl::{IdentifyToOtherBehaviourEvent, IDENTIFY_PROTOCOL_VERSION}; +use crate::discovery::kad_impl::KadToOtherBehaviourEvent; +use crate::peer_manager::PeerManagerConfig; +use crate::{discovery, gossipsub_impl, peer_manager, sqmr}; + +const ONE_MEGA: usize = 1 << 20; + +// TODO: consider reducing the pulicity of all behaviour to pub(crate) +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "Event")] +pub struct MixedBehaviour { + pub peer_manager: peer_manager::PeerManager, + pub discovery: Toggle, + pub identify: identify::Behaviour, + // TODO(shahak): Consider using a different store. + pub kademlia: kad::Behaviour, + pub sqmr: sqmr::Behaviour, + pub gossipsub: gossipsub::Behaviour, +} + +#[derive(Debug)] +pub enum Event { + ExternalEvent(ExternalEvent), + ToOtherBehaviourEvent(ToOtherBehaviourEvent), +} + +#[derive(Debug)] +pub enum ExternalEvent { + Sqmr(sqmr::behaviour::ExternalEvent), + GossipSub(gossipsub_impl::ExternalEvent), +} + +#[derive(Debug)] +pub enum ToOtherBehaviourEvent { + NoOp, + Identify(IdentifyToOtherBehaviourEvent), + Kad(KadToOtherBehaviourEvent), + Discovery(discovery::ToOtherBehaviourEvent), + PeerManager(peer_manager::ToOtherBehaviourEvent), + Sqmr(sqmr::ToOtherBehaviourEvent), +} + +pub trait BridgedBehaviour { + fn on_other_behaviour_event(&mut self, event: &ToOtherBehaviourEvent); +} + +impl MixedBehaviour { + // TODO: get config details from network manager config + /// Panics if bootstrap_peer_multiaddr doesn't have a peer id. + pub fn new( + keypair: Keypair, + bootstrap_peer_multiaddr: Option, + streamed_bytes_config: sqmr::Config, + ) -> Self { + let public_key = keypair.public(); + let local_peer_id = PeerId::from_public_key(&public_key); + Self { + peer_manager: peer_manager::PeerManager::new(PeerManagerConfig::default()), + discovery: bootstrap_peer_multiaddr + .map(|bootstrap_peer_multiaddr| { + discovery::Behaviour::new( + DialOpts::from(bootstrap_peer_multiaddr.clone()) + .get_peer_id() + .expect("bootstrap_peer_multiaddr doesn't have a peer id"), + bootstrap_peer_multiaddr.clone(), + ) + }) + .into(), + identify: identify::Behaviour::new(identify::Config::new( + IDENTIFY_PROTOCOL_VERSION.to_string(), + public_key, + )), + // TODO: change kademlia protocol name + kademlia: kad::Behaviour::new(local_peer_id, MemoryStore::new(local_peer_id)), + sqmr: sqmr::Behaviour::new(streamed_bytes_config), + gossipsub: gossipsub::Behaviour::new( + gossipsub::MessageAuthenticity::Signed(keypair), + gossipsub::ConfigBuilder::default() + .max_transmit_size(ONE_MEGA) + .build() + .expect("Failed to build gossipsub config"), + ) + .unwrap_or_else(|err_string| { + panic!( + "Failed creating gossipsub behaviour due to the following error: {err_string}" + ) + }), + } + } +} diff --git a/crates/papyrus_network/src/network_manager/mod.rs b/crates/papyrus_network/src/network_manager/mod.rs new file mode 100644 index 00000000000..2e723469c31 --- /dev/null +++ b/crates/papyrus_network/src/network_manager/mod.rs @@ -0,0 +1,753 @@ +mod swarm_trait; + +#[cfg(test)] +mod test; + +use std::collections::HashMap; + +use futures::channel::mpsc::{Receiver, SendError, Sender}; +use futures::channel::oneshot; +use futures::future::{ready, BoxFuture, Ready}; +use futures::sink::With; +use futures::stream::{self, BoxStream, FuturesUnordered, Map, Stream}; +use futures::{pin_mut, FutureExt, Sink, SinkExt, StreamExt}; +use libp2p::gossipsub::{SubscriptionError, TopicHash}; +use libp2p::swarm::SwarmEvent; +use libp2p::{PeerId, StreamProtocol, Swarm}; +use metrics::gauge; +use papyrus_common::metrics as papyrus_metrics; +use sqmr::Bytes; +use tracing::{debug, error, info, trace}; + +use self::swarm_trait::SwarmTrait; +use crate::bin_utils::build_swarm; +use crate::gossipsub_impl::Topic; +use crate::mixed_behaviour::{self, BridgedBehaviour}; +use crate::sqmr::{self, InboundSessionId, OutboundSessionId, SessionId}; +use crate::utils::StreamHashMap; +use crate::{gossipsub_impl, NetworkConfig}; + +#[derive(thiserror::Error, Debug)] +pub enum NetworkError { + #[error(transparent)] + DialError(#[from] libp2p::swarm::DialError), +} + +pub struct GenericNetworkManager { + swarm: SwarmT, + inbound_protocol_to_buffer_size: HashMap, + sqmr_inbound_response_receivers: + StreamHashMap>>, + sqmr_inbound_query_senders: HashMap)>>, + + sqmr_outbound_payload_receivers: StreamHashMap, + sqmr_outbound_response_senders: HashMap, + sqmr_outbound_report_receivers: HashMap, + // Splitting the broadcast receivers from the broadcasted senders in order to poll all + // receivers simultaneously. + // Each receiver has a matching sender and vice versa (i.e the maps have the same keys). + messages_to_broadcast_receivers: StreamHashMap>, + broadcasted_messages_senders: HashMap>, + reported_peer_receivers: FuturesUnordered>>, + // Fields for metrics + num_active_inbound_sessions: usize, + num_active_outbound_sessions: usize, +} + +impl GenericNetworkManager { + pub async fn run(mut self) -> Result<(), NetworkError> { + loop { + tokio::select! { + Some(event) = self.swarm.next() => self.handle_swarm_event(event), + Some(res) = self.sqmr_inbound_response_receivers.next() => self.handle_response_for_inbound_query(res), + Some((protocol, client_payload)) = self.sqmr_outbound_payload_receivers.next() => { + self.handle_local_sqmr_payload(protocol, client_payload) + } + Some((topic_hash, message)) = self.messages_to_broadcast_receivers.next() => { + self.broadcast_message(message, topic_hash); + } + Some(Some(peer_id)) = self.reported_peer_receivers.next() => self.swarm.report_peer(peer_id), + } + } + } + + pub(crate) fn generic_new(swarm: SwarmT) -> Self { + gauge!(papyrus_metrics::PAPYRUS_NUM_CONNECTED_PEERS, 0f64); + let reported_peer_receivers = FuturesUnordered::new(); + reported_peer_receivers.push(futures::future::pending().boxed()); + Self { + swarm, + inbound_protocol_to_buffer_size: HashMap::new(), + sqmr_inbound_response_receivers: StreamHashMap::new(HashMap::new()), + sqmr_inbound_query_senders: HashMap::new(), + sqmr_outbound_payload_receivers: StreamHashMap::new(HashMap::new()), + sqmr_outbound_response_senders: HashMap::new(), + sqmr_outbound_report_receivers: HashMap::new(), + messages_to_broadcast_receivers: StreamHashMap::new(HashMap::new()), + broadcasted_messages_senders: HashMap::new(), + reported_peer_receivers, + num_active_inbound_sessions: 0, + num_active_outbound_sessions: 0, + } + } + + /// TODO: Support multiple protocols where they're all different versions of the same protocol + pub fn register_sqmr_protocol_server( + &mut self, + protocol: String, + buffer_size: usize, + ) -> SqmrQueryReceiver + where + Bytes: From, + Query: TryFrom, + { + let protocol = StreamProtocol::try_from_owned(protocol) + .expect("Could not parse protocol into StreamProtocol."); + self.swarm.add_new_supported_inbound_protocol(protocol.clone()); + if let Some(_old_buffer_size) = + self.inbound_protocol_to_buffer_size.insert(protocol.clone(), buffer_size) + { + panic!("Protocol '{}' has already been registered as a server.", protocol); + } + let (inbound_query_sender, inbound_query_receiver) = + futures::channel::mpsc::channel(buffer_size); + let result = self.sqmr_inbound_query_senders.insert(protocol.clone(), inbound_query_sender); + if result.is_some() { + panic!("Protocol '{}' has already been registered as a server.", protocol); + } + + inbound_query_receiver.map(|(query_bytes, response_bytes_sender)| { + ( + Query::try_from(query_bytes), + response_bytes_sender.with(|response| ready(Ok(Bytes::from(response)))), + ) + }) + } + + /// TODO: Support multiple protocols where they're all different versions of the same protocol + /// Register a new subscriber for sending a single query and receiving multiple responses. + /// Panics if the given protocol is already subscribed. + pub fn register_sqmr_protocol_client( + &mut self, + protocol: String, + buffer_size: usize, + ) -> SqmrClientSender + where + Bytes: From, + Response: TryFrom + 'static + Send, + >::Error: 'static + Send, + Query: 'static, + { + let protocol = StreamProtocol::try_from_owned(protocol) + .expect("Could not parse protocol into StreamProtocol."); + self.swarm.add_new_supported_inbound_protocol(protocol.clone()); + let (payload_sender, payload_receiver) = futures::channel::mpsc::channel(buffer_size); + + let insert_result = self + .sqmr_outbound_payload_receivers + .insert(protocol.clone(), Box::new(payload_receiver)); + if insert_result.is_some() { + panic!("Protocol '{}' has already been registered as a client.", protocol); + } + + let payload_fn = |payload: SqmrClientPayload| { + ready(Ok(SqmrClientPayloadForNetwork::from(payload))) + }; + let payload_sender = payload_sender.with(payload_fn); + + // let response_fn: ReceivedMessagesConverterFn = |x| Response::try_from(x); + + Box::new(payload_sender) + } + + /// Register a new subscriber for broadcasting and receiving broadcasts for a given topic. + /// Panics if this topic is already subscribed. + pub fn register_broadcast_topic( + &mut self, + topic: Topic, + buffer_size: usize, + ) -> Result, SubscriptionError> + where + T: TryFrom, + Bytes: From, + { + self.swarm.subscribe_to_topic(&topic)?; + + let topic_hash = topic.hash(); + + let (messages_to_broadcast_sender, messages_to_broadcast_receiver) = + futures::channel::mpsc::channel(buffer_size); + let (broadcasted_messages_sender, broadcasted_messages_receiver) = + futures::channel::mpsc::channel(buffer_size); + + let insert_result = self + .messages_to_broadcast_receivers + .insert(topic_hash.clone(), messages_to_broadcast_receiver); + if insert_result.is_some() { + panic!("Topic '{}' has already been registered.", topic); + } + + let insert_result = self + .broadcasted_messages_senders + .insert(topic_hash.clone(), broadcasted_messages_sender); + if insert_result.is_some() { + panic!("Topic '{}' has already been registered.", topic); + } + + let messages_to_broadcast_fn: fn(T) -> Ready> = + |x| ready(Ok(Bytes::from(x))); + let messages_to_broadcast_sender = + messages_to_broadcast_sender.with(messages_to_broadcast_fn); + + let broadcasted_messages_fn: BroadcastReceivedMessagesConverterFn = + |(x, report_sender)| (T::try_from(x), report_sender); + let broadcasted_messages_receiver = + broadcasted_messages_receiver.map(broadcasted_messages_fn); + + Ok(BroadcastSubscriberChannels { + messages_to_broadcast_sender, + broadcasted_messages_receiver, + }) + } + + fn handle_swarm_event(&mut self, event: SwarmEvent) { + match event { + SwarmEvent::ConnectionEstablished { peer_id, .. } => { + debug!("Connected to peer id: {peer_id:?}"); + gauge!( + papyrus_metrics::PAPYRUS_NUM_CONNECTED_PEERS, + self.swarm.num_connected_peers() as f64 + ); + } + SwarmEvent::ConnectionClosed { peer_id, cause, .. } => { + match cause { + Some(connection_error) => { + debug!("Connection to {peer_id:?} closed due to {connection_error:?}.") + } + None => debug!("Connection to {peer_id:?} closed."), + } + gauge!( + papyrus_metrics::PAPYRUS_NUM_CONNECTED_PEERS, + self.swarm.num_connected_peers() as f64 + ); + } + SwarmEvent::Behaviour(event) => { + self.handle_behaviour_event(event); + } + SwarmEvent::OutgoingConnectionError { connection_id, peer_id, error } => { + error!( + "Outgoing connection error. connection id: {connection_id:?}, requested peer \ + id: {peer_id:?}, error: {error:?}" + ); + } + SwarmEvent::IncomingConnectionError { + connection_id, + local_addr, + send_back_addr, + error, + } => { + // No need to panic here since this is a result of another peer trying to dial to us + // and failing. Other peers are welcome to retry. + error!( + "Incoming connection error. connection id: {connection_id:?}, local addr: \ + {local_addr:?}, send back addr: {send_back_addr:?}, error: {error:?}" + ); + } + SwarmEvent::NewListenAddr { address, .. } => { + // TODO(shahak): Once we support nodes behind a NAT, fix this to only add external + // addresses. + self.swarm.add_external_address(address); + } + SwarmEvent::IncomingConnection { .. } + | SwarmEvent::Dialing { .. } + | SwarmEvent::NewExternalAddrCandidate { .. } => {} + _ => { + error!("Unexpected event {event:?}"); + } + } + } + + fn handle_behaviour_event(&mut self, event: mixed_behaviour::Event) { + match event { + mixed_behaviour::Event::ExternalEvent(external_event) => { + self.handle_behaviour_external_event(external_event); + } + mixed_behaviour::Event::ToOtherBehaviourEvent(internal_event) => { + self.handle_to_other_behaviour_event(internal_event); + } + } + } + + fn handle_behaviour_external_event(&mut self, event: mixed_behaviour::ExternalEvent) { + match event { + mixed_behaviour::ExternalEvent::Sqmr(event) => { + self.handle_sqmr_behaviour_event(event); + } + mixed_behaviour::ExternalEvent::GossipSub(event) => { + self.handle_gossipsub_behaviour_event(event); + } + } + } + + fn handle_to_other_behaviour_event(&mut self, event: mixed_behaviour::ToOtherBehaviourEvent) { + // TODO(shahak): Move this logic to mixed_behaviour. + if let mixed_behaviour::ToOtherBehaviourEvent::NoOp = event { + return; + } + self.swarm.behaviour_mut().identify.on_other_behaviour_event(&event); + self.swarm.behaviour_mut().kademlia.on_other_behaviour_event(&event); + if let Some(discovery) = self.swarm.behaviour_mut().discovery.as_mut() { + discovery.on_other_behaviour_event(&event); + } + self.swarm.behaviour_mut().sqmr.on_other_behaviour_event(&event); + self.swarm.behaviour_mut().peer_manager.on_other_behaviour_event(&event); + self.swarm.behaviour_mut().gossipsub.on_other_behaviour_event(&event); + } + + fn handle_sqmr_behaviour_event(&mut self, event: sqmr::behaviour::ExternalEvent) { + // TODO(shahak): Extract the body of each match arm to a separate function. + match event { + sqmr::behaviour::ExternalEvent::NewInboundSession { + query, + inbound_session_id, + peer_id: _, + protocol_name, + } => { + info!( + "Received new inbound query: {query:?} for session id: {inbound_session_id:?}" + ); + self.num_active_inbound_sessions += 1; + gauge!( + papyrus_metrics::PAPYRUS_NUM_ACTIVE_INBOUND_SESSIONS, + self.num_active_inbound_sessions as f64 + ); + // TODO: consider returning error instead of panic. + let Some(query_sender) = self.sqmr_inbound_query_senders.get_mut(&protocol_name) + else { + return; + }; + let (response_sender, response_receiver) = futures::channel::mpsc::channel( + *self.inbound_protocol_to_buffer_size.get(&protocol_name).expect( + "A protocol is registered in NetworkManager but it has no buffer size.", + ), + ); + + // TODO(shahak): Close the inbound session if the buffer is full. + server_send_now( + query_sender, + (query, response_sender), + format!( + "Received an inbound query while the buffer is full. Dropping query for \ + session {inbound_session_id:?}" + ), + ); + self.sqmr_inbound_response_receivers.insert( + inbound_session_id, + response_receiver.map(Some).chain(stream::once(ready(None))).boxed(), + ); + } + sqmr::behaviour::ExternalEvent::ReceivedResponse { + outbound_session_id, + response, + peer_id: _peer_id, + } => { + trace!( + "Received response from peer for session id: {outbound_session_id:?}. sending \ + to sync subscriber." + ); + + if let Some(response_sender) = + self.sqmr_outbound_response_senders.get_mut(&outbound_session_id) + { + // TODO(shahak): Close the channel if the buffer is full. + network_send_now( + response_sender, + response, + format!( + "Received response for an outbound query while the buffer is full. \ + Dropping it. Session: {outbound_session_id:?}" + ), + ); + } + } + sqmr::behaviour::ExternalEvent::SessionFailed { session_id, error } => { + error!("Session {session_id:?} failed on {error:?}"); + self.report_session_removed_to_metrics(session_id); + // TODO: Handle reputation and retry. + if let SessionId::OutboundSessionId(outbound_session_id) = session_id { + self.sqmr_outbound_response_senders.remove(&outbound_session_id); + // TODO: check if the report receiver was already removed when session was + // assigned + self.sqmr_outbound_report_receivers.remove(&outbound_session_id); + } + } + sqmr::behaviour::ExternalEvent::SessionFinishedSuccessfully { session_id } => { + debug!("Session completed successfully. session_id: {session_id:?}"); + self.report_session_removed_to_metrics(session_id); + if let SessionId::OutboundSessionId(outbound_session_id) = session_id { + self.sqmr_outbound_response_senders.remove(&outbound_session_id); + // TODO: check if the report receiver was already removed when session was + // assigned + self.sqmr_outbound_report_receivers.remove(&outbound_session_id); + } + } + } + } + + fn handle_gossipsub_behaviour_event(&mut self, event: gossipsub_impl::ExternalEvent) { + match event { + gossipsub_impl::ExternalEvent::Received { originated_peer_id, message, topic_hash } => { + let (report_sender, report_receiver) = oneshot::channel::<()>(); + self.handle_new_report_receiver(originated_peer_id, report_receiver); + let Some(sender) = self.broadcasted_messages_senders.get_mut(&topic_hash) else { + error!( + "Received a message from a topic we're not subscribed to with hash \ + {topic_hash:?}" + ); + return; + }; + let send_result = sender.try_send((message, report_sender)); + if let Err(e) = send_result { + if e.is_disconnected() { + panic!("Receiver was dropped. This should never happen.") + } else if e.is_full() { + error!( + "Receiver buffer is full. Dropping broadcasted message for topic with \ + hash: {topic_hash:?}." + ); + } + } + } + } + } + + fn handle_response_for_inbound_query(&mut self, res: (InboundSessionId, Option)) { + let (inbound_session_id, maybe_response) = res; + match maybe_response { + Some(response) => { + self.swarm.send_response(response, inbound_session_id).unwrap_or_else(|e| { + error!( + "Failed to send response to peer. Session id: {inbound_session_id:?} not \ + found error: {e:?}" + ); + }); + } + None => { + self.swarm.close_inbound_session(inbound_session_id).unwrap_or_else(|e| { + error!( + "Failed to close session after sending all response. Session id: \ + {inbound_session_id:?} not found error: {e:?}" + ) + }); + } + }; + } + + fn handle_local_sqmr_payload( + &mut self, + protocol: StreamProtocol, + client_payload: SqmrClientPayloadForNetwork, + ) { + let SqmrClientPayloadForNetwork { query, report_receiver, responses_sender } = + client_payload; + match self.swarm.send_query(query, PeerId::random(), protocol.clone()) { + Ok(outbound_session_id) => { + debug!("Sent query to peer. outbound_session_id: {outbound_session_id:?}"); + self.num_active_outbound_sessions += 1; + gauge!( + papyrus_metrics::PAPYRUS_NUM_ACTIVE_OUTBOUND_SESSIONS, + self.num_active_outbound_sessions as f64 + ); + self.sqmr_outbound_response_senders.insert(outbound_session_id, responses_sender); + // TODO(eitan): once session is assigned call handle_new_report_receiver using map + // below + self.sqmr_outbound_report_receivers.insert(outbound_session_id, report_receiver); + } + Err(e) => { + info!( + "Failed to send query to peer. Peer not connected error: {e:?} Returning \ + empty response to sync subscriber." + ); + } + } + } + + fn broadcast_message(&mut self, message: Bytes, topic_hash: TopicHash) { + self.swarm.broadcast_message(message, topic_hash); + } + + fn report_session_removed_to_metrics(&mut self, session_id: SessionId) { + match session_id { + SessionId::InboundSessionId(_) => { + self.num_active_inbound_sessions -= 1; + gauge!( + papyrus_metrics::PAPYRUS_NUM_ACTIVE_INBOUND_SESSIONS, + self.num_active_inbound_sessions as f64 + ); + } + SessionId::OutboundSessionId(_) => { + self.num_active_outbound_sessions += 1; + gauge!( + papyrus_metrics::PAPYRUS_NUM_ACTIVE_OUTBOUND_SESSIONS, + self.num_active_outbound_sessions as f64 + ); + } + } + } + fn handle_new_report_receiver(&self, peer_id: PeerId, report_receiver: oneshot::Receiver<()>) { + self.reported_peer_receivers.push( + report_receiver + .map(move |result| match result { + Ok(_) => Some(peer_id), + Err(_) => None, + }) + .boxed(), + ); + } +} + +fn network_send_now( + sender: &mut GenericSender, + item: Item, + buffer_full_message: String, +) { + pin_mut!(sender); + match sender.as_mut().send(item).now_or_never() { + Some(Ok(())) => {} + Some(Err(error)) => { + error!("Received error while sending message: {:?}", error); + } + None => { + error!(buffer_full_message); + } + } +} + +fn server_send_now(sender: &mut Sender, item: Item, buffer_full_message: String) { + if let Err(error) = sender.try_send(item) { + if error.is_disconnected() { + panic!("Receiver was dropped. This should never happen.") + } else if error.is_full() { + // TODO(shahak): Consider doing something else rather than dropping the message. + error!(buffer_full_message); + } + } +} + +pub type NetworkManager = GenericNetworkManager>; + +impl NetworkManager { + pub fn new(config: NetworkConfig) -> Self { + let NetworkConfig { + tcp_port, + quic_port: _, + session_timeout, + idle_connection_timeout, + bootstrap_peer_multiaddr, + secret_key, + } = config; + + let listen_addresses = vec![ + // TODO: uncomment once quic transpot works. + // format!("/ip4/0.0.0.0/udp/{quic_port}/quic-v1"), + format!("/ip4/0.0.0.0/tcp/{tcp_port}"), + ]; + let swarm = build_swarm(listen_addresses, idle_connection_timeout, secret_key, |key| { + mixed_behaviour::MixedBehaviour::new( + key, + bootstrap_peer_multiaddr.clone(), + sqmr::Config { session_timeout }, + ) + }); + Self::generic_new(swarm) + } + + pub fn get_local_peer_id(&self) -> String { + self.swarm.local_peer_id().to_string() + } +} + +#[cfg(feature = "testing")] +const CHANNEL_BUFFER_SIZE: usize = 1000; + +#[cfg(feature = "testing")] +pub fn mock_register_broadcast_subscriber() +-> Result, SubscriptionError> +where + T: TryFrom, + Bytes: From, +{ + let (messages_to_broadcast_sender, mock_messages_to_broadcast_receiver) = + futures::channel::mpsc::channel(CHANNEL_BUFFER_SIZE); + let (mock_broadcasted_messages_sender, broadcasted_messages_receiver) = + futures::channel::mpsc::channel(CHANNEL_BUFFER_SIZE); + + let messages_to_broadcast_fn: fn(T) -> Ready> = + |x| ready(Ok(Bytes::from(x))); + let messages_to_broadcast_sender = messages_to_broadcast_sender.with(messages_to_broadcast_fn); + + let broadcasted_messages_fn: BroadcastReceivedMessagesConverterFn = + |(x, report_sender)| (T::try_from(x), report_sender); + let broadcasted_messages_receiver = broadcasted_messages_receiver.map(broadcasted_messages_fn); + + let subscriber_channels = + BroadcastSubscriberChannels { messages_to_broadcast_sender, broadcasted_messages_receiver }; + + let mock_broadcasted_messages_fn: MockBroadcastedMessagesFn = + |(x, report_call_back)| ready(Ok((Bytes::from(x), report_call_back))); + let mock_broadcasted_messages_sender = + mock_broadcasted_messages_sender.with(mock_broadcasted_messages_fn); + + let mock_messages_to_broadcast_fn: fn(Bytes) -> T = |x| match T::try_from(x) { + Ok(result) => result, + Err(_) => { + panic!("Failed to convert Bytes that we received from conversion to bytes"); + } + }; + let mock_messages_to_broadcast_receiver = + mock_messages_to_broadcast_receiver.map(mock_messages_to_broadcast_fn); + + let mock_network = BroadcastNetworkMock { + broadcasted_messages_sender: mock_broadcasted_messages_sender, + messages_to_broadcast_receiver: mock_messages_to_broadcast_receiver, + }; + + Ok(TestSubscriberChannels { subscriber_channels, mock_network }) +} + +#[cfg(feature = "testing")] +pub fn dummy_report_sender() -> ReportSender { + oneshot::channel::<()>().0 +} + +type GenericSender = Box + Unpin + Send>; +// Box implements Stream only if S: Stream + Unpin +type GenericReceiver = Box + Unpin + Send>; + +type ResponsesSenderForNetwork = GenericSender; +type ResponsesSender = + GenericSender>::Error>>; + +type ReportSender = oneshot::Sender<()>; +type ReportReceiver = oneshot::Receiver<()>; + +pub struct SqmrClientPayload> { + pub query: Query, + pub report_receiver: ReportReceiver, + pub responses_sender: ResponsesSender, +} + +pub type SqmrClientSender = GenericSender>; + +pub struct SqmrServerPayload, Response> { + pub query: Result>::Error>, + pub report_sender: ReportSender, + pub responses_sender: GenericSender, +} + +// TODO(shahak): Return this type in register_sqmr_protocol_server +pub type SqmrServerReceiver = GenericReceiver>; + +struct SqmrClientPayloadForNetwork { + query: Bytes, + report_receiver: ReportReceiver, + responses_sender: ResponsesSenderForNetwork, +} + +type SqmrClientReceiver = GenericReceiver; + +#[allow(dead_code)] +struct SqmrServerPayloadForNetwork { + query: Bytes, + report_sender: ReportSender, + responses_sender: ResponsesSenderForNetwork, +} + +#[allow(dead_code)] +type SqmrServerSender = GenericSender; + +impl From> for SqmrClientPayloadForNetwork +where + Bytes: From, + Response: TryFrom + 'static + Send, + >::Error: 'static + Send, +{ + fn from(payload: SqmrClientPayload) -> Self { + let SqmrClientPayload { query, report_receiver, responses_sender } = payload; + let query = Bytes::from(query); + let responses_sender = + Box::new(responses_sender.with(|response| ready(Ok(Response::try_from(response))))); + Self { query, report_receiver, responses_sender } + } +} + +impl, Response> From + for SqmrServerPayload +where + Bytes: From, + Response: 'static, +{ + fn from(payload: SqmrServerPayloadForNetwork) -> Self { + let SqmrServerPayloadForNetwork { query, report_sender, responses_sender } = payload; + let query = Query::try_from(query); + let responses_sender = + Box::new(responses_sender.with(|response| ready(Ok(Bytes::from(response))))); + Self { query, report_sender, responses_sender } + } +} + +pub type SqmrQueryReceiver = + Map)>, ReceivedQueryConverterFn>; + +type ReceivedQueryConverterFn = + fn( + (Bytes, Sender), + ) + -> (Result>::Error>, BroadcastSubscriberSender); + +// TODO(eitan): improve naming of final channel types +pub type BroadcastSubscriberSender = With< + Sender, + Bytes, + T, + Ready>, + fn(T) -> Ready>, +>; + +pub type SendQueryConverterFn = + fn((Query, ReportReceiver)) -> Ready>; + +pub type BroadcastSubscriberReceiver = + Map, BroadcastReceivedMessagesConverterFn>; + +type BroadcastReceivedMessagesConverterFn = + fn((Bytes, ReportSender)) -> (Result>::Error>, ReportSender); + +pub struct BroadcastSubscriberChannels> { + pub messages_to_broadcast_sender: BroadcastSubscriberSender, + pub broadcasted_messages_receiver: BroadcastSubscriberReceiver, +} + +#[cfg(feature = "testing")] +pub type MockBroadcastedMessagesSender = With< + Sender<(Bytes, ReportSender)>, + (Bytes, ReportSender), + (T, ReportSender), + Ready>, + MockBroadcastedMessagesFn, +>; +#[cfg(feature = "testing")] +type MockBroadcastedMessagesFn = + fn((T, ReportSender)) -> Ready>; +#[cfg(feature = "testing")] +pub type MockMessagesToBroadcastReceiver = Map, fn(Bytes) -> T>; +#[cfg(feature = "testing")] +pub struct BroadcastNetworkMock> { + pub broadcasted_messages_sender: MockBroadcastedMessagesSender, + pub messages_to_broadcast_receiver: MockMessagesToBroadcastReceiver, +} +#[cfg(feature = "testing")] +pub struct TestSubscriberChannels> { + pub subscriber_channels: BroadcastSubscriberChannels, + pub mock_network: BroadcastNetworkMock, +} diff --git a/crates/papyrus_network/src/network_manager/swarm_trait.rs b/crates/papyrus_network/src/network_manager/swarm_trait.rs new file mode 100644 index 00000000000..270154f962c --- /dev/null +++ b/crates/papyrus_network/src/network_manager/swarm_trait.rs @@ -0,0 +1,131 @@ +use futures::stream::Stream; +use libp2p::gossipsub::{SubscriptionError, TopicHash}; +use libp2p::swarm::dial_opts::DialOpts; +use libp2p::swarm::{DialError, NetworkBehaviour, SwarmEvent}; +use libp2p::{Multiaddr, PeerId, StreamProtocol, Swarm}; +use tracing::error; + +use crate::gossipsub_impl::Topic; +use crate::mixed_behaviour; +use crate::peer_manager::ReputationModifier; +use crate::sqmr::behaviour::{PeerNotConnected, SessionIdNotFoundError}; +use crate::sqmr::{Bytes, InboundSessionId, OutboundSessionId, SessionId}; + +pub type Event = SwarmEvent<::ToSwarm>; + +pub trait SwarmTrait: Stream + Unpin { + fn send_response( + &mut self, + response: Vec, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError>; + + fn send_query( + &mut self, + query: Vec, + peer_id: PeerId, + protocol: StreamProtocol, + ) -> Result; + + fn dial(&mut self, peer_multiaddr: Multiaddr) -> Result<(), DialError>; + + fn num_connected_peers(&self) -> usize; + + fn close_inbound_session( + &mut self, + session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError>; + + fn behaviour_mut(&mut self) -> &mut mixed_behaviour::MixedBehaviour; + + fn get_peer_id_from_session_id( + &self, + session_id: SessionId, + ) -> Result; + + fn add_external_address(&mut self, address: Multiaddr); + + fn subscribe_to_topic(&mut self, topic: &Topic) -> Result<(), SubscriptionError>; + + fn broadcast_message(&mut self, message: Bytes, topic_hash: TopicHash); + + fn report_peer(&mut self, peer_id: PeerId); + + fn add_new_supported_inbound_protocol(&mut self, protocol_name: StreamProtocol); +} + +impl SwarmTrait for Swarm { + fn send_response( + &mut self, + response: Vec, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + self.behaviour_mut().sqmr.send_response(response, inbound_session_id) + } + + // TODO: change this function signature + fn send_query( + &mut self, + query: Vec, + _peer_id: PeerId, + protocol: StreamProtocol, + ) -> Result { + Ok(self.behaviour_mut().sqmr.start_query(query, protocol)) + } + + fn dial(&mut self, peer_multiaddr: Multiaddr) -> Result<(), DialError> { + self.dial(DialOpts::from(peer_multiaddr)) + } + + fn num_connected_peers(&self) -> usize { + self.network_info().num_peers() + } + fn close_inbound_session( + &mut self, + session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + self.behaviour_mut().sqmr.close_inbound_session(session_id) + } + + fn behaviour_mut(&mut self) -> &mut mixed_behaviour::MixedBehaviour { + self.behaviour_mut() + } + + fn get_peer_id_from_session_id( + &self, + session_id: SessionId, + ) -> Result { + self.behaviour() + .sqmr + .get_peer_id_and_connection_id_from_session_id(session_id) + .map(|(peer_id, _)| peer_id) + } + + fn add_external_address(&mut self, address: Multiaddr) { + self.add_external_address(address); + } + + fn subscribe_to_topic(&mut self, topic: &Topic) -> Result<(), SubscriptionError> { + self.behaviour_mut().gossipsub.subscribe(topic).map(|_| ()) + } + + fn broadcast_message(&mut self, message: Bytes, topic_hash: TopicHash) { + let result = self.behaviour_mut().gossipsub.publish(topic_hash.clone(), message); + if let Err(err) = result { + // TODO(shahak): Consider reporting to the subscriber broadcast failures or retrying + // upon failure. + error!( + "Error occured while broadcasting a message to the topic with hash \ + {topic_hash:?}: {err:?}" + ); + } + } + + fn report_peer(&mut self, peer_id: PeerId) { + let _ = self.behaviour_mut().peer_manager.report_peer(peer_id, ReputationModifier::Bad {}); + } + + fn add_new_supported_inbound_protocol(&mut self, protocol: StreamProtocol) { + self.behaviour_mut().sqmr.add_new_supported_inbound_protocol(protocol); + } +} diff --git a/crates/papyrus_network/src/network_manager/test.rs b/crates/papyrus_network/src/network_manager/test.rs new file mode 100644 index 00000000000..4d076e20e90 --- /dev/null +++ b/crates/papyrus_network/src/network_manager/test.rs @@ -0,0 +1,391 @@ +use std::collections::{HashMap, HashSet}; +use std::convert::Infallible; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll}; +use std::time::Duration; +use std::vec; + +use deadqueue::unlimited::Queue; +use futures::channel::mpsc::{unbounded, UnboundedSender}; +use futures::channel::oneshot; +use futures::future::{poll_fn, FutureExt}; +use futures::stream::Stream; +use futures::{pin_mut, Future, SinkExt, StreamExt}; +use lazy_static::lazy_static; +use libp2p::core::ConnectedPoint; +use libp2p::gossipsub::{SubscriptionError, TopicHash}; +use libp2p::swarm::ConnectionId; +use libp2p::{Multiaddr, PeerId, StreamProtocol}; +use tokio::select; +use tokio::sync::Mutex; +use tokio::time::sleep; + +use super::swarm_trait::{Event, SwarmTrait}; +use super::GenericNetworkManager; +use crate::gossipsub_impl::{self, Topic}; +use crate::mixed_behaviour; +use crate::network_manager::SqmrClientPayload; +use crate::sqmr::behaviour::{PeerNotConnected, SessionIdNotFoundError}; +use crate::sqmr::{Bytes, GenericEvent, InboundSessionId, OutboundSessionId}; + +const TIMEOUT: Duration = Duration::from_secs(1); + +lazy_static! { + static ref VEC1: Vec = vec![1, 2, 3, 4, 5]; + static ref VEC2: Vec = vec![6, 7, 8]; + static ref VEC3: Vec = vec![9, 10]; +} + +#[derive(Default)] +struct MockSwarm { + pub pending_events: Queue, + pub subscribed_topics: HashSet, + broadcasted_messages_senders: Vec>, + reported_peer_senders: Vec>, + supported_inbound_protocols_senders: Vec>, + inbound_session_id_to_response_sender: HashMap>, + next_outbound_session_id: usize, + first_polled_event_notifier: Option>, +} + +impl Stream for MockSwarm { + type Item = Event; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut_self = self.get_mut(); + let mut fut = mut_self.pending_events.pop().map(Some).boxed(); + if let Some(sender) = mut_self.first_polled_event_notifier.take() { + fut = fut + .then(|res| async { + sender.send(()).unwrap(); + res + }) + .boxed(); + }; + pin_mut!(fut); + fut.poll_unpin(cx) + } +} + +impl MockSwarm { + pub fn get_responses_sent_to_inbound_session( + &mut self, + inbound_session_id: InboundSessionId, + ) -> impl Future> { + let (responses_sender, responses_receiver) = unbounded(); + if self + .inbound_session_id_to_response_sender + .insert(inbound_session_id, responses_sender) + .is_some() + { + panic!("Called get_responses_sent_to_inbound_session on {inbound_session_id:?} twice"); + } + responses_receiver.collect() + } + + pub fn stream_messages_we_broadcasted(&mut self) -> impl Stream { + let (sender, receiver) = unbounded(); + self.broadcasted_messages_senders.push(sender); + receiver + } + + pub fn get_reported_peers_stream(&mut self) -> impl Stream { + let (sender, receiver) = unbounded(); + self.reported_peer_senders.push(sender); + receiver + } + + pub fn get_supported_inbound_protocol(&mut self) -> impl Stream { + let (sender, receiver) = unbounded(); + self.supported_inbound_protocols_senders.push(sender); + receiver + } + + fn create_response_events_for_query_each_num_becomes_response( + &self, + query: Vec, + outbound_session_id: OutboundSessionId, + peer_id: PeerId, + ) { + for response in query { + self.pending_events.push(Event::Behaviour(mixed_behaviour::Event::ExternalEvent( + mixed_behaviour::ExternalEvent::Sqmr(GenericEvent::ReceivedResponse { + response: vec![response], + outbound_session_id, + peer_id, + }), + ))); + } + } +} + +impl SwarmTrait for MockSwarm { + fn send_response( + &mut self, + response: Vec, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + let responses_sender = + self.inbound_session_id_to_response_sender.get(&inbound_session_id).expect( + "Called send_response without calling get_responses_sent_to_inbound_session first", + ); + responses_sender.unbounded_send(response).unwrap(); + Ok(()) + } + + fn send_query( + &mut self, + query: Vec, + peer_id: PeerId, + _protocol: StreamProtocol, + ) -> Result { + let outbound_session_id = OutboundSessionId { value: self.next_outbound_session_id }; + self.create_response_events_for_query_each_num_becomes_response( + query, + outbound_session_id, + peer_id, + ); + self.next_outbound_session_id += 1; + Ok(outbound_session_id) + } + + fn dial(&mut self, _peer: Multiaddr) -> Result<(), libp2p::swarm::DialError> { + Ok(()) + } + fn num_connected_peers(&self) -> usize { + 0 + } + fn close_inbound_session( + &mut self, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + let responses_sender = + self.inbound_session_id_to_response_sender.get(&inbound_session_id).expect( + "Called close_inbound_session without calling \ + get_responses_sent_to_inbound_session first", + ); + responses_sender.close_channel(); + Ok(()) + } + + fn behaviour_mut(&mut self) -> &mut mixed_behaviour::MixedBehaviour { + unimplemented!() + } + + fn add_external_address(&mut self, _address: Multiaddr) {} + + fn subscribe_to_topic(&mut self, topic: &Topic) -> Result<(), SubscriptionError> { + self.subscribed_topics.insert(topic.hash()); + Ok(()) + } + + fn broadcast_message(&mut self, message: Bytes, topic_hash: TopicHash) { + for sender in &self.broadcasted_messages_senders { + sender.unbounded_send((message.clone(), topic_hash.clone())).unwrap(); + } + } + + fn report_peer(&mut self, peer_id: PeerId) { + for sender in &self.reported_peer_senders { + sender.unbounded_send(peer_id).unwrap(); + } + } + fn add_new_supported_inbound_protocol(&mut self, protocol_name: StreamProtocol) { + for sender in &self.supported_inbound_protocols_senders { + sender.unbounded_send(protocol_name.clone()).unwrap(); + } + } + + fn get_peer_id_from_session_id( + &self, + _session_id: crate::sqmr::SessionId, + ) -> Result { + Ok(PeerId::random()) + } +} + +const BUFFER_SIZE: usize = 100; +const SIGNED_BLOCK_HEADER_PROTOCOL: StreamProtocol = StreamProtocol::new("/starknet/headers/1"); + +#[tokio::test] +async fn register_sqmr_protocol_client_and_use_channels() { + // mock swarm to send and track connection established event + let mut mock_swarm = MockSwarm::default(); + let peer_id = PeerId::random(); + mock_swarm.pending_events.push(get_test_connection_established_event(peer_id)); + let (event_notifier, mut event_listner) = oneshot::channel(); + mock_swarm.first_polled_event_notifier = Some(event_notifier); + + // network manager to register subscriber + let mut network_manager = GenericNetworkManager::generic_new(mock_swarm); + + // register subscriber and send payload + let mut payload_sender = network_manager.register_sqmr_protocol_client::, Vec>( + SIGNED_BLOCK_HEADER_PROTOCOL.to_string(), + BUFFER_SIZE, + ); + + let response_receiver_length = Arc::new(Mutex::new(0)); + let cloned_response_receiver_length = Arc::clone(&response_receiver_length); + let (responses_sender, response_receiver) = + futures::channel::mpsc::channel::, Infallible>>(BUFFER_SIZE); + let responses_sender = Box::new(responses_sender); + let response_receiver_collector = response_receiver + .enumerate() + .take(VEC1.len()) + .map(|(i, result)| { + let result = result.unwrap(); + // this simulates how the mock swarm parses the query and sends responses to it + assert_eq!(result, vec![VEC1[i]]); + result + }) + .collect::>(); + let (_report_sender, report_receiver) = oneshot::channel::<()>(); + tokio::select! { + _ = network_manager.run() => panic!("network manager ended"), + _ = poll_fn(|cx| event_listner.poll_unpin(cx)).then(|_| async move { + payload_sender.send(SqmrClientPayload{query : VEC1.clone(), report_receiver, responses_sender}).await.unwrap()}) + .then(|_| async move { + *cloned_response_receiver_length.lock().await = response_receiver_collector.await.len(); + }) => {}, + _ = sleep(Duration::from_secs(5)) => { + panic!("Test timed out"); + } + } + assert_eq!(*response_receiver_length.lock().await, VEC1.len()); +} + +// TODO(shahak): Add multiple protocols and multiple queries in the test. +#[tokio::test] +async fn process_incoming_query() { + // Create responses for test. + let query = VEC1.clone(); + let responses = vec![VEC1.clone(), VEC2.clone(), VEC3.clone()]; + let protocol: StreamProtocol = SIGNED_BLOCK_HEADER_PROTOCOL; + + // Setup mock swarm and tell it to return an event of new inbound query. + let mut mock_swarm = MockSwarm::default(); + let inbound_session_id = InboundSessionId { value: 0 }; + mock_swarm.pending_events.push(Event::Behaviour(mixed_behaviour::Event::ExternalEvent( + mixed_behaviour::ExternalEvent::Sqmr(GenericEvent::NewInboundSession { + query: query.clone(), + inbound_session_id, + peer_id: PeerId::random(), + protocol_name: protocol.clone(), + }), + ))); + + // Create a future that will return when the session is closed with the responses sent on the + // swarm. + let get_responses_fut = mock_swarm.get_responses_sent_to_inbound_session(inbound_session_id); + let mut get_supported_inbound_protocol_fut = mock_swarm.get_supported_inbound_protocol(); + + let mut network_manager = GenericNetworkManager::generic_new(mock_swarm); + + let mut inbound_query_receiver = network_manager + .register_sqmr_protocol_server::, Vec>(protocol.to_string(), BUFFER_SIZE); + + let actual_protocol = get_supported_inbound_protocol_fut.next().await.unwrap(); + assert_eq!(protocol, actual_protocol); + + let responses_clone = responses.clone(); + select! { + _ = async move { + let (query_got, mut responses_sender) = inbound_query_receiver.next().await.unwrap(); + assert_eq!(query_got.unwrap(), query); + for response in responses_clone { + responses_sender.feed(response).await.unwrap(); + } + responses_sender.close().await.unwrap(); + assert_eq!(get_responses_fut.await, responses); + } => {} + _ = network_manager.run() => { + panic!("GenericNetworkManager::run finished before the session finished"); + } + _ = sleep(Duration::from_secs(5)) => { + panic!("Test timed out"); + } + } +} + +#[tokio::test] +async fn broadcast_message() { + let topic = Topic::new("TOPIC"); + let message = vec![1u8, 2u8, 3u8]; + + let mut mock_swarm = MockSwarm::default(); + let mut messages_we_broadcasted_stream = mock_swarm.stream_messages_we_broadcasted(); + + let mut network_manager = GenericNetworkManager::generic_new(mock_swarm); + + let mut messages_to_broadcast_sender = network_manager + .register_broadcast_topic(topic.clone(), BUFFER_SIZE) + .unwrap() + .messages_to_broadcast_sender; + messages_to_broadcast_sender.send(message.clone()).await.unwrap(); + + tokio::select! { + _ = network_manager.run() => panic!("network manager ended"), + result = tokio::time::timeout( + TIMEOUT, messages_we_broadcasted_stream.next() + ) => { + let (actual_message, topic_hash) = result.unwrap().unwrap(); + assert_eq!(message, actual_message); + assert_eq!(topic.hash(), topic_hash); + } + } +} + +#[tokio::test] +async fn receive_broadcasted_message_and_report_it() { + let topic = Topic::new("TOPIC"); + let message = vec![1u8, 2u8, 3u8]; + let originated_peer_id = PeerId::random(); + + let mut mock_swarm = MockSwarm::default(); + mock_swarm.pending_events.push(Event::Behaviour(mixed_behaviour::Event::ExternalEvent( + mixed_behaviour::ExternalEvent::GossipSub(gossipsub_impl::ExternalEvent::Received { + originated_peer_id, + message: message.clone(), + topic_hash: topic.hash(), + }), + ))); + let mut reported_peer_receiver = mock_swarm.get_reported_peers_stream(); + + let mut network_manager = GenericNetworkManager::generic_new(mock_swarm); + + let mut broadcasted_messages_receiver = network_manager + .register_broadcast_topic::(topic.clone(), BUFFER_SIZE) + .unwrap() + .broadcasted_messages_receiver; + + tokio::select! { + _ = network_manager.run() => panic!("network manager ended"), + // We need to do the entire calculation in the future here so that the network will keep + // running while we call report_callback. + reported_peer_result = tokio::time::timeout(TIMEOUT, broadcasted_messages_receiver.next()) + .then(|result| { + let (message_result, report_callback) = result.unwrap().unwrap(); + assert_eq!(message, message_result.unwrap()); + report_callback.send(()).unwrap(); + tokio::time::timeout(TIMEOUT, reported_peer_receiver.next()) + }) => { + assert_eq!(originated_peer_id, reported_peer_result.unwrap().unwrap()); + } + } +} + +fn get_test_connection_established_event(mock_peer_id: PeerId) -> Event { + Event::ConnectionEstablished { + peer_id: mock_peer_id, + connection_id: ConnectionId::new_unchecked(0), + endpoint: ConnectedPoint::Dialer { + address: Multiaddr::empty(), + role_override: libp2p::core::Endpoint::Dialer, + }, + num_established: std::num::NonZeroU32::new(1).unwrap(), + concurrent_dial_errors: None, + established_in: Duration::from_secs(0), + } +} diff --git a/crates/papyrus_network/src/peer_manager/behaviour_impl.rs b/crates/papyrus_network/src/peer_manager/behaviour_impl.rs new file mode 100644 index 00000000000..ec5ffc6bf1e --- /dev/null +++ b/crates/papyrus_network/src/peer_manager/behaviour_impl.rs @@ -0,0 +1,193 @@ +use std::task::{ready, Poll}; + +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::{ + dummy, + ConnectionClosed, + ConnectionId, + DialError, + DialFailure, + NetworkBehaviour, + ToSwarm, +}; +use libp2p::{Multiaddr, PeerId}; +use tracing::{debug, error}; + +use super::peer::PeerTrait; +use super::{PeerManager, PeerManagerError}; +use crate::sqmr::OutboundSessionId; + +#[derive(Debug)] +pub enum ToOtherBehaviourEvent { + SessionAssigned { + outbound_session_id: OutboundSessionId, + peer_id: PeerId, + connection_id: ConnectionId, + }, + PauseDiscovery, + ResumeDiscovery, +} + +impl NetworkBehaviour for PeerManager

+where + P: PeerTrait, +{ + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = ToOtherBehaviourEvent; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + inbound_peer_id: libp2p::PeerId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result, libp2p::swarm::ConnectionDenied> { + // TODO: consider implementing a better lookup mechanism in case there's a lot of peers this + // will be slow + match self + .peers + .iter() + .find(|(peer_id, peer)| (*peer_id == &inbound_peer_id) && peer.is_blocked()) + { + Some(_) => Err(libp2p::swarm::ConnectionDenied::new(PeerManagerError::PeerIsBlocked( + inbound_peer_id, + ))), + None => Ok(dummy::ConnectionHandler {}), + } + } + + // TODO: in case we want to deny a connection based on the remote address + // we probably need to keep a separate list of banned addresses since extracting it from the + // peers multiaddrs will be slow + fn handle_pending_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result<(), libp2p::swarm::ConnectionDenied> { + Ok(()) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _peer: libp2p::PeerId, + _addr: &libp2p::Multiaddr, + _role_override: libp2p::core::Endpoint, + ) -> Result, libp2p::swarm::ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn on_connection_handler_event( + &mut self, + _peer_id: libp2p::PeerId, + _connection_id: libp2p::swarm::ConnectionId, + _event: libp2p::swarm::THandlerOutEvent, + ) { + // no events from dummy handler + } + + fn on_swarm_event(&mut self, event: libp2p::swarm::FromSwarm<'_>) { + // TODO: consider if we should handle other events + #[allow(clippy::single_match)] + match event { + libp2p::swarm::FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error, + connection_id: _, + }) => { + debug!("Dial failure for peer: {}, error: {}", peer_id, error); + if let DialError::DialPeerConditionFalse(_) = error { + debug!( + "There is another active connection or a dial attempt in progress, not \ + doing anything" + ); + return; + } + let res = self.report_peer(peer_id, super::ReputationModifier::Bad); + if res.is_err() { + error!("Dial failure of an unknow peer. peer id: {}", peer_id) + } + // Re-assign a peer to the session so that a SessionAssgined Event will be emitted. + // TODO: test this case + let queries_to_assign = + self.session_to_peer_map + .iter() + .filter_map(|(outbound_session_id, p_id)| { + if *p_id == peer_id { Some(*outbound_session_id) } else { None } + }) + .collect::>(); + for outbound_session_id in queries_to_assign { + self.assign_peer_to_session(outbound_session_id); + } + } + libp2p::swarm::FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + connection_id, + .. + }) => { + if let Some(sessions) = self.peers_pending_dial_with_sessions.remove(&peer_id) { + self.pending_events.extend(sessions.iter().map(|outbound_session_id| { + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id: *outbound_session_id, + peer_id, + connection_id, + }) + })); + self.peers + .get_mut(&peer_id) + .expect( + "in case we are waiting for a connection established event we assum \ + the peer is known to the peer manager", + ) + .add_connection_id(connection_id); + } else { + let Some(peer) = self.peers.get_mut(&peer_id) else { + // TODO(shahak): Consider tracking connection ids for peers we don't know + // yet because once a connection is established we'll shortly receive an + // identify message and add this peer. + return; + }; + peer.add_connection_id(connection_id); + } + } + libp2p::swarm::FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + connection_id, + .. + }) => { + if let Some(peer) = self.peers.get_mut(&peer_id) { + let known_connection_ids = peer.connection_ids(); + if known_connection_ids.contains(&connection_id) { + peer.remove_connection_id(connection_id); + } else { + error!( + "Connection closed event for a peer with a different connection id. \ + known connection ids: {:?}, emitted connection id: {}", + known_connection_ids, connection_id + ); + } + } + } + _ => {} + } + } + + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll>> + { + if let Some(event) = self.pending_events.pop() { + return Poll::Ready(event); + } + if let Some(sleep_future) = &mut self.sleep_waiting_for_unblocked_peer { + ready!(sleep_future.as_mut().poll(cx)); + for outbound_session_id in std::mem::take(&mut self.sessions_received_when_no_peers) { + self.assign_peer_to_session(outbound_session_id); + } + } + self.sleep_waiting_for_unblocked_peer = None; + self.pending_events.pop().map(Poll::Ready).unwrap_or(Poll::Pending) + } +} diff --git a/crates/papyrus_network/src/peer_manager/mod.rs b/crates/papyrus_network/src/peer_manager/mod.rs new file mode 100644 index 00000000000..95dd26daa58 --- /dev/null +++ b/crates/papyrus_network/src/peer_manager/mod.rs @@ -0,0 +1,264 @@ +use std::collections::HashMap; +use std::time::Duration; + +use futures::future::BoxFuture; +use futures::FutureExt; +use libp2p::swarm::dial_opts::DialOpts; +use libp2p::swarm::ToSwarm; +use libp2p::PeerId; +use tracing::info; + +pub use self::behaviour_impl::ToOtherBehaviourEvent; +use self::peer::PeerTrait; +use crate::discovery::identify_impl::IdentifyToOtherBehaviourEvent; +use crate::mixed_behaviour::BridgedBehaviour; +use crate::sqmr::OutboundSessionId; +use crate::{discovery, mixed_behaviour, sqmr}; + +pub(crate) mod behaviour_impl; +pub(crate) mod peer; +#[cfg(test)] +mod test; + +#[cfg_attr(test, derive(Debug, PartialEq))] +pub enum ReputationModifier { + // TODO: Implement this enum + Bad, +} + +pub struct PeerManager { + peers: HashMap, + // TODO: consider implementing a cleanup mechanism to not store all queries forever + session_to_peer_map: HashMap, + config: PeerManagerConfig, + last_peer_index: usize, + // TODO(shahak): Change to VecDeque and awake when item is added. + pending_events: Vec>>, + peers_pending_dial_with_sessions: HashMap>, + sessions_received_when_no_peers: Vec, + sleep_waiting_for_unblocked_peer: Option>, +} + +#[derive(Clone)] +pub struct PeerManagerConfig { + target_num_for_peers: usize, + blacklist_timeout: Duration, +} + +#[derive(thiserror::Error, Debug)] +pub(crate) enum PeerManagerError { + #[error("No such peer: {0}")] + NoSuchPeer(PeerId), + #[error("No such session: {0}")] + NoSuchSession(OutboundSessionId), + #[error("Peer is blocked: {0}")] + PeerIsBlocked(PeerId), +} + +impl Default for PeerManagerConfig { + fn default() -> Self { + Self { + target_num_for_peers: 100, + // 1 year. + blacklist_timeout: Duration::from_secs(3600 * 24 * 365), + } + } +} + +#[allow(dead_code)] +impl

PeerManager

+where + P: PeerTrait, +{ + pub(crate) fn new(config: PeerManagerConfig) -> Self { + let peers = HashMap::new(); + Self { + peers, + session_to_peer_map: HashMap::new(), + config, + last_peer_index: 0, + pending_events: Vec::new(), + peers_pending_dial_with_sessions: HashMap::new(), + sessions_received_when_no_peers: Vec::new(), + sleep_waiting_for_unblocked_peer: None, + } + } + + fn add_peer(&mut self, mut peer: P) { + info!("Peer Manager found new peer {:?}", peer.peer_id()); + peer.set_timeout_duration(self.config.blacklist_timeout); + self.peers.insert(peer.peer_id(), peer); + // The new peer is unblocked so we don't need to wait for unblocked peer. + self.sleep_waiting_for_unblocked_peer = None; + for outbound_session_id in std::mem::take(&mut self.sessions_received_when_no_peers) { + self.assign_peer_to_session(outbound_session_id); + } + } + + #[cfg(test)] + fn get_mut_peer(&mut self, peer_id: PeerId) -> Option<&mut P> { + self.peers.get_mut(&peer_id) + } + + // TODO(shahak): Remove return value and use events in tests. + // TODO(shahak): Split this function for readability. + fn assign_peer_to_session(&mut self, outbound_session_id: OutboundSessionId) -> Option { + // TODO: consider moving this logic to be async (on a different tokio task) + // until then we can return the assignment even if we use events for the notification. + if self.peers.is_empty() { + info!("No peers. Waiting for a new peer to be connected for {outbound_session_id:?}"); + self.sessions_received_when_no_peers.push(outbound_session_id); + return None; + } + let peer = self + .peers + .iter() + .skip(self.last_peer_index) + .find(|(_, peer)| !peer.is_blocked()) + .or_else(|| { + self.peers.iter().take(self.last_peer_index).find(|(_, peer)| !peer.is_blocked()) + }); + self.last_peer_index = (self.last_peer_index + 1) % self.peers.len(); + if peer.is_none() { + info!( + "No unblocked peers. Waiting for a new peer to be connected or for a peer to \ + become unblocked for {outbound_session_id:?}" + ); + self.sessions_received_when_no_peers.push(outbound_session_id); + // Find the peer closest to becoming unblocked. + let sleep_deadline = self + .peers + .values() + .map(|peer| peer.blocked_until()) + .min() + .expect("min should not return None on a non-empty iterator"); + self.sleep_waiting_for_unblocked_peer = + Some(tokio::time::sleep_until(sleep_deadline.into()).boxed()); + return None; + } + peer.map(|(peer_id, peer)| { + // TODO: consider not allowing reassignment of the same session + self.session_to_peer_map.insert(outbound_session_id, *peer_id); + let peer_connection_ids = peer.connection_ids(); + if !peer_connection_ids.is_empty() { + let connection_id = peer_connection_ids[0]; + info!( + "Session {:?} assigned to peer {:?} with connection id: {:?}", + outbound_session_id, peer_id, connection_id + ); + self.pending_events.push(ToSwarm::GenerateEvent( + ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id, + peer_id: *peer_id, + connection_id, + }, + )); + } else { + // In case we have a race condition where the connection is closed after we added to + // the pending list, the reciever will get an error and will need to ask for + // re-assignment + if let Some(sessions) = self.peers_pending_dial_with_sessions.get_mut(peer_id) { + sessions.push(outbound_session_id); + } else { + self.peers_pending_dial_with_sessions + .insert(*peer_id, vec![outbound_session_id]); + } + info!("Dialing peer {:?} with multiaddr {:?}", peer_id, peer.multiaddr()); + self.pending_events.push(ToSwarm::Dial { + opts: DialOpts::peer_id(*peer_id) + .addresses(vec![peer.multiaddr()]) + // The default condition is Disconnected + // TODO(shahak): Solve this instead by adding new peers through + // ConnectionEstablished without address. + .condition(libp2p::swarm::dial_opts::PeerCondition::Always) + .build(), + }); + } + *peer_id + }) + } + + pub(crate) fn report_peer( + &mut self, + peer_id: PeerId, + reason: ReputationModifier, + ) -> Result<(), PeerManagerError> { + // TODO(shahak): Add time blacklisted to log. + info!("Peer {:?} reported as misbehaving.", peer_id); + if let Some(peer) = self.peers.get_mut(&peer_id) { + peer.update_reputation(reason); + Ok(()) + } else { + Err(PeerManagerError::NoSuchPeer(peer_id)) + } + } + + fn report_session( + &mut self, + outbound_session_id: OutboundSessionId, + reason: ReputationModifier, + ) -> Result<(), PeerManagerError> { + if let Some(peer_id) = self.session_to_peer_map.get(&outbound_session_id) { + if let Some(peer) = self.peers.get_mut(peer_id) { + peer.update_reputation(reason); + Ok(()) + } else { + Err(PeerManagerError::NoSuchPeer(*peer_id)) + } + } else { + Err(PeerManagerError::NoSuchSession(outbound_session_id)) + } + } + + fn more_peers_needed(&self) -> bool { + // TODO: consider if we should count blocked peers (and in what cases? what if they are + // blocked temporarily?) + self.peers.len() < self.config.target_num_for_peers + } +} + +impl From for mixed_behaviour::Event { + fn from(event: ToOtherBehaviourEvent) -> Self { + Self::ToOtherBehaviourEvent(mixed_behaviour::ToOtherBehaviourEvent::PeerManager(event)) + } +} + +impl BridgedBehaviour for PeerManager

{ + fn on_other_behaviour_event(&mut self, event: &mixed_behaviour::ToOtherBehaviourEvent) { + match event { + mixed_behaviour::ToOtherBehaviourEvent::Sqmr( + sqmr::ToOtherBehaviourEvent::RequestPeerAssignment { outbound_session_id }, + ) => { + self.assign_peer_to_session(*outbound_session_id); + } + mixed_behaviour::ToOtherBehaviourEvent::Identify( + IdentifyToOtherBehaviourEvent::FoundListenAddresses { peer_id, listen_addresses }, + ) + | mixed_behaviour::ToOtherBehaviourEvent::Discovery( + discovery::ToOtherBehaviourEvent::FoundListenAddresses { + peer_id, + listen_addresses, + }, + ) => { + // TODO(shahak): Handle changed addresses + if self.peers.contains_key(peer_id) { + return; + } + // TODO(shahak): Track multiple addresses per peer. + let Some(address) = listen_addresses.first() else { + return; + }; + + let peer = P::new(*peer_id, address.clone()); + self.add_peer(peer); + if !self.more_peers_needed() { + // TODO: consider how and in which cases we resume discovery + self.pending_events.push(libp2p::swarm::ToSwarm::GenerateEvent( + ToOtherBehaviourEvent::PauseDiscovery, + )) + } + } + _ => {} + } + } +} diff --git a/crates/papyrus_network/src/peer_manager/peer.rs b/crates/papyrus_network/src/peer_manager/peer.rs new file mode 100644 index 00000000000..0fa6459debc --- /dev/null +++ b/crates/papyrus_network/src/peer_manager/peer.rs @@ -0,0 +1,98 @@ +use std::time::{Duration, Instant}; + +use libp2p::swarm::ConnectionId; +use libp2p::{Multiaddr, PeerId}; +#[cfg(test)] +use mockall::automock; +use tracing::debug; + +use super::ReputationModifier; + +#[cfg_attr(test, automock)] +pub trait PeerTrait { + fn new(peer_id: PeerId, multiaddr: Multiaddr) -> Self; + + fn update_reputation(&mut self, reason: ReputationModifier); + + fn peer_id(&self) -> PeerId; + + fn multiaddr(&self) -> Multiaddr; + + fn set_timeout_duration(&mut self, duration: Duration); + + fn is_blocked(&self) -> bool; + + /// Returns Instant::now if not blocked. + fn blocked_until(&self) -> Instant; + + fn connection_ids(&self) -> &Vec; + + fn add_connection_id(&mut self, connection_id: ConnectionId); + + fn remove_connection_id(&mut self, connection_id: ConnectionId); +} + +#[derive(Clone)] +pub struct Peer { + peer_id: PeerId, + multiaddr: Multiaddr, + timed_out_until: Option, + timeout_duration: Option, + connection_ids: Vec, +} + +impl PeerTrait for Peer { + fn new(peer_id: PeerId, multiaddr: Multiaddr) -> Self { + Self { + peer_id, + multiaddr, + timeout_duration: None, + timed_out_until: None, + connection_ids: Vec::new(), + } + } + + fn update_reputation(&mut self, _reason: ReputationModifier) { + if let Some(timeout_duration) = self.timeout_duration { + self.timed_out_until = Some(Instant::now() + timeout_duration); + } else { + debug!("Timeout duration not set for peer: {:?}", self.peer_id); + } + } + + fn peer_id(&self) -> PeerId { + self.peer_id + } + + fn multiaddr(&self) -> Multiaddr { + self.multiaddr.clone() + } + + fn set_timeout_duration(&mut self, duration: Duration) { + self.timeout_duration = Some(duration); + } + + fn is_blocked(&self) -> bool { + if let Some(timed_out_until) = self.timed_out_until { + timed_out_until > Instant::now() + } else { + false + } + } + + fn blocked_until(&self) -> Instant { + self.timed_out_until.unwrap_or_else(Instant::now) + } + + fn connection_ids(&self) -> &Vec { + &self.connection_ids + } + + fn add_connection_id(&mut self, connection_id: ConnectionId) { + self.connection_ids.push(connection_id); + } + + fn remove_connection_id(&mut self, connection_id: ConnectionId) { + self.connection_ids.retain(|&id| id != connection_id); + } +} diff --git a/crates/papyrus_network/src/peer_manager/test.rs b/crates/papyrus_network/src/peer_manager/test.rs new file mode 100644 index 00000000000..d4ca95c897f --- /dev/null +++ b/crates/papyrus_network/src/peer_manager/test.rs @@ -0,0 +1,546 @@ +// TODO(shahak): Add tests for multiple connection ids + +use core::{panic, time}; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::time::{Duration, Instant}; + +use assert_matches::assert_matches; +use futures::future::poll_fn; +use futures::{FutureExt, Stream, StreamExt}; +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::{ConnectionId, NetworkBehaviour, ToSwarm}; +use libp2p::{Multiaddr, PeerId}; +use mockall::predicate::eq; +use tokio::time::sleep; +use void::Void; + +use super::behaviour_impl::ToOtherBehaviourEvent; +use crate::discovery::identify_impl::IdentifyToOtherBehaviourEvent; +use crate::mixed_behaviour; +use crate::mixed_behaviour::BridgedBehaviour; +use crate::peer_manager::peer::{MockPeerTrait, Peer, PeerTrait}; +use crate::peer_manager::{PeerManager, PeerManagerConfig, ReputationModifier}; +use crate::sqmr::OutboundSessionId; + +impl Unpin for PeerManager

{} + +impl Stream for PeerManager

{ + type Item = ToSwarm; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match Pin::into_inner(self).poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(Some(event)), + } + } +} + +#[test] +fn peer_assignment_round_robin() { + // Create a new peer manager + let mut peer_manager = PeerManager::new(PeerManagerConfig::default()); + + // Add two peers to the peer manager + let peer1 = Peer::new(PeerId::random(), Multiaddr::empty()); + let peer2 = Peer::new(PeerId::random(), Multiaddr::empty()); + peer_manager.add_peer(peer1.clone()); + peer_manager.add_peer(peer2.clone()); + + // Create three queries + let session1 = OutboundSessionId { value: 1 }; + let session2 = OutboundSessionId { value: 2 }; + let session3 = OutboundSessionId { value: 3 }; + + // Assign peers to the queries in a round-robin fashion + let res1 = peer_manager.assign_peer_to_session(session1); + let res2 = peer_manager.assign_peer_to_session(session2); + let res3 = peer_manager.assign_peer_to_session(session3); + + // Verify that the peers are assigned in a round-robin fashion + let is_peer1_first: bool; + match res1.unwrap() { + peer_id if peer_id == peer1.peer_id() => { + is_peer1_first = true; + assert_eq!(res2.unwrap(), peer2.peer_id()); + assert_eq!(res3.unwrap(), peer1.peer_id()); + } + peer_id if peer_id == peer2.peer_id() => { + is_peer1_first = false; + assert_eq!(res2.unwrap(), peer1.peer_id()); + assert_eq!(res3.unwrap(), peer2.peer_id()); + } + peer_id => panic!("Unexpected peer_id: {:?}", peer_id), + } + + // check assignment events + for event in peer_manager.pending_events { + let ToSwarm::GenerateEvent(ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id, + peer_id, + connection_id, + }) = event + else { + continue; + }; + if is_peer1_first { + match outbound_session_id { + OutboundSessionId { value: 1 } => { + assert_eq!(peer_id, peer1.peer_id()); + assert_eq!(connection_id, *peer1.connection_ids().first().unwrap()) + } + OutboundSessionId { value: 2 } => { + assert_eq!(peer_id, peer2.peer_id()); + assert_eq!(connection_id, *peer2.connection_ids().first().unwrap()); + } + OutboundSessionId { value: 3 } => { + assert_eq!(peer_id, peer1.peer_id()); + assert_eq!(connection_id, *peer1.connection_ids().first().unwrap()); + } + _ => panic!("Unexpected outbound_session_id: {:?}", outbound_session_id), + } + } else { + match outbound_session_id { + OutboundSessionId { value: 1 } => { + assert_eq!(peer_id, peer2.peer_id()); + assert_eq!(connection_id, *peer2.connection_ids().first().unwrap()); + } + OutboundSessionId { value: 2 } => { + assert_eq!(peer_id, peer1.peer_id()); + assert_eq!(connection_id, *peer1.connection_ids().first().unwrap()); + } + OutboundSessionId { value: 3 } => { + assert_eq!(peer_id, peer2.peer_id()); + assert_eq!(connection_id, *peer2.connection_ids().first().unwrap()); + } + _ => panic!("Unexpected outbound_session_id: {:?}", outbound_session_id), + } + } + } +} + +#[tokio::test] +async fn peer_assignment_no_peers() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign a peer to the session + assert_matches!(peer_manager.assign_peer_to_session(outbound_session_id), None); + assert!(peer_manager.next().now_or_never().is_none()); + + // Now the peer manager finds a new peer and can assign the session. + let connection_id = ConnectionId::new_unchecked(0); + let (mut peer, peer_id) = + create_mock_peer(config.blacklist_timeout, false, Some(connection_id)); + peer.expect_is_blocked().times(1).return_const(false); + peer_manager.add_peer(peer); + assert_matches!( + peer_manager.next().await.unwrap(), + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id: event_outbound_session_id, + peer_id: event_peer_id, + connection_id: event_connection_id, + } + ) if outbound_session_id == event_outbound_session_id && + peer_id == event_peer_id && + connection_id == event_connection_id + ); + assert!(peer_manager.next().now_or_never().is_none()); +} + +#[tokio::test] +async fn peer_assignment_no_unblocked_peers() { + const BLOCKED_UNTIL: Duration = Duration::from_secs(5); + const TIMEOUT: Duration = Duration::from_secs(1); + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Create a peer + let connection_id = ConnectionId::new_unchecked(0); + let (mut peer, peer_id) = create_mock_peer(config.blacklist_timeout, true, Some(connection_id)); + peer.expect_is_blocked().times(1).return_const(true); + peer.expect_is_blocked().times(1).return_const(false); + peer.expect_blocked_until().times(1).returning(|| Instant::now() + BLOCKED_UNTIL); + + peer_manager.add_peer(peer); + peer_manager.report_peer(peer_id, ReputationModifier::Bad {}).unwrap(); + + // Try to assign a peer to the session, and check there wasn't any assignment. + assert_matches!(peer_manager.assign_peer_to_session(outbound_session_id), None); + assert!(peer_manager.next().now_or_never().is_none()); + + // Simulate that BLOCKED_UNTIL has passed. + tokio::time::pause(); + tokio::time::advance(BLOCKED_UNTIL).await; + tokio::time::resume(); + + // After BLOCKED_UNTIL has passed, the peer manager can assign the session. + let event = tokio::time::timeout(TIMEOUT, peer_manager.next()).await.unwrap().unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id: event_outbound_session_id, + peer_id: event_peer_id, + connection_id: event_connection_id, + } + ) if outbound_session_id == event_outbound_session_id && + peer_id == event_peer_id && + connection_id == event_connection_id + ); + assert!(peer_manager.next().now_or_never().is_none()); +} + +#[test] +fn report_peer_calls_update_reputation() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (peer, peer_id) = create_mock_peer(config.blacklist_timeout, true, None); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer); + + // Call the report_peer function on the peer manager + peer_manager.report_peer(peer_id, ReputationModifier::Bad {}).unwrap(); + peer_manager.get_mut_peer(peer_id).unwrap().checkpoint(); +} + +#[tokio::test] +async fn peer_block_realeased_after_timeout() { + const DURATION_IN_MILLIS: u64 = 50; + let mut peer = Peer::new(PeerId::random(), Multiaddr::empty()); + peer.set_timeout_duration(Duration::from_millis(DURATION_IN_MILLIS)); + peer.update_reputation(ReputationModifier::Bad {}); + assert!(peer.is_blocked()); + sleep(time::Duration::from_millis(DURATION_IN_MILLIS)).await; + assert!(!peer.is_blocked()); +} + +#[test] +fn report_peer_on_unknown_peer_id() { + // Create a new peer manager + let mut peer_manager: PeerManager = + PeerManager::new(PeerManagerConfig::default()); + + // report peer on an unknown peer_id + let peer_id = PeerId::random(); + peer_manager + .report_peer(peer_id, ReputationModifier::Bad {}) + .expect_err("report_peer on unknown peer_id should return an error"); +} + +#[test] +fn report_session_calls_update_reputation() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (mut peer, peer_id) = + create_mock_peer(config.blacklist_timeout, true, Some(ConnectionId::new_unchecked(0))); + peer.expect_is_blocked().times(1).return_const(false); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign peer to the session + let res_peer_id = peer_manager.assign_peer_to_session(outbound_session_id).unwrap(); + assert_eq!(res_peer_id, peer_id); + + // Call the report_peer function on the peer manager + peer_manager.report_session(outbound_session_id, ReputationModifier::Bad {}).unwrap(); + peer_manager.get_mut_peer(peer_id).unwrap().checkpoint(); +} + +#[test] +fn report_session_on_unknown_session_id() { + // Create a new peer manager + let mut peer_manager: PeerManager = + PeerManager::new(PeerManagerConfig::default()); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + peer_manager + .report_session(outbound_session_id, ReputationModifier::Bad {}) + .expect_err("report_session on unknown outbound_session_id should return an error"); +} + +#[test] +fn more_peers_needed() { + // Create a new peer manager + let config = PeerManagerConfig { target_num_for_peers: 2, ..Default::default() }; + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Add a peer to the peer manager + let (peer1, _peer_id1) = create_mock_peer(config.blacklist_timeout, false, None); + peer_manager.add_peer(peer1); + + // assert more peers are needed + assert!(peer_manager.more_peers_needed()); + + // Add another peer to the peer manager + let (peer2, _peer_id2) = create_mock_peer(config.blacklist_timeout, false, None); + peer_manager.add_peer(peer2); + + // assert no more peers are needed + assert!(!peer_manager.more_peers_needed()); +} + +#[tokio::test] +async fn timed_out_peer_not_assignable_to_queries() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (mut peer, peer_id) = create_mock_peer(config.blacklist_timeout, true, None); + peer.expect_is_blocked().times(1).return_const(true); + peer.expect_blocked_until().times(1).returning(|| Instant::now() + Duration::from_secs(1)); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer); + + // Report the peer as bad + peer_manager.report_peer(peer_id, ReputationModifier::Bad {}).unwrap(); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign peer to the session + assert_matches!(peer_manager.assign_peer_to_session(outbound_session_id), None); +} + +#[test] +fn wrap_around_in_peer_assignment() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (mut peer1, peer_id1) = + create_mock_peer(config.blacklist_timeout, true, Some(ConnectionId::new_unchecked(0))); + peer1.expect_is_blocked().times(..2).return_const(true); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer1); + + // Report the peer as bad + peer_manager.report_peer(peer_id1, ReputationModifier::Bad {}).unwrap(); + + // Create a mock peer + let (mut peer2, peer_id2) = + create_mock_peer(config.blacklist_timeout, false, Some(ConnectionId::new_unchecked(0))); + peer2.expect_is_blocked().times(2).return_const(false); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer2); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign peer to the session - since we don't know what is the order of the peers in the + // HashMap, we need to assign twice to make sure we wrap around + assert_matches!(peer_manager.assign_peer_to_session(outbound_session_id), Some(peer_id) if peer_id == peer_id2); + assert_matches!(peer_manager.assign_peer_to_session(outbound_session_id), Some(peer_id) if peer_id == peer_id2); +} + +fn create_mock_peer( + blacklist_timeout_duration: Duration, + call_update_reputaion: bool, + connection_id: Option, +) -> (MockPeerTrait, PeerId) { + let peer_id = PeerId::random(); + let mut peer = MockPeerTrait::default(); + let mut mockall_seq = mockall::Sequence::new(); + + peer.expect_peer_id().return_const(peer_id); + peer.expect_set_timeout_duration() + .times(1) + .with(eq(blacklist_timeout_duration)) + .return_const(()) + .in_sequence(&mut mockall_seq); + if call_update_reputaion { + peer.expect_update_reputation() + .times(1) + .with(eq(ReputationModifier::Bad {})) + .return_once(|_| ()) + .in_sequence(&mut mockall_seq); + } + peer.expect_connection_ids().return_const(connection_id.map(|x| vec![x]).unwrap_or_default()); + + (peer, peer_id) +} + +#[test] +fn block_and_allow_inbound_connection() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer - blocked + let (mut peer1, peer_id1) = create_mock_peer(config.blacklist_timeout, false, None); + peer1.expect_is_blocked().times(..2).return_const(true); + + // Create a mock peer - not blocked + let (mut peer2, peer_id2) = create_mock_peer(config.blacklist_timeout, false, None); + peer2.expect_is_blocked().times(..2).return_const(false); + + // Add the mock peers to the peer manager + peer_manager.add_peer(peer1); + peer_manager.add_peer(peer2); + + // call handle_established_inbound_connection with the blocked peer + let res = peer_manager.handle_established_inbound_connection( + libp2p::swarm::ConnectionId::new_unchecked(0), + peer_id1, + &Multiaddr::empty(), + &Multiaddr::empty(), + ); + // ConnectionHandler doesn't implement Debug so we have to assert the result like that. + assert!(res.is_err()); + + // call handle_established_inbound_connection with the blocked peer + let res = peer_manager.handle_established_inbound_connection( + libp2p::swarm::ConnectionId::new_unchecked(0), + peer_id2, + &Multiaddr::empty(), + &Multiaddr::empty(), + ); + // ConnectionHandler doesn't implement Debug so we have to assert the result like that. + assert!(res.is_ok()); +} + +#[test] +fn assign_non_connected_peer_raises_dial_event() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (mut peer, _) = create_mock_peer(config.blacklist_timeout, false, None); + peer.expect_is_blocked().times(1).return_const(false); + peer.expect_multiaddr().return_const(Multiaddr::empty()); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign peer to the session + let res_peer_id = peer_manager.assign_peer_to_session(outbound_session_id).unwrap(); + + // check events + for event in peer_manager.pending_events { + assert_matches!(event, ToSwarm::Dial {opts} if opts.get_peer_id() == Some(res_peer_id)); + } +} + +#[tokio::test] +async fn flow_test_assign_non_connected_peer() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Create a mock peer + let (mut peer, peer_id) = create_mock_peer(config.blacklist_timeout, false, None); + peer.expect_is_blocked().times(1).return_const(false); + peer.expect_multiaddr().return_const(Multiaddr::empty()); + peer.expect_add_connection_id().times(1).return_const(()); + + // Add the mock peer to the peer manager + peer_manager.add_peer(peer); + + // Create a session + let outbound_session_id = OutboundSessionId { value: 1 }; + + // Assign peer to the session + let res_peer_id = peer_manager.assign_peer_to_session(outbound_session_id).unwrap(); + assert_eq!(res_peer_id, peer_id); + + // Expect dial event + assert_matches!(poll_fn(|cx| peer_manager.poll(cx)).await, ToSwarm::Dial{opts} if opts.get_peer_id() == Some(peer_id)); + + // Send ConnectionEstablished event from swarm + peer_manager.on_swarm_event(libp2p::swarm::FromSwarm::ConnectionEstablished( + ConnectionEstablished { + peer_id, + connection_id: ConnectionId::new_unchecked(0), + endpoint: &libp2p::core::ConnectedPoint::Dialer { + address: Multiaddr::empty(), + role_override: libp2p::core::Endpoint::Dialer, + }, + failed_addresses: &[], + other_established: 0, + }, + )); + + // Expect SessionAssigned event + assert_matches!( + poll_fn(|cx| peer_manager.poll(cx)).await, + ToSwarm::GenerateEvent(ToOtherBehaviourEvent::SessionAssigned { .. }) + ); +} + +#[test] +fn identify_on_unknown_peer_is_added_to_peer_manager() { + // Create a new peer manager + let config = PeerManagerConfig::default(); + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Send Identify event + let peer_id = PeerId::random(); + let address = Multiaddr::empty().with_p2p(peer_id).unwrap(); + peer_manager.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::Identify( + IdentifyToOtherBehaviourEvent::FoundListenAddresses { + peer_id, + listen_addresses: vec![address.clone()], + }, + )); + + // Check that the peer is added to the peer manager + let res_peer_id = peer_manager.get_mut_peer(peer_id).unwrap(); + assert!(res_peer_id.peer_id() == peer_id); + assert!(res_peer_id.multiaddr() == address); +} + +#[test] +fn no_more_peers_needed_stops_discovery() { + // Create a new peer manager + let config = PeerManagerConfig { target_num_for_peers: 1, ..Default::default() }; + let mut peer_manager: PeerManager = PeerManager::new(config.clone()); + + // Send Identify event + let peer_id = PeerId::random(); + peer_manager.on_other_behaviour_event(&mixed_behaviour::ToOtherBehaviourEvent::Identify( + IdentifyToOtherBehaviourEvent::FoundListenAddresses { + peer_id, + listen_addresses: vec![Multiaddr::empty()], + }, + )); + + // Check that the peer is added to the peer manager + assert!(peer_manager.get_mut_peer(peer_id).is_some()); + + // Check that the discovery pause event emitted + for event in peer_manager.pending_events { + if let ToSwarm::GenerateEvent(ToOtherBehaviourEvent::PauseDiscovery) = event { + return; + } + } + panic!("Discovery pause event not emitted"); +} diff --git a/crates/papyrus_network/src/sqmr/behaviour.rs b/crates/papyrus_network/src/sqmr/behaviour.rs new file mode 100644 index 00000000000..0c646dfaad7 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/behaviour.rs @@ -0,0 +1,431 @@ +#[cfg(test)] +#[path = "behaviour_test.rs"] +mod behaviour_test; + +use std::collections::{HashMap, HashSet, VecDeque}; +use std::io; +use std::sync::atomic::AtomicUsize; +use std::sync::Arc; +use std::task::{Context, Poll, Waker}; +use std::time::Duration; + +use defaultmap::DefaultHashMap; +use libp2p::core::Endpoint; +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::{ + ConnectionClosed, + ConnectionDenied, + ConnectionHandler, + ConnectionId, + FromSwarm, + NetworkBehaviour, + NotifyHandler, + ToSwarm, +}; +use libp2p::{Multiaddr, PeerId, StreamProtocol}; +use tracing::{error, info}; + +use super::handler::{ + Handler, + RequestFromBehaviourEvent, + RequestToBehaviourEvent, + SessionError as HandlerSessionError, +}; +use super::{Bytes, Config, GenericEvent, InboundSessionId, OutboundSessionId, SessionId}; +use crate::mixed_behaviour::{self, BridgedBehaviour}; +use crate::peer_manager; + +#[derive(thiserror::Error, Debug)] +pub enum SessionError { + #[error("Connection timed out after {} seconds.", session_timeout.as_secs())] + Timeout { session_timeout: Duration }, + #[error(transparent)] + IOError(#[from] io::Error), + #[error("Remote peer doesn't support the given protocol.")] + RemoteDoesntSupportProtocol, + // If there's a connection with a single session and it was closed because of another reason, + // we might get ConnectionClosed instead of that reason because the swarm automatically closes + // a connection that has no sessions. If this is a problem, set the swarm's + // idle_connection_timeout to a non-zero number. + #[error("Connection to remote peer closed.")] + ConnectionClosed, +} + +impl From> for GenericEvent { + fn from(event: GenericEvent) -> Self { + match event { + GenericEvent::NewInboundSession { + query, + inbound_session_id, + peer_id, + protocol_name, + } => Self::NewInboundSession { query, inbound_session_id, peer_id, protocol_name }, + GenericEvent::ReceivedResponse { outbound_session_id, response, peer_id } => { + Self::ReceivedResponse { outbound_session_id, response, peer_id } + } + GenericEvent::SessionFailed { + session_id, + error: HandlerSessionError::Timeout { session_timeout }, + } => { + Self::SessionFailed { session_id, error: SessionError::Timeout { session_timeout } } + } + GenericEvent::SessionFailed { + session_id, + error: HandlerSessionError::IOError(error), + } => Self::SessionFailed { session_id, error: SessionError::IOError(error) }, + GenericEvent::SessionFailed { + session_id, + error: HandlerSessionError::RemoteDoesntSupportProtocol, + } => { + Self::SessionFailed { session_id, error: SessionError::RemoteDoesntSupportProtocol } + } + GenericEvent::SessionFinishedSuccessfully { session_id } => { + Self::SessionFinishedSuccessfully { session_id } + } + } + } +} + +pub type ExternalEvent = GenericEvent; + +#[derive(Debug)] +pub enum ToOtherBehaviourEvent { + RequestPeerAssignment { outbound_session_id: OutboundSessionId }, +} + +#[derive(Debug)] +pub enum Event { + External(ExternalEvent), + ToOtherBehaviourEvent(ToOtherBehaviourEvent), +} + +#[derive(thiserror::Error, Debug)] +#[error("The given session ID doesn't exist.")] +pub struct SessionIdNotFoundError; + +#[derive(thiserror::Error, Debug)] +#[error("We are not connected to the given peer. Dial to the given peer and try again.")] +pub struct PeerNotConnected; + +pub struct Behaviour { + config: Config, + pending_events: VecDeque>, + // TODO(shahak) Remove this once we remove send_query. + connection_ids_map: DefaultHashMap>, + session_id_to_peer_id_and_connection_id: HashMap, + next_outbound_session_id: OutboundSessionId, + next_inbound_session_id: Arc, + dropped_sessions: HashSet, + wakers_waiting_for_event: Vec, + outbound_sessions_pending_peer_assignment: HashMap, + supported_inbound_protocols: HashSet, +} + +impl Behaviour { + pub fn new(config: Config) -> Self { + Self { + config, + pending_events: Default::default(), + connection_ids_map: Default::default(), + session_id_to_peer_id_and_connection_id: Default::default(), + next_outbound_session_id: Default::default(), + next_inbound_session_id: Arc::new(Default::default()), + dropped_sessions: Default::default(), + wakers_waiting_for_event: Default::default(), + outbound_sessions_pending_peer_assignment: Default::default(), + supported_inbound_protocols: Default::default(), + } + } + + /// Send query to the given peer and start a new outbound session with it. Return the id of the + /// new session. + // TODO(shahak) Remove this function once Network manager uses start_query. + pub fn send_query( + &mut self, + query: Bytes, + peer_id: PeerId, + protocol_name: StreamProtocol, + ) -> Result { + let connection_id = + *self.connection_ids_map.get(peer_id).iter().next().ok_or(PeerNotConnected)?; + + let outbound_session_id = self.next_outbound_session_id; + self.next_outbound_session_id.value += 1; + + self.session_id_to_peer_id_and_connection_id + .insert(outbound_session_id.into(), (peer_id, connection_id)); + + self.add_event_to_queue(ToSwarm::NotifyHandler { + peer_id, + handler: NotifyHandler::One(connection_id), + event: RequestFromBehaviourEvent::CreateOutboundSession { + query, + outbound_session_id, + protocol_name, + }, + }); + + Ok(outbound_session_id) + } + + /// Assign some peer and start a query. Return the id of the new session. + pub fn start_query( + &mut self, + query: Bytes, + protocol_name: StreamProtocol, + ) -> OutboundSessionId { + let outbound_session_id = self.next_outbound_session_id; + self.next_outbound_session_id.value += 1; + + self.outbound_sessions_pending_peer_assignment + .insert(outbound_session_id, (query, protocol_name)); + info!("Requesting peer assignment for outbound session: {:?}.", outbound_session_id); + self.add_event_to_queue(ToSwarm::GenerateEvent(Event::ToOtherBehaviourEvent( + ToOtherBehaviourEvent::RequestPeerAssignment { outbound_session_id }, + ))); + + outbound_session_id + } + + /// Send a response message to an open inbound session. + pub fn send_response( + &mut self, + response: Bytes, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + let (peer_id, connection_id) = + self.get_peer_id_and_connection_id_from_session_id(inbound_session_id.into())?; + self.add_event_to_queue(ToSwarm::NotifyHandler { + peer_id, + handler: NotifyHandler::One(connection_id), + event: RequestFromBehaviourEvent::SendResponse { response, inbound_session_id }, + }); + Ok(()) + } + + /// Instruct behaviour to close session. A corresponding SessionFinishedSuccessfully event will + /// be reported when the session is closed. + pub fn close_inbound_session( + &mut self, + inbound_session_id: InboundSessionId, + ) -> Result<(), SessionIdNotFoundError> { + let (peer_id, connection_id) = + self.get_peer_id_and_connection_id_from_session_id(inbound_session_id.into())?; + self.add_event_to_queue(ToSwarm::NotifyHandler { + peer_id, + handler: NotifyHandler::One(connection_id), + event: RequestFromBehaviourEvent::CloseInboundSession { inbound_session_id }, + }); + Ok(()) + } + + /// Instruct behaviour to drop outbound session. The session won't emit any events once dropped. + /// The other peer will receive an IOError on their corresponding inbound session. + pub fn drop_session(&mut self, session_id: SessionId) -> Result<(), SessionIdNotFoundError> { + let (peer_id, connection_id) = + self.get_peer_id_and_connection_id_from_session_id(session_id)?; + if self.dropped_sessions.insert(session_id) { + self.add_event_to_queue(ToSwarm::NotifyHandler { + peer_id, + handler: NotifyHandler::One(connection_id), + event: RequestFromBehaviourEvent::DropSession { session_id }, + }); + } + Ok(()) + } + + pub(crate) fn get_peer_id_and_connection_id_from_session_id( + &self, + session_id: SessionId, + ) -> Result<(PeerId, ConnectionId), SessionIdNotFoundError> { + self.session_id_to_peer_id_and_connection_id + .get(&session_id) + .copied() + .ok_or(SessionIdNotFoundError) + } + + fn add_event_to_queue(&mut self, event: ToSwarm) { + self.pending_events.push_back(event); + for waker in self.wakers_waiting_for_event.drain(..) { + waker.wake(); + } + } + pub fn add_new_supported_inbound_protocol(&mut self, protocol: StreamProtocol) { + if !self.supported_inbound_protocols.contains(&protocol) { + self.supported_inbound_protocols.insert(protocol); + } + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = Handler; + type ToSwarm = Event; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: ConnectionId, + peer_id: PeerId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result { + Ok(Handler::new( + self.config.clone(), + self.next_inbound_session_id.clone(), + peer_id, + self.supported_inbound_protocols.clone(), + )) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: ConnectionId, + peer_id: PeerId, + _addr: &Multiaddr, + _role_override: Endpoint, + ) -> Result { + Ok(Handler::new( + self.config.clone(), + self.next_inbound_session_id.clone(), + peer_id, + self.supported_inbound_protocols.clone(), + )) + } + + fn on_swarm_event(&mut self, event: FromSwarm<'_>) { + match event { + FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + connection_id, + .. + }) => { + self.connection_ids_map.get_mut(peer_id).insert(connection_id); + } + FromSwarm::ConnectionClosed(ConnectionClosed { peer_id, connection_id, .. }) => { + let mut session_ids = Vec::new(); + self.session_id_to_peer_id_and_connection_id.retain( + |session_id, (session_peer_id, session_connection_id)| { + if peer_id == *session_peer_id && connection_id == *session_connection_id { + session_ids.push(*session_id); + false + } else { + true + } + }, + ); + for session_id in session_ids { + self.add_event_to_queue(ToSwarm::GenerateEvent(Event::External( + ExternalEvent::SessionFailed { + session_id, + error: SessionError::ConnectionClosed, + }, + ))); + } + } + _ => {} + } + } + + fn on_connection_handler_event( + &mut self, + peer_id: PeerId, + connection_id: ConnectionId, + event: ::ToBehaviour, + ) { + match event { + RequestToBehaviourEvent::GenerateEvent(event) => { + let converted_event = event.into(); + let mut is_event_muted = false; + match converted_event { + ExternalEvent::NewInboundSession { inbound_session_id, .. } => { + self.session_id_to_peer_id_and_connection_id + .insert(inbound_session_id.into(), (peer_id, connection_id)); + } + ExternalEvent::SessionFailed { session_id, .. } + | ExternalEvent::SessionFinishedSuccessfully { session_id, .. } => { + self.session_id_to_peer_id_and_connection_id.remove(&session_id); + let is_dropped = self.dropped_sessions.remove(&session_id); + if is_dropped { + is_event_muted = true; + } + } + ExternalEvent::ReceivedResponse { outbound_session_id, .. } => { + if self.dropped_sessions.contains(&outbound_session_id.into()) { + is_event_muted = true; + } + } + } + if !is_event_muted { + self.add_event_to_queue(ToSwarm::GenerateEvent(Event::External( + converted_event, + ))); + } + } + RequestToBehaviourEvent::NotifySessionDropped { session_id } => { + self.dropped_sessions.remove(&session_id); + } + } + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll::FromBehaviour>> + { + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(event); + } + self.wakers_waiting_for_event.push(cx.waker().clone()); + Poll::Pending + } +} + +impl BridgedBehaviour for Behaviour { + fn on_other_behaviour_event(&mut self, event: &mixed_behaviour::ToOtherBehaviourEvent) { + let mixed_behaviour::ToOtherBehaviourEvent::PeerManager( + peer_manager::ToOtherBehaviourEvent::SessionAssigned { + outbound_session_id, + peer_id, + connection_id, + }, + ) = event + else { + return; + }; + info!("Assigned {outbound_session_id:?} to {peer_id:?}"); + self.session_id_to_peer_id_and_connection_id + .insert((*outbound_session_id).into(), (*peer_id, *connection_id)); + + let Some((query, protocol_name)) = + self.outbound_sessions_pending_peer_assignment.remove(outbound_session_id) + else { + error!( + "Outbound session assigned peer but it isn't in \ + outbound_sessions_pending_peer_assignment. Not running query." + ); + return; + }; + + self.add_event_to_queue(ToSwarm::NotifyHandler { + peer_id: *peer_id, + handler: NotifyHandler::One(*connection_id), + event: RequestFromBehaviourEvent::CreateOutboundSession { + query, + outbound_session_id: *outbound_session_id, + protocol_name, + }, + }); + } +} + +impl From for mixed_behaviour::Event { + fn from(event: Event) -> Self { + match event { + Event::External(external_event) => { + Self::ExternalEvent(mixed_behaviour::ExternalEvent::Sqmr(external_event)) + } + Event::ToOtherBehaviourEvent(event) => { + Self::ToOtherBehaviourEvent(mixed_behaviour::ToOtherBehaviourEvent::Sqmr(event)) + } + } + } +} diff --git a/crates/papyrus_network/src/sqmr/behaviour_test.rs b/crates/papyrus_network/src/sqmr/behaviour_test.rs new file mode 100644 index 00000000000..9bc73cfa499 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/behaviour_test.rs @@ -0,0 +1,477 @@ +// TODO(shahak): Use start_query in all tests instead of send_query + +use std::pin::Pin; +use std::task::{Context, Poll}; + +use assert_matches::assert_matches; +use futures::{FutureExt, Stream, StreamExt}; +use lazy_static::lazy_static; +use libp2p::core::{ConnectedPoint, Endpoint}; +use libp2p::swarm::behaviour::ConnectionEstablished; +use libp2p::swarm::{ConnectionClosed, ConnectionId, FromSwarm, NetworkBehaviour, ToSwarm}; +use libp2p::{Multiaddr, PeerId, StreamProtocol}; + +use super::super::handler::{RequestFromBehaviourEvent, RequestToBehaviourEvent}; +use super::super::{Bytes, Config, GenericEvent, InboundSessionId, OutboundSessionId, SessionId}; +use super::{Behaviour, Event, ExternalEvent, SessionError}; +use crate::test_utils::dummy_data; + +impl Unpin for Behaviour {} + +impl Stream for Behaviour { + type Item = ToSwarm; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match Pin::into_inner(self).poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(Some(event)), + } + } +} + +lazy_static! { + static ref QUERY: Bytes = vec![1u8, 2u8, 3u8]; + static ref PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/"); +} + +fn simulate_connection_established(behaviour: &mut Behaviour, peer_id: PeerId) { + let connection_id = ConnectionId::new_unchecked(0); + let address = Multiaddr::empty(); + let role_override = Endpoint::Dialer; + let _handler = behaviour + .handle_established_outbound_connection(connection_id, peer_id, &address, role_override) + .unwrap(); + behaviour.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + connection_id, + endpoint: &ConnectedPoint::Dialer { address, role_override }, + failed_addresses: &[], + other_established: 0, + })); +} + +fn simulate_listener_connection(behaviour: &mut Behaviour, peer_id: PeerId) { + let connection_id = ConnectionId::new_unchecked(0); + let address = Multiaddr::empty(); + let local_addr = Multiaddr::empty(); + let role_override = Endpoint::Listener; + let _handler = behaviour + .handle_established_outbound_connection(connection_id, peer_id, &address, role_override) + .unwrap(); + behaviour.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + connection_id, + endpoint: &ConnectedPoint::Listener { send_back_addr: address, local_addr }, + failed_addresses: &[], + other_established: 0, + })); +} + +fn simulate_new_inbound_session( + behaviour: &mut Behaviour, + peer_id: PeerId, + inbound_session_id: InboundSessionId, + query: Bytes, +) { + behaviour.on_connection_handler_event( + peer_id, + ConnectionId::new_unchecked(0), + RequestToBehaviourEvent::GenerateEvent(GenericEvent::NewInboundSession { + query, + inbound_session_id, + peer_id, + protocol_name: PROTOCOL_NAME.clone(), + }), + ); +} + +fn simulate_received_response( + behaviour: &mut Behaviour, + peer_id: PeerId, + response: Bytes, + outbound_session_id: OutboundSessionId, +) { + behaviour.on_connection_handler_event( + peer_id, + ConnectionId::new_unchecked(0), + RequestToBehaviourEvent::GenerateEvent(GenericEvent::ReceivedResponse { + response, + outbound_session_id, + peer_id, + }), + ); +} + +fn simulate_session_finished_successfully( + behaviour: &mut Behaviour, + peer_id: PeerId, + session_id: SessionId, +) { + behaviour.on_connection_handler_event( + peer_id, + ConnectionId::new_unchecked(0), + RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFinishedSuccessfully { + session_id, + }), + ); +} + +fn simulate_connection_closed(behaviour: &mut Behaviour, peer_id: PeerId) { + // This is the same connection_id from simulate_connection_established + let connection_id = ConnectionId::new_unchecked(0); + behaviour.on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + connection_id, + // Filling these fields with arbitrary values since the behaviour doesn't look at these + // fields. + endpoint: &ConnectedPoint::Dialer { + address: Multiaddr::empty(), + role_override: Endpoint::Dialer, + }, + remaining_established: 0, + })) +} + +fn simulate_session_dropped(behaviour: &mut Behaviour, peer_id: PeerId, session_id: SessionId) { + behaviour.on_connection_handler_event( + peer_id, + ConnectionId::new_unchecked(0), + RequestToBehaviourEvent::NotifySessionDropped { session_id }, + ); +} + +async fn validate_create_outbound_session_event( + behaviour: &mut Behaviour, + peer_id: &PeerId, + query: &Bytes, + outbound_session_id: &OutboundSessionId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::NotifyHandler { + peer_id: event_peer_id, + event: RequestFromBehaviourEvent::CreateOutboundSession { query: event_query, outbound_session_id: event_outbound_session_id, protocol_name }, + .. + } if *peer_id == event_peer_id + && *outbound_session_id == event_outbound_session_id + && *query == event_query + && protocol_name == PROTOCOL_NAME.clone() + ); +} + +async fn validate_new_inbound_session_event( + behaviour: &mut Behaviour, + peer_id: &PeerId, + inbound_session_id: InboundSessionId, + query: &Bytes, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(Event::External(ExternalEvent::NewInboundSession { + query: event_query, + inbound_session_id: event_inbound_session_id, + peer_id: event_peer_id, + protocol_name, + })) if event_query == *query + && event_inbound_session_id == inbound_session_id + && event_peer_id == *peer_id + && protocol_name == PROTOCOL_NAME.clone() + ); +} + +async fn validate_received_response_event( + behaviour: &mut Behaviour, + response: &Bytes, + outbound_session_id: OutboundSessionId, + peer_id: PeerId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(Event::External(ExternalEvent::ReceivedResponse { + response: event_response, outbound_session_id: event_outbound_session_id, + peer_id: event_peer_id, + })) if event_response == *response && event_outbound_session_id == outbound_session_id && peer_id == event_peer_id + ); +} + +async fn validate_request_send_response_event( + behaviour: &mut Behaviour, + peer_id: &PeerId, + response: &Bytes, + inbound_session_id: InboundSessionId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::NotifyHandler { + peer_id: event_peer_id, + event: RequestFromBehaviourEvent::SendResponse { + inbound_session_id: event_inbound_session_id, response: event_response + }, + .. + } if *peer_id == event_peer_id + && inbound_session_id == event_inbound_session_id + && *response == event_response + ); +} + +async fn validate_request_close_inbound_session_event( + behaviour: &mut Behaviour, + peer_id: &PeerId, + inbound_session_id: InboundSessionId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::NotifyHandler { + peer_id: event_peer_id, + event: RequestFromBehaviourEvent::CloseInboundSession { + inbound_session_id: event_inbound_session_id + }, + .. + } if *peer_id == event_peer_id + && inbound_session_id == event_inbound_session_id + ); +} + +async fn validate_request_drop_session_event( + behaviour: &mut Behaviour, + peer_id: &PeerId, + session_id: SessionId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::NotifyHandler { + peer_id: event_peer_id, + event: RequestFromBehaviourEvent::DropSession { + session_id: event_session_id + }, + .. + } if *peer_id == event_peer_id && session_id == event_session_id + ); +} + +async fn validate_session_finished_successfully_event( + behaviour: &mut Behaviour, + session_id: SessionId, +) { + let event = behaviour.next().await.unwrap(); + assert_matches!( + event, + ToSwarm::GenerateEvent(Event::External(ExternalEvent::SessionFinishedSuccessfully { + session_id: event_session_id + })) if event_session_id == session_id + ); +} + +// TODO(shahak): Fix code duplication with handler test. +fn validate_no_events(behaviour: &mut Behaviour) { + assert!(behaviour.next().now_or_never().is_none()); +} + +#[tokio::test] +async fn process_inbound_session() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + let inbound_session_id = InboundSessionId::default(); + + simulate_listener_connection(&mut behaviour, peer_id); + + simulate_new_inbound_session(&mut behaviour, peer_id, inbound_session_id, QUERY.clone()); + validate_new_inbound_session_event(&mut behaviour, &peer_id, inbound_session_id, &QUERY).await; + validate_no_events(&mut behaviour); + + let dummy_data_vec = dummy_data(); + for response in &dummy_data_vec { + behaviour.send_response(response.clone(), inbound_session_id).unwrap(); + } + + for response in &dummy_data_vec { + validate_request_send_response_event( + &mut behaviour, + &peer_id, + response, + inbound_session_id, + ) + .await; + } + validate_no_events(&mut behaviour); + + behaviour.close_inbound_session(inbound_session_id).unwrap(); + validate_request_close_inbound_session_event(&mut behaviour, &peer_id, inbound_session_id) + .await; + validate_no_events(&mut behaviour); + + let session_id = inbound_session_id.into(); + simulate_session_finished_successfully(&mut behaviour, peer_id, session_id); + validate_session_finished_successfully_event(&mut behaviour, session_id).await; + validate_no_events(&mut behaviour); +} + +#[tokio::test] +async fn create_and_process_outbound_session() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + + simulate_connection_established(&mut behaviour, peer_id); + let outbound_session_id = + behaviour.send_query(QUERY.clone(), peer_id, PROTOCOL_NAME.clone()).unwrap(); + + validate_create_outbound_session_event(&mut behaviour, &peer_id, &QUERY, &outbound_session_id) + .await; + validate_no_events(&mut behaviour); + + let dummy_data_vec = dummy_data(); + for response in &dummy_data_vec { + simulate_received_response(&mut behaviour, peer_id, response.clone(), outbound_session_id); + } + + for response in &dummy_data_vec { + validate_received_response_event(&mut behaviour, response, outbound_session_id, peer_id) + .await; + } + validate_no_events(&mut behaviour); + + let session_id = outbound_session_id.into(); + simulate_session_finished_successfully(&mut behaviour, peer_id, session_id); + validate_session_finished_successfully_event(&mut behaviour, session_id).await; + validate_no_events(&mut behaviour); +} + +// TODO(shahak): Test the other variants of SessionError. +#[tokio::test] +async fn connection_closed() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + + simulate_connection_established(&mut behaviour, peer_id); + + let outbound_session_id = + behaviour.send_query(QUERY.clone(), peer_id, PROTOCOL_NAME.clone()).unwrap(); + + // Consume the event to create an outbound session. + behaviour.next().await.unwrap(); + + let inbound_session_id = InboundSessionId::default(); + simulate_new_inbound_session(&mut behaviour, peer_id, inbound_session_id, QUERY.clone()); + + // Consume the event to notify the user about the new inbound session. + behaviour.next().await.unwrap(); + + simulate_connection_closed(&mut behaviour, peer_id); + + let event1 = behaviour.next().await.unwrap(); + let event2 = behaviour.next().await.unwrap(); + let failed_session_ids = [event1, event2] + .iter() + .map(|event| { + let ToSwarm::GenerateEvent(Event::External(ExternalEvent::SessionFailed { + error: SessionError::ConnectionClosed, + session_id, + })) = event + else { + panic!( + "Event {:?} doesn't match expected event \ + ToSwarm::GenerateEvent(Event::External(ExternalEvent::SessionFailed {{ \ + error: SessionError::ConnectionClosed }}))", + event + ); + }; + *session_id + }) + .collect::>(); + assert!( + failed_session_ids == vec![inbound_session_id.into(), outbound_session_id.into()] + || failed_session_ids == vec![outbound_session_id.into(), inbound_session_id.into()] + ); +} + +#[tokio::test] +async fn drop_outbound_session() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + + simulate_connection_established(&mut behaviour, peer_id); + + let outbound_session_id = + behaviour.send_query(QUERY.clone(), peer_id, PROTOCOL_NAME.clone()).unwrap(); + + // Consume the event to create an outbound session. + behaviour.next().await.unwrap(); + + behaviour.drop_session(outbound_session_id.into()).unwrap(); + validate_request_drop_session_event(&mut behaviour, &peer_id, outbound_session_id.into()).await; + + for response in dummy_data() { + simulate_received_response(&mut behaviour, peer_id, response, outbound_session_id); + } + + validate_no_events(&mut behaviour); + + simulate_session_finished_successfully(&mut behaviour, peer_id, outbound_session_id.into()); + + validate_no_events(&mut behaviour); + + simulate_session_dropped(&mut behaviour, peer_id, outbound_session_id.into()); + + // After this event the handler should not send any events to the behaviour about this session, + // so if it will the behaviour might output them. +} + +#[tokio::test] +async fn drop_inbound_session() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + let inbound_session_id = InboundSessionId::default(); + + simulate_listener_connection(&mut behaviour, peer_id); + + simulate_new_inbound_session(&mut behaviour, peer_id, inbound_session_id, QUERY.clone()); + + // Consume the event that a new inbound session was created. + behaviour.next().await.unwrap(); + + behaviour.drop_session(inbound_session_id.into()).unwrap(); + validate_request_drop_session_event(&mut behaviour, &peer_id, inbound_session_id.into()).await; + + simulate_session_finished_successfully(&mut behaviour, peer_id, inbound_session_id.into()); + + validate_no_events(&mut behaviour); + + simulate_session_dropped(&mut behaviour, peer_id, inbound_session_id.into()); + + // After this event the handler should not send any events to the behaviour about this session, + // so if it will the behaviour might output them. +} + +#[test] +fn close_non_existing_session_fails() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + behaviour.close_inbound_session(InboundSessionId::default()).unwrap_err(); +} + +#[test] +fn send_response_non_existing_session_fails() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + for response in dummy_data() { + behaviour.send_response(response, InboundSessionId::default()).unwrap_err(); + } +} + +#[test] +fn send_query_peer_not_connected_fails() { + let mut behaviour = Behaviour::new(Config::get_test_config()); + + let peer_id = PeerId::random(); + + behaviour.send_query(QUERY.clone(), peer_id, PROTOCOL_NAME.clone()).unwrap_err(); +} diff --git a/crates/papyrus_network/src/sqmr/flow_test.rs b/crates/papyrus_network/src/sqmr/flow_test.rs new file mode 100644 index 00000000000..820ab8cfe67 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/flow_test.rs @@ -0,0 +1,262 @@ +use std::collections::hash_map::DefaultHasher; +use std::collections::HashMap; +use std::hash::{Hash, Hasher}; +use std::time::Duration; + +use defaultmap::DefaultHashMap; +use futures::StreamExt; +use libp2p::swarm::{NetworkBehaviour, SwarmEvent}; +use libp2p::{PeerId, StreamProtocol, Swarm}; + +use super::behaviour::{Behaviour, Event, ExternalEvent}; +use super::{Bytes, Config, InboundSessionId, OutboundSessionId, SessionId}; +use crate::test_utils::create_fully_connected_swarms_stream; +use crate::utils::StreamHashMap; + +const NUM_PEERS: usize = 3; +const NUM_MESSAGES_PER_SESSION: usize = 5; + +pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/example"); +pub const OTHER_PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/other"); + +type SwarmEventAlias = SwarmEvent<::ToSwarm>; + +async fn collect_events_from_swarms( + swarms_stream: &mut StreamHashMap>, + mut map_and_filter_event: impl FnMut(PeerId, SwarmEventAlias) -> Option<(PeerId, T)>, + assert_unique: bool, +) -> HashMap<(PeerId, PeerId), T> { + let mut results = HashMap::<(PeerId, PeerId), T>::new(); + loop { + // Swarms should never finish, so we can unwrap the option. + let (peer_id, event) = swarms_stream.next().await.unwrap(); + if let Some((other_peer_id, value)) = map_and_filter_event(peer_id, event) { + let is_unique = results.insert((peer_id, other_peer_id), value).is_none(); + if assert_unique { + assert!(is_unique); + } + if results.len() == (NUM_PEERS - 1) * NUM_PEERS { + break; + } + } + } + results +} + +fn perform_action_on_swarms( + swarms_stream: &mut StreamHashMap>, + peer_ids: &[PeerId], + action: &mut dyn FnMut(&mut Swarm, PeerId), +) { + for swarm in swarms_stream.values_mut() { + let peer_id = *swarm.local_peer_id(); + for other_peer_id in peer_ids.iter().cloned() { + if peer_id == other_peer_id { + continue; + } + action(swarm, other_peer_id); + } + } +} + +fn send_query_and_update_map( + outbound_swarm: &mut Swarm, + inbound_peer_id: PeerId, + outbound_session_id_to_peer_id: &mut HashMap<(PeerId, OutboundSessionId), PeerId>, +) { + let outbound_peer_id = *outbound_swarm.local_peer_id(); + let outbound_session_id = outbound_swarm + .behaviour_mut() + .send_query( + get_bytes_from_query_indices(outbound_peer_id, inbound_peer_id), + inbound_peer_id, + PROTOCOL_NAME, + ) + .unwrap(); + outbound_session_id_to_peer_id.insert((outbound_peer_id, outbound_session_id), inbound_peer_id); +} + +fn send_response( + inbound_swarm: &mut Swarm, + outbound_peer_id: PeerId, + inbound_session_ids: &HashMap<(PeerId, PeerId), InboundSessionId>, +) { + let inbound_peer_id = *inbound_swarm.local_peer_id(); + for i in 0..NUM_MESSAGES_PER_SESSION { + inbound_swarm + .behaviour_mut() + .send_response( + get_response_from_indices(inbound_peer_id, outbound_peer_id, i), + inbound_session_ids[&(inbound_peer_id, outbound_peer_id)], + ) + .unwrap(); + } +} + +fn close_inbound_session( + inbound_swarm: &mut Swarm, + outbound_peer_id: PeerId, + inbound_session_ids: &HashMap<(PeerId, PeerId), InboundSessionId>, +) { + let inbound_peer_id = *inbound_swarm.local_peer_id(); + inbound_swarm + .behaviour_mut() + .close_inbound_session(inbound_session_ids[&(inbound_peer_id, outbound_peer_id)]) + .unwrap(); +} + +fn check_new_inbound_session_event_and_return_id( + inbound_peer_id: PeerId, + swarm_event: SwarmEventAlias, +) -> Option<(PeerId, InboundSessionId)> { + let SwarmEvent::Behaviour(event) = swarm_event else { + return None; + }; + let Event::External(ExternalEvent::NewInboundSession { + query, + inbound_session_id, + peer_id: outbound_peer_id, + protocol_name, + }) = event + else { + panic!("Got unexpected event {:?} when expecting NewInboundSession", event); + }; + assert_eq!(query, get_bytes_from_query_indices(outbound_peer_id, inbound_peer_id)); + assert_eq!(protocol_name, PROTOCOL_NAME); + Some((outbound_peer_id, inbound_session_id)) +} + +fn check_received_response_event( + outbound_peer_id: PeerId, + swarm_event: SwarmEventAlias, + current_message: &mut DefaultHashMap<(PeerId, PeerId), usize>, + outbound_session_id_to_peer_id: &HashMap<(PeerId, OutboundSessionId), PeerId>, +) -> Option<(PeerId, ())> { + let SwarmEvent::Behaviour(event) = swarm_event else { + return None; + }; + let Event::External(ExternalEvent::ReceivedResponse { + outbound_session_id: _outbound_session_id, + response, + peer_id: inbound_peer_id, + }) = event + else { + panic!("Got unexpected event {:?} when expecting ReceivedResponse", event); + }; + assert_eq!( + outbound_session_id_to_peer_id[&(outbound_peer_id, _outbound_session_id)], + inbound_peer_id + ); + let message_index = *current_message.get((outbound_peer_id, inbound_peer_id)); + assert_eq!( + response, + get_response_from_indices(inbound_peer_id, outbound_peer_id, message_index), + ); + current_message.insert((outbound_peer_id, inbound_peer_id), message_index + 1); + Some((inbound_peer_id, ())) +} + +fn check_outbound_session_finished_event( + peer_id: PeerId, + swarm_event: SwarmEventAlias, + outbound_session_id_to_peer_id: &HashMap<(PeerId, OutboundSessionId), PeerId>, +) -> Option<(PeerId, ())> { + let SwarmEvent::Behaviour(Event::External(ExternalEvent::SessionFinishedSuccessfully { + session_id: SessionId::OutboundSessionId(outbound_session_id), + .. + })) = swarm_event + else { + return None; + }; + Some((outbound_session_id_to_peer_id[&(peer_id, outbound_session_id)], ())) +} + +fn get_bytes_from_query_indices(peer_id1: PeerId, peer_id2: PeerId) -> Bytes { + let mut hasher = DefaultHasher::new(); + peer_id1.hash(&mut hasher); + peer_id2.hash(&mut hasher); + hasher.finish().to_be_bytes().to_vec() +} + +fn get_response_from_indices(peer_id1: PeerId, peer_id2: PeerId, message_index: usize) -> Bytes { + let mut hasher = DefaultHasher::new(); + peer_id1.hash(&mut hasher); + peer_id2.hash(&mut hasher); + message_index.hash(&mut hasher); + hasher.finish().to_be_bytes().to_vec() +} + +#[tokio::test] +async fn everyone_sends_to_everyone() { + let mut swarms_stream = create_fully_connected_swarms_stream(NUM_PEERS, || { + let mut behaviour = Behaviour::new(Config { session_timeout: Duration::from_secs(5) }); + let supported_inbound_protocols = vec![PROTOCOL_NAME, OTHER_PROTOCOL_NAME]; + for protocol in supported_inbound_protocols { + behaviour.add_new_supported_inbound_protocol(protocol); + } + behaviour + }) + .await; + + let peer_ids = swarms_stream.keys().copied().collect::>(); + + let mut outbound_session_id_to_peer_id = HashMap::<(PeerId, OutboundSessionId), PeerId>::new(); + perform_action_on_swarms( + &mut swarms_stream, + &peer_ids, + &mut |outbound_swarm, inbound_peer_id| { + send_query_and_update_map( + outbound_swarm, + inbound_peer_id, + &mut outbound_session_id_to_peer_id, + ) + }, + ); + + let inbound_session_ids = collect_events_from_swarms( + &mut swarms_stream, + check_new_inbound_session_event_and_return_id, + true, + ) + .await; + + perform_action_on_swarms( + &mut swarms_stream, + &peer_ids, + &mut |inbound_swarm, outbound_peer_id| { + send_response(inbound_swarm, outbound_peer_id, &inbound_session_ids); + }, + ); + + let mut current_message = DefaultHashMap::<(PeerId, PeerId), usize>::new(0); + collect_events_from_swarms( + &mut swarms_stream, + |peer_id, event| { + check_received_response_event( + peer_id, + event, + &mut current_message, + &outbound_session_id_to_peer_id, + ) + }, + false, + ) + .await; + + perform_action_on_swarms( + &mut swarms_stream, + &peer_ids, + &mut |outbound_swarm, inbound_peer_id| { + close_inbound_session(outbound_swarm, inbound_peer_id, &inbound_session_ids) + }, + ); + + collect_events_from_swarms( + &mut swarms_stream, + |peer_id, event| { + check_outbound_session_finished_event(peer_id, event, &outbound_session_id_to_peer_id) + }, + false, + ) + .await; +} diff --git a/crates/papyrus_network/src/sqmr/handler.rs b/crates/papyrus_network/src/sqmr/handler.rs new file mode 100644 index 00000000000..5a6dc3bee0a --- /dev/null +++ b/crates/papyrus_network/src/sqmr/handler.rs @@ -0,0 +1,407 @@ +#[cfg(test)] +#[path = "handler_test.rs"] +mod handler_test; +mod inbound_session; + +use std::collections::{HashMap, HashSet, VecDeque}; +use std::io; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::task::{Context, Poll}; +use std::time::Duration; + +use async_stream::stream; +use futures::stream::BoxStream; +use futures::{FutureExt, StreamExt}; +use libp2p::swarm::handler::{ + ConnectionEvent, + DialUpgradeError, + FullyNegotiatedInbound, + FullyNegotiatedOutbound, +}; +use libp2p::swarm::{ + ConnectionHandler, + ConnectionHandlerEvent, + StreamUpgradeError, + SubstreamProtocol, +}; +use libp2p::{PeerId, StreamProtocol}; +use tracing::debug; + +use self::inbound_session::InboundSession; +use super::messages::read_message; +use super::protocol::{InboundProtocol, OutboundProtocol}; +use super::{Bytes, Config, GenericEvent, InboundSessionId, OutboundSessionId, SessionId}; + +#[derive(Debug)] +pub enum RequestFromBehaviourEvent { + CreateOutboundSession { + query: Bytes, + outbound_session_id: OutboundSessionId, + protocol_name: StreamProtocol, + }, + SendResponse { + response: Bytes, + inbound_session_id: InboundSessionId, + }, + CloseInboundSession { + inbound_session_id: InboundSessionId, + }, + DropSession { + session_id: SessionId, + }, +} + +#[derive(Debug)] +pub enum RequestToBehaviourEvent { + GenerateEvent(GenericEvent), + NotifySessionDropped { session_id: SessionId }, +} + +#[derive(thiserror::Error, Debug)] +pub enum SessionError { + #[error("Connection timed out after {} seconds.", session_timeout.as_secs())] + Timeout { session_timeout: Duration }, + #[error(transparent)] + IOError(#[from] io::Error), + #[error("Remote peer doesn't support the given protocol.")] + RemoteDoesntSupportProtocol, +} + +type HandlerEvent = ConnectionHandlerEvent< + ::OutboundProtocol, + ::OutboundOpenInfo, + ::ToBehaviour, +>; + +pub struct Handler { + // TODO(shahak): Consider changing to Arc if the config becomes heavy to clone. + config: Config, + next_inbound_session_id: Arc, + peer_id: PeerId, + id_to_inbound_session: HashMap, + id_to_outbound_session: + HashMap>>, + // TODO(shahak): Use deadqueue if using a VecDeque is a bug (libp2p uses VecDeque, so we opened + // an issue on it https://github.com/libp2p/rust-libp2p/issues/5147) + pending_events: VecDeque>, + inbound_sessions_marked_to_end: HashSet, + dropped_outbound_sessions_non_negotiated: HashSet, + supported_inbound_protocols: HashSet, +} + +impl Handler { + // TODO(shahak) If we'll add more parameters, consider creating a HandlerConfig struct. + pub fn new( + config: Config, + next_inbound_session_id: Arc, + peer_id: PeerId, + supported_inbound_protocols: HashSet, + ) -> Self { + Self { + config, + next_inbound_session_id, + peer_id, + id_to_inbound_session: Default::default(), + id_to_outbound_session: Default::default(), + pending_events: Default::default(), + inbound_sessions_marked_to_end: Default::default(), + dropped_outbound_sessions_non_negotiated: Default::default(), + supported_inbound_protocols, + } + } + + /// Poll an inbound session, inserting any events needed to pending_events, and return whether + /// the inbound session has finished. + fn poll_inbound_session( + inbound_session: &mut InboundSession, + inbound_session_id: InboundSessionId, + pending_events: &mut VecDeque>, + cx: &mut Context<'_>, + ) -> bool { + match inbound_session.poll_unpin(cx) { + Poll::Ready(Err(io_error)) => { + // No need to wake those waiting for pending events because this function is called + // inside `poll`. + pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFailed { + session_id: inbound_session_id.into(), + error: SessionError::IOError(io_error), + }), + )); + true + } + Poll::Ready(Ok(())) => { + // No need to wake those waiting for pending events because this function is called + // inside `poll`. + pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent( + GenericEvent::SessionFinishedSuccessfully { + session_id: inbound_session_id.into(), + }, + ), + )); + true + } + Poll::Pending => false, + } + } +} + +impl ConnectionHandler for Handler { + type FromBehaviour = RequestFromBehaviourEvent; + type ToBehaviour = RequestToBehaviourEvent; + type InboundProtocol = InboundProtocol; + type OutboundProtocol = OutboundProtocol; + type InboundOpenInfo = InboundSessionId; + type OutboundOpenInfo = OutboundSessionId; + + fn listen_protocol(&self) -> SubstreamProtocol { + let supported_inbound_protocols_vec = + self.supported_inbound_protocols.iter().cloned().collect(); + SubstreamProtocol::new( + InboundProtocol::new(supported_inbound_protocols_vec), + InboundSessionId { value: self.next_inbound_session_id.fetch_add(1, Ordering::AcqRel) }, + ) + .with_timeout(self.config.session_timeout) + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + // Handle inbound sessions. + self.id_to_inbound_session.retain(|inbound_session_id, inbound_session| { + if Self::poll_inbound_session( + inbound_session, + *inbound_session_id, + &mut self.pending_events, + cx, + ) { + let is_session_alive = false; + return is_session_alive; + } + if self.inbound_sessions_marked_to_end.contains(inbound_session_id) + && inbound_session.is_waiting() + { + inbound_session.start_closing(); + if Self::poll_inbound_session( + inbound_session, + *inbound_session_id, + &mut self.pending_events, + cx, + ) { + let is_session_alive = false; + return is_session_alive; + } + } + true + }); + + // Handle outbound sessions. + self.id_to_outbound_session.retain(|outbound_session_id, outbound_session| { + match outbound_session.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(response))) => { + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::ReceivedResponse { + outbound_session_id: *outbound_session_id, + response, + peer_id: self.peer_id, + }), + )); + true + } + Poll::Ready(Some(Err(io_error))) => { + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFailed { + session_id: SessionId::OutboundSessionId(*outbound_session_id), + error: SessionError::IOError(io_error), + }), + )); + false + } + Poll::Ready(None) => { + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent( + GenericEvent::SessionFinishedSuccessfully { + session_id: SessionId::OutboundSessionId(*outbound_session_id), + }, + ), + )); + false + } + Poll::Pending => true, + } + }); + + // Handling pending_events at the end of the function to avoid starvation and to make sure + // we don't return Pending if the code above created an event. + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(event); + } + Poll::Pending + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + match event { + RequestFromBehaviourEvent::CreateOutboundSession { + query, + outbound_session_id, + protocol_name, + } => { + // TODO(shahak) Consider extracting to a utility function to prevent forgetfulness + // of the timeout. + + // No need to wake because the swarm guarantees that `poll` will be called after + // on_behaviour_event. See https://github.com/libp2p/rust-libp2p/issues/5147 + self.pending_events.push_back(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new( + OutboundProtocol { query, protocol_name }, + outbound_session_id, + ) + .with_timeout(self.config.session_timeout), + }); + } + RequestFromBehaviourEvent::SendResponse { response, inbound_session_id } => { + if let Some(inbound_session) = + self.id_to_inbound_session.get_mut(&inbound_session_id) + { + if self.inbound_sessions_marked_to_end.contains(&inbound_session_id) { + // TODO(shahak): Consider handling this in a different way than just + // logging. + debug!( + "Got a request to send response on a closed inbound session with id \ + {inbound_session_id}. Ignoring request." + ); + } else { + inbound_session.add_message_to_queue(response); + } + } else { + // TODO(shahak): Consider handling this in a different way than just logging. + debug!( + "Got a request to send response on a non-existing or closed inbound \ + session with id {inbound_session_id}. Ignoring request." + ); + } + } + RequestFromBehaviourEvent::CloseInboundSession { inbound_session_id } => { + self.inbound_sessions_marked_to_end.insert(inbound_session_id); + } + RequestFromBehaviourEvent::DropSession { + session_id: SessionId::OutboundSessionId(outbound_session_id), + } => { + let remove_result = self.id_to_outbound_session.remove(&outbound_session_id); + if remove_result.is_none() { + self.dropped_outbound_sessions_non_negotiated.insert(outbound_session_id); + } + // No need to wake because the swarm guarantees that `poll` will be called after + // on_behaviour_event. See https://github.com/libp2p/rust-libp2p/issues/5147 + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::NotifySessionDropped { + session_id: outbound_session_id.into(), + }, + )); + } + RequestFromBehaviourEvent::DropSession { + session_id: SessionId::InboundSessionId(inbound_session_id), + } => { + self.id_to_inbound_session.remove(&inbound_session_id); + // No need to wake because the swarm guarantees that `poll` will be called after + // on_behaviour_event. See https://github.com/libp2p/rust-libp2p/issues/5147 + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::NotifySessionDropped { + session_id: inbound_session_id.into(), + }, + )); + } + } + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + '_, + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol: mut read_stream, + info: outbound_session_id, + }) => { + if self.dropped_outbound_sessions_non_negotiated.remove(&outbound_session_id) { + return; + } + self.id_to_outbound_session.insert( + outbound_session_id, + stream! { + loop { + let result_opt = read_message(&mut read_stream).await; + let result = match result_opt { + Ok(Some(response)) => Ok(response), + Ok(None) => break, + Err(error) => Err(error), + }; + let is_err = result.is_err(); + yield result; + if is_err { + break; + } + } + } + .boxed(), + ); + } + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol: (query, write_stream, protocol_name), + info: inbound_session_id, + }) => { + // No need to wake because the swarm guarantees that `poll` will be called after + // on_connection_event. See https://github.com/libp2p/rust-libp2p/issues/5147 + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::NewInboundSession { + query, + inbound_session_id, + peer_id: self.peer_id, + protocol_name, + }), + )); + self.id_to_inbound_session + .insert(inbound_session_id, InboundSession::new(write_stream)); + } + ConnectionEvent::DialUpgradeError(DialUpgradeError { + info: outbound_session_id, + error: upgrade_error, + }) => { + let session_error = match upgrade_error { + StreamUpgradeError::Timeout => { + SessionError::Timeout { session_timeout: self.config.session_timeout } + } + StreamUpgradeError::Apply(outbound_protocol_error) => { + SessionError::IOError(outbound_protocol_error) + } + StreamUpgradeError::NegotiationFailed => { + SessionError::RemoteDoesntSupportProtocol + } + StreamUpgradeError::Io(error) => SessionError::IOError(error), + }; + // No need to wake because the swarm guarantees that `poll` will be called after + // on_connection_event. See https://github.com/libp2p/rust-libp2p/issues/5147 + self.pending_events.push_back(ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFailed { + session_id: outbound_session_id.into(), + error: session_error, + }), + )); + } + // We don't need to handle a ListenUpgradeError because an inbound session is created + // only after a successful upgrade so there's no session failure to report. + _ => {} + } + } +} diff --git a/crates/papyrus_network/src/sqmr/handler/inbound_session.rs b/crates/papyrus_network/src/sqmr/handler/inbound_session.rs new file mode 100644 index 00000000000..26819cc0f9c --- /dev/null +++ b/crates/papyrus_network/src/sqmr/handler/inbound_session.rs @@ -0,0 +1,133 @@ +use std::collections::VecDeque; +use std::future::Future; +use std::io; +use std::pin::Pin; +use std::task::{ready, Context, Poll, Waker}; + +use futures::future::BoxFuture; +use futures::io::WriteHalf; +use futures::{AsyncWriteExt, FutureExt}; +use libp2p::swarm::Stream; +use replace_with::replace_with_or_abort; + +use super::super::messages::write_message; +use super::super::Bytes; + +pub(super) struct InboundSession { + pending_messages: VecDeque, + current_task: WriteMessageTask, + wakers_waiting_for_new_message: Vec, +} + +enum FinishReason { + Error(io::Error), + Closed, +} + +enum WriteMessageTask { + Waiting(WriteHalf), + Running(BoxFuture<'static, Result, io::Error>>), + Closing(BoxFuture<'static, Result<(), io::Error>>), +} + +impl InboundSession { + pub fn new(write_stream: WriteHalf) -> Self { + Self { + pending_messages: Default::default(), + current_task: WriteMessageTask::Waiting(write_stream), + wakers_waiting_for_new_message: Default::default(), + } + } + + pub fn add_message_to_queue(&mut self, data: Bytes) { + self.pending_messages.push_back(data); + for waker in self.wakers_waiting_for_new_message.drain(..) { + waker.wake(); + } + } + + pub fn is_waiting(&self) -> bool { + matches!(self.current_task, WriteMessageTask::Waiting(_)) + && self.pending_messages.is_empty() + } + + pub fn start_closing(&mut self) { + replace_with_or_abort(&mut self.current_task, |current_task| { + let WriteMessageTask::Waiting(mut write_stream) = current_task else { + panic!("Called start_closing while not waiting."); + }; + WriteMessageTask::Closing(async move { write_stream.close().await }.boxed()) + }) + } + + fn handle_waiting(&mut self, cx: &mut Context<'_>) -> Poll<()> { + if let Some(data) = self.pending_messages.pop_front() { + replace_with_or_abort(&mut self.current_task, |current_task| { + let WriteMessageTask::Waiting(mut write_stream) = current_task else { + panic!("Called handle_waiting while not waiting."); + }; + WriteMessageTask::Running( + async move { + write_message(&data, &mut write_stream).await?; + Ok(write_stream) + } + .boxed(), + ) + }); + Poll::Ready(()) + } else { + self.wakers_waiting_for_new_message.push(cx.waker().clone()); + Poll::Pending + } + } + + fn handle_running(&mut self, cx: &mut Context<'_>) -> Poll> { + let WriteMessageTask::Running(fut) = &mut self.current_task else { + panic!("Called handle_running while not running."); + }; + fut.poll_unpin(cx).map(|result| match result { + Ok(write_stream) => { + self.current_task = WriteMessageTask::Waiting(write_stream); + None + } + Err(io_error) => Some(FinishReason::Error(io_error)), + }) + } + + fn handle_closing(&mut self, cx: &mut Context<'_>) -> Poll { + let WriteMessageTask::Closing(fut) = &mut self.current_task else { + panic!("Called handle_closing while not closing."); + }; + fut.poll_unpin(cx).map(|result| match result { + Ok(()) => FinishReason::Closed, + Err(io_error) => FinishReason::Error(io_error), + }) + } +} + +impl Future for InboundSession { + type Output = Result<(), io::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let unpinned_self = Pin::into_inner(self); + let finish_reason = loop { + match &mut unpinned_self.current_task { + WriteMessageTask::Running(_) => { + if let Some(finish_reason) = ready!(unpinned_self.handle_running(cx)) { + break finish_reason; + } + } + WriteMessageTask::Waiting(_) => { + ready!(unpinned_self.handle_waiting(cx)); + } + WriteMessageTask::Closing(_) => { + break ready!(unpinned_self.handle_closing(cx)); + } + } + }; + match finish_reason { + FinishReason::Error(io_error) => Poll::Ready(Err(io_error)), + FinishReason::Closed => Poll::Ready(Ok(())), + } + } +} diff --git a/crates/papyrus_network/src/sqmr/handler_test.rs b/crates/papyrus_network/src/sqmr/handler_test.rs new file mode 100644 index 00000000000..22d34afe990 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/handler_test.rs @@ -0,0 +1,555 @@ +use std::collections::HashSet; +use std::io; +use std::pin::Pin; +use std::sync::atomic::AtomicUsize; +use std::sync::Arc; + +use assert_matches::assert_matches; +use futures::task::{Context, Poll}; +use futures::{select, AsyncReadExt, AsyncWriteExt, FutureExt, Stream as StreamTrait, StreamExt}; +use lazy_static::lazy_static; +use libp2p::swarm::handler::{ + ConnectionEvent, + DialUpgradeError, + FullyNegotiatedInbound, + FullyNegotiatedOutbound, +}; +use libp2p::swarm::{ConnectionHandler, ConnectionHandlerEvent, Stream, StreamUpgradeError}; +use libp2p::{PeerId, StreamProtocol}; + +use super::super::messages::{read_message, write_message}; +use super::super::{Bytes, Config, GenericEvent, InboundSessionId, OutboundSessionId, SessionId}; +use super::{ + Handler, + HandlerEvent, + RequestFromBehaviourEvent, + RequestToBehaviourEvent, + SessionError, +}; +use crate::sqmr::handler; +use crate::test_utils::{dummy_data, get_connected_streams}; + +impl Unpin for Handler {} + +impl StreamTrait for Handler { + type Item = HandlerEvent; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match Pin::into_inner(self).poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(Some(event)), + } + } +} + +lazy_static! { + static ref QUERY: Bytes = vec![1u8, 2u8, 3u8]; + static ref PROTOCOL_NAME: StreamProtocol = + handler::Handler::get_test_supported_protocols().into_iter().next().unwrap(); +} + +fn simulate_request_to_send_response_from_swarm( + handler: &mut Handler, + response: Bytes, + inbound_session_id: InboundSessionId, +) { + handler.on_behaviour_event(RequestFromBehaviourEvent::SendResponse { + response, + inbound_session_id, + }); +} + +fn simulate_request_to_send_query_from_swarm( + handler: &mut Handler, + query: Bytes, + outbound_session_id: OutboundSessionId, +) { + handler.on_behaviour_event(RequestFromBehaviourEvent::CreateOutboundSession { + query, + outbound_session_id, + protocol_name: PROTOCOL_NAME.clone(), + }); +} + +fn simulate_request_to_close_inbound_session( + handler: &mut Handler, + inbound_session_id: InboundSessionId, +) { + handler + .on_behaviour_event(RequestFromBehaviourEvent::CloseInboundSession { inbound_session_id }); +} + +fn simulate_request_to_drop_session(handler: &mut Handler, session_id: SessionId) { + handler.on_behaviour_event(RequestFromBehaviourEvent::DropSession { session_id }); +} + +fn simulate_negotiated_inbound_session_from_swarm( + handler: &mut Handler, + query: Bytes, + inbound_stream: Stream, + inbound_session_id: InboundSessionId, +) { + handler.on_connection_event(ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol: (query, inbound_stream.split().1, PROTOCOL_NAME.clone()), + info: inbound_session_id, + })); +} + +fn simulate_negotiated_outbound_session_from_swarm( + handler: &mut Handler, + outbound_stream: Stream, + outbound_session_id: OutboundSessionId, +) { + handler.on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + FullyNegotiatedOutbound { protocol: outbound_stream.split().0, info: outbound_session_id }, + )); +} + +fn simulate_outbound_negotiation_failed( + handler: &mut Handler, + outbound_session_id: OutboundSessionId, + error: StreamUpgradeError, +) { + handler.on_connection_event(ConnectionEvent::DialUpgradeError(DialUpgradeError { + info: outbound_session_id, + error, + })); +} + +async fn validate_new_inbound_session_event( + handler: &mut Handler, + query: &Bytes, + inbound_session_id: InboundSessionId, +) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent( + GenericEvent::NewInboundSession { + query: event_query, + inbound_session_id: event_inbound_session_id, + peer_id: event_peer_id, + protocol_name, + } + ) + ) if event_query == *query + && event_inbound_session_id == inbound_session_id + && event_peer_id == handler.peer_id + && protocol_name == PROTOCOL_NAME.clone() => {} + ); +} + +async fn validate_received_response_event( + handler: &mut Handler, + response: &Bytes, + outbound_session_id: OutboundSessionId, +) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent( + GenericEvent::ReceivedResponse { + response: event_response, outbound_session_id: event_outbound_session_id, peer_id : event_peer_id + + } + ) + ) if event_response == *response && event_outbound_session_id == outbound_session_id && event_peer_id == handler.peer_id + ); +} + +async fn validate_session_finished_successfully_event( + handler: &mut Handler, + session_id: SessionId, +) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::NotifyBehaviour(RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFinishedSuccessfully { + session_id: event_session_id + })) if event_session_id == session_id + ); +} + +async fn validate_session_failed_event( + handler: &mut Handler, + session_id: SessionId, + session_error_matcher: impl FnOnce(&SessionError) -> bool, +) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::GenerateEvent(GenericEvent::SessionFailed { + session_id: event_session_id, + error, + }) + ) if event_session_id == session_id && session_error_matcher(&error) + ); +} + +async fn validate_session_dropped_event(handler: &mut Handler, session_id: SessionId) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::NotifyBehaviour( + RequestToBehaviourEvent::NotifySessionDropped { + session_id: event_session_id + } + ) if event_session_id == session_id + ); +} + +fn validate_no_events(handler: &mut Handler) { + assert!(handler.next().now_or_never().is_none()); +} + +async fn validate_request_to_swarm_new_outbound_session_to_swarm_event( + handler: &mut Handler, + query: &Bytes, + outbound_session_id: OutboundSessionId, +) { + let event = handler.next().await.unwrap(); + assert_matches!( + event, + ConnectionHandlerEvent::OutboundSubstreamRequest{ protocol } + if protocol.upgrade().query == *query && *protocol.info() == outbound_session_id + ); +} + +async fn read_messages(handler: Handler, stream: &mut Stream, num_messages: usize) -> Vec { + async fn read_messages_inner(stream: &mut Stream, num_messages: usize) -> Vec { + let mut result = Vec::new(); + for _ in 0..num_messages { + match read_message(&mut *stream).await.unwrap() { + Some(message) => result.push(message), + None => return result, + } + } + result + } + + let mut fused_handler = handler.fuse(); + select! { + response = read_messages_inner(stream, num_messages).fuse() => response, + _ = fused_handler.next() => panic!("There shouldn't be another event from the handler"), + } +} + +#[tokio::test] +async fn process_inbound_session() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (inbound_stream, mut outbound_stream, _) = get_connected_streams().await; + let inbound_session_id = InboundSessionId { value: 1 }; + + simulate_negotiated_inbound_session_from_swarm( + &mut handler, + QUERY.clone(), + inbound_stream, + inbound_session_id, + ); + validate_new_inbound_session_event(&mut handler, &QUERY, inbound_session_id).await; + let dummy_data_vec = dummy_data(); + for response in &dummy_data_vec { + simulate_request_to_send_response_from_swarm( + &mut handler, + response.clone(), + inbound_session_id, + ); + } + + let responses_received = + read_messages(handler, &mut outbound_stream, dummy_data_vec.len()).await; + assert_eq!(dummy_data_vec, responses_received); +} + +#[tokio::test] +async fn closed_inbound_session_ignores_behaviour_request_to_send_response() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (inbound_stream, mut outbound_stream, _) = get_connected_streams().await; + let inbound_session_id = InboundSessionId { value: 1 }; + + simulate_negotiated_inbound_session_from_swarm( + &mut handler, + QUERY.clone(), + inbound_stream, + inbound_session_id, + ); + + // consume the new inbound session event without reading it. + handler.next().await; + + simulate_request_to_close_inbound_session(&mut handler, inbound_session_id); + validate_session_finished_successfully_event(&mut handler, inbound_session_id.into()).await; + + let dummy_data_vec = dummy_data(); + for response in &dummy_data_vec { + simulate_request_to_send_response_from_swarm( + &mut handler, + response.clone(), + inbound_session_id, + ); + } + let responses_received = read_messages(handler, &mut outbound_stream, 1).await; + assert!(responses_received.is_empty()); +} + +#[test] +fn listen_protocol_across_multiple_handlers() { + let next_inbound_session_id = Arc::new(AtomicUsize::default()); + const NUM_HANDLERS: usize = 5; + const NUM_PROTOCOLS_PER_HANDLER: usize = 10; + let thread_handles = (0..NUM_HANDLERS).map(|_| { + let next_inbound_session_id = next_inbound_session_id.clone(); + std::thread::spawn(|| { + let handler = Handler::new( + Config::get_test_config(), + next_inbound_session_id, + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + (0..NUM_PROTOCOLS_PER_HANDLER) + .map(|_| handler.listen_protocol().info().value) + .collect::>() + }) + }); + let inbound_session_ids = + thread_handles.flat_map(|handle| handle.join().unwrap()).collect::>(); + assert_eq!( + (0..(NUM_HANDLERS * NUM_PROTOCOLS_PER_HANDLER)).collect::>(), + inbound_session_ids + ); +} + +#[tokio::test] +async fn process_outbound_session() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (mut inbound_stream, outbound_stream, _) = get_connected_streams().await; + let outbound_session_id = OutboundSessionId { value: 1 }; + + simulate_request_to_send_query_from_swarm(&mut handler, QUERY.clone(), outbound_session_id); + validate_request_to_swarm_new_outbound_session_to_swarm_event( + &mut handler, + &QUERY, + outbound_session_id, + ) + .await; + + simulate_negotiated_outbound_session_from_swarm( + &mut handler, + outbound_stream, + outbound_session_id, + ); + + let dummy_data_vec = dummy_data(); + for response in &dummy_data_vec { + write_message(response, &mut inbound_stream).await.unwrap(); + } + + for response in &dummy_data_vec { + validate_received_response_event(&mut handler, response, outbound_session_id).await; + } + + validate_no_events(&mut handler); + + inbound_stream.close().await.unwrap(); + validate_session_finished_successfully_event(&mut handler, outbound_session_id.into()).await; +} + +// Extracting to a function because two closures have different types. +async fn test_outbound_session_negotiation_failure( + upgrade_error: StreamUpgradeError, + session_error_matcher: impl FnOnce(&SessionError) -> bool, + config: Config, +) { + let outbound_session_id = OutboundSessionId { value: 1 }; + let mut handler = Handler::new( + config, + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + simulate_outbound_negotiation_failed(&mut handler, outbound_session_id, upgrade_error); + validate_session_failed_event(&mut handler, outbound_session_id.into(), session_error_matcher) + .await; + validate_no_events(&mut handler); +} + +// TODO(shahak): Add tests where session fails after negotiation. +#[tokio::test] +async fn outbound_session_negotiation_failure() { + let error_kind = io::ErrorKind::UnexpectedEof; + let config = Config::get_test_config(); + test_outbound_session_negotiation_failure( + StreamUpgradeError::Timeout, + |session_error| { + matches!( + session_error, + SessionError::Timeout { session_timeout } + if *session_timeout == config.session_timeout + ) + }, + config.clone(), + ) + .await; + test_outbound_session_negotiation_failure( + StreamUpgradeError::Apply(error_kind.into()), + |session_error| { + matches!( + session_error, + SessionError::IOError(error) + if error.kind() == error_kind + ) + }, + config.clone(), + ) + .await; + test_outbound_session_negotiation_failure( + StreamUpgradeError::NegotiationFailed, + |session_error| matches!(session_error, SessionError::RemoteDoesntSupportProtocol), + config.clone(), + ) + .await; + test_outbound_session_negotiation_failure( + StreamUpgradeError::Io(error_kind.into()), + |session_error| { + matches!( + session_error, + SessionError::IOError(error) + if error.kind() == error_kind + ) + }, + config.clone(), + ) + .await; +} + +#[tokio::test] +async fn outbound_session_dropped_after_negotiation() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (mut inbound_stream, outbound_stream, _) = get_connected_streams().await; + let outbound_session_id = OutboundSessionId { value: 1 }; + + simulate_request_to_send_query_from_swarm(&mut handler, QUERY.clone(), outbound_session_id); + // consume the new outbound session event without reading it. + handler.next().await; + + simulate_negotiated_outbound_session_from_swarm( + &mut handler, + outbound_stream, + outbound_session_id, + ); + + simulate_request_to_drop_session(&mut handler, outbound_session_id.into()); + validate_session_dropped_event(&mut handler, outbound_session_id.into()).await; + + // Need to sleep to make sure the dropping occurs on the other stream. + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + write_message(dummy_data().first().unwrap(), &mut inbound_stream).await.unwrap_err(); + + // Need to sleep to make sure that if we did send a message the stream inside the handle will + // receive it + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + validate_no_events(&mut handler); +} + +#[tokio::test] +async fn outbound_session_dropped_before_negotiation() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (mut inbound_stream, outbound_stream, _) = get_connected_streams().await; + let outbound_session_id = OutboundSessionId { value: 1 }; + + simulate_request_to_send_query_from_swarm(&mut handler, QUERY.clone(), outbound_session_id); + // consume the new outbound session event without reading it. + handler.next().await; + + simulate_request_to_drop_session(&mut handler, outbound_session_id.into()); + validate_session_dropped_event(&mut handler, outbound_session_id.into()).await; + + simulate_negotiated_outbound_session_from_swarm( + &mut handler, + outbound_stream, + outbound_session_id, + ); + + // Need to sleep to make sure the dropping occurs on the other stream. + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + write_message(&dummy_data().first().unwrap().clone(), &mut inbound_stream).await.unwrap_err(); + + // Need to sleep to make sure that if we did send a message the stream inside the handle will + // receive it + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + validate_no_events(&mut handler); +} + +#[tokio::test] +async fn inbound_session_dropped() { + let mut handler = Handler::new( + Config::get_test_config(), + Arc::new(Default::default()), + PeerId::random(), + Handler::get_test_supported_protocols(), + ); + + let (inbound_stream, mut outbound_stream, _) = get_connected_streams().await; + let inbound_session_id = InboundSessionId { value: 1 }; + + simulate_negotiated_inbound_session_from_swarm( + &mut handler, + QUERY.clone(), + inbound_stream, + inbound_session_id, + ); + // consume the new inbound session event without reading it. + handler.next().await; + + simulate_request_to_drop_session(&mut handler, inbound_session_id.into()); + validate_session_dropped_event(&mut handler, inbound_session_id.into()).await; + + // Need to sleep to make sure the dropping occurs on the other stream. + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + // A dropped inbound session will return EOF. + assert!(read_message(&mut outbound_stream).await.unwrap().is_none()); + + // Need to sleep to make sure that if we did send a message the stream inside the handle will + // receive it + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + validate_no_events(&mut handler); +} diff --git a/crates/papyrus_network/src/sqmr/messages.rs b/crates/papyrus_network/src/sqmr/messages.rs new file mode 100644 index 00000000000..cd5c95aaf87 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/messages.rs @@ -0,0 +1,110 @@ +#[cfg(test)] +#[path = "messages_test.rs"] +mod messages_test; + +use std::io; + +use futures::io::{ReadHalf, WriteHalf}; +use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use unsigned_varint::encode::usize_buffer; + +use super::Bytes; + +pub const MAX_MESSAGE_SIZE: usize = 1 << 20; + +pub async fn write_message( + message: &Bytes, + io: &mut Stream, +) -> Result<(), io::Error> { + write_usize(io, message.len()).await?; + io.write_all(message).await?; + Ok(()) +} + +pub async fn write_message_without_length_prefix( + message: &Bytes, + // We require `io` to be WriteHalf and not Stream in order to ensure it's not a + // reference. + // We want to ensure it's not a reference because this function will make it unusable + mut io: WriteHalf, +) -> Result<(), io::Error> { + io.write_all(message).await?; + io.close().await?; + Ok(()) +} + +pub async fn read_message( + io: &mut Stream, +) -> Result, io::Error> { + // This code is based on read_length_prefixed from libp2p v0.52 which was erased in v0.53. + let Some(message_len) = read_usize(io).await? else { return Ok(None) }; + if message_len > MAX_MESSAGE_SIZE { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!( + "Received message of size ({message_len} bytes), which exceeds maximum \ + ({MAX_MESSAGE_SIZE} bytes)" + ), + )); + } + let mut buf = vec![0u8; message_len]; + io.read_exact(&mut buf).await?; + Ok(Some(buf)) +} + +pub async fn read_message_without_length_prefix( + // We require `io` to be ReadHalf and not Stream in order to ensure it's not a + // reference. + // We want to ensure it's not a reference because this function will make it unusable + mut io: ReadHalf, +) -> Result { + let mut buf = vec![]; + io.read_to_end(&mut buf).await?; + Ok(buf) +} + +// This code is based on read_varint from libp2p v0.52 which was erased in v0.53. The difference +// from there is that here we return None if we have EOF before starting to read. +async fn read_usize( + io: &mut Stream, +) -> Result, io::Error> { + let mut buffer = unsigned_varint::encode::usize_buffer(); + let mut buffer_len = 0; + + loop { + match io.read(&mut buffer[buffer_len..buffer_len + 1]).await? { + 0 => { + // Reaching EOF before finishing to read the length is an error, unless the EOF is + // at the very beginning of the substream, in which case we return None. + if buffer_len == 0 { + return Ok(None); + } else { + return Err(io::ErrorKind::UnexpectedEof.into()); + } + } + n => debug_assert_eq!(n, 1), + } + + buffer_len += 1; + + match unsigned_varint::decode::usize(&buffer[..buffer_len]) { + Ok((len, _)) => return Ok(Some(len)), + Err(unsigned_varint::decode::Error::Insufficient) => {} + Err(error) => { + return Err(io::Error::new(io::ErrorKind::InvalidData, error)); + } + } + } +} + +// This code is based on write_varint from libp2p v0.52 which was erased in v0.53. +async fn write_usize( + io: &mut Stream, + num: usize, +) -> Result<(), io::Error> { + let mut buffer = usize_buffer(); + let encoded_len = unsigned_varint::encode::usize(num, &mut buffer).len(); + io.write_all(&buffer[..encoded_len]).await?; + + Ok(()) +} diff --git a/crates/papyrus_network/src/sqmr/messages_test.rs b/crates/papyrus_network/src/sqmr/messages_test.rs new file mode 100644 index 00000000000..72545b5904c --- /dev/null +++ b/crates/papyrus_network/src/sqmr/messages_test.rs @@ -0,0 +1,49 @@ +use std::time::Duration; + +use futures::{AsyncReadExt, AsyncWriteExt}; +use pretty_assertions::assert_eq; + +use super::{ + read_message, + read_message_without_length_prefix, + write_message, + write_message_without_length_prefix, +}; +use crate::test_utils::{dummy_data, get_connected_streams}; + +#[tokio::test] +async fn read_write_positive_flow() { + let (mut stream1, mut stream2, _) = get_connected_streams().await; + let messages = dummy_data(); + for message in &messages { + write_message(message, &mut stream1).await.unwrap(); + } + for expected_message in &messages { + assert_eq!(*expected_message, read_message(&mut stream2).await.unwrap().unwrap()); + } +} + +#[tokio::test] +async fn read_write_without_length_prefix_positive_flow() { + let (stream1, stream2, _) = get_connected_streams().await; + let (_read_stream1, write_stream1) = stream1.split(); + let (read_stream2, _write_stream2) = stream2.split(); + let message = dummy_data().first().unwrap().clone(); + write_message_without_length_prefix(&message, write_stream1).await.unwrap(); + assert_eq!(message, read_message_without_length_prefix(read_stream2).await.unwrap()); +} + +#[tokio::test] +async fn read_message_returns_none_when_other_stream_is_closed() { + let (mut stream1, mut stream2, _) = get_connected_streams().await; + stream1.close().await.unwrap(); + assert!(read_message(&mut stream2).await.unwrap().is_none()); +} + +#[tokio::test] +async fn read_message_is_pending_when_other_stream_didnt_send() { + let (_stream1, mut stream2, _) = get_connected_streams().await; + assert!( + tokio::time::timeout(Duration::from_millis(10), read_message(&mut stream2)).await.is_err() + ); +} diff --git a/crates/papyrus_network/src/sqmr/mod.rs b/crates/papyrus_network/src/sqmr/mod.rs new file mode 100644 index 00000000000..acff2361223 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/mod.rs @@ -0,0 +1,70 @@ +pub mod behaviour; +pub mod handler; +mod messages; +pub mod protocol; + +#[cfg(test)] +mod flow_test; + +use std::time::Duration; + +pub use behaviour::{Behaviour, ToOtherBehaviourEvent}; +use derive_more::Display; +use libp2p::{PeerId, StreamProtocol}; + +pub type Bytes = Vec; + +#[derive(Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq)] +pub struct OutboundSessionId { + pub value: usize, +} + +#[derive(Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq)] +pub struct InboundSessionId { + pub value: usize, +} + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum SessionId { + OutboundSessionId(OutboundSessionId), + InboundSessionId(InboundSessionId), +} + +impl From for SessionId { + fn from(outbound_session_id: OutboundSessionId) -> Self { + Self::OutboundSessionId(outbound_session_id) + } +} + +impl From for SessionId { + fn from(inbound_session_id: InboundSessionId) -> Self { + Self::InboundSessionId(inbound_session_id) + } +} + +#[derive(Debug)] +pub enum GenericEvent { + NewInboundSession { + query: Bytes, + inbound_session_id: InboundSessionId, + peer_id: PeerId, + protocol_name: StreamProtocol, + }, + ReceivedResponse { + outbound_session_id: OutboundSessionId, + response: Bytes, + peer_id: PeerId, + }, + SessionFailed { + session_id: SessionId, + error: SessionError, + }, + SessionFinishedSuccessfully { + session_id: SessionId, + }, +} + +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct Config { + pub session_timeout: Duration, +} diff --git a/crates/papyrus_network/src/sqmr/protocol.rs b/crates/papyrus_network/src/sqmr/protocol.rs new file mode 100644 index 00000000000..6b910578187 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/protocol.rs @@ -0,0 +1,84 @@ +#[cfg(test)] +#[path = "protocol_test.rs"] +mod protocol_test; + +use std::{io, iter}; + +use futures::future::BoxFuture; +use futures::io::{ReadHalf, WriteHalf}; +use futures::{AsyncRead, AsyncReadExt, AsyncWrite, FutureExt}; +use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p::StreamProtocol; + +use super::messages::{read_message_without_length_prefix, write_message_without_length_prefix}; +use super::Bytes; + +pub struct InboundProtocol { + supported_protocols: Vec, +} + +impl InboundProtocol { + pub fn new(supported_protocols: Vec) -> Self { + Self { supported_protocols } + } +} + +impl UpgradeInfo for InboundProtocol { + type Info = StreamProtocol; + type InfoIter = Vec; + + fn protocol_info(&self) -> Self::InfoIter { + self.supported_protocols.clone() + } +} + +impl InboundUpgrade for InboundProtocol +where + Stream: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = (Bytes, WriteHalf, StreamProtocol); + type Error = io::Error; + type Future = BoxFuture<'static, Result>; + + fn upgrade_inbound(self, stream: Stream, protocol_name: Self::Info) -> Self::Future { + async move { + let (read_half, write_half) = stream.split(); + let request = read_message_without_length_prefix(read_half).await?; + Ok((request, write_half, protocol_name)) + } + .boxed() + } +} + +#[derive(Debug)] +pub struct OutboundProtocol { + pub query: Bytes, + pub protocol_name: StreamProtocol, +} + +impl UpgradeInfo for OutboundProtocol { + type Info = StreamProtocol; + type InfoIter = iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + iter::once(self.protocol_name.clone()) + } +} + +impl OutboundUpgrade for OutboundProtocol +where + Stream: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = ReadHalf; + type Error = io::Error; + type Future = BoxFuture<'static, Result>; + + fn upgrade_outbound(self, stream: Stream, _: Self::Info) -> Self::Future { + async move { + let (read_half, write_half) = stream.split(); + write_message_without_length_prefix(&self.query, write_half).await?; + Ok(read_half) + } + .boxed() + } +} diff --git a/crates/papyrus_network/src/sqmr/protocol_test.rs b/crates/papyrus_network/src/sqmr/protocol_test.rs new file mode 100644 index 00000000000..f061153e815 --- /dev/null +++ b/crates/papyrus_network/src/sqmr/protocol_test.rs @@ -0,0 +1,66 @@ +use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade}; +use libp2p::core::UpgradeInfo; +use libp2p::StreamProtocol; +use pretty_assertions::assert_eq; + +use super::super::messages::{read_message, write_message}; +use super::{InboundProtocol, OutboundProtocol}; +use crate::test_utils::{dummy_data, get_connected_streams}; + +pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/example/1.0.0"); + +#[test] +fn outbound_protocol_info() { + let outbound_protocol = + OutboundProtocol { query: Default::default(), protocol_name: PROTOCOL_NAME }; + assert_eq!(outbound_protocol.protocol_info().collect::>(), vec![PROTOCOL_NAME]); +} + +#[test] +fn inbound_protocol_info() { + let protocol_names = vec![PROTOCOL_NAME, StreamProtocol::new("/example/2.0.0")]; + let inbound_protocol = InboundProtocol::new(protocol_names.clone()); + assert_eq!(inbound_protocol.protocol_info(), protocol_names); +} + +#[tokio::test] +async fn positive_flow() { + let (inbound_stream, outbound_stream, _) = get_connected_streams().await; + + let query = vec![1u8, 2u8, 3u8]; + let outbound_protocol = OutboundProtocol { query: query.clone(), protocol_name: PROTOCOL_NAME }; + let inbound_protocol = InboundProtocol::new(vec![PROTOCOL_NAME]); + + tokio::join!( + async move { + let (received_query, mut stream, protocol_name) = + inbound_protocol.upgrade_inbound(inbound_stream, PROTOCOL_NAME).await.unwrap(); + assert_eq!(query, received_query); + assert_eq!(protocol_name, PROTOCOL_NAME); + for response in dummy_data() { + write_message(&response, &mut stream).await.unwrap(); + } + }, + async move { + let mut stream = + outbound_protocol.upgrade_outbound(outbound_stream, PROTOCOL_NAME).await.unwrap(); + for expected_response in dummy_data() { + let response = read_message(&mut stream).await.unwrap().unwrap(); + assert_eq!(response, expected_response); + } + } + ); +} + +#[tokio::test] +async fn inbound_dropped() { + let (inbound_stream, outbound_stream, _) = get_connected_streams().await; + let outbound_protocol = OutboundProtocol { query: vec![0u8], protocol_name: PROTOCOL_NAME }; + + drop(inbound_stream); + + // Need to sleep to make sure the dropping occurs on the other stream. + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + assert!(outbound_protocol.upgrade_outbound(outbound_stream, PROTOCOL_NAME).await.is_err()); +} diff --git a/crates/papyrus_network/src/test_utils/get_stream.rs b/crates/papyrus_network/src/test_utils/get_stream.rs new file mode 100644 index 00000000000..62ca75a0293 --- /dev/null +++ b/crates/papyrus_network/src/test_utils/get_stream.rs @@ -0,0 +1,172 @@ +use std::iter; +use std::task::{Context, Poll}; + +use futures::future::BoxFuture; +use futures::{AsyncRead, AsyncWrite, FutureExt}; +use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p::core::Endpoint; +use libp2p::swarm::handler::{ConnectionEvent, FullyNegotiatedInbound, FullyNegotiatedOutbound}; +use libp2p::swarm::{ + ConnectionDenied, + ConnectionHandler, + ConnectionHandlerEvent, + ConnectionId, + FromSwarm, + NetworkBehaviour, + Stream, + SubstreamProtocol, + ToSwarm, +}; +use libp2p::{Multiaddr, PeerId, StreamProtocol}; + +#[derive(Default)] +pub(crate) struct Behaviour { + stream: Option, +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = Handler; + type ToSwarm = Stream; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result { + Ok(Handler { request_outbound_session: false, stream: None }) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _addr: &Multiaddr, + _role_override: Endpoint, + ) -> Result { + Ok(Handler { request_outbound_session: true, stream: None }) + } + + fn on_swarm_event(&mut self, _event: FromSwarm<'_>) {} + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + stream: ::ToBehaviour, + ) { + self.stream = Some(stream); + } + + fn poll( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll::FromBehaviour>> + { + if let Some(stream) = self.stream.take() { + return Poll::Ready(ToSwarm::GenerateEvent(stream)); + } + Poll::Pending + } +} + +pub(crate) struct Handler { + request_outbound_session: bool, + stream: Option, +} + +impl ConnectionHandler for Handler { + type FromBehaviour = (); + type ToBehaviour = Stream; + type InboundProtocol = Protocol; + type OutboundProtocol = Protocol; + type InboundOpenInfo = (); + type OutboundOpenInfo = (); + + fn listen_protocol(&self) -> SubstreamProtocol { + SubstreamProtocol::new(Protocol, ()) + } + + fn poll( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + if self.request_outbound_session { + self.request_outbound_session = false; + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new(Protocol, ()), + }); + } + if let Some(stream) = self.stream.take() { + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(stream)); + } + Poll::Pending + } + + fn on_behaviour_event(&mut self, _event: Self::FromBehaviour) {} + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + '_, + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol: stream, + info: _, + }) => self.stream = Some(stream), + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol: stream, + info: _, + }) => self.stream = Some(stream), + _ => {} + } + } +} + +pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/get_stream"); + +pub(crate) struct Protocol; + +impl UpgradeInfo for Protocol { + type Info = StreamProtocol; + type InfoIter = iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + iter::once(PROTOCOL_NAME) + } +} + +impl OutboundUpgrade for Protocol +where + Stream: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = Stream; + type Error = (); + type Future = BoxFuture<'static, Result>; + + fn upgrade_outbound(self, stream: Stream, _: Self::Info) -> Self::Future { + async move { Ok(stream) }.boxed() + } +} + +impl InboundUpgrade for Protocol +where + Stream: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = Stream; + type Error = (); + type Future = BoxFuture<'static, Result>; + + fn upgrade_inbound(self, stream: Stream, _: Self::Info) -> Self::Future { + async move { Ok(stream) }.boxed() + } +} diff --git a/crates/papyrus_network/src/test_utils/mod.rs b/crates/papyrus_network/src/test_utils/mod.rs new file mode 100644 index 00000000000..fc54f668239 --- /dev/null +++ b/crates/papyrus_network/src/test_utils/mod.rs @@ -0,0 +1,113 @@ +mod get_stream; + +use std::collections::HashSet; +use std::fmt::Debug; +use std::pin::Pin; +use std::task::{ready, Context, Poll}; +use std::time::Duration; + +use futures::future::Future; +use futures::pin_mut; +use futures::stream::Stream as StreamTrait; +use libp2p::swarm::{NetworkBehaviour, Swarm, SwarmEvent}; +use libp2p::{PeerId, Stream, StreamProtocol}; +use libp2p_swarm_test::SwarmExt; +use tokio::sync::Mutex; +use tokio::task::JoinHandle; +use tokio_stream::StreamExt; + +use crate::sqmr::Bytes; +use crate::utils::StreamHashMap; + +/// Create two streams that are connected to each other. Return them and a join handle for a thread +/// that will perform the sends between the streams (this thread will run forever so it shouldn't +/// be joined). +pub(crate) async fn get_connected_streams() -> (Stream, Stream, JoinHandle<()>) { + let mut swarm1 = Swarm::new_ephemeral(|_| get_stream::Behaviour::default()); + let mut swarm2 = Swarm::new_ephemeral(|_| get_stream::Behaviour::default()); + swarm1.listen().with_memory_addr_external().await; + swarm2.listen().with_memory_addr_external().await; + + swarm1.connect(&mut swarm2).await; + + let merged_swarm = swarm1.merge(swarm2); + let mut filtered_swarm = merged_swarm.filter_map(|event| { + if let SwarmEvent::Behaviour(stream) = event { Some(stream) } else { None } + }); + ( + filtered_swarm.next().await.unwrap(), + filtered_swarm.next().await.unwrap(), + tokio::task::spawn(async move { while filtered_swarm.next().await.is_some() {} }), + ) +} + +pub(crate) fn dummy_data() -> Vec { + vec![vec![1u8], vec![2u8, 3u8], vec![4u8, 5u8, 6u8]] +} + +impl crate::sqmr::Config { + pub fn get_test_config() -> Self { + Self { session_timeout: Duration::MAX } + } +} +// TODO(eitan): create a lazy static constant of SUPPORTED_PROTOCOLS which is this vec +impl crate::sqmr::handler::Handler { + pub fn get_test_supported_protocols() -> HashSet { + let mut protocols = HashSet::new(); + protocols.insert(StreamProtocol::new("/")); + protocols + } +} + +/// Create num_swarms swarms and connect each pair of swarms. Return them as a combined stream of +/// events. +pub(crate) async fn create_fully_connected_swarms_stream( + num_swarms: usize, + behaviour_gen: impl Fn() -> TBehaviour, +) -> StreamHashMap> +where + ::ToSwarm: Debug, +{ + let mut swarms = + (0..num_swarms).map(|_| Swarm::new_ephemeral(|_| behaviour_gen())).collect::>(); + + for swarm in &mut swarms { + swarm.listen().with_memory_addr_external().await; + } + + for i in 0..(swarms.len() - 1) { + let (swarms1, swarms2) = swarms.split_at_mut(i + 1); + let swarm1 = &mut swarms1[i]; + for swarm2 in swarms2 { + swarm1.connect(swarm2).await; + } + } + + StreamHashMap::new(swarms.into_iter().map(|swarm| (*swarm.local_peer_id(), swarm)).collect()) +} + +// I tried making this generic on the async function we run, but it caused a lot of lifetime +// issues. +/// Run `next` on a mutex of a stream, unlocking it while the function is pending. +pub(crate) fn next_on_mutex_stream( + mutex: &Mutex, +) -> NextOnMutexStream<'_, T> { + NextOnMutexStream { mutex } +} + +pub(crate) struct NextOnMutexStream<'a, T: StreamTrait + Unpin> { + mutex: &'a Mutex, +} + +impl<'a, T: StreamTrait + Unpin> Future for NextOnMutexStream<'a, T> { + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let lock_fut = self.mutex.lock(); + pin_mut!(lock_fut); + let mut locked_value = ready!(lock_fut.poll(cx)); + let fut = StreamExt::next(&mut *locked_value); + pin_mut!(fut); + fut.poll(cx) + } +} diff --git a/crates/papyrus_network/src/utils.rs b/crates/papyrus_network/src/utils.rs new file mode 100644 index 00000000000..2ac26a8c156 --- /dev/null +++ b/crates/papyrus_network/src/utils.rs @@ -0,0 +1,68 @@ +use std::collections::hash_map::{Keys, ValuesMut}; +use std::collections::{HashMap, HashSet}; +use std::hash::Hash; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use futures::stream::{Stream, StreamExt}; + +// This is an implementation of `StreamMap` from tokio_stream. The reason we're implementing it +// ourselves is that the implementation in tokio_stream requires that the values implement the +// Stream trait from tokio_stream and not from futures. +pub(crate) struct StreamHashMap { + map: HashMap, + finished_streams: HashSet, +} + +impl StreamHashMap { + #[allow(dead_code)] + pub fn new(map: HashMap) -> Self { + Self { map, finished_streams: Default::default() } + } + + #[allow(dead_code)] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + self.map.values_mut() + } + + #[allow(dead_code)] + pub fn keys(&self) -> Keys<'_, K, V> { + self.map.keys() + } + + #[allow(dead_code)] + pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { + self.map.get_mut(key) + } + + pub fn insert(&mut self, key: K, value: V) -> Option { + self.map.insert(key, value) + } +} + +impl Stream for StreamHashMap { + type Item = (K, ::Item); + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let unpinned_self = Pin::into_inner(self); + let mut finished = true; + for (key, stream) in &mut unpinned_self.map { + match stream.poll_next_unpin(cx) { + Poll::Ready(Some(value)) => { + return Poll::Ready(Some((key.clone(), value))); + } + Poll::Ready(None) => { + unpinned_self.finished_streams.insert(key.clone()); + } + Poll::Pending => { + finished = false; + } + } + } + if finished { + // TODO(shahak): Make StreamHashMap not end in order to accept new inserted streams. + return Poll::Ready(None); + } + Poll::Pending + } +} diff --git a/crates/papyrus_node/Cargo.toml b/crates/papyrus_node/Cargo.toml new file mode 100644 index 00000000000..1b0593cf4e2 --- /dev/null +++ b/crates/papyrus_node/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "papyrus_node" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[package.metadata.cargo-udeps.ignore] +normal = ["papyrus_base_layer", "clap", "reqwest", "tokio"] + +[features] +default = ["rpc"] +rpc = ["papyrus_rpc"] + +[[bin]] +name = "central_source_integration_test" +required-features = ["futures-util", "tokio-stream"] +path = "src/bin/central_source_integration_test.rs" + +[dependencies] +anyhow.workspace = true +clap = { workspace = true } +const_format.workspace = true +futures.workspace = true +itertools.workspace = true +lazy_static.workspace = true +once_cell.workspace = true +papyrus_base_layer = { path = "../papyrus_base_layer", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_consensus = { path = "../sequencing/papyrus_consensus", version = "0.4.0-rc.0" } +papyrus_monitoring_gateway = { path = "../papyrus_monitoring_gateway", version = "0.4.0-rc.0" } +papyrus_network = { path = "../papyrus_network", version = "0.4.0-rc.0" } +papyrus_p2p_sync = { path = "../papyrus_p2p_sync", version = "0.4.0-rc.0" } +papyrus_protobuf = { path = "../papyrus_protobuf", version = "0.4.0-rc.0" } +papyrus_rpc = { path = "../papyrus_rpc", version = "0.4.0-rc.0", optional = true } +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +papyrus_sync = { path = "../papyrus_sync", version = "0.4.0-rc.0" } +reqwest = { workspace = true, features = ["json", "blocking"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +starknet_api = { workspace = true, features = ["testing"] } +starknet_client = { path = "../starknet_client" } +strum.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing.workspace = true +validator = { workspace = true, features = ["derive"] } + +# Binaries dependencies +futures-util = { workspace = true, optional = true } +tokio-stream = { workspace = true, optional = true } + + +[dev-dependencies] +assert-json-diff.workspace = true +colored.workspace = true +metrics-exporter-prometheus.workspace = true +pretty_assertions.workspace = true +insta = { workspace = true, features = ["json"] } +tempfile.workspace = true +test_utils = { path = "../test_utils" } diff --git a/crates/papyrus_node/examples/get_transaction_hash.rs b/crates/papyrus_node/examples/get_transaction_hash.rs new file mode 100644 index 00000000000..3222610dba6 --- /dev/null +++ b/crates/papyrus_node/examples/get_transaction_hash.rs @@ -0,0 +1,417 @@ +use std::cmp::min; +use std::collections::{BTreeMap, HashSet}; +use std::sync::Mutex; + +use clap::{Arg, Command}; +use futures::future::join_all; +use once_cell::sync::OnceCell; +use papyrus_common::transaction_hash::{ + get_transaction_hash, + MAINNET_TRANSACTION_HASH_WITH_VERSION, +}; +use papyrus_common::TransactionOptions; +use reqwest::Client; +use serde_json::{json, to_writer_pretty, Map, Value}; +use starknet_api::core::ChainId; +use starknet_api::transaction::{self, Transaction}; +use starknet_client::reader::objects::transaction::TransactionType; +use strum::IntoEnumIterator; + +const DEFAULT_TRANSACTION_HASH_PATH: &str = + "crates/papyrus_common/resources/transaction_hash_new.json"; +const MAX_CONCURRENT_REQUESTS: u64 = 100; + +struct CliParams { + node_url: String, + iteration_increments: u64, + file_path: String, + deprecated: bool, + concurrent_requests: u64, +} + +/// The start_block and end_block arguments are mandatory and define the block range to dump, +/// start_block is inclusive and end_block is exclusive. The file_path is an optional parameter, +/// otherwise the data will be dumped to "dump_declared_classes.json". +fn get_cli_params() -> CliParams { + let matches = Command::new("Get transaction hash") + .arg( + Arg::new("file_path") + .short('f') + .long("file_path") + .default_value(DEFAULT_TRANSACTION_HASH_PATH) + .help("The file path to dump the transactions."), + ) + .arg( + Arg::new("node_url") + .short('n') + .long("node_url") + .required(true) + .help("The node url to query."), + ) + .arg( + Arg::new("iteration_increments") + .short('i') + .long("iteration_increments") + .default_value("1") + .help("The iteration increments used to query the node."), + ) + .arg( + Arg::new("concurrent_requests") + .short('c') + .long("concurrent_requests") + .default_value(MAX_CONCURRENT_REQUESTS.to_string()) + .help("The maximum number of concurrent requests."), + ) + .arg( + Arg::new("deprecated") + .short('d') + .long("deprecated") + .default_value("false") + .help("Create a dump of deprecated transactions."), + ) + .get_matches(); + + let file_path = + matches.get_one::("file_path").expect("Failed parsing file_path").to_string(); + let node_url = + matches.get_one::("node_url").expect("Failed parsing node_url").to_string(); + let iteration_increments = matches + .get_one::("iteration_increments") + .expect("Failed parsing iteration_increments") + .parse::() + .expect("Failed parsing iteration_increments"); + let concurrent_requests = matches + .get_one::("concurrent_requests") + .expect("Failed parsing concurrent_requests") + .parse::() + .expect("Failed parsing concurrent_requests"); + let deprecated = matches + .get_one::("deprecated") + .expect("Failed parsing deprecated") + .parse::() + .expect("Failed parsing deprecated"); + CliParams { node_url, iteration_increments, file_path, deprecated, concurrent_requests } +} + +// Define a tuple struct to hold transaction type and version +#[derive(Eq, PartialEq, Hash, Debug)] +struct TransactionInfo { + pub transaction_type: TransactionType, + pub transaction_version: String, +} +fn get_all_transaction_types() -> HashSet { + TransactionType::iter() + .flat_map(|transaction_type| { + let transaction_version = match transaction_type { + TransactionType::Declare => vec!["0x0", "0x1", "0x2", "0x3"], + TransactionType::InvokeFunction => vec!["0x0", "0x1", "0x3"], + TransactionType::DeployAccount => vec!["0x1", "0x3"], + TransactionType::Deploy => vec!["0x0"], + TransactionType::L1Handler => vec!["0x0"], + }; + transaction_version + .iter() + .map(|version| TransactionInfo { + transaction_type, + transaction_version: version.to_string(), + }) + .collect::>() + }) + .collect() +} +#[tokio::main] +async fn main() -> Result<(), Box> { + println!("Starting Starknet transaction hash dump."); + + let CliParams { node_url, iteration_increments, file_path, deprecated, concurrent_requests } = + get_cli_params(); + let file = std::fs::File::create(file_path)?; + let mut writer = std::io::BufWriter::new(&file); + + static TRANSACTION_TYPES: OnceCell>> = + OnceCell::>>::new(); + let _ = TRANSACTION_TYPES.set(Mutex::new(get_all_transaction_types())); + static ACUMULATED_TRANSACTIONS: OnceCell>>> = + OnceCell::>>>::new(); + let _ = ACUMULATED_TRANSACTIONS.set(Mutex::new(vec![])); + let client = reqwest::Client::new(); + + // TODO(Eitan): Fix the block number to start from min of deprecated and synced block number + let mut block_number: u64 = if deprecated { + MAINNET_TRANSACTION_HASH_WITH_VERSION.0 + } else { + get_current_block_number_via_rpc(&client, node_url.clone()).await? + }; + + while block_number > 0 + && !TRANSACTION_TYPES + .get() + .expect("Couldn't get transaction types") + .lock() + .expect("Couldn't lock transaction types") + .is_empty() + { + let mut handles = vec![]; + + while block_number > 0 + && !TRANSACTION_TYPES + .get() + .expect("Couldn't get transaction types") + .lock() + .expect("Couldn't lock transaction types") + .is_empty() + && handles.len() < concurrent_requests as usize + { + let client_ref = client.clone(); + let node_url_ref = node_url.clone(); + + let handle = async move { + println!("Processing block number: {}", block_number); + let block_transactions = + get_block_transactions_via_rpc(&client_ref, node_url_ref.clone(), block_number) + .await + .unwrap_or_else(|_| { + println!( + "Failed to get block transactions for block number: {}", + block_number + ); + vec![] + }); + + // For each transaction in the block, check if it's a unique transaction type and + // version and add it to the acumulated_transactions + for transaction in block_transactions.iter().cloned() { + let transaction_info = parse_transaction_info_from_value(&transaction); + let mut transaction_types_handle = TRANSACTION_TYPES + .get() + .expect("Couldn't get transaction types") + .lock() + .expect("Couldn't lock transaction types"); + if transaction_types_handle.remove(&transaction_info) { + let unique_transaction = construct_transaction_from_value( + transaction.clone(), + &transaction_info.transaction_type, + &transaction_info.transaction_version, + ) + .expect("Couldn't construct transaction from value"); + let transaction_hash = transaction["transaction_hash"] + .as_str() + .expect("Couldn't parse 'transaction_hash' from json transaction") + .to_string(); + + let transaction_map = create_map_of_transaction( + &unique_transaction, + block_number, + transaction_hash, + deprecated, + ); + ACUMULATED_TRANSACTIONS + .get() + .expect("Couldn't get acumulated transactions") + .lock() + .expect("Couldn't lock acumulated transactions") + .push(transaction_map); + } + } + }; + // Decrement the block number by the iteration_increments + block_number -= min(iteration_increments, block_number); + handles.push(handle); + } + // Wait for all the spawned tasks to finish + join_all(handles).await; + } + + to_writer_pretty( + &mut writer, + &ACUMULATED_TRANSACTIONS.get().expect("Couldn't get acumulated transactions"), + )?; + println!("Transaction hash dump completed."); + Ok(()) +} + +fn create_map_of_transaction( + transaction: &Transaction, + block_number: u64, + transaction_hash: String, + deprecated: bool, +) -> BTreeMap { + let chain_id = ChainId::Mainnet; + let mut transaction_info = BTreeMap::new(); + transaction_info.insert("transaction".to_string(), json!(transaction)); + transaction_info.insert("chain_id".to_string(), json!(chain_id)); + transaction_info.insert("block_number".to_string(), json!(block_number)); + transaction_info.insert("transaction_hash".to_string(), json!(transaction_hash)); + // If the transaction is deprecated, only the transaction hash is needed + if !deprecated { + if let Transaction::L1Handler(_) = transaction { + return transaction_info; + } + // Note that we test the only_query_transaction_hash using the same method thats used to + // insert the only_query_transaction_hash into the json file. + transaction_info.insert( + "only_query_transaction_hash".to_string(), + json!( + get_transaction_hash( + transaction, + &chain_id, + &TransactionOptions { only_query: true } + ) + .expect("Couldn't get only query transaction hash") + ), + ); + } + transaction_info +} +fn construct_transaction_from_value( + mut transaction: Value, + transaction_type: &TransactionType, + transaction_version: &str, +) -> Result> { + println!( + "Constructing transaction from type: {} version: {}", + serde_json::to_string(transaction_type).expect("Couldn't parse transaction type"), + transaction_version + ); + let transaction_map = + transaction.as_object_mut().expect("Couldn't parse json transaction into object"); + if transaction_map.contains_key("resource_bounds") { + if let Some(resource_bounds) = transaction_map.remove("resource_bounds") { + let mut updated_resource_bounds = Map::new(); + for (key, value) in resource_bounds + .as_object() + .expect("Couldn't parse json value `resource_bounds` into object") + { + updated_resource_bounds.insert(key.clone().to_ascii_uppercase(), value.clone()); + } + transaction_map.insert("resource_bounds".to_string(), json!(updated_resource_bounds)); + } + } + match transaction_type { + TransactionType::Declare => match transaction_version { + "0x0" => Ok(Transaction::Declare(transaction::DeclareTransaction::V0( + serde_json::from_value(transaction)?, + ))), + "0x1" => Ok(Transaction::Declare(transaction::DeclareTransaction::V1( + serde_json::from_value(transaction)?, + ))), + "0x2" => Ok(Transaction::Declare(transaction::DeclareTransaction::V2( + serde_json::from_value(transaction)?, + ))), + "0x3" => Ok(Transaction::Declare(transaction::DeclareTransaction::V3( + serde_json::from_value(transaction)?, + ))), + _ => Err("Invalid transaction version".into()), + }, + TransactionType::InvokeFunction => match transaction_version { + "0x0" => Ok(Transaction::Invoke(transaction::InvokeTransaction::V0( + serde_json::from_value(transaction)?, + ))), + "0x1" => Ok(Transaction::Invoke(transaction::InvokeTransaction::V1( + serde_json::from_value(transaction)?, + ))), + "0x3" => Ok(Transaction::Invoke(transaction::InvokeTransaction::V3( + serde_json::from_value(transaction)?, + ))), + _ => Err("Invalid transaction version".into()), + }, + TransactionType::DeployAccount => match transaction_version { + "0x1" => Ok(Transaction::DeployAccount(transaction::DeployAccountTransaction::V1( + serde_json::from_value(transaction)?, + ))), + "0x3" => Ok(Transaction::DeployAccount(transaction::DeployAccountTransaction::V3( + serde_json::from_value(transaction)?, + ))), + _ => Err("Invalid transaction version".into()), + }, + TransactionType::Deploy => Ok(Transaction::Deploy(serde_json::from_value(transaction)?)), + TransactionType::L1Handler => { + Ok(Transaction::L1Handler(serde_json::from_value(transaction)?)) + } + } +} + +// JSON RPC for block transactions +async fn get_block_transactions_via_rpc( + client: &Client, + node_url: String, + block_number: u64, +) -> Result, Box> { + let request_body = json!({ + "jsonrpc": "2.0", + "id": 0, + "method": "starknet_getBlockWithTxs", + "params": { + "block_id": {"block_number": block_number} + } + }); + let res: reqwest::Response = client + .post(node_url) + .header("Content-Type", "application/json") + .body(request_body.to_string()) + .send() + .await?; + + // Check if the request was successful + if !res.status().is_success() { + // Handle the error if the request was not successful + return Err(format!("Request failed with status code: {}", res.status()).into()); + } + let value = res.json::().await?; + let block_transactions = value["result"]["transactions"] + .as_array() + .expect("Couldn't parse json result into array.") + .clone(); + Ok(block_transactions) +} + +// JSON RPC for current block number +async fn get_current_block_number_via_rpc( + client: &Client, + node_url: String, +) -> Result> { + let request_body = json!({ + "jsonrpc": "2.0", + "id": 0, + "method": "starknet_blockNumber", + "params": { + } + }); + + // Send the HTTP POST request + let res: reqwest::Response = client + .post(node_url) + .header("Content-Type", "application/json") + .body(request_body.to_string()) + .send() + .await?; + + // Check if the request was successful + if !res.status().is_success() { + // Handle the error if the request was not successful + return Err(format!("Request failed with status code: {}", res.status()).into()); + } + let res = res.json::().await?; + res["result"].as_u64().ok_or_else(|| ("Couldn't parse json response.").into()) +} + +fn parse_transaction_info_from_value(transaction: &Value) -> TransactionInfo { + let transaction_type = transaction["type"].clone(); + if transaction_type.as_str().expect("Couldn't parse 'type' from transaction") == "INVOKE" { + return TransactionInfo { + transaction_type: TransactionType::InvokeFunction, + transaction_version: transaction["version"] + .as_str() + .expect("Couldn't parse 'version' from json transaction") + .to_string(), + }; + } + TransactionInfo { + transaction_type: serde_json::from_value(transaction_type) + .expect("Couldn't parse 'type' from json transaction"), + transaction_version: transaction["version"] + .as_str() + .expect("Couldn't parse 'version' from json transaction") + .to_string(), + } +} diff --git a/crates/papyrus_node/src/bin/central_source_integration_test.rs b/crates/papyrus_node/src/bin/central_source_integration_test.rs new file mode 100644 index 00000000000..48b7abdcaae --- /dev/null +++ b/crates/papyrus_node/src/bin/central_source_integration_test.rs @@ -0,0 +1,64 @@ +use std::{env, fs}; + +use futures_util::pin_mut; +use papyrus_node::config::NodeConfig; +use papyrus_node::version::VERSION_FULL; +use papyrus_storage::open_storage; +use papyrus_sync::sources::central::{CentralSource, CentralSourceTrait}; +use starknet_api::block::BlockNumber; +use tokio_stream::StreamExt; + +const STREAM_LENGTH: u64 = 10; + +#[tokio::main] +async fn main() { + let mut path = env::temp_dir(); + path.push("data"); + let _ = fs::remove_dir_all(path.clone()); + fs::create_dir_all(path.clone()).expect("Should make a temporary `data` directory"); + let config = NodeConfig::load_and_process(vec![ + "--chain_id=SN_SEPOLIA".to_owned(), + "--starknet_url=https://alpha-sepolia.starknet.io/".to_owned(), + "--base_layer.node_url=https://mainnet.infura.io/v3/1234".to_owned(), + format!("--storage.db_config.path_prefix={}", path.display()), + ]) + .expect("Load config"); + let (storage_reader, _) = open_storage(config.storage).expect("Open storage"); + let central_source = CentralSource::new(config.central, VERSION_FULL, storage_reader) + .expect("Create new client"); + let last_block_number = central_source + .get_latest_block() + .await + .expect("Central get latest_block") + .expect("No blocks in central") + .block_number + .unchecked_next(); + let initial_block_number = BlockNumber(last_block_number.0 - STREAM_LENGTH); + + let mut block_marker = initial_block_number; + let block_stream = central_source.stream_new_blocks(block_marker, last_block_number).fuse(); + pin_mut!(block_stream); + while let Some(Ok((block_number, _block, _block_signature_data))) = block_stream.next().await { + assert!( + block_marker == block_number, + "Expected block number ({block_marker}) does not match the result ({block_number}).", + ); + block_marker = block_marker.unchecked_next(); + } + assert!(block_marker == last_block_number); + + let mut state_marker = initial_block_number; + let state_update_stream = + central_source.stream_state_updates(state_marker, last_block_number).fuse(); + pin_mut!(state_update_stream); + while let Some(Ok((block_number, _block_hash, _state_diff, _deployed_classes))) = + state_update_stream.next().await + { + assert!( + state_marker == block_number, + "Expected block number ({state_marker}) does not match the result ({block_number}).", + ); + state_marker = state_marker.unchecked_next(); + } + assert!(state_marker == last_block_number); +} diff --git a/crates/papyrus_node/src/bin/dump_config.rs b/crates/papyrus_node/src/bin/dump_config.rs new file mode 100644 index 00000000000..6f2012ffbae --- /dev/null +++ b/crates/papyrus_node/src/bin/dump_config.rs @@ -0,0 +1,24 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +#[cfg(feature = "rpc")] +use papyrus_config::dumping::SerializeConfig; +#[cfg(feature = "rpc")] +use papyrus_node::config::pointers::CONFIG_POINTERS; +#[cfg(feature = "rpc")] +use papyrus_node::config::{NodeConfig, DEFAULT_CONFIG_PATH}; + +/// Updates the default config file by: +/// cargo run --bin dump_config -q +#[cfg_attr(coverage_nightly, coverage_attribute)] +fn main() { + #[cfg(feature = "rpc")] + NodeConfig::default() + .dump_to_file(&CONFIG_POINTERS, DEFAULT_CONFIG_PATH) + .expect("dump to file error"); + // TODO(shahak): Try to find a way to remove this binary altogether when the feature rpc is + // turned off. + #[cfg(not(feature = "rpc"))] + panic!("Can't dump config when the rpc feature is deactivated"); +} diff --git a/crates/papyrus_node/src/config/config_test.rs b/crates/papyrus_node/src/config/config_test.rs new file mode 100644 index 00000000000..da6e6bb3fe9 --- /dev/null +++ b/crates/papyrus_node/src/config/config_test.rs @@ -0,0 +1,155 @@ +use std::collections::{BTreeMap, HashMap}; +use std::env::{self, args}; +use std::fs; +use std::fs::File; +use std::io::{BufWriter, Read, Write}; +use std::ops::IndexMut; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use assert_json_diff::assert_json_eq; +use colored::Colorize; +use itertools::Itertools; +use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerConfig; +use papyrus_config::dumping::SerializeConfig; +use papyrus_config::presentation::get_config_presentation; +use papyrus_config::{SerializationType, SerializedContent, SerializedParam}; +use papyrus_monitoring_gateway::MonitoringGatewayConfig; +use pretty_assertions::assert_eq; +use serde_json::{json, Map, Value}; +use starknet_api::core::ChainId; +use tempfile::NamedTempFile; +use test_utils::get_absolute_path; +use validator::Validate; + +#[cfg(feature = "rpc")] +use crate::config::pointers::CONFIG_POINTERS; +use crate::config::{node_command, NodeConfig, DEFAULT_CONFIG_PATH}; + +// Returns the required and generated params in default_config.json with the default value from the +// config presentation. +fn required_args() -> Vec { + let default_config = NodeConfig::default(); + let mut args = Vec::new(); + let mut config_presentation = get_config_presentation(&default_config, true).unwrap(); + + for (param_path, serialized_param) in default_config.dump() { + let serialization_type = match serialized_param.content { + SerializedContent::DefaultValue(_) | SerializedContent::PointerTarget(_) => continue, + SerializedContent::ParamType(serialization_type) => { + let parent_path = param_path.split('.').next().unwrap().to_string(); + let parent_json_value = + parent_path.split('.').fold(&mut config_presentation, |entry, config_name| { + entry.index_mut(config_name) + }); + // Skip the param if it is a field of an optional component and by default is None. + if parent_json_value.is_null() { + continue; + } + serialization_type + } + }; + args.push(format!("--{param_path}")); + + let required_param_json_value = param_path + .split('.') + .fold(&mut config_presentation, |entry, config_name| entry.index_mut(config_name)); + + let required_param_string_value = match serialization_type { + SerializationType::String => required_param_json_value.as_str().unwrap().to_string(), + _ => required_param_json_value.to_string(), + }; + args.push(required_param_string_value); + } + args +} + +fn get_args(additional_args: Vec<&str>) -> Vec { + let mut args = vec!["Papyrus".to_owned()]; + args.append(&mut required_args()); + args.append(&mut additional_args.into_iter().map(|s| s.to_owned()).collect()); + args +} + +#[test] +fn load_default_config() { + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + NodeConfig::load_and_process(get_args(vec![])).expect("Failed to load the config."); +} + +#[test] +fn load_http_headers() { + let args = get_args(vec!["--central.http_headers", "NAME_1:VALUE_1 NAME_2:VALUE_2"]); + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + let config = NodeConfig::load_and_process(args).unwrap(); + let target_http_headers = HashMap::from([ + ("NAME_1".to_string(), "VALUE_1".to_string()), + ("NAME_2".to_string(), "VALUE_2".to_string()), + ]); + assert_eq!(config.central.http_headers.unwrap(), target_http_headers); +} + +// insta doesn't work well with features, so if the output between two features are different we +// can only test one of them. We chose to test rpc over testing not(rpc). +#[cfg(feature = "rpc")] +#[test] +// Regression test which checks that the default config dumping hasn't changed. +fn test_dump_default_config() { + let mut default_config = NodeConfig::default(); + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + let dumped_default_config = default_config.dump(); + insta::assert_json_snapshot!(dumped_default_config); + + // The validate function will fail if the data directory does not exist so we change the path to + // point to an existing directory. + default_config.storage.db_config.path_prefix = PathBuf::from("."); + default_config.validate().unwrap(); +} + +#[test] +fn test_default_config_process() { + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + assert_eq!(NodeConfig::load_and_process(get_args(vec![])).unwrap(), NodeConfig::default()); +} + +#[test] +fn test_update_dumped_config_by_command() { + let args = get_args(vec![ + "--central.retry_config.retry_max_delay_millis", + "1234", + "--storage.db_config.path_prefix", + "/abc", + ]); + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + let config = NodeConfig::load_and_process(args).unwrap(); + + assert_eq!(config.central.retry_config.retry_max_delay_millis, 1234); + assert_eq!(config.storage.db_config.path_prefix.to_str(), Some("/abc")); +} + +#[cfg(feature = "rpc")] +#[test] +fn default_config_file_is_up_to_date() { + env::set_current_dir(get_absolute_path("")).expect("Couldn't set working dir."); + let from_default_config_file: serde_json::Value = + serde_json::from_reader(File::open(DEFAULT_CONFIG_PATH).unwrap()).unwrap(); + + // Create a temporary file and dump the default config to it. + let mut tmp_file_path = env::temp_dir(); + tmp_file_path.push("cfg.json"); + NodeConfig::default().dump_to_file(&CONFIG_POINTERS, tmp_file_path.to_str().unwrap()).unwrap(); + + // Read the dumped config from the file. + let from_code: serde_json::Value = + serde_json::from_reader(File::open(tmp_file_path).unwrap()).unwrap(); + + println!( + "{}", + "Default config file doesn't match the default NodeConfig implementation. Please update \ + it using the dump_config binary." + .purple() + .bold() + ); + println!("Diffs shown below."); + assert_json_eq!(from_default_config_file, from_code) +} diff --git a/crates/papyrus_node/src/config/mod.rs b/crates/papyrus_node/src/config/mod.rs new file mode 100644 index 00000000000..8932acfc9f4 --- /dev/null +++ b/crates/papyrus_node/src/config/mod.rs @@ -0,0 +1,131 @@ +#[cfg(test)] +mod config_test; +#[cfg(feature = "rpc")] +pub mod pointers; + +use std::collections::{BTreeMap, HashMap}; +use std::fs::File; +use std::io::{BufWriter, Write}; +use std::mem::discriminant; +use std::ops::IndexMut; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use std::{env, fs, io}; + +use clap::{arg, value_parser, Arg, ArgMatches, Command}; +use itertools::{chain, Itertools}; +use lazy_static::lazy_static; +use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerConfig; +use papyrus_config::dumping::{ + append_sub_config_name, + ser_optional_sub_config, + ser_param, + ser_pointer_target_param, + SerializeConfig, +}; +use papyrus_config::loading::load_and_process_config; +use papyrus_config::{ConfigError, ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_consensus::config::ConsensusConfig; +use papyrus_monitoring_gateway::MonitoringGatewayConfig; +use papyrus_network::NetworkConfig; +use papyrus_p2p_sync::client::{P2PSyncClient, P2PSyncClientConfig}; +#[cfg(feature = "rpc")] +use papyrus_rpc::RpcConfig; +use papyrus_storage::db::DbConfig; +use papyrus_storage::StorageConfig; +use papyrus_sync::sources::central::CentralSourceConfig; +use papyrus_sync::SyncConfig; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; +use starknet_api::core::ChainId; +use starknet_client::RetryConfig; +use validator::Validate; + +use crate::version::VERSION_FULL; + +// The path of the default configuration file, provided as part of the crate. +pub const DEFAULT_CONFIG_PATH: &str = "config/default_config.json"; + +/// The configurations of the various components of the node. +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Validate)] +pub struct NodeConfig { + #[cfg(feature = "rpc")] + #[validate] + pub rpc: RpcConfig, + pub central: CentralSourceConfig, + pub base_layer: EthereumBaseLayerConfig, + pub monitoring_gateway: MonitoringGatewayConfig, + #[validate] + pub storage: StorageConfig, + /// None if the syncing should be disabled. + pub sync: Option, + /// One of p2p_sync or sync must be None. + /// If P2P sync is active, then network must be active too. + // TODO(yair): Change NodeConfig to have an option of enum of SyncConfig or P2PSyncConfig. + pub p2p_sync: Option, + pub consensus: Option, + // TODO(shahak): Make network non-optional once it's developed enough. + pub network: Option, + pub collect_profiling_metrics: bool, +} + +// Default configuration values. +impl Default for NodeConfig { + fn default() -> Self { + NodeConfig { + central: CentralSourceConfig::default(), + base_layer: EthereumBaseLayerConfig::default(), + #[cfg(feature = "rpc")] + rpc: RpcConfig::default(), + monitoring_gateway: MonitoringGatewayConfig::default(), + storage: StorageConfig::default(), + sync: Some(SyncConfig::default()), + p2p_sync: None, + consensus: None, + network: None, + collect_profiling_metrics: false, + } + } +} + +impl SerializeConfig for NodeConfig { + fn dump(&self) -> BTreeMap { + #[allow(unused_mut)] + let mut sub_configs = vec![ + append_sub_config_name(self.central.dump(), "central"), + append_sub_config_name(self.base_layer.dump(), "base_layer"), + append_sub_config_name(self.monitoring_gateway.dump(), "monitoring_gateway"), + append_sub_config_name(self.storage.dump(), "storage"), + ser_optional_sub_config(&self.sync, "sync"), + ser_optional_sub_config(&self.p2p_sync, "p2p_sync"), + ser_optional_sub_config(&self.consensus, "consensus"), + ser_optional_sub_config(&self.network, "network"), + BTreeMap::from_iter([ser_param( + "collect_profiling_metrics", + &self.collect_profiling_metrics, + "If true, collect profiling metrics for the node.", + ParamPrivacyInput::Public, + )]), + ]; + #[cfg(feature = "rpc")] + sub_configs.push(append_sub_config_name(self.rpc.dump(), "rpc")); + + sub_configs.into_iter().flatten().collect() + } +} + +impl NodeConfig { + /// Creates a config object. Selects the values from the default file and from resources with + /// higher priority. + pub fn load_and_process(args: Vec) -> Result { + let default_config_file = std::fs::File::open(Path::new(DEFAULT_CONFIG_PATH))?; + load_and_process_config(default_config_file, node_command(), args) + } +} + +/// The command line interface of this node. +pub fn node_command() -> Command { + Command::new("Papyrus") + .version(VERSION_FULL) + .about("Papyrus is a StarkNet full node written in Rust.") +} diff --git a/crates/papyrus_node/src/config/pointers.rs b/crates/papyrus_node/src/config/pointers.rs new file mode 100644 index 00000000000..b4f1bf2bbad --- /dev/null +++ b/crates/papyrus_node/src/config/pointers.rs @@ -0,0 +1,72 @@ +use std::collections::{BTreeMap, HashMap}; +use std::fs::File; +use std::io::{BufWriter, Write}; +use std::mem::discriminant; +use std::ops::IndexMut; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use std::{env, fs, io}; + +use clap::{arg, value_parser, Arg, ArgMatches, Command}; +use itertools::{chain, Itertools}; +use lazy_static::lazy_static; +use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerConfig; +#[cfg(not(feature = "rpc"))] +use papyrus_config::dumping::ser_param; +use papyrus_config::dumping::{ + append_sub_config_name, + ser_optional_sub_config, + ser_pointer_target_param, + SerializeConfig, +}; +use papyrus_config::loading::load_and_process_config; +#[cfg(not(feature = "rpc"))] +use papyrus_config::ParamPrivacyInput; +use papyrus_config::{ConfigError, ParamPath, SerializedParam}; +use papyrus_monitoring_gateway::MonitoringGatewayConfig; +use papyrus_network::NetworkConfig; +use papyrus_p2p_sync::client::{P2PSyncClient, P2PSyncClientConfig}; +#[cfg(feature = "rpc")] +use papyrus_rpc::RpcConfig; +use papyrus_storage::db::DbConfig; +use papyrus_storage::StorageConfig; +use papyrus_sync::sources::central::CentralSourceConfig; +use papyrus_sync::SyncConfig; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; +use starknet_api::core::ChainId; +use starknet_client::RetryConfig; +use validator::Validate; + +use crate::version::VERSION_FULL; + +lazy_static! { + /// Returns vector of (pointer target name, pointer target serialized param, vec) + /// to be applied on the dumped node config. + /// The config updates will be performed on the shared pointer targets, and finally, the values + /// will be propagated to the pointer params. + pub static ref CONFIG_POINTERS: Vec<((ParamPath, SerializedParam), Vec)> = vec![( + ser_pointer_target_param( + "chain_id", + &ChainId::Mainnet, + "The chain to follow. For more details see https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#chain-id.", + ), + vec!["storage.db_config.chain_id".to_owned(), "rpc.chain_id".to_owned()], + ), + ( + ser_pointer_target_param( + "starknet_url", + &"https://alpha-mainnet.starknet.io/".to_string(), + "The URL of a centralized Starknet gateway.", + ), + vec!["rpc.starknet_url".to_owned(), "central.url".to_owned(), "monitoring_gateway.starknet_url".to_owned()], + ), + ( + ser_pointer_target_param( + "collect_metrics", + &false, + "If true, collect metrics for the node.", + ), + vec!["rpc.collect_metrics".to_owned(), "monitoring_gateway.collect_metrics".to_owned()], + )]; +} diff --git a/crates/papyrus_node/src/config/snapshots/papyrus_node__config__config_test__dump_default_config.snap b/crates/papyrus_node/src/config/snapshots/papyrus_node__config__config_test__dump_default_config.snap new file mode 100644 index 00000000000..7b76e5e02ea --- /dev/null +++ b/crates/papyrus_node/src/config/snapshots/papyrus_node__config__config_test__dump_default_config.snap @@ -0,0 +1,413 @@ +--- +source: crates/papyrus_node/src/config/config_test.rs +expression: dumped_default_config +--- +{ + "base_layer.node_url": { + "description": "A required param! Ethereum node URL. A schema to match to Infura node: https://mainnet.infura.io/v3/, but any other node can be used.", + "param_type": "String", + "privacy": "Private" + }, + "base_layer.starknet_contract_address": { + "description": "Starknet contract address in ethereum.", + "value": "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4", + "privacy": "Public" + }, + "central.class_cache_size": { + "description": "Size of class cache, must be a positive integer.", + "value": { + "$serde_json::private::Number": "100" + }, + "privacy": "Public" + }, + "central.concurrent_requests": { + "description": "Maximum number of concurrent requests to Starknet feeder-gateway for getting a type of data (for example, blocks).", + "value": { + "$serde_json::private::Number": "10" + }, + "privacy": "Public" + }, + "central.http_headers": { + "description": "'k1:v1 k2:v2 ...' headers for SN-client.", + "value": "", + "privacy": "Private" + }, + "central.max_classes_to_download": { + "description": "Maximum number of classes to download at a given time.", + "value": { + "$serde_json::private::Number": "20" + }, + "privacy": "Public" + }, + "central.max_state_updates_to_download": { + "description": "Maximum number of state updates to download at a given time.", + "value": { + "$serde_json::private::Number": "20" + }, + "privacy": "Public" + }, + "central.max_state_updates_to_store_in_memory": { + "description": "Maximum number of state updates to store in memory at a given time.", + "value": { + "$serde_json::private::Number": "20" + }, + "privacy": "Public" + }, + "central.retry_config.max_retries": { + "description": "Maximum number of retries before the node stops retrying.", + "value": { + "$serde_json::private::Number": "10" + }, + "privacy": "Public" + }, + "central.retry_config.retry_base_millis": { + "description": "Base waiting time after a failed request. After that, the time increases exponentially.", + "value": { + "$serde_json::private::Number": "30" + }, + "privacy": "Public" + }, + "central.retry_config.retry_max_delay_millis": { + "description": "Max waiting time after a failed request.", + "value": { + "$serde_json::private::Number": "30000" + }, + "privacy": "Public" + }, + "central.url": { + "description": "Starknet feeder-gateway URL. It should match chain_id.", + "value": "https://alpha-mainnet.starknet.io/", + "privacy": "Public" + }, + "collect_profiling_metrics": { + "description": "If true, collect profiling metrics for the node.", + "value": false, + "privacy": "Public" + }, + "consensus.#is_none": { + "description": "Flag for an optional field.", + "value": true, + "privacy": "TemporaryValue" + }, + "consensus.num_validators": { + "description": "The number of validators in the consensus.", + "value": { + "$serde_json::private::Number": "4" + }, + "privacy": "Public" + }, + "consensus.start_height": { + "description": "The height to start the consensus from.", + "value": { + "$serde_json::private::Number": "0" + }, + "privacy": "Public" + }, + "consensus.topic": { + "description": "The topic of the consensus.", + "value": "consensus", + "privacy": "Public" + }, + "consensus.validator_id": { + "description": "A required param! The validator id of the node.", + "param_type": "String", + "privacy": "Public" + }, + "monitoring_gateway.collect_metrics": { + "description": "If true, collect and return metrics in the monitoring gateway.", + "value": false, + "privacy": "Public" + }, + "monitoring_gateway.metric_labels": { + "description": "'label1:value1 label2:value2 ...' additional labels for metrics.", + "value": "", + "privacy": "Public" + }, + "monitoring_gateway.present_full_config_secret": { + "description": "A secret for presenting the full general config. If no value is provided, the system will generate one.", + "param_type": "String", + "privacy": "Private" + }, + "monitoring_gateway.server_address": { + "description": "node's monitoring server.", + "value": "0.0.0.0:8081", + "privacy": "Public" + }, + "monitoring_gateway.starknet_url": { + "description": "The URL of a centralized Starknet gateway.", + "value": "https://alpha-mainnet.starknet.io/", + "privacy": "Public" + }, + "network.#is_none": { + "description": "Flag for an optional field.", + "value": true, + "privacy": "TemporaryValue" + }, + "network.bootstrap_peer_multiaddr": { + "description": "The multiaddress of the peer node. It should include the peer's id. For more info: https://docs.libp2p.io/concepts/fundamentals/peers/", + "value": "", + "privacy": "Public" + }, + "network.bootstrap_peer_multiaddr.#is_none": { + "description": "Flag for an optional field.", + "value": true, + "privacy": "TemporaryValue" + }, + "network.idle_connection_timeout": { + "description": "Amount of time in seconds that a connection with no active sessions will stay alive.", + "value": { + "$serde_json::private::Number": "120" + }, + "privacy": "Public" + }, + "network.quic_port": { + "description": "The port that the node listens on for incoming quic connections.", + "value": { + "$serde_json::private::Number": "10001" + }, + "privacy": "Public" + }, + "network.secret_key": { + "description": "The secret key used for building the peer id. If it's an empty string a random one will be used.", + "value": "", + "privacy": "Private" + }, + "network.session_timeout": { + "description": "Maximal time in seconds that each session can take before failing on timeout.", + "value": { + "$serde_json::private::Number": "120" + }, + "privacy": "Public" + }, + "network.tcp_port": { + "description": "The port that the node listens on for incoming tcp connections.", + "value": { + "$serde_json::private::Number": "10000" + }, + "privacy": "Public" + }, + "p2p_sync.#is_none": { + "description": "Flag for an optional field.", + "value": true, + "privacy": "TemporaryValue" + }, + "p2p_sync.buffer_size": { + "description": "Size of the buffer for read from the storage and for incoming responses.", + "value": { + "$serde_json::private::Number": "100000" + }, + "privacy": "Public" + }, + "p2p_sync.num_block_state_diffs_per_query": { + "description": "The maximum amount of block's state diffs to ask from peers in each iteration.", + "value": { + "$serde_json::private::Number": "100" + }, + "privacy": "Public" + }, + "p2p_sync.num_headers_per_query": { + "description": "The maximum amount of headers to ask from peers in each iteration.", + "value": { + "$serde_json::private::Number": "10000" + }, + "privacy": "Public" + }, + "p2p_sync.stop_sync_at_block_number": { + "description": "Stops the sync at given block number and closes the node cleanly. Used to run profiling on the node.", + "value": { + "$serde_json::private::Number": "1000" + }, + "privacy": "Public" + }, + "p2p_sync.stop_sync_at_block_number.#is_none": { + "description": "Flag for an optional field.", + "value": true, + "privacy": "TemporaryValue" + }, + "p2p_sync.wait_period_for_new_data": { + "description": "Time in seconds to wait when a query returned with partial data before sending a new query", + "value": { + "$serde_json::private::Number": "5" + }, + "privacy": "Public" + }, + "rpc.chain_id": { + "description": "The chain to follow. For more details see https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#chain-id.", + "value": "SN_MAIN", + "privacy": "Public" + }, + "rpc.collect_metrics": { + "description": "If true, collect metrics for the rpc.", + "value": false, + "privacy": "Public" + }, + "rpc.execution_config.eth_fee_contract_address": { + "description": "The eth fee token address to receive fees", + "value": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "privacy": "Public" + }, + "rpc.execution_config.initial_gas_cost": { + "description": "The initial gas cost for a transaction", + "value": { + "$serde_json::private::Number": "10000000000" + }, + "privacy": "Public" + }, + "rpc.execution_config.strk_fee_contract_address": { + "description": "The strk fee token address to receive fees", + "value": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "privacy": "Public" + }, + "rpc.max_events_chunk_size": { + "description": "Maximum chunk size supported by the node in get_events requests.", + "value": { + "$serde_json::private::Number": "1000" + }, + "privacy": "Public" + }, + "rpc.max_events_keys": { + "description": "Maximum number of keys supported by the node in get_events requests.", + "value": { + "$serde_json::private::Number": "100" + }, + "privacy": "Public" + }, + "rpc.server_address": { + "description": "IP:PORT of the node`s JSON-RPC server.", + "value": "0.0.0.0:8080", + "privacy": "Public" + }, + "rpc.starknet_gateway_retry_config.max_retries": { + "description": "For communicating with Starknet gateway, maximum number of retries before the node stops retrying.", + "value": { + "$serde_json::private::Number": "5" + }, + "privacy": "Public" + }, + "rpc.starknet_gateway_retry_config.retry_base_millis": { + "description": "For communicating with Starknet gateway, base waiting time after a failed request. After that, the time increases exponentially.", + "value": { + "$serde_json::private::Number": "50" + }, + "privacy": "Public" + }, + "rpc.starknet_gateway_retry_config.retry_max_delay_millis": { + "description": "For communicating with Starknet gateway, max waiting time after a failed request.", + "value": { + "$serde_json::private::Number": "1000" + }, + "privacy": "Public" + }, + "rpc.starknet_url": { + "description": "URL for communicating with Starknet in write_api methods.", + "value": "https://alpha-mainnet.starknet.io/", + "privacy": "Public" + }, + "storage.db_config.chain_id": { + "description": "The chain to follow. For more details see https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#chain-id.", + "value": "SN_MAIN", + "privacy": "Public" + }, + "storage.db_config.enforce_file_exists": { + "description": "Whether to enforce that the path exists. If true, `open_env` fails when the mdbx.dat file does not exist.", + "value": false, + "privacy": "Public" + }, + "storage.db_config.growth_step": { + "description": "The growth step in bytes, must be greater than zero to allow the database to grow.", + "value": { + "$serde_json::private::Number": "4294967296" + }, + "privacy": "Public" + }, + "storage.db_config.max_size": { + "description": "The maximum size of the node's storage in bytes.", + "value": { + "$serde_json::private::Number": "1099511627776" + }, + "privacy": "Public" + }, + "storage.db_config.min_size": { + "description": "The minimum size of the node's storage in bytes.", + "value": { + "$serde_json::private::Number": "1048576" + }, + "privacy": "Public" + }, + "storage.db_config.path_prefix": { + "description": "Prefix of the path of the node's storage directory, the storage file path will be /. The path is not created automatically.", + "value": "./data", + "privacy": "Public" + }, + "storage.mmap_file_config.growth_step": { + "description": "The growth step in bytes, must be greater than max_object_size.", + "value": { + "$serde_json::private::Number": "1073741824" + }, + "privacy": "Public" + }, + "storage.mmap_file_config.max_object_size": { + "description": "The maximum size of a single object in the file in bytes", + "value": { + "$serde_json::private::Number": "268435456" + }, + "privacy": "Public" + }, + "storage.mmap_file_config.max_size": { + "description": "The maximum size of a memory mapped file in bytes. Must be greater than growth_step.", + "value": { + "$serde_json::private::Number": "1099511627776" + }, + "privacy": "Public" + }, + "storage.scope": { + "description": "The categories of data saved in storage.", + "value": "FullArchive", + "privacy": "Public" + }, + "sync.#is_none": { + "description": "Flag for an optional field.", + "value": false, + "privacy": "TemporaryValue" + }, + "sync.base_layer_propagation_sleep_duration": { + "description": "Time in seconds to poll the base layer to get the latest proved block.", + "value": { + "$serde_json::private::Number": "10" + }, + "privacy": "Public" + }, + "sync.block_propagation_sleep_duration": { + "description": "Time in seconds before checking for a new block after the node is synchronized.", + "value": { + "$serde_json::private::Number": "2" + }, + "privacy": "Public" + }, + "sync.blocks_max_stream_size": { + "description": "Max amount of blocks to download in a stream.", + "value": { + "$serde_json::private::Number": "1000" + }, + "privacy": "Public" + }, + "sync.recoverable_error_sleep_duration": { + "description": "Waiting time in seconds before restarting synchronization after a recoverable error.", + "value": { + "$serde_json::private::Number": "3" + }, + "privacy": "Public" + }, + "sync.state_updates_max_stream_size": { + "description": "Max amount of state updates to download in a stream.", + "value": { + "$serde_json::private::Number": "1000" + }, + "privacy": "Public" + }, + "sync.verify_blocks": { + "description": "Whether to verify incoming blocks.", + "value": true, + "privacy": "Public" + } +} diff --git a/crates/papyrus_node/src/lib.rs b/crates/papyrus_node/src/lib.rs new file mode 100644 index 00000000000..924916d963e --- /dev/null +++ b/crates/papyrus_node/src/lib.rs @@ -0,0 +1,9 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +#[allow(unused_imports)] +pub mod config; +#[cfg(test)] +mod precision_test; +pub mod version; diff --git a/crates/papyrus_node/src/main.rs b/crates/papyrus_node/src/main.rs new file mode 100644 index 00000000000..71d3e5f3507 --- /dev/null +++ b/crates/papyrus_node/src/main.rs @@ -0,0 +1,455 @@ +#[cfg(test)] +mod main_test; + +use std::env::args; +use std::future::{pending, Future}; +use std::process::exit; +use std::sync::Arc; +use std::time::Duration; + +use futures::future::BoxFuture; +use futures::FutureExt; +use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerConfig; +use papyrus_common::metrics::COLLECT_PROFILING_METRICS; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses}; +use papyrus_common::BlockHashAndNumber; +use papyrus_config::presentation::get_config_presentation; +use papyrus_config::validators::config_validate; +use papyrus_config::ConfigError; +use papyrus_consensus::config::ConsensusConfig; +use papyrus_consensus::papyrus_consensus_context::PapyrusConsensusContext; +use papyrus_consensus::types::ConsensusError; +use papyrus_monitoring_gateway::MonitoringServer; +use papyrus_network::gossipsub_impl::Topic; +use papyrus_network::network_manager::{ + BroadcastSubscriberChannels, + NetworkError, + SqmrQueryReceiver, +}; +use papyrus_network::{network_manager, NetworkConfig}; +use papyrus_node::config::NodeConfig; +use papyrus_node::version::VERSION_FULL; +use papyrus_p2p_sync::client::{ + P2PSyncClient, + P2PSyncClientChannels, + P2PSyncClientConfig, + P2PSyncError, +}; +use papyrus_p2p_sync::server::P2PSyncServer; +use papyrus_p2p_sync::{Protocol, BUFFER_SIZE}; +use papyrus_protobuf::consensus::ConsensusMessage; +use papyrus_protobuf::sync::{ + ClassQuery, + DataOrFin, + EventQuery, + HeaderQuery, + SignedBlockHeader, + StateDiffChunk, + StateDiffQuery, + TransactionQuery, +}; +#[cfg(feature = "rpc")] +use papyrus_rpc::run_server; +use papyrus_storage::{open_storage, update_storage_metrics, StorageReader, StorageWriter}; +use papyrus_sync::sources::base_layer::{BaseLayerSourceError, EthereumBaseLayerSource}; +use papyrus_sync::sources::central::{CentralError, CentralSource, CentralSourceConfig}; +use papyrus_sync::sources::pending::PendingSource; +use papyrus_sync::{StateSync, StateSyncError, SyncConfig}; +use starknet_api::block::BlockHash; +use starknet_api::felt; +use starknet_api::transaction::{Event, Transaction, TransactionHash, TransactionOutput}; +use starknet_client::reader::objects::pending_data::{PendingBlock, PendingBlockOrDeprecated}; +use starknet_client::reader::PendingData; +use tokio::sync::RwLock; +use tokio::task::{JoinError, JoinHandle}; +use tracing::metadata::LevelFilter; +use tracing::{debug_span, error, info, warn, Instrument}; +use tracing_subscriber::prelude::*; +use tracing_subscriber::{fmt, EnvFilter}; + +// TODO(yair): Add to config. +const DEFAULT_LEVEL: LevelFilter = LevelFilter::INFO; + +// TODO(shahak): Consider adding genesis hash to the config to support chains that have +// different genesis hash. +// TODO: Consider moving to a more general place. +const GENESIS_HASH: &str = "0x0"; + +// TODO(dvir): add this to config. +// Duration between updates to the storage metrics (those in the collect_storage_metrics function). +const STORAGE_METRICS_UPDATE_INTERVAL: Duration = Duration::from_secs(10); + +#[cfg(feature = "rpc")] +async fn create_rpc_server_future( + config: &NodeConfig, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + storage_reader: StorageReader, +) -> anyhow::Result>> { + let (_, server_handle) = run_server( + &config.rpc, + shared_highest_block, + pending_data, + pending_classes, + storage_reader, + VERSION_FULL, + ) + .await?; + Ok(tokio::spawn(server_handle.stopped())) +} + +#[cfg(not(feature = "rpc"))] +async fn create_rpc_server_future( + _config: &NodeConfig, + _shared_highest_block: Arc>>, + _pending_data: Arc>, + _pending_classes: Arc>, + _storage_reader: StorageReader, +) -> anyhow::Result>> { + Ok(pending()) +} + +fn run_consensus( + config: ConsensusConfig, + storage_reader: StorageReader, + consensus_channels: BroadcastSubscriberChannels, +) -> anyhow::Result>> { + let validator_id = config.validator_id; + info!("Running consensus as validator {validator_id}"); + let context = PapyrusConsensusContext::new( + storage_reader.clone(), + consensus_channels.messages_to_broadcast_sender, + config.num_validators, + ); + let start_height = config.start_height; + + Ok(tokio::spawn(papyrus_consensus::run_consensus( + context, + start_height, + validator_id, + consensus_channels.broadcasted_messages_receiver, + ))) +} + +async fn run_threads(config: NodeConfig) -> anyhow::Result<()> { + let (storage_reader, storage_writer) = open_storage(config.storage.clone())?; + + let storage_metrics_handle = if config.monitoring_gateway.collect_metrics { + spawn_storage_metrics_collector(storage_reader.clone(), STORAGE_METRICS_UPDATE_INTERVAL) + } else { + tokio::spawn(pending()) + }; + + // P2P network. + let ( + network_future, + maybe_sync_client_channels, + maybe_sync_server_channels, + maybe_consensus_channels, + local_peer_id, + ) = run_network(config.network.clone(), config.consensus.clone())?; + let network_handle = tokio::spawn(network_future); + + // Monitoring server. + let monitoring_server = MonitoringServer::new( + config.monitoring_gateway.clone(), + get_config_presentation(&config, true)?, + get_config_presentation(&config, false)?, + storage_reader.clone(), + VERSION_FULL, + local_peer_id, + )?; + let monitoring_server_handle = monitoring_server.spawn_server().await; + + // The sync is the only writer of the syncing state. + let shared_highest_block = Arc::new(RwLock::new(None)); + let pending_data = Arc::new(RwLock::new(PendingData { + // The pending data might change later to DeprecatedPendingBlock, depending on the response + // from the feeder gateway. + block: PendingBlockOrDeprecated::Current(PendingBlock { + parent_block_hash: BlockHash(felt!(GENESIS_HASH)), + ..Default::default() + }), + ..Default::default() + })); + let pending_classes = Arc::new(RwLock::new(PendingClasses::default())); + + // JSON-RPC server. + let server_handle_future = create_rpc_server_future( + &config, + shared_highest_block.clone(), + pending_data.clone(), + pending_classes.clone(), + storage_reader.clone(), + ) + .await?; + + // P2P Sync Server task. + let p2p_sync_server_future = match maybe_sync_server_channels { + Some(( + header_server_channel, + state_diff_server_channel, + transaction_server_channel, + class_server_channel, + event_server_channel, + )) => { + let p2p_sync_server = P2PSyncServer::new( + storage_reader.clone(), + header_server_channel, + state_diff_server_channel, + transaction_server_channel, + class_server_channel, + event_server_channel, + ); + p2p_sync_server.run().boxed() + } + None => pending().boxed(), + }; + let p2p_sync_server_handle = tokio::spawn(p2p_sync_server_future); + + // Sync task. + let (sync_future, p2p_sync_client_future) = match (config.sync, config.p2p_sync) { + (Some(_), Some(_)) => { + panic!("One of --sync.#is_none or --p2p_sync.#is_none must be turned on"); + } + (Some(sync_config), None) => { + let configs = (sync_config, config.central, config.base_layer); + let storage = (storage_reader.clone(), storage_writer); + let sync_fut = + run_sync(configs, shared_highest_block, pending_data, pending_classes, storage); + (sync_fut.boxed(), pending().boxed()) + } + (None, Some(p2p_sync_client_config)) => { + let p2p_sync_client_channels = maybe_sync_client_channels + .expect("If p2p sync is enabled, network needs to be enabled too"); + ( + pending().boxed(), + run_p2p_sync_client( + p2p_sync_client_config, + storage_reader.clone(), + storage_writer, + p2p_sync_client_channels, + ) + .boxed(), + ) + } + (None, None) => (pending().boxed(), pending().boxed()), + }; + let sync_handle = tokio::spawn(sync_future); + let p2p_sync_client_handle = tokio::spawn(p2p_sync_client_future); + + let consensus_handle = if let Some(consensus_channels) = maybe_consensus_channels { + run_consensus( + config.consensus.expect("If consensus_channels is Some, consensus must be Some too."), + storage_reader.clone(), + consensus_channels, + )? + } else { + tokio::spawn(pending()) + }; + + tokio::select! { + res = storage_metrics_handle => { + error!("collecting storage metrics stopped."); + res? + } + res = server_handle_future => { + error!("RPC server stopped."); + res? + } + res = monitoring_server_handle => { + error!("Monitoring server stopped."); + res?? + } + res = sync_handle => { + error!("Sync stopped."); + res?? + } + res = p2p_sync_client_handle => { + error!("P2P Sync stopped."); + res?? + } + res = p2p_sync_server_handle => { + error!("P2P Sync server stopped"); + res? + } + res = network_handle => { + error!("Network stopped."); + res?? + } + res = consensus_handle => { + error!("Consensus stopped."); + res?? + } + }; + error!("Task ended with unexpected Ok."); + return Ok(()); + + async fn run_sync( + configs: (SyncConfig, CentralSourceConfig, EthereumBaseLayerConfig), + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + storage: (StorageReader, StorageWriter), + ) -> Result<(), StateSyncError> { + let (sync_config, central_config, base_layer_config) = configs; + let (storage_reader, storage_writer) = storage; + let central_source = + CentralSource::new(central_config.clone(), VERSION_FULL, storage_reader.clone()) + .map_err(CentralError::ClientCreation)?; + let pending_source = PendingSource::new(central_config, VERSION_FULL) + .map_err(CentralError::ClientCreation)?; + let base_layer_source = EthereumBaseLayerSource::new(base_layer_config) + .map_err(|e| BaseLayerSourceError::BaseLayerSourceCreationError(e.to_string()))?; + let mut sync = StateSync::new( + sync_config, + shared_highest_block, + pending_data, + pending_classes, + central_source, + pending_source, + base_layer_source, + storage_reader.clone(), + storage_writer, + ); + sync.run().await + } + + async fn run_p2p_sync_client( + p2p_sync_client_config: P2PSyncClientConfig, + storage_reader: StorageReader, + storage_writer: StorageWriter, + p2p_sync_client_channels: P2PSyncClientChannels, + ) -> Result<(), P2PSyncError> { + let p2p_sync = P2PSyncClient::new( + p2p_sync_client_config, + storage_reader, + storage_writer, + p2p_sync_client_channels, + ); + p2p_sync.run().await + } +} + +type NetworkRunReturn = ( + BoxFuture<'static, Result<(), NetworkError>>, + Option, + Option<( + SqmrQueryReceiver>, + SqmrQueryReceiver>, + SqmrQueryReceiver>, + SqmrQueryReceiver>, + SqmrQueryReceiver>, + )>, + Option>, + String, +); + +fn run_network( + network_config: Option, + consensus_config: Option, +) -> anyhow::Result { + let Some(network_config) = network_config else { + return Ok((pending().boxed(), None, None, None, "".to_string())); + }; + let mut network_manager = network_manager::NetworkManager::new(network_config.clone()); + let local_peer_id = network_manager.get_local_peer_id(); + let header_client_sender = network_manager + .register_sqmr_protocol_client(Protocol::SignedBlockHeader.into(), BUFFER_SIZE); + let state_diff_client_sender = + network_manager.register_sqmr_protocol_client(Protocol::StateDiff.into(), BUFFER_SIZE); + let transaction_client_sender = + network_manager.register_sqmr_protocol_client(Protocol::Transaction.into(), BUFFER_SIZE); + + let header_server_channel = network_manager + .register_sqmr_protocol_server(Protocol::SignedBlockHeader.into(), BUFFER_SIZE); + let state_diff_server_channel = + network_manager.register_sqmr_protocol_server(Protocol::StateDiff.into(), BUFFER_SIZE); + let transaction_server_channel = + network_manager.register_sqmr_protocol_server(Protocol::Transaction.into(), BUFFER_SIZE); + let class_server_channel = + network_manager.register_sqmr_protocol_server(Protocol::Class.into(), BUFFER_SIZE); + let event_server_channel = + network_manager.register_sqmr_protocol_server(Protocol::Event.into(), BUFFER_SIZE); + + let consensus_channels = match consensus_config { + Some(consensus_config) => Some( + network_manager + .register_broadcast_topic(Topic::new(consensus_config.topic), BUFFER_SIZE)?, + ), + None => None, + }; + let p2p_sync_channels = P2PSyncClientChannels { + header_payload_sender: header_client_sender, + state_diff_payload_sender: state_diff_client_sender, + transaction_payload_sender: transaction_client_sender, + }; + + Ok(( + network_manager.run().boxed(), + Some(p2p_sync_channels), + Some(( + header_server_channel, + state_diff_server_channel, + transaction_server_channel, + class_server_channel, + event_server_channel, + )), + consensus_channels, + local_peer_id, + )) +} + +// TODO(yair): add dynamic level filtering. +// TODO(dan): filter out logs from dependencies (happens when RUST_LOG=DEBUG) +// TODO(yair): define and implement configurable filtering. +fn configure_tracing() { + let fmt_layer = fmt::layer().compact().with_target(false); + let level_filter_layer = + EnvFilter::builder().with_default_directive(DEFAULT_LEVEL.into()).from_env_lossy(); + + // This sets a single subscriber to all of the threads. We may want to implement different + // subscriber for some threads and use set_global_default instead of init. + tracing_subscriber::registry().with(fmt_layer).with(level_filter_layer).init(); +} + +fn spawn_storage_metrics_collector( + storage_reader: StorageReader, + update_interval: Duration, +) -> JoinHandle<()> { + tokio::spawn( + async move { + loop { + if let Err(error) = update_storage_metrics(&storage_reader) { + warn!("Failed to update storage metrics: {error}"); + } + tokio::time::sleep(update_interval).await; + } + } + .instrument(debug_span!("collect_storage_metrics")), + ) +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let config = NodeConfig::load_and_process(args().collect()); + if let Err(ConfigError::CommandInput(clap_err)) = config { + clap_err.exit(); + } + + configure_tracing(); + + let config = config?; + if let Err(errors) = config_validate(&config) { + error!("{}", errors); + exit(1); + } + + COLLECT_PROFILING_METRICS + .set(config.collect_profiling_metrics) + .expect("This should be the first and only time we set this value."); + + info!("Booting up."); + run_threads(config).await +} diff --git a/crates/papyrus_node/src/main_test.rs b/crates/papyrus_node/src/main_test.rs new file mode 100644 index 00000000000..7b4864e2e4f --- /dev/null +++ b/crates/papyrus_node/src/main_test.rs @@ -0,0 +1,43 @@ +use std::time::Duration; + +use metrics_exporter_prometheus::PrometheusBuilder; +use papyrus_node::config::NodeConfig; +use papyrus_storage::{open_storage, StorageConfig}; +use tempfile::TempDir; +use test_utils::prometheus_is_contained; + +use crate::{run_threads, spawn_storage_metrics_collector}; + +// The mission of this test is to ensure that if an error is returned from one of the spawned tasks, +// the node will stop, and this error will be returned. This is done by checking the case of an +// illegal central URL, which will cause the sync task to return an error. +#[tokio::test] +async fn run_threads_stop() { + let mut config = NodeConfig::default(); + let temp_dir = TempDir::new().unwrap(); + config.storage.db_config.path_prefix = temp_dir.path().into(); + + // Error when not supplying legal central URL. + config.central.url = "_not_legal_url".to_string(); + let error = run_threads(config).await.expect_err("Should be an error."); + assert_eq!("relative URL without a base", error.to_string()); +} + +// TODO(dvir): use here metrics names from the storage instead of hard-coded ones. This will be done +// only after changes to the metrics structure in papyrus. +#[tokio::test] +async fn storage_metrics_collector() { + let mut storage_config = StorageConfig::default(); + let temp_dir = TempDir::new().unwrap(); + storage_config.db_config.path_prefix = temp_dir.path().into(); + let (storage_reader, _storage_writer) = open_storage(storage_config).unwrap(); + let handle = PrometheusBuilder::new().install_recorder().unwrap(); + + assert!(prometheus_is_contained(handle.render(), "storage_free_pages_number", &[]).is_none()); + + spawn_storage_metrics_collector(storage_reader, Duration::from_secs(1)); + // To make sure the metrics in the spawned thread are updated. + tokio::time::sleep(Duration::from_millis(1)).await; + + assert!(prometheus_is_contained(handle.render(), "storage_free_pages_number", &[]).is_some()); +} diff --git a/crates/papyrus_node/src/precision_test.rs b/crates/papyrus_node/src/precision_test.rs new file mode 100644 index 00000000000..18138b3f646 --- /dev/null +++ b/crates/papyrus_node/src/precision_test.rs @@ -0,0 +1,10 @@ +use pretty_assertions::assert_eq; + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_node/src/version.rs b/crates/papyrus_node/src/version.rs new file mode 100644 index 00000000000..fdc95909c5a --- /dev/null +++ b/crates/papyrus_node/src/version.rs @@ -0,0 +1,52 @@ +#[cfg(test)] +#[path = "version_test.rs"] +mod version_test; + +/// Major version component of the current release. +const VERSION_MAJOR: u32 = 0; + +/// Minor version component of the current release. +const VERSION_MINOR: u32 = 5; + +/// Patch version component of the current release. +const VERSION_PATCH: u32 = 0; + +/// Version metadata to append to the version string. +/// Expected values are `dev` and `stable`. +const VERSION_META: Metadata = Metadata::Dev; + +/// Textual version string. +pub const VERSION: &str = version_str(); +/// Textual version string including the metadata. +pub const VERSION_FULL: &str = full_version_str(); + +const DEV_VERSION_META: &str = "dev"; +const STABLE_VERSION_META: &str = "stable"; + +#[allow(dead_code)] +#[derive(PartialEq)] +enum Metadata { + Dev, + Stable, +} + +#[cfg_attr(coverage_nightly, coverage_attribute)] +const fn version_str() -> &'static str { + const_format::concatcp!(VERSION_MAJOR, ".", VERSION_MINOR, ".", VERSION_PATCH) +} + +#[cfg_attr(coverage_nightly, coverage_attribute)] +const fn full_version_str() -> &'static str { + match VERSION_META { + Metadata::Dev => const_format::concatcp!(VERSION, "-", DEV_VERSION_META), + Metadata::Stable => VERSION, + } +} + +#[allow(dead_code)] +const fn metadata_str(metadata: Metadata) -> &'static str { + match metadata { + Metadata::Dev => DEV_VERSION_META, + Metadata::Stable => STABLE_VERSION_META, + } +} diff --git a/crates/papyrus_node/src/version_test.rs b/crates/papyrus_node/src/version_test.rs new file mode 100644 index 00000000000..13afebce468 --- /dev/null +++ b/crates/papyrus_node/src/version_test.rs @@ -0,0 +1,16 @@ +use pretty_assertions::assert_eq; + +#[test] +fn version() { + let expected_version = + format!("{}.{}.{}", super::VERSION_MAJOR, super::VERSION_MINOR, super::VERSION_PATCH); + assert_eq!(super::VERSION, expected_version); + + let expected_version_with_meta = match super::VERSION_META { + crate::version::Metadata::Dev => { + format!("{}-{}", expected_version, super::metadata_str(super::VERSION_META)) + } + crate::version::Metadata::Stable => expected_version, + }; + assert_eq!(super::VERSION_FULL, expected_version_with_meta); +} diff --git a/crates/papyrus_p2p_sync/Cargo.toml b/crates/papyrus_p2p_sync/Cargo.toml new file mode 100644 index 00000000000..e2e2bdef455 --- /dev/null +++ b/crates/papyrus_p2p_sync/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "papyrus_p2p_sync" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[dependencies] +async-stream.workspace = true +enum-iterator.workspace = true +futures.workspace = true +indexmap.workspace = true +lazy_static.workspace = true +metrics.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_network = { path = "../papyrus_network", version = "0.4.0-rc.0" } +papyrus_proc_macros = { path = "../papyrus_proc_macros", version = "0.4.0-rc.0" } +papyrus_protobuf = { path = "../papyrus_protobuf", version = "0.4.0-rc.0" } +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +serde.workspace = true +starknet_api.workspace = true +starknet-types-core.workspace = true +thiserror.workspace = true +tokio.workspace = true +tokio-stream.workspace = true +tracing.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +lazy_static.workspace = true +papyrus_storage = { path = "../papyrus_storage", features = ["testing"] } +static_assertions.workspace = true +rand.workspace = true +rand_chacha.workspace = true +test_utils = { path = "../test_utils" } +papyrus_protobuf = { path = "../papyrus_protobuf", features = ["testing"]} + +# The `metrics` crate is used by `latency_histogram` proc macro, which is used in this crate. +[package.metadata.cargo-machete] +ignored = ["metrics"] diff --git a/crates/papyrus_p2p_sync/src/client/header.rs b/crates/papyrus_p2p_sync/src/client/header.rs new file mode 100644 index 00000000000..32c2acc53c1 --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/header.rs @@ -0,0 +1,77 @@ +use futures::future::BoxFuture; +use futures::{FutureExt, StreamExt}; +use papyrus_protobuf::sync::SignedBlockHeader; +use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use starknet_api::block::BlockNumber; + +use super::stream_builder::{BlockData, BlockNumberLimit, DataStreamBuilder}; +use super::{P2PSyncError, ResponseReceiver, ALLOWED_SIGNATURES_LENGTH, NETWORK_DATA_TIMEOUT}; + +impl BlockData for SignedBlockHeader { + fn write_to_storage( + self: Box, + storage_writer: &mut StorageWriter, + ) -> Result<(), StorageError> { + storage_writer + .begin_rw_txn()? + .append_header(self.block_header.block_number, &self.block_header)? + .append_block_signature( + self.block_header.block_number, + self + .signatures + // In the future we will support multiple signatures. + .first() + // The verification that the size of the vector is 1 is done in the data + // verification. + .expect("Vec::first should return a value on a vector of size 1"), + )? + .commit() + } +} + +pub(crate) struct HeaderStreamBuilder; + +impl DataStreamBuilder for HeaderStreamBuilder { + type Output = SignedBlockHeader; + + const TYPE_DESCRIPTION: &'static str = "headers"; + const BLOCK_NUMBER_LIMIT: BlockNumberLimit = BlockNumberLimit::Unlimited; + + fn parse_data_for_block<'a>( + signed_headers_receiver: &'a mut ResponseReceiver, + block_number: BlockNumber, + _storage_reader: &'a StorageReader, + ) -> BoxFuture<'a, Result, P2PSyncError>> { + async move { + let maybe_signed_header = + tokio::time::timeout(NETWORK_DATA_TIMEOUT, signed_headers_receiver.next()) + .await? + .ok_or(P2PSyncError::ReceiverChannelTerminated { + type_description: Self::TYPE_DESCRIPTION, + })?; + let Some(signed_block_header) = maybe_signed_header?.0 else { + return Ok(None); + }; + // TODO(shahak): Check that parent_hash is the same as the previous block's hash + // and handle reverts. + if block_number != signed_block_header.block_header.block_number { + return Err(P2PSyncError::HeadersUnordered { + expected_block_number: block_number, + actual_block_number: signed_block_header.block_header.block_number, + }); + } + if signed_block_header.signatures.len() != ALLOWED_SIGNATURES_LENGTH { + return Err(P2PSyncError::WrongSignaturesLength { + signatures: signed_block_header.signatures, + }); + } + Ok(Some(signed_block_header)) + } + .boxed() + } + + fn get_start_block_number(storage_reader: &StorageReader) -> Result { + storage_reader.begin_ro_txn()?.get_header_marker() + } +} diff --git a/crates/papyrus_p2p_sync/src/client/header_test.rs b/crates/papyrus_p2p_sync/src/client/header_test.rs new file mode 100644 index 00000000000..912c48f106b --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/header_test.rs @@ -0,0 +1,177 @@ +use futures::{SinkExt, StreamExt}; +use papyrus_network::network_manager::SqmrClientPayload; +use papyrus_protobuf::sync::{ + BlockHashOrNumber, + DataOrFin, + Direction, + HeaderQuery, + Query, + SignedBlockHeader, +}; +use papyrus_storage::header::HeaderStorageReader; +use starknet_api::block::{BlockHeader, BlockNumber}; +use tokio::time::timeout; + +use super::test_utils::{ + create_block_hashes_and_signatures, + setup, + TestArgs, + HEADER_QUERY_LENGTH, + SLEEP_DURATION_TO_LET_SYNC_ADVANCE, + TIMEOUT_FOR_NEW_QUERY_AFTER_PARTIAL_RESPONSE, +}; + +#[tokio::test] +async fn signed_headers_basic_flow() { + const NUM_QUERIES: u64 = 3; + + let TestArgs { + p2p_sync, + storage_reader, + mut header_payload_receiver, + // The test will fail if we drop these + state_diff_payload_receiver: _state_diff_query_receiver, + .. + } = setup(); + let block_hashes_and_signatures = + create_block_hashes_and_signatures((NUM_QUERIES * HEADER_QUERY_LENGTH).try_into().unwrap()); + + // Create a future that will receive queries, send responses and validate the results. + let parse_queries_future = async move { + for query_index in 0..NUM_QUERIES { + let start_block_number = query_index * HEADER_QUERY_LENGTH; + let end_block_number = (query_index + 1) * HEADER_QUERY_LENGTH; + + // Receive query and validate it. + let SqmrClientPayload { + query, + report_receiver: _report_receiver, + responses_sender: mut headers_sender, + } = header_payload_receiver.next().await.unwrap(); + assert_eq!( + query, + HeaderQuery(Query { + start_block: BlockHashOrNumber::Number(BlockNumber(start_block_number)), + direction: Direction::Forward, + limit: HEADER_QUERY_LENGTH, + step: 1, + }) + ); + + for (i, (block_hash, block_signature)) in block_hashes_and_signatures + .iter() + .enumerate() + .take(end_block_number.try_into().expect("Failed converting u64 to usize")) + .skip(start_block_number.try_into().expect("Failed converting u64 to usize")) + { + // Send responses + headers_sender + .send(Ok(DataOrFin(Some(SignedBlockHeader { + block_header: BlockHeader { + block_number: BlockNumber(i.try_into().unwrap()), + block_hash: *block_hash, + state_diff_length: Some(0), + ..Default::default() + }, + signatures: vec![*block_signature], + })))) + .await + .unwrap(); + + tokio::time::sleep(SLEEP_DURATION_TO_LET_SYNC_ADVANCE).await; + + // Check responses were written to the storage. This way we make sure that the sync + // writes to the storage each response it receives before all query responses were + // sent. + let block_number = BlockNumber(i.try_into().unwrap()); + let txn = storage_reader.begin_ro_txn().unwrap(); + assert_eq!(block_number.unchecked_next(), txn.get_header_marker().unwrap()); + let block_header = txn.get_block_header(block_number).unwrap().unwrap(); + assert_eq!(block_number, block_header.block_number); + assert_eq!(*block_hash, block_header.block_hash); + let actual_block_signature = + txn.get_block_signature(block_number).unwrap().unwrap(); + assert_eq!(*block_signature, actual_block_signature); + } + headers_sender.send(Ok(DataOrFin(None))).await.unwrap(); + } + }; + + tokio::select! { + sync_result = p2p_sync.run() => { + sync_result.unwrap(); + panic!("P2P sync aborted with no failure."); + } + _ = parse_queries_future => {} + } +} + +#[tokio::test] +async fn sync_sends_new_header_query_if_it_got_partial_responses() { + const NUM_ACTUAL_RESPONSES: u8 = 2; + assert!(u64::from(NUM_ACTUAL_RESPONSES) < HEADER_QUERY_LENGTH); + + let TestArgs { + p2p_sync, + mut header_payload_receiver, + // The test will fail if we drop these + state_diff_payload_receiver: _state_diff_query_receiver, + .. + } = setup(); + let block_hashes_and_signatures = create_block_hashes_and_signatures(NUM_ACTUAL_RESPONSES); + + // Create a future that will receive a query, send partial responses and receive the next query. + let parse_queries_future = async move { + let SqmrClientPayload { + query: _query, + report_receiver: _report_receiver, + responses_sender: mut headers_sender, + } = header_payload_receiver.next().await.unwrap(); + + for (i, (block_hash, signature)) in block_hashes_and_signatures.into_iter().enumerate() { + headers_sender + .send(Ok(DataOrFin(Some(SignedBlockHeader { + block_header: BlockHeader { + block_number: BlockNumber(i.try_into().unwrap()), + block_hash, + state_diff_length: Some(0), + ..Default::default() + }, + signatures: vec![signature], + })))) + .await + .unwrap(); + } + headers_sender.send(Ok(DataOrFin(None))).await.unwrap(); + + // First unwrap is for the timeout. Second unwrap is for the Option returned from Stream. + let SqmrClientPayload { + query, + report_receiver: _report_receiver, + responses_sender: _responses_sender, + } = timeout(TIMEOUT_FOR_NEW_QUERY_AFTER_PARTIAL_RESPONSE, header_payload_receiver.next()) + .await + .unwrap() + .unwrap(); + + assert_eq!( + query, + HeaderQuery(Query { + start_block: BlockHashOrNumber::Number(BlockNumber(NUM_ACTUAL_RESPONSES.into())), + direction: Direction::Forward, + limit: HEADER_QUERY_LENGTH, + step: 1, + }) + ); + }; + + tokio::select! { + sync_result = p2p_sync.run() => { + sync_result.unwrap(); + panic!("P2P sync aborted with no failure."); + } + _ = parse_queries_future => {} + } +} + +// TODO(shahak): Add negative tests. diff --git a/crates/papyrus_p2p_sync/src/client/mod.rs b/crates/papyrus_p2p_sync/src/client/mod.rs new file mode 100644 index 00000000000..cf6112db378 --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/mod.rs @@ -0,0 +1,256 @@ +mod header; +#[cfg(test)] +mod header_test; +mod state_diff; +#[cfg(test)] +mod state_diff_test; +mod stream_builder; +#[cfg(test)] +mod test_utils; + +use std::collections::BTreeMap; +use std::time::Duration; + +use futures::channel::mpsc::SendError; +use futures::future::{ready, Ready}; +use futures::sink::With; +use futures::{SinkExt, Stream}; +use header::HeaderStreamBuilder; +use papyrus_config::converters::deserialize_seconds_to_duration; +use papyrus_config::dumping::{ser_optional_param, ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_network::network_manager::{SqmrClientPayload, SqmrClientSender}; +use papyrus_protobuf::converters::ProtobufConversionError; +use papyrus_protobuf::sync::{ + DataOrFin, + HeaderQuery, + Query, + SignedBlockHeader, + StateDiffChunk, + StateDiffQuery, + TransactionQuery, +}; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockNumber, BlockSignature}; +use starknet_api::transaction::{Transaction, TransactionOutput}; +use state_diff::StateDiffStreamBuilder; +use stream_builder::{DataStreamBuilder, DataStreamResult}; +use tokio_stream::StreamExt; +use tracing::instrument; + +const STEP: u64 = 1; +const ALLOWED_SIGNATURES_LENGTH: usize = 1; + +const NETWORK_DATA_TIMEOUT: Duration = Duration::from_secs(300); + +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +pub struct P2PSyncClientConfig { + pub num_headers_per_query: u64, + pub num_block_state_diffs_per_query: u64, + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub wait_period_for_new_data: Duration, + pub buffer_size: usize, + pub stop_sync_at_block_number: Option, +} + +impl SerializeConfig for P2PSyncClientConfig { + fn dump(&self) -> BTreeMap { + let mut config = BTreeMap::from_iter([ + ser_param( + "num_headers_per_query", + &self.num_headers_per_query, + "The maximum amount of headers to ask from peers in each iteration.", + ParamPrivacyInput::Public, + ), + ser_param( + "num_block_state_diffs_per_query", + &self.num_block_state_diffs_per_query, + "The maximum amount of block's state diffs to ask from peers in each iteration.", + ParamPrivacyInput::Public, + ), + ser_param( + "wait_period_for_new_data", + &self.wait_period_for_new_data.as_secs(), + "Time in seconds to wait when a query returned with partial data before sending a \ + new query", + ParamPrivacyInput::Public, + ), + ser_param( + "buffer_size", + &self.buffer_size, + "Size of the buffer for read from the storage and for incoming responses.", + ParamPrivacyInput::Public, + ), + ]); + config.extend(ser_optional_param( + &self.stop_sync_at_block_number, + BlockNumber(1000), + "stop_sync_at_block_number", + "Stops the sync at given block number and closes the node cleanly. Used to run \ + profiling on the node.", + ParamPrivacyInput::Public, + )); + config + } +} + +impl Default for P2PSyncClientConfig { + fn default() -> Self { + P2PSyncClientConfig { + num_headers_per_query: 10000, + // State diffs are split into multiple messages, so big queries can lead to a lot of + // messages in the network buffers. + num_block_state_diffs_per_query: 100, + wait_period_for_new_data: Duration::from_secs(5), + // TODO(eitan): split this by protocol + buffer_size: 100000, + stop_sync_at_block_number: None, + } + } +} + +#[derive(thiserror::Error, Debug)] +pub enum P2PSyncError { + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + // TODO(shahak): Consider removing this error and handling unordered headers without failing. + #[error( + "Blocks returned unordered from the network. Expected header with \ + {expected_block_number}, got {actual_block_number}." + )] + HeadersUnordered { expected_block_number: BlockNumber, actual_block_number: BlockNumber }, + #[error("Expected to receive one signature from the network. got {signatures:?} instead.")] + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + // Right now we support only one signature. In the future we will support many signatures. + WrongSignaturesLength { signatures: Vec }, + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + #[error( + "The header says that the block's state diff should be of length {expected_length}. Can \ + only divide the state diff parts into the following lengths: {possible_lengths:?}." + )] + WrongStateDiffLength { expected_length: usize, possible_lengths: Vec }, + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + #[error("Two state diff parts for the same state diff are conflicting.")] + ConflictingStateDiffParts, + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + #[error( + "Received an empty state diff part from the network (this is a potential DDoS vector)." + )] + EmptyStateDiffPart, + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + #[error("Network returned more responses than expected for a query.")] + TooManyResponses, + // TODO(shahak): Remove this and report to network on invalid data once that's possible. + #[error(transparent)] + ProtobufConversionError(#[from] ProtobufConversionError), + #[error( + "Encountered an old header in the storage at {block_number:?} that's missing the field \ + {missing_field}. Re-sync the node from {block_number:?} from a node that provides this \ + field." + )] + OldHeaderInStorage { block_number: BlockNumber, missing_field: &'static str }, + #[error("The sender end of the response receivers for {type_description:?} was closed.")] + ReceiverChannelTerminated { type_description: &'static str }, + #[error(transparent)] + NetworkTimeout(#[from] tokio::time::error::Elapsed), + #[error(transparent)] + StorageError(#[from] StorageError), + #[error(transparent)] + SendError(#[from] SendError), +} + +// TODO(Eitan): Use SqmrSubscriberChannels once there is a utility function for testing + +type WithPayloadSender = With< + SqmrClientSender, + SqmrClientPayload, + SqmrClientPayload, + Ready, SendError>>, + fn( + SqmrClientPayload, + ) -> Ready, SendError>>, +>; +type SyncResponse = Result, ProtobufConversionError>; +type ResponseReceiver = Box> + Unpin + Send>; + +type HeaderPayloadSender = SqmrClientSender>; +type StateDiffPayloadSender = SqmrClientSender>; +type TransactionPayloadSender = + SqmrClientSender>; + +pub struct P2PSyncClientChannels { + pub header_payload_sender: HeaderPayloadSender, + pub state_diff_payload_sender: StateDiffPayloadSender, + pub transaction_payload_sender: TransactionPayloadSender, +} + +impl P2PSyncClientChannels { + pub(crate) fn create_stream( + self, + storage_reader: StorageReader, + config: P2PSyncClientConfig, + ) -> impl Stream + Send + 'static { + let header_stream = HeaderStreamBuilder::create_stream( + self.header_payload_sender.with( + |SqmrClientPayload { query, report_receiver, responses_sender }| { + ready(Ok(SqmrClientPayload { + query: HeaderQuery(query), + report_receiver, + responses_sender, + })) + }, + ), + storage_reader.clone(), + config.wait_period_for_new_data, + config.num_headers_per_query, + config.stop_sync_at_block_number, + ); + + let state_diff_stream = StateDiffStreamBuilder::create_stream( + self.state_diff_payload_sender.with( + |SqmrClientPayload { query, report_receiver, responses_sender }| { + ready(Ok(SqmrClientPayload { + query: StateDiffQuery(query), + report_receiver, + responses_sender, + })) + }, + ), + storage_reader.clone(), + config.wait_period_for_new_data, + config.num_block_state_diffs_per_query, + config.stop_sync_at_block_number, + ); + + header_stream.merge(state_diff_stream) + } +} + +pub struct P2PSyncClient { + config: P2PSyncClientConfig, + storage_reader: StorageReader, + storage_writer: StorageWriter, + p2p_sync_channels: P2PSyncClientChannels, +} + +impl P2PSyncClient { + pub fn new( + config: P2PSyncClientConfig, + storage_reader: StorageReader, + storage_writer: StorageWriter, + p2p_sync_channels: P2PSyncClientChannels, + ) -> Self { + Self { config, storage_reader, storage_writer, p2p_sync_channels } + } + + #[instrument(skip(self), level = "debug", err)] + pub async fn run(mut self) -> Result<(), P2PSyncError> { + let mut data_stream = + self.p2p_sync_channels.create_stream(self.storage_reader.clone(), self.config); + + loop { + let data = data_stream.next().await.expect("Sync data stream should never end")?; + data.write_to_storage(&mut self.storage_writer)?; + } + } +} diff --git a/crates/papyrus_p2p_sync/src/client/p2p_sync_test.rs b/crates/papyrus_p2p_sync/src/client/p2p_sync_test.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/p2p_sync_test.rs @@ -0,0 +1 @@ + diff --git a/crates/papyrus_p2p_sync/src/client/state_diff.rs b/crates/papyrus_p2p_sync/src/client/state_diff.rs new file mode 100644 index 00000000000..ab31de6e4db --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/state_diff.rs @@ -0,0 +1,171 @@ +use std::collections::HashSet; + +use futures::future::BoxFuture; +use futures::{FutureExt, StreamExt}; +use papyrus_proc_macros::latency_histogram; +use papyrus_protobuf::sync::StateDiffChunk; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::state::{StateStorageReader, StateStorageWriter}; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use starknet_api::block::BlockNumber; +use starknet_api::state::ThinStateDiff; + +use super::ResponseReceiver; +use crate::client::stream_builder::{BlockData, BlockNumberLimit, DataStreamBuilder}; +use crate::client::{P2PSyncError, NETWORK_DATA_TIMEOUT}; + +impl BlockData for (ThinStateDiff, BlockNumber) { + #[latency_histogram("p2p_sync_state_diff_write_to_storage_latency_seconds", true)] + fn write_to_storage( + self: Box, + storage_writer: &mut StorageWriter, + ) -> Result<(), StorageError> { + storage_writer.begin_rw_txn()?.append_state_diff(self.1, self.0)?.commit() + } +} + +pub(crate) struct StateDiffStreamBuilder; + +impl DataStreamBuilder for StateDiffStreamBuilder { + type Output = (ThinStateDiff, BlockNumber); + + const TYPE_DESCRIPTION: &'static str = "state diffs"; + const BLOCK_NUMBER_LIMIT: BlockNumberLimit = BlockNumberLimit::HeaderMarker; + + #[latency_histogram("p2p_sync_state_diff_parse_data_for_block_latency_seconds", true)] + fn parse_data_for_block<'a>( + state_diff_chunks_receiver: &'a mut ResponseReceiver, + block_number: BlockNumber, + storage_reader: &'a StorageReader, + ) -> BoxFuture<'a, Result, P2PSyncError>> { + async move { + let mut result = ThinStateDiff::default(); + let mut prev_result_len = 0; + let mut current_state_diff_len = 0; + let target_state_diff_len = storage_reader + .begin_ro_txn()? + .get_block_header(block_number)? + .expect("A header with number lower than the header marker is missing") + .state_diff_length + .ok_or(P2PSyncError::OldHeaderInStorage { + block_number, + missing_field: "state_diff_length", + })?; + + while current_state_diff_len < target_state_diff_len { + let maybe_state_diff_chunk = + tokio::time::timeout(NETWORK_DATA_TIMEOUT, state_diff_chunks_receiver.next()) + .await? + .ok_or(P2PSyncError::ReceiverChannelTerminated { + type_description: Self::TYPE_DESCRIPTION, + })?; + let Some(state_diff_chunk) = maybe_state_diff_chunk?.0 else { + if current_state_diff_len == 0 { + return Ok(None); + } else { + return Err(P2PSyncError::WrongStateDiffLength { + expected_length: target_state_diff_len, + possible_lengths: vec![current_state_diff_len], + }); + } + }; + prev_result_len = current_state_diff_len; + if state_diff_chunk.is_empty() { + return Err(P2PSyncError::EmptyStateDiffPart); + } + // It's cheaper to calculate the length of `state_diff_part` than the length of + // `result`. + current_state_diff_len += state_diff_chunk.len(); + unite_state_diffs(&mut result, state_diff_chunk)?; + } + + if current_state_diff_len != target_state_diff_len { + return Err(P2PSyncError::WrongStateDiffLength { + expected_length: target_state_diff_len, + possible_lengths: vec![prev_result_len, current_state_diff_len], + }); + } + + validate_deprecated_declared_classes_non_conflicting(&result)?; + Ok(Some((result, block_number))) + } + .boxed() + } + + fn get_start_block_number(storage_reader: &StorageReader) -> Result { + storage_reader.begin_ro_txn()?.get_state_marker() + } +} + +// For performance reasons, this function does not check if a deprecated class was declared twice. +// That check is done after we get the final state diff. +#[latency_histogram("p2p_sync_state_diff_unite_state_diffs_latency_seconds", true)] +fn unite_state_diffs( + state_diff: &mut ThinStateDiff, + state_diff_chunk: StateDiffChunk, +) -> Result<(), P2PSyncError> { + match state_diff_chunk { + StateDiffChunk::ContractDiff(contract_diff) => { + if let Some(class_hash) = contract_diff.class_hash { + if state_diff + .deployed_contracts + .insert(contract_diff.contract_address, class_hash) + .is_some() + { + return Err(P2PSyncError::ConflictingStateDiffParts); + } + } + if let Some(nonce) = contract_diff.nonce { + if state_diff.nonces.insert(contract_diff.contract_address, nonce).is_some() { + return Err(P2PSyncError::ConflictingStateDiffParts); + } + } + if !contract_diff.storage_diffs.is_empty() { + match state_diff.storage_diffs.get_mut(&contract_diff.contract_address) { + Some(storage_diffs) => { + for (k, v) in contract_diff.storage_diffs { + if storage_diffs.insert(k, v).is_some() { + return Err(P2PSyncError::ConflictingStateDiffParts); + } + } + } + None => { + state_diff + .storage_diffs + .insert(contract_diff.contract_address, contract_diff.storage_diffs); + } + } + } + } + StateDiffChunk::DeclaredClass(declared_class) => { + if state_diff + .declared_classes + .insert(declared_class.class_hash, declared_class.compiled_class_hash) + .is_some() + { + return Err(P2PSyncError::ConflictingStateDiffParts); + } + } + StateDiffChunk::DeprecatedDeclaredClass(deprecated_declared_class) => { + state_diff.deprecated_declared_classes.push(deprecated_declared_class.class_hash); + } + } + Ok(()) +} + +#[latency_histogram( + "p2p_sync_state_diff_validate_deprecated_declared_classes_non_conflicting_latency_seconds", + true +)] +fn validate_deprecated_declared_classes_non_conflicting( + state_diff: &ThinStateDiff, +) -> Result<(), P2PSyncError> { + // TODO(shahak): Check if sorting is more efficient. + if state_diff.deprecated_declared_classes.len() + == state_diff.deprecated_declared_classes.iter().cloned().collect::>().len() + { + Ok(()) + } else { + Err(P2PSyncError::ConflictingStateDiffParts) + } +} diff --git a/crates/papyrus_p2p_sync/src/client/state_diff_test.rs b/crates/papyrus_p2p_sync/src/client/state_diff_test.rs new file mode 100644 index 00000000000..1f720fbfd4a --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/state_diff_test.rs @@ -0,0 +1,398 @@ +use std::time::Duration; + +use assert_matches::assert_matches; +use futures::{FutureExt, SinkExt, StreamExt}; +use indexmap::indexmap; +use papyrus_network::network_manager::SqmrClientPayload; +use papyrus_protobuf::sync::{ + BlockHashOrNumber, + ContractDiff, + DataOrFin, + DeclaredClass, + DeprecatedDeclaredClass, + Direction, + Query, + SignedBlockHeader, + StateDiffChunk, +}; +use papyrus_storage::state::StateStorageReader; +use rand::RngCore; +use rand_chacha::ChaCha8Rng; +use starknet_api::block::{BlockHeader, BlockNumber}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::{StorageKey, ThinStateDiff}; +use starknet_types_core::felt::Felt; +use static_assertions::const_assert; +use test_utils::{get_rng, GetTestInstance}; + +use super::test_utils::{ + create_block_hashes_and_signatures, + setup, + TestArgs, + HEADER_QUERY_LENGTH, + SLEEP_DURATION_TO_LET_SYNC_ADVANCE, + STATE_DIFF_QUERY_LENGTH, +}; +use super::{P2PSyncError, StateDiffQuery}; + +const TIMEOUT_FOR_TEST: Duration = Duration::from_secs(5); + +#[tokio::test] +async fn state_diff_basic_flow() { + // Asserting the constants so the test can assume there will be 2 state diff queries for a + // single header query and the second will be smaller than the first. + const_assert!(STATE_DIFF_QUERY_LENGTH < HEADER_QUERY_LENGTH); + const_assert!(HEADER_QUERY_LENGTH < 2 * STATE_DIFF_QUERY_LENGTH); + + let TestArgs { + p2p_sync, + storage_reader, + mut state_diff_payload_receiver, + mut header_payload_receiver, + .. + } = setup(); + + let block_hashes_and_signatures = + create_block_hashes_and_signatures(HEADER_QUERY_LENGTH.try_into().unwrap()); + let mut rng = get_rng(); + // TODO(eitan): Add a 3rd constant for NUM_CHUNKS_PER_BLOCK so that ThinStateDiff is made from + // multiple StateDiffChunks + let state_diffs = (0..HEADER_QUERY_LENGTH) + .map(|_| create_random_state_diff_chunk(&mut rng)) + .collect::>(); + + // Create a future that will receive queries, send responses and validate the results. + let parse_queries_future = async move { + // We wait for the state diff sync to see that there are no headers and start sleeping + tokio::time::sleep(SLEEP_DURATION_TO_LET_SYNC_ADVANCE).await; + + // Check that before we send headers there is no state diff query. + assert!(state_diff_payload_receiver.next().now_or_never().is_none()); + let SqmrClientPayload { + query: _query, + report_receiver: _report_receiver, + responses_sender: mut headers_sender, + } = header_payload_receiver.next().await.unwrap(); + + // Send headers for entire query. + for (i, ((block_hash, block_signature), state_diff)) in + block_hashes_and_signatures.iter().zip(state_diffs.iter()).enumerate() + { + // Send responses + headers_sender + .send(Ok(DataOrFin(Some(SignedBlockHeader { + block_header: BlockHeader { + block_number: BlockNumber(i.try_into().unwrap()), + block_hash: *block_hash, + state_diff_length: Some(state_diff.len()), + ..Default::default() + }, + signatures: vec![*block_signature], + })))) + .await + .unwrap(); + } + for (start_block_number, num_blocks) in [ + (0u64, STATE_DIFF_QUERY_LENGTH), + (STATE_DIFF_QUERY_LENGTH, HEADER_QUERY_LENGTH - STATE_DIFF_QUERY_LENGTH), + ] { + // Get a state diff query and validate it + let SqmrClientPayload { + query, + report_receiver: _report_receiver, + responses_sender: mut state_diff_sender, + } = state_diff_payload_receiver.next().await.unwrap(); + assert_eq!( + query, + StateDiffQuery(Query { + start_block: BlockHashOrNumber::Number(BlockNumber(start_block_number)), + direction: Direction::Forward, + limit: num_blocks, + step: 1, + }) + ); + + for block_number in start_block_number..(start_block_number + num_blocks) { + let state_diff_chunk = state_diffs[usize::try_from(block_number).unwrap()].clone(); + + let block_number = BlockNumber(block_number); + + // Check that before we've sent all parts the state diff wasn't written yet. + let txn = storage_reader.begin_ro_txn().unwrap(); + assert_eq!(block_number, txn.get_state_marker().unwrap()); + + state_diff_sender + .send(Ok(DataOrFin(Some(state_diff_chunk.clone())))) + .await + .unwrap(); + + tokio::time::sleep(SLEEP_DURATION_TO_LET_SYNC_ADVANCE).await; + + // Check state diff was written to the storage. This way we make sure that the sync + // writes to the storage each block's state diff before receiving all query + // responses. + let txn = storage_reader.begin_ro_txn().unwrap(); + assert_eq!(block_number.unchecked_next(), txn.get_state_marker().unwrap()); + + let state_diff = txn.get_state_diff(block_number).unwrap().unwrap(); + let expected_state_diff = match state_diff_chunk { + StateDiffChunk::ContractDiff(contract_diff) => { + let mut deployed_contracts = indexmap! {}; + if let Some(class_hash) = contract_diff.class_hash { + deployed_contracts.insert(contract_diff.contract_address, class_hash); + }; + let mut nonces = indexmap! {}; + if let Some(nonce) = contract_diff.nonce { + nonces.insert(contract_diff.contract_address, nonce); + } + ThinStateDiff { + deployed_contracts, + nonces, + storage_diffs: indexmap! { + contract_diff.contract_address => contract_diff.storage_diffs + }, + ..Default::default() + } + } + StateDiffChunk::DeclaredClass(declared_class) => ThinStateDiff { + declared_classes: indexmap! { + declared_class.class_hash => declared_class.compiled_class_hash + }, + ..Default::default() + }, + StateDiffChunk::DeprecatedDeclaredClass(deprecated_declared_class) => { + ThinStateDiff { + deprecated_declared_classes: vec![deprecated_declared_class.class_hash], + ..Default::default() + } + } + }; + assert_eq!(state_diff, expected_state_diff); + } + state_diff_sender.send(Ok(DataOrFin(None))).await.unwrap(); + } + }; + + tokio::select! { + sync_result = p2p_sync.run() => { + sync_result.unwrap(); + panic!("P2P sync aborted with no failure."); + } + _ = parse_queries_future => {} + } +} + +#[tokio::test] +async fn state_diff_empty_state_diff() { + validate_state_diff_fails(1, vec![Some(StateDiffChunk::default())], |error| { + assert_matches!(error, P2PSyncError::EmptyStateDiffPart) + }) + .await; +} + +#[tokio::test] +async fn state_diff_stopped_in_middle() { + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::DeprecatedDeclaredClass(DeprecatedDeclaredClass::default())), + None, + ], + |error| assert_matches!(error, P2PSyncError::WrongStateDiffLength { expected_length, possible_lengths } if expected_length == 2 && possible_lengths == vec![1]), + ) + .await; +} + +#[tokio::test] +async fn state_diff_not_split_correctly() { + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::DeprecatedDeclaredClass(DeprecatedDeclaredClass::default())), + Some(StateDiffChunk::ContractDiff(ContractDiff{ + contract_address: ContractAddress::default(), + class_hash: Some(ClassHash::default()), + nonce: Some(Nonce::default()), + ..Default::default() + }),) + ], + |error| assert_matches!(error, P2PSyncError::WrongStateDiffLength { expected_length, possible_lengths } if expected_length == 2 && possible_lengths == vec![1, 3]), + ) + .await; +} + +#[tokio::test] +async fn state_diff_conflicting() { + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + class_hash: Some(ClassHash::default()), + ..Default::default() + })), + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + class_hash: Some(ClassHash::default()), + ..Default::default() + })), + ], + |error| assert_matches!(error, P2PSyncError::ConflictingStateDiffParts), + ) + .await; + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + storage_diffs: indexmap! { StorageKey::default() => Felt::default() }, + ..Default::default() + })), + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + storage_diffs: indexmap! { StorageKey::default() => Felt::default() }, + ..Default::default() + })), + ], + |error| assert_matches!(error, P2PSyncError::ConflictingStateDiffParts), + ) + .await; + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::DeclaredClass(DeclaredClass { + class_hash: ClassHash::default(), + compiled_class_hash: CompiledClassHash::default(), + })), + Some(StateDiffChunk::DeclaredClass(DeclaredClass { + class_hash: ClassHash::default(), + compiled_class_hash: CompiledClassHash::default(), + })), + ], + |error| assert_matches!(error, P2PSyncError::ConflictingStateDiffParts), + ) + .await; + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::DeprecatedDeclaredClass(DeprecatedDeclaredClass { + class_hash: ClassHash::default(), + })), + Some(StateDiffChunk::DeprecatedDeclaredClass(DeprecatedDeclaredClass { + class_hash: ClassHash::default(), + })), + ], + |error| assert_matches!(error, P2PSyncError::ConflictingStateDiffParts), + ) + .await; + validate_state_diff_fails( + 2, + vec![ + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + nonce: Some(Nonce::default()), + ..Default::default() + })), + Some(StateDiffChunk::ContractDiff(ContractDiff { + contract_address: ContractAddress::default(), + nonce: Some(Nonce::default()), + ..Default::default() + })), + ], + |error| assert_matches!(error, P2PSyncError::ConflictingStateDiffParts), + ) + .await; +} + +async fn validate_state_diff_fails( + state_diff_length_in_header: usize, + state_diff_chunks: Vec>, + error_validator: impl Fn(P2PSyncError), +) { + let TestArgs { + p2p_sync, + storage_reader, + mut state_diff_payload_receiver, + mut header_payload_receiver, + .. + } = setup(); + + let (block_hash, block_signature) = *create_block_hashes_and_signatures(1).first().unwrap(); + + // Create a future that will receive queries, send responses and validate the results. + let parse_queries_future = async move { + // Send a single header. There's no need to fill the entire query. + let SqmrClientPayload { + query: _query, + report_receiver: _report_receiver, + responses_sender: mut headers_sender, + } = header_payload_receiver.next().await.unwrap(); + headers_sender + .send(Ok(DataOrFin(Some(SignedBlockHeader { + block_header: BlockHeader { + block_number: BlockNumber(0), + block_hash, + state_diff_length: Some(state_diff_length_in_header), + ..Default::default() + }, + signatures: vec![block_signature], + })))) + .await + .unwrap(); + + // Get a state diff query and validate it + let SqmrClientPayload { + query, + report_receiver: _report_reciever, + responses_sender: mut state_diffs_sender, + } = state_diff_payload_receiver.next().await.unwrap(); + assert_eq!( + query, + StateDiffQuery(Query { + start_block: BlockHashOrNumber::Number(BlockNumber(0)), + direction: Direction::Forward, + limit: 1, + step: 1, + }) + ); + + // Send state diffs. + for state_diff_chunk in state_diff_chunks { + // Check that before we've sent all parts the state diff wasn't written yet. + let txn = storage_reader.begin_ro_txn().unwrap(); + assert_eq!(0, txn.get_state_marker().unwrap().0); + + state_diffs_sender.send(Ok(DataOrFin(state_diff_chunk))).await.unwrap(); + } + tokio::time::sleep(TIMEOUT_FOR_TEST).await; + panic!("P2P sync did not receive error"); + }; + + tokio::select! { + sync_result = p2p_sync.run() => { + let sync_err = sync_result.unwrap_err(); + error_validator(sync_err); + } + _ = parse_queries_future => {} + } +} + +fn create_random_state_diff_chunk(rng: &mut ChaCha8Rng) -> StateDiffChunk { + let mut state_diff_chunk = StateDiffChunk::get_test_instance(rng); + let contract_address = ContractAddress::from(rng.next_u64()); + let class_hash = ClassHash(rng.next_u64().into()); + match &mut state_diff_chunk { + StateDiffChunk::ContractDiff(contract_diff) => { + contract_diff.contract_address = contract_address; + contract_diff.class_hash = Some(class_hash); + } + StateDiffChunk::DeclaredClass(declared_class) => { + declared_class.class_hash = class_hash; + declared_class.compiled_class_hash = CompiledClassHash(rng.next_u64().into()); + } + StateDiffChunk::DeprecatedDeclaredClass(deprecated_declared_class) => { + deprecated_declared_class.class_hash = class_hash; + } + } + state_diff_chunk +} diff --git a/crates/papyrus_p2p_sync/src/client/stream_builder.rs b/crates/papyrus_p2p_sync/src/client/stream_builder.rs new file mode 100644 index 00000000000..13b88011a4f --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/stream_builder.rs @@ -0,0 +1,147 @@ +use std::cmp::min; +use std::time::Duration; + +use async_stream::stream; +use futures::channel::oneshot; +use futures::future::BoxFuture; +use futures::stream::BoxStream; +use futures::{SinkExt, StreamExt}; +use papyrus_network::network_manager::SqmrClientPayload; +use papyrus_protobuf::converters::ProtobufConversionError; +use papyrus_protobuf::sync::{BlockHashOrNumber, DataOrFin, Direction, Query}; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use starknet_api::block::BlockNumber; +use tracing::{debug, info}; + +use super::{P2PSyncError, ResponseReceiver, WithPayloadSender, STEP}; +use crate::client::SyncResponse; +use crate::BUFFER_SIZE; + +pub type DataStreamResult = Result, P2PSyncError>; + +pub(crate) trait BlockData: Send { + fn write_to_storage( + // This is Box in order to allow using it with `Box`. + self: Box, + storage_writer: &mut StorageWriter, + ) -> Result<(), StorageError>; +} + +pub(crate) enum BlockNumberLimit { + Unlimited, + HeaderMarker, + // TODO(shahak): Add variant for state diff marker once we support classes sync. +} + +pub(crate) trait DataStreamBuilder +where + InputFromNetwork: Send + 'static, + DataOrFin: TryFrom, Error = ProtobufConversionError>, +{ + type Output: BlockData + 'static; + + const TYPE_DESCRIPTION: &'static str; + const BLOCK_NUMBER_LIMIT: BlockNumberLimit; + + // Async functions in trait don't work well with argument references + fn parse_data_for_block<'a>( + data_receiver: &'a mut ResponseReceiver, + block_number: BlockNumber, + storage_reader: &'a StorageReader, + ) -> BoxFuture<'a, Result, P2PSyncError>>; + + fn get_start_block_number(storage_reader: &StorageReader) -> Result; + + fn create_stream( + mut payload_sender: WithPayloadSender>, + storage_reader: StorageReader, + wait_period_for_new_data: Duration, + num_blocks_per_query: u64, + stop_sync_at_block_number: Option, + ) -> BoxStream<'static, DataStreamResult> { + stream! { + let mut current_block_number = Self::get_start_block_number(&storage_reader)?; + 'send_query_and_parse_responses: loop { + let limit = match Self::BLOCK_NUMBER_LIMIT { + BlockNumberLimit::Unlimited => num_blocks_per_query, + BlockNumberLimit::HeaderMarker => { + let last_block_number = storage_reader.begin_ro_txn()?.get_header_marker()?; + let limit = min( + last_block_number.0 - current_block_number.0, + num_blocks_per_query, + ); + if limit == 0 { + debug!("{:?} sync is waiting for a new header", Self::TYPE_DESCRIPTION); + tokio::time::sleep(wait_period_for_new_data).await; + continue; + } + limit + } + }; + let end_block_number = current_block_number.0 + limit; + debug!( + "Downloading {:?} for blocks [{}, {})", + Self::TYPE_DESCRIPTION, + current_block_number.0, + end_block_number, + ); + // TODO(shahak): Use the report callback. + //TODO(Eitan): abstract report functionality to the channel struct + let (_report_sender, report_receiver) = oneshot::channel::<()>(); + let (responses_sender, responses_receiver) = futures::channel::mpsc::channel::>(BUFFER_SIZE); + let responses_sender = Box::new(responses_sender); + let mut responses_receiver: ResponseReceiver = Box::new(responses_receiver); + payload_sender + .send(SqmrClientPayload { query: + Query { + start_block: BlockHashOrNumber::Number(current_block_number), + direction: Direction::Forward, + limit, + step: STEP, + }, report_receiver, responses_sender + } + ) + .await?; + + while current_block_number.0 < end_block_number { + match Self::parse_data_for_block( + &mut responses_receiver, current_block_number, &storage_reader + ).await? { + Some(output) => yield Ok(Box::::from(Box::new(output))), + None => { + debug!( + "Query for {:?} returned with partial data. Waiting {:?} before \ + sending another query.", + Self::TYPE_DESCRIPTION, + wait_period_for_new_data + ); + tokio::time::sleep(wait_period_for_new_data).await; + continue 'send_query_and_parse_responses; + } + } + info!("Added {:?} for block {}.", Self::TYPE_DESCRIPTION, current_block_number); + current_block_number = current_block_number.unchecked_next(); + if stop_sync_at_block_number.is_some_and(|stop_sync_at_block_number| { + current_block_number >= stop_sync_at_block_number + }) { + info!("{:?} hit the stop sync block number.", Self::TYPE_DESCRIPTION); + return; + } + } + + // Consume the None message signaling the end of the query. + match responses_receiver.next().await { + Some(Ok(DataOrFin(None))) => { + debug!("Query sent to network for {:?} finished", Self::TYPE_DESCRIPTION); + }, + Some(_) => Err(P2PSyncError::TooManyResponses)?, + None => Err(P2PSyncError::ReceiverChannelTerminated { + type_description: Self::TYPE_DESCRIPTION + })?, + } + } + } + .boxed() + } +} diff --git a/crates/papyrus_p2p_sync/src/client/test_utils.rs b/crates/papyrus_p2p_sync/src/client/test_utils.rs new file mode 100644 index 00000000000..aa35e05a400 --- /dev/null +++ b/crates/papyrus_p2p_sync/src/client/test_utils.rs @@ -0,0 +1,100 @@ +use std::time::Duration; + +use futures::channel::mpsc::Receiver; +use lazy_static::lazy_static; +use papyrus_network::network_manager::SqmrClientPayload; +use papyrus_protobuf::sync::{ + DataOrFin, + HeaderQuery, + SignedBlockHeader, + StateDiffChunk, + StateDiffQuery, + TransactionQuery, +}; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::StorageReader; +use starknet_api::block::{BlockHash, BlockSignature}; +use starknet_api::crypto::utils::Signature; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::{Transaction, TransactionOutput}; +use starknet_types_core::felt::Felt; + +use super::{P2PSyncClient, P2PSyncClientChannels, P2PSyncClientConfig}; + +pub const BUFFER_SIZE: usize = 1000; +pub const HEADER_QUERY_LENGTH: u64 = 5; +pub const STATE_DIFF_QUERY_LENGTH: u64 = 3; +pub const SLEEP_DURATION_TO_LET_SYNC_ADVANCE: Duration = Duration::from_millis(10); +// This should be substantially bigger than SLEEP_DURATION_TO_LET_SYNC_ADVANCE. +pub const WAIT_PERIOD_FOR_NEW_DATA: Duration = Duration::from_millis(50); +pub const TIMEOUT_FOR_NEW_QUERY_AFTER_PARTIAL_RESPONSE: Duration = + WAIT_PERIOD_FOR_NEW_DATA.saturating_add(SLEEP_DURATION_TO_LET_SYNC_ADVANCE.saturating_mul(10)); + +lazy_static! { + static ref TEST_CONFIG: P2PSyncClientConfig = P2PSyncClientConfig { + num_headers_per_query: HEADER_QUERY_LENGTH, + num_block_state_diffs_per_query: STATE_DIFF_QUERY_LENGTH, + wait_period_for_new_data: WAIT_PERIOD_FOR_NEW_DATA, + buffer_size: BUFFER_SIZE, + stop_sync_at_block_number: None, + }; +} + +pub struct TestArgs { + #[allow(clippy::type_complexity)] + pub p2p_sync: P2PSyncClient, + pub storage_reader: StorageReader, + pub header_payload_receiver: + Receiver>>, + pub state_diff_payload_receiver: + Receiver>>, + #[allow(dead_code)] + pub transaction_payload_receiver: + Receiver>>, +} + +pub fn setup() -> TestArgs { + let p2p_sync_config = *TEST_CONFIG; + let buffer_size = p2p_sync_config.buffer_size; + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + let (header_payload_sender, header_payload_receiver) = + futures::channel::mpsc::channel(buffer_size); + let (state_diff_payload_sender, state_diff_payload_receiver) = + futures::channel::mpsc::channel(buffer_size); + let (transaction_payload_sender, transaction_payload_receiver) = + futures::channel::mpsc::channel(buffer_size); + let p2p_sync_channels = P2PSyncClientChannels { + header_payload_sender: Box::new(header_payload_sender), + state_diff_payload_sender: Box::new(state_diff_payload_sender), + transaction_payload_sender: Box::new(transaction_payload_sender), + }; + let p2p_sync = P2PSyncClient::new( + p2p_sync_config, + storage_reader.clone(), + storage_writer, + p2p_sync_channels, + ); + TestArgs { + p2p_sync, + storage_reader, + header_payload_receiver, + state_diff_payload_receiver, + transaction_payload_receiver, + } +} + +pub fn create_block_hashes_and_signatures(n_blocks: u8) -> Vec<(BlockHash, BlockSignature)> { + let mut bytes = [0u8; 32]; + (0u8..n_blocks) + .map(|i| { + bytes[31] = i; + ( + BlockHash(StarkHash::from_bytes_be(&bytes)), + BlockSignature(Signature { + r: Felt::from_bytes_be(&bytes), + s: Felt::from_bytes_be(&bytes), + }), + ) + }) + .collect() +} diff --git a/crates/papyrus_p2p_sync/src/lib.rs b/crates/papyrus_p2p_sync/src/lib.rs new file mode 100644 index 00000000000..3b2828878ec --- /dev/null +++ b/crates/papyrus_p2p_sync/src/lib.rs @@ -0,0 +1,34 @@ +pub mod client; +pub mod server; + +use enum_iterator::Sequence; + +pub const BUFFER_SIZE: usize = 100000; + +/// The p2p sync protocol names needed for negotiation, as they appear in the p2p specs +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Sequence)] +pub enum Protocol { + SignedBlockHeader, + StateDiff, + Transaction, + Class, + Event, +} + +impl Protocol { + pub fn as_str(&self) -> &'static str { + match self { + Protocol::SignedBlockHeader => "/starknet/headers/0.1.0-rc.0", + Protocol::StateDiff => "/starknet/state_diffs/0.1.0-rc.0", + Protocol::Transaction => "/starknet/transactions/0.1.0-rc.0", + Protocol::Class => "/starknet/classes/0.1.0-rc.0", + Protocol::Event => "/starknet/events/0.1.0-rc.0", + } + } +} + +impl From for String { + fn from(protocol: Protocol) -> String { + protocol.as_str().to_string() + } +} diff --git a/crates/papyrus_p2p_sync/src/server/mod.rs b/crates/papyrus_p2p_sync/src/server/mod.rs new file mode 100644 index 00000000000..5a4bca89bec --- /dev/null +++ b/crates/papyrus_p2p_sync/src/server/mod.rs @@ -0,0 +1,439 @@ +use std::vec; + +use futures::channel::mpsc::SendError; +use futures::{Sink, SinkExt, Stream, StreamExt}; +use papyrus_common::pending_classes::ApiContractClass; +use papyrus_protobuf::converters::ProtobufConversionError; +use papyrus_protobuf::sync::{ + BlockHashOrNumber, + ClassQuery, + ContractDiff, + DataOrFin, + DeclaredClass, + DeprecatedDeclaredClass, + EventQuery, + HeaderQuery, + Query, + SignedBlockHeader, + StateDiffChunk, + StateDiffQuery, + TransactionQuery, +}; +use papyrus_storage::body::BodyStorageReader; +use papyrus_storage::class::ClassStorageReader; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{db, StorageReader, StorageTxn}; +use starknet_api::block::BlockNumber; +use starknet_api::core::ClassHash; +use starknet_api::state::ThinStateDiff; +use starknet_api::transaction::{Event, Transaction, TransactionHash, TransactionOutput}; +use tracing::error; + +#[cfg(test)] +mod test; + +mod utils; + +#[derive(thiserror::Error, Debug)] +pub enum P2PSyncServerError { + #[error(transparent)] + DBInternalError(#[from] papyrus_storage::StorageError), + #[error("Block number is out of range. Query: {query:?}, counter: {counter}")] + BlockNumberOutOfRange { query: Query, counter: u64 }, + // TODO: add data type to the error message. + #[error("Block not found. Block: {block_hash_or_number:?}")] + BlockNotFound { block_hash_or_number: BlockHashOrNumber }, + #[error("Class not found. Class hash: {class_hash}")] + ClassNotFound { class_hash: ClassHash }, + // This error should be non recoverable. + #[error(transparent)] + JoinError(#[from] tokio::task::JoinError), + // TODO: remove this error, use BlockNotFound instead. + // This error should be non recoverable. + #[error("Block {block_number:?} is in the storage but its signature isn't.")] + SignatureNotFound { block_number: BlockNumber }, + #[error(transparent)] + SendError(#[from] futures::channel::mpsc::SendError), +} + +impl P2PSyncServerError { + pub fn should_log_in_error_level(&self) -> bool { + match self { + Self::JoinError(_) | Self::SignatureNotFound { .. } | Self::SendError { .. } + // TODO(shahak): Consider returning false for some of the StorageError variants. + | Self::DBInternalError { .. } => true, + Self::BlockNumberOutOfRange { .. } | Self::BlockNotFound { .. } | Self::ClassNotFound { .. } => false, + } + } +} + +/// A P2PSyncServer receives inbound queries and returns their corresponding data. +pub struct P2PSyncServer< + HeaderQueryReceiver, + StateDiffQueryReceiver, + TransactionQueryReceiver, + ClassQueryReceiver, + EventQueryReceiver, +> { + storage_reader: StorageReader, + header_queries_receiver: HeaderQueryReceiver, + state_diff_queries_receiver: StateDiffQueryReceiver, + transaction_queries_receiver: TransactionQueryReceiver, + class_queries_receiver: ClassQueryReceiver, + event_queries_receiver: EventQueryReceiver, +} + +impl< + HeaderQueryReceiver, + StateDiffQueryReceiver, + TransactionQueryReceiver, + ClassQueryReceiver, + EventQueryReceiver, + HeaderResponsesSender, + StateDiffResponsesSender, + TransactionResponsesSender, + ClassResponsesSender, + EventResponsesSender, +> + P2PSyncServer< + HeaderQueryReceiver, + StateDiffQueryReceiver, + TransactionQueryReceiver, + ClassQueryReceiver, + EventQueryReceiver, + > +where + HeaderQueryReceiver: Stream, HeaderResponsesSender)> + + Unpin, + HeaderResponsesSender: + Sink, Error = SendError> + Unpin + Send + 'static, + StateDiffQueryReceiver: Stream, StateDiffResponsesSender)> + + Unpin, + StateDiffResponsesSender: + Sink, Error = SendError> + Unpin + Send + 'static, + TransactionQueryReceiver: Stream< + Item = (Result, TransactionResponsesSender), + > + Unpin, + TransactionResponsesSender: Sink, Error = SendError> + + Unpin + + Send + + 'static, + ClassQueryReceiver: + Stream, ClassResponsesSender)> + Unpin, + ClassResponsesSender: + Sink, Error = SendError> + Unpin + Send + 'static, + EventQueryReceiver: + Stream, EventResponsesSender)> + Unpin, + EventResponsesSender: + Sink, Error = SendError> + Unpin + Send + 'static, +{ + pub async fn run(mut self) { + loop { + tokio::select! { + result = self.header_queries_receiver.next() => { + let (query_result, response_sender) = result.expect( + "Header queries sender was unexpectedly dropped." + ); + // TODO(shahak): Report if query_result is Err. + if let Ok(query) = query_result { + self.register_query(query.0, response_sender); + } + } + result = self.state_diff_queries_receiver.next() => { + let (query_result, response_sender) = result.expect( + "State diff queries sender was unexpectedly dropped." + ); + // TODO(shahak): Report if query_result is Err. + if let Ok(query) = query_result { + self.register_query(query.0, response_sender); + } + } + result = self.transaction_queries_receiver.next() => { + let (query_result, response_sender) = result.expect( + "Transaction queries sender was unexpectedly dropped." + ); + // TODO: Report if query_result is Err. + if let Ok(query) = query_result { + self.register_query(query.0, response_sender); + } + } + result = self.class_queries_receiver.next() => { + let (query_result, response_sender) = result.expect( + "Class queries sender was unexpectedly dropped." + ); + // TODO: Report if query_result is Err. + if let Ok(query) = query_result { + self.register_query(query.0, response_sender); + } + } + result = self.event_queries_receiver.next() => { + let (query_result, response_sender) = result.expect( + "Event queries sender was unexpectedly dropped." + ); + // TODO: Report if query_result is Err. + if let Ok(query) = query_result { + self.register_query(query.0, response_sender); + } + } + }; + } + } + + pub fn new( + storage_reader: StorageReader, + header_queries_receiver: HeaderQueryReceiver, + state_diff_queries_receiver: StateDiffQueryReceiver, + transaction_queries_receiver: TransactionQueryReceiver, + class_queries_receiver: ClassQueryReceiver, + event_queries_receiver: EventQueryReceiver, + ) -> Self { + Self { + storage_reader, + header_queries_receiver, + state_diff_queries_receiver, + transaction_queries_receiver, + class_queries_receiver, + event_queries_receiver, + } + } + + fn register_query(&self, query: Query, sender: Sender) + where + Data: FetchBlockDataFromDb + Send + 'static, + Sender: Sink> + Unpin + Send + 'static, + P2PSyncServerError: From<>>::Error>, + { + let storage_reader_clone = self.storage_reader.clone(); + tokio::task::spawn(async move { + let result = send_data_for_query(storage_reader_clone, query.clone(), sender).await; + if let Err(error) = result { + if error.should_log_in_error_level() { + error!("Running inbound query {query:?} failed on {error:?}"); + } + Err(error) + } else { + Ok(()) + } + }); + } +} + +pub trait FetchBlockDataFromDb: Sized { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError>; +} + +impl FetchBlockDataFromDb for SignedBlockHeader { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError> { + let mut header = + txn.get_block_header(block_number)?.ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + })?; + // TODO(shahak) Remove this once central sync fills the state_diff_length field. + if header.state_diff_length.is_none() { + header.state_diff_length = Some( + txn.get_state_diff(block_number)? + .ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + })? + .len(), + ); + } + let signature = txn + .get_block_signature(block_number)? + .ok_or(P2PSyncServerError::SignatureNotFound { block_number })?; + Ok(vec![SignedBlockHeader { block_header: header, signatures: vec![signature] }]) + } +} + +impl FetchBlockDataFromDb for StateDiffChunk { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError> { + let thin_state_diff = + txn.get_state_diff(block_number)?.ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + })?; + Ok(split_thin_state_diff(thin_state_diff)) + } +} + +impl FetchBlockDataFromDb for (Transaction, TransactionOutput) { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError> { + let transactions = + txn.get_block_transactions(block_number)?.ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + })?; + let transaction_outputs = txn.get_block_transaction_outputs(block_number)?.ok_or( + P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + }, + )?; + let mut result: Vec<(Transaction, TransactionOutput)> = Vec::new(); + for (transaction, transaction_output) in + transactions.into_iter().zip(transaction_outputs.into_iter()) + { + result.push((transaction, transaction_output)); + } + Ok(result) + } +} + +impl FetchBlockDataFromDb for ApiContractClass { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError> { + let thin_state_diff = + txn.get_state_diff(block_number)?.ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + })?; + let declared_classes = thin_state_diff.declared_classes; + let deprecated_declared_classes = thin_state_diff.deprecated_declared_classes; + let mut result = Vec::new(); + for class_hash in &deprecated_declared_classes { + result.push(ApiContractClass::DeprecatedContractClass( + txn.get_deprecated_class(class_hash)? + .ok_or(P2PSyncServerError::ClassNotFound { class_hash: *class_hash })?, + )); + } + for (class_hash, _) in &declared_classes { + result.push(ApiContractClass::ContractClass( + txn.get_class(class_hash)? + .ok_or(P2PSyncServerError::ClassNotFound { class_hash: *class_hash })?, + )); + } + Ok(result) + } +} + +impl FetchBlockDataFromDb for (Event, TransactionHash) { + fn fetch_block_data_from_db( + block_number: BlockNumber, + txn: &StorageTxn<'_, db::RO>, + ) -> Result, P2PSyncServerError> { + let transaction_outputs = txn.get_block_transaction_outputs(block_number)?.ok_or( + P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + }, + )?; + let transaction_hashes = txn.get_block_transaction_hashes(block_number)?.ok_or( + P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Number(block_number), + }, + )?; + + let mut result = Vec::new(); + for (transaction_output, transaction_hash) in + transaction_outputs.into_iter().zip(transaction_hashes) + { + for event in transaction_output.events() { + result.push((event.clone(), transaction_hash)); + } + } + Ok(result) + } +} + +pub fn split_thin_state_diff(thin_state_diff: ThinStateDiff) -> Vec { + let mut state_diff_chunks = Vec::new(); + #[cfg(not(test))] + let mut contract_addresses = std::collections::HashSet::new(); + #[cfg(test)] + let mut contract_addresses = std::collections::BTreeSet::new(); + + contract_addresses.extend( + thin_state_diff + .deployed_contracts + .keys() + .chain(thin_state_diff.replaced_classes.keys()) + .chain(thin_state_diff.nonces.keys()) + .chain(thin_state_diff.storage_diffs.keys()), + ); + for contract_address in contract_addresses { + let class_hash = thin_state_diff + .deployed_contracts + .get(&contract_address) + .or_else(|| thin_state_diff.replaced_classes.get(&contract_address)) + .cloned(); + let storage_diffs = + thin_state_diff.storage_diffs.get(&contract_address).cloned().unwrap_or_default(); + let nonce = thin_state_diff.nonces.get(&contract_address).cloned(); + state_diff_chunks.push(StateDiffChunk::ContractDiff(ContractDiff { + contract_address, + class_hash, + nonce, + storage_diffs, + })); + } + + for (class_hash, compiled_class_hash) in thin_state_diff.declared_classes { + state_diff_chunks + .push(StateDiffChunk::DeclaredClass(DeclaredClass { class_hash, compiled_class_hash })); + } + + for class_hash in thin_state_diff.deprecated_declared_classes { + state_diff_chunks + .push(StateDiffChunk::DeprecatedDeclaredClass(DeprecatedDeclaredClass { class_hash })); + } + state_diff_chunks +} + +async fn send_data_for_query( + storage_reader: StorageReader, + query: Query, + mut sender: Sender, +) -> Result<(), P2PSyncServerError> +where + Data: FetchBlockDataFromDb + Send + 'static, + Sender: Sink> + Unpin + Send + 'static, + P2PSyncServerError: From<>>::Error>, +{ + // If this function fails, we still want to send fin before failing. + let result = send_data_without_fin_for_query(&storage_reader, query, &mut sender).await; + sender.feed(DataOrFin(None)).await?; + result +} + +async fn send_data_without_fin_for_query( + storage_reader: &StorageReader, + query: Query, + sender: &mut Sender, +) -> Result<(), P2PSyncServerError> +where + Data: FetchBlockDataFromDb + Send + 'static, + Sender: Sink> + Unpin + Send + 'static, + P2PSyncServerError: From<>>::Error>, +{ + let txn = storage_reader.begin_ro_txn()?; + let start_block_number = match query.start_block { + BlockHashOrNumber::Number(BlockNumber(num)) => num, + BlockHashOrNumber::Hash(block_hash) => { + txn.get_block_number_by_hash(&block_hash)? + .ok_or(P2PSyncServerError::BlockNotFound { + block_hash_or_number: BlockHashOrNumber::Hash(block_hash), + })? + .0 + } + }; + for block_counter in 0..query.limit { + let block_number = + BlockNumber(utils::calculate_block_number(&query, start_block_number, block_counter)?); + let data_vec = Data::fetch_block_data_from_db(block_number, &txn)?; + for data in data_vec { + // TODO: consider implement retry mechanism. + sender.feed(DataOrFin(Some(data))).await?; + } + } + Ok(()) +} diff --git a/crates/papyrus_p2p_sync/src/server/test.rs b/crates/papyrus_p2p_sync/src/server/test.rs new file mode 100644 index 00000000000..9eee0bc03cd --- /dev/null +++ b/crates/papyrus_p2p_sync/src/server/test.rs @@ -0,0 +1,467 @@ +use futures::channel::mpsc::{Receiver, Sender}; +use futures::StreamExt; +use lazy_static::lazy_static; +use papyrus_common::pending_classes::ApiContractClass; +use papyrus_common::state::create_random_state_diff; +use papyrus_protobuf::converters::ProtobufConversionError; +use papyrus_protobuf::sync::{ + BlockHashOrNumber, + ClassQuery, + DataOrFin, + Direction, + EventQuery, + HeaderQuery, + Query, + SignedBlockHeader, + StateDiffChunk, + StateDiffQuery, + TransactionQuery, +}; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::{StorageReader, StorageWriter}; +use rand::random; +use starknet_api::block::{BlockBody, BlockHash, BlockHeader, BlockNumber, BlockSignature}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::ContractClass; +use starknet_api::transaction::{Event, Transaction, TransactionHash, TransactionOutput}; +use test_utils::{get_rng, get_test_body, GetTestInstance}; + +use super::{split_thin_state_diff, FetchBlockDataFromDb, P2PSyncServer}; +const BUFFER_SIZE: usize = 10; +const NUM_OF_BLOCKS: u64 = 10; +const NUM_TXS_PER_BLOCK: usize = 5; +const EVENTS_PER_TX: usize = 2; +const BLOCKS_DELTA: u64 = 5; + +enum StartBlockType { + Hash, + Number, +} + +// TODO(shahak): Change tests to use channels and not register_query +#[tokio::test] +async fn header_query_positive_flow() { + let assert_signed_block_header = |data: Vec| { + let len = data.len(); + assert!(len == NUM_OF_BLOCKS as usize); + for (i, signed_header) in data.into_iter().enumerate() { + assert_eq!(signed_header.block_header.block_number.0, i as u64); + } + }; + + run_test(assert_signed_block_header, 0, StartBlockType::Hash).await; + run_test(assert_signed_block_header, 0, StartBlockType::Number).await; +} + +#[tokio::test] +async fn transaction_query_positive_flow() { + let assert_transaction_and_output = |data: Vec<(Transaction, TransactionOutput)>| { + let len = data.len(); + assert_eq!(len, NUM_OF_BLOCKS as usize * NUM_TXS_PER_BLOCK); + for (i, (tx, tx_output)) in data.into_iter().enumerate() { + assert_eq!(tx, TXS[i / NUM_TXS_PER_BLOCK][i % NUM_TXS_PER_BLOCK]); + assert_eq!(tx_output, TX_OUTPUTS[i / NUM_TXS_PER_BLOCK][i % NUM_TXS_PER_BLOCK]); + } + }; + + run_test(assert_transaction_and_output, 0, StartBlockType::Hash).await; + run_test(assert_transaction_and_output, 0, StartBlockType::Number).await; +} + +#[tokio::test] +async fn state_diff_query_positive_flow() { + let assert_state_diff_chunk = |data: Vec| { + assert_eq!(data.len(), STATE_DIFF_CHUNCKS.len()); + + for (data, expected_data) in data.iter().zip(STATE_DIFF_CHUNCKS.iter()) { + assert_eq!(data, expected_data); + } + }; + run_test(assert_state_diff_chunk, 0, StartBlockType::Hash).await; + run_test(assert_state_diff_chunk, 0, StartBlockType::Number).await; +} + +#[tokio::test] +async fn event_query_positive_flow() { + let assert_event = |data: Vec<(Event, TransactionHash)>| { + assert_eq!(data.len(), NUM_OF_BLOCKS as usize * NUM_TXS_PER_BLOCK * EVENTS_PER_TX); + for (i, (event, tx_hash)) in data.into_iter().enumerate() { + assert_eq!( + tx_hash, + TX_HASHES[i / (NUM_TXS_PER_BLOCK * EVENTS_PER_TX)] + [i / EVENTS_PER_TX % NUM_TXS_PER_BLOCK] + ); + assert_eq!( + event, + EVENTS[i / (NUM_TXS_PER_BLOCK * EVENTS_PER_TX) + + i / EVENTS_PER_TX % NUM_TXS_PER_BLOCK] + ); + } + }; + + run_test(assert_event, 0, StartBlockType::Hash).await; + run_test(assert_event, 0, StartBlockType::Number).await; +} + +#[tokio::test] +async fn class_query_positive_flow() { + let assert_class = |data: Vec| { + // create_random_state_diff creates a state diff with 1 declared class + // and 1 deprecated declared class + assert_eq!(data.len(), CLASSES.len() + DEPRECATED_CLASSES.len()); + for (i, data) in data.iter().enumerate() { + match data { + ApiContractClass::ContractClass(contract_class) => { + assert_eq!(contract_class, &CLASSES[i / 2]); + } + ApiContractClass::DeprecatedContractClass(deprecated_contract_class) => { + assert_eq!(deprecated_contract_class, &DEPRECATED_CLASSES[i / 2]) + } + } + } + }; + run_test(assert_class, 0, StartBlockType::Hash).await; + run_test(assert_class, 0, StartBlockType::Number).await; +} + +#[tokio::test] +async fn header_query_some_blocks_are_missing() { + let assert_signed_block_header = |data: Vec| { + let len = data.len(); + assert!(len == BLOCKS_DELTA as usize); + for (i, signed_header) in data.into_iter().enumerate() { + assert_eq!( + signed_header.block_header.block_number.0, + i as u64 + NUM_OF_BLOCKS - BLOCKS_DELTA + ); + } + }; + + run_test(assert_signed_block_header, NUM_OF_BLOCKS - BLOCKS_DELTA, StartBlockType::Number) + .await; +} + +#[tokio::test] +async fn transaction_query_some_blocks_are_missing() { + let assert_transaction_and_output = |data: Vec<(Transaction, TransactionOutput)>| { + let len = data.len(); + assert!(len == (BLOCKS_DELTA as usize * NUM_TXS_PER_BLOCK)); + for (i, (tx, tx_output)) in data.into_iter().enumerate() { + assert_eq!( + tx, + TXS[i / NUM_TXS_PER_BLOCK + NUM_OF_BLOCKS as usize - BLOCKS_DELTA as usize] + [i % NUM_TXS_PER_BLOCK] + ); + assert_eq!( + tx_output, + TX_OUTPUTS[i / NUM_TXS_PER_BLOCK + NUM_OF_BLOCKS as usize - BLOCKS_DELTA as usize] + [i % NUM_TXS_PER_BLOCK] + ); + } + }; + + run_test(assert_transaction_and_output, NUM_OF_BLOCKS - BLOCKS_DELTA, StartBlockType::Number) + .await; +} + +#[tokio::test] +async fn state_diff_query_some_blocks_are_missing() { + let assert_state_diff_chunk = |data: Vec| { + // create_random_state_diff creates a state diff with 5 chunks. + const STATE_DIFF_CHUNK_PER_BLOCK: usize = 5; + assert_eq!(data.len(), BLOCKS_DELTA as usize * STATE_DIFF_CHUNK_PER_BLOCK); + for (i, data) in data.into_iter().enumerate() { + assert_eq!( + data, + STATE_DIFF_CHUNCKS[i + + (NUM_OF_BLOCKS as usize - BLOCKS_DELTA as usize) + * STATE_DIFF_CHUNK_PER_BLOCK] + ); + } + }; + + run_test(assert_state_diff_chunk, NUM_OF_BLOCKS - BLOCKS_DELTA, StartBlockType::Number).await; +} + +#[tokio::test] +async fn event_query_some_blocks_are_missing() { + let assert_event = |data: Vec<(Event, TransactionHash)>| { + let len = data.len(); + assert_eq!(len, BLOCKS_DELTA as usize * NUM_TXS_PER_BLOCK * EVENTS_PER_TX); + for (i, (event, tx_hash)) in data.into_iter().enumerate() { + assert_eq!( + tx_hash, + TX_HASHES[i / (NUM_TXS_PER_BLOCK * EVENTS_PER_TX) + + (NUM_OF_BLOCKS - BLOCKS_DELTA) as usize] + [i / EVENTS_PER_TX % NUM_TXS_PER_BLOCK] + ); + assert_eq!( + event, + EVENTS[i / (NUM_TXS_PER_BLOCK * EVENTS_PER_TX) + + (NUM_OF_BLOCKS - BLOCKS_DELTA) as usize + + i / EVENTS_PER_TX % NUM_TXS_PER_BLOCK] + ); + } + }; + + run_test(assert_event, NUM_OF_BLOCKS - BLOCKS_DELTA, StartBlockType::Number).await; +} + +#[tokio::test] +async fn class_query_some_blocks_are_missing() { + let assert_class = |data: Vec| { + // create_random_state_diff creates a state diff with 1 declared class + // and 1 deprecated declared class + assert_eq!(data.len(), BLOCKS_DELTA as usize * 2); + for (i, data) in data.iter().enumerate() { + match data { + ApiContractClass::ContractClass(contract_class) => { + assert_eq!( + contract_class, + &CLASSES[i / 2 + (NUM_OF_BLOCKS - BLOCKS_DELTA) as usize] + ); + } + ApiContractClass::DeprecatedContractClass(deprecated_contract_class) => { + assert_eq!( + deprecated_contract_class, + &DEPRECATED_CLASSES[i / 2 + (NUM_OF_BLOCKS - BLOCKS_DELTA) as usize] + ) + } + } + } + }; + run_test(assert_class, NUM_OF_BLOCKS - BLOCKS_DELTA, StartBlockType::Number).await; +} + +async fn run_test(assert_fn: F, start_block_number: u64, start_block_type: StartBlockType) +where + T: FetchBlockDataFromDb + std::fmt::Debug + PartialEq + Send + Sync + 'static, + F: FnOnce(Vec), +{ + let ( + p2p_sync_server, + storage_reader, + mut storage_writer, + _header_queries_sender, + _state_diff_queries_sender, + _transaction_queries_sender, + _class_queries_sender, + _event_queries_sender, + ) = setup(); + + // put some data in the storage. + insert_to_storage_test_blocks_up_to(&mut storage_writer); + + let start_block = match start_block_type { + StartBlockType::Hash => BlockHashOrNumber::Hash( + storage_reader + .begin_ro_txn() + .unwrap() + .get_block_header(BlockNumber(start_block_number)) + .unwrap() + .unwrap() + .block_hash, + ), + StartBlockType::Number => BlockHashOrNumber::Number(BlockNumber(start_block_number)), + }; + + // register a query. + let (sender, receiver) = futures::channel::mpsc::channel(BUFFER_SIZE); + let query = Query { start_block, direction: Direction::Forward, limit: NUM_OF_BLOCKS, step: 1 }; + p2p_sync_server.register_query::(query, sender); + + // run p2p_sync_server and collect query results. + tokio::select! { + _ = p2p_sync_server.run() => { + panic!("p2p_sync_server should never finish its run."); + }, + mut res = receiver.collect::>() => { + assert_eq!(DataOrFin(None), res.pop().unwrap()); + let filtered_res: Vec = res.into_iter() + .map(|data| data.0.expect("P2PSyncServer returned Fin and then returned another response")) + .collect(); + assert_fn(filtered_res); + } + } +} + +#[allow(clippy::type_complexity)] +fn setup() -> ( + P2PSyncServer< + Receiver<( + Result, + Sender>, + )>, + Receiver<( + Result, + Sender>, + )>, + Receiver<( + Result, + Sender>, + )>, + Receiver<( + Result, + Sender>, + )>, + Receiver<( + Result, + Sender>, + )>, + >, + StorageReader, + StorageWriter, + Sender<(Result, Sender>)>, + Sender<(Result, Sender>)>, + Sender<( + Result, + Sender>, + )>, + Sender<(Result, Sender>)>, + Sender<( + Result, + Sender>, + )>, +) { + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage(); + let (header_queries_sender, header_queries_receiver) = futures::channel::mpsc::channel::<( + Result, + Sender>, + )>(BUFFER_SIZE); + let (state_diff_queries_sender, state_diff_queries_receiver) = futures::channel::mpsc::channel::< + (Result, Sender>), + >(BUFFER_SIZE); + let (transaction_sender, transaction_queries_receiver) = futures::channel::mpsc::channel::<( + Result, + Sender>, + )>(BUFFER_SIZE); + let (class_sender, class_queries_receiver) = futures::channel::mpsc::channel::<( + Result, + Sender>, + )>(BUFFER_SIZE); + let (event_sender, event_queries_receiver) = futures::channel::mpsc::channel::<( + Result, + Sender>, + )>(BUFFER_SIZE); + + let p2p_sync_server = super::P2PSyncServer::new( + storage_reader.clone(), + header_queries_receiver, + state_diff_queries_receiver, + transaction_queries_receiver, + class_queries_receiver, + event_queries_receiver, + ); + ( + p2p_sync_server, + storage_reader, + storage_writer, + header_queries_sender, + state_diff_queries_sender, + transaction_sender, + class_sender, + event_sender, + ) +} +use starknet_api::core::ClassHash; +fn insert_to_storage_test_blocks_up_to(storage_writer: &mut StorageWriter) { + for i in 0..NUM_OF_BLOCKS { + let i_usize = usize::try_from(i).unwrap(); + let block_header = BlockHeader { + block_number: BlockNumber(i), + block_hash: BlockHash(random::().into()), + ..Default::default() + }; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(i), &block_header) + .unwrap() + // TODO(shahak): Put different signatures for each block to test that we retrieve the + // right signatures. + .append_block_signature(BlockNumber(i), &BlockSignature::default()) + .unwrap() + .append_state_diff(BlockNumber(i), THIN_STATE_DIFFS[i_usize].clone()) + .unwrap() + .append_body(BlockNumber(i), BlockBody{transactions: TXS[i_usize].clone(), + transaction_outputs: TX_OUTPUTS[i_usize].clone(), + transaction_hashes: TX_HASHES[i_usize].clone(),}).unwrap() + .append_classes(BlockNumber(i), &CLASSES_WITH_HASHES[i_usize], &DEPRECATED_CLASSES_WITH_HASHES[i_usize]) + .unwrap() + .commit() + .unwrap(); + } +} + +lazy_static! { + static ref THIN_STATE_DIFFS: Vec = { + let mut rng = get_rng(); + (0..NUM_OF_BLOCKS).map(|_| create_random_state_diff(&mut rng)).collect::>() + }; + static ref STATE_DIFF_CHUNCKS: Vec = + THIN_STATE_DIFFS.iter().flat_map(|diff| split_thin_state_diff(diff.clone())).collect(); + static ref BODY: BlockBody = + get_test_body(NUM_OF_BLOCKS as usize * NUM_TXS_PER_BLOCK, Some(EVENTS_PER_TX), None, None); + static ref TXS: Vec> = + BODY.clone().transactions.chunks(NUM_TXS_PER_BLOCK).map(|chunk| chunk.to_vec()).collect(); + static ref TX_OUTPUTS: Vec> = BODY + .clone() + .transaction_outputs + .chunks(NUM_TXS_PER_BLOCK) + .map(|chunk| chunk.to_vec()) + .collect(); + static ref TX_HASHES: Vec> = BODY + .clone() + .transaction_hashes + .chunks(NUM_TXS_PER_BLOCK) + .map(|chunk| chunk.to_vec()) + .collect(); + static ref EVENTS: Vec = TX_OUTPUTS + .clone() + .into_iter() + .flat_map(|tx_output| tx_output.into_iter().flat_map(|output| output.events().to_vec())) + .collect(); + static ref CLASSES: Vec = { + (0..NUM_OF_BLOCKS) + .map(|_| ContractClass::get_test_instance(&mut get_rng())) + .collect::>() + }; + static ref CLASSES_WITH_HASHES: Vec> = { + THIN_STATE_DIFFS + .iter() + .enumerate() + .map(|(i, state_diff)| { + let contract_class = &CLASSES[i]; + let class_vec = state_diff + .declared_classes + .iter() + .map(|(class_hash, _)| (*class_hash, contract_class)) + .collect::>(); + class_vec + }) + .collect::>() + }; + static ref DEPRECATED_CLASSES: Vec = { + (0..NUM_OF_BLOCKS) + .map(|_| DeprecatedContractClass::get_test_instance(&mut get_rng())) + .collect::>() + }; + static ref DEPRECATED_CLASSES_WITH_HASHES: Vec> = { + THIN_STATE_DIFFS + .iter() + .enumerate() + .map(|(i, state_diff)| { + let deprecated_declared_classes_hashes = + state_diff.deprecated_declared_classes.clone(); + deprecated_declared_classes_hashes + .iter() + .map(|class_hash| (*class_hash, &DEPRECATED_CLASSES[i])) + .collect::>() + }) + .collect::>() + }; +} diff --git a/crates/papyrus_p2p_sync/src/server/utils.rs b/crates/papyrus_p2p_sync/src/server/utils.rs new file mode 100644 index 00000000000..6e91ea43c39 --- /dev/null +++ b/crates/papyrus_p2p_sync/src/server/utils.rs @@ -0,0 +1,24 @@ +use papyrus_protobuf::sync::{Direction, Query}; + +use super::P2PSyncServerError; + +pub(crate) fn calculate_block_number( + query: &Query, + start_block: u64, + read_blocks_counter: u64, +) -> Result { + let direction_factor: i128 = match query.direction { + Direction::Forward => 1, + Direction::Backward => -1, + }; + // TODO(shahak): Fix this code. + let blocks_delta: i128 = direction_factor * (query.step * read_blocks_counter) as i128; + let block_number: i128 = start_block as i128 + blocks_delta; + if block_number < 0 || block_number > u64::MAX as i128 { + return Err(P2PSyncServerError::BlockNumberOutOfRange { + query: query.clone(), + counter: read_blocks_counter, + }); + } + Ok(block_number as u64) +} diff --git a/crates/papyrus_proc_macros/Cargo.toml b/crates/papyrus_proc_macros/Cargo.toml new file mode 100644 index 00000000000..b625328baff --- /dev/null +++ b/crates/papyrus_proc_macros/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "papyrus_proc_macros" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Procedural macros for the Papyrus node" + +[dependencies] +syn = { version = "2.0.39", features = ["full"] } +quote = "1.0.26" + +[dev-dependencies] +metrics.workspace = true +metrics-exporter-prometheus.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-dev.1" } +prometheus-parse.workspace = true +test_utils = { path = "../test_utils" } + +[lib] +proc-macro = true diff --git a/crates/papyrus_proc_macros/src/lib.rs b/crates/papyrus_proc_macros/src/lib.rs new file mode 100644 index 00000000000..bec181d18f9 --- /dev/null +++ b/crates/papyrus_proc_macros/src/lib.rs @@ -0,0 +1,167 @@ +use std::str::FromStr; + +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::{parse_macro_input, ExprLit, ItemFn, ItemTrait, LitBool, LitStr, Meta, TraitItem}; + +/// This macro is a wrapper around the "rpc" macro supplied by the jsonrpsee library that generates +/// a server and client traits from a given trait definition. The wrapper gets a version id and +/// prepend the version id to the trait name and to every method name (note method name refers to +/// the name the API has for the function not the actual function name). We need this in order to be +/// able to merge multiple versions of jsonrpc APIs into one server and not have a clash in method +/// resolution. +/// +/// # Example: +/// +/// Given this code: +/// ```rust,ignore +/// #[versioned_rpc("V0_6_0")] +/// pub trait JsonRpc { +/// #[method(name = "blockNumber")] +/// fn block_number(&self) -> Result; +/// } +/// ``` +/// +/// The macro will generate this code: +/// ```rust,ignore +/// #[rpc(server, client, namespace = "starknet")] +/// pub trait JsonRpcV0_6_0 { +/// #[method(name = "V0_6_0_blockNumber")] +/// fn block_number(&self) -> Result; +/// } +/// ``` +#[proc_macro_attribute] +pub fn versioned_rpc(attr: TokenStream, input: TokenStream) -> TokenStream { + let version = parse_macro_input!(attr as syn::LitStr); + let item_trait = parse_macro_input!(input as ItemTrait); + + let trait_name = &item_trait.ident; + let visibility = &item_trait.vis; + + // generate the new method signatures with the version prefix + let versioned_methods = item_trait + .items + .iter() + .map(|item| { + if let TraitItem::Fn(method) = item { + let new_method = syn::TraitItemFn { + attrs: method + .attrs + .iter() + .filter(|attr| !matches!(attr.meta, Meta::NameValue(_))) + .map(|attr| { + let mut new_attr = attr.clone(); + if attr.path().is_ident("method") { + let _ = attr.parse_nested_meta(|meta| { + if meta.path.is_ident("name") { + let value = meta.value()?; + let method_name: LitStr = value.parse()?; + let new_meta_str = format!( + "method(name = \"{}_{}\")", + version.value(), + method_name.value() + ); + new_attr.meta = syn::parse_str::(&new_meta_str)?; + } + Ok(()) + }); + } + new_attr + }) + .collect::>(), + sig: method.sig.clone(), + default: method.default.clone(), + semi_token: method.semi_token, + }; + new_method.into() + } else { + item.clone() + } + }) + .collect::>(); + + // generate the versioned trait with the new method signatures + let versioned_trait = syn::ItemTrait { + attrs: vec![syn::parse_quote!(#[rpc(server, client, namespace = "starknet")])], + vis: visibility.clone(), + unsafety: None, + auto_token: None, + ident: syn::Ident::new(&format!("{}{}", trait_name, version.value()), trait_name.span()), + colon_token: None, + supertraits: item_trait.supertraits.clone(), + brace_token: item_trait.brace_token, + items: versioned_methods, + restriction: item_trait.restriction.clone(), + generics: item_trait.generics.clone(), + trait_token: item_trait.trait_token, + }; + + versioned_trait.to_token_stream().into() +} + +/// This macro will emit a histogram metric with the given name and the latency of the function. +/// The macro also receives a boolean for whether it will be emitted only when +/// profiling is activated or at all times. +/// +/// # Example +/// Given this code: +/// +/// ```rust,ignore +/// #[latency_histogram("metric_name", false)] +/// fn foo() { +/// // Some code ... +/// } +/// ``` +/// Every call to foo will update the histogram metric with the name “metric_name” with the time it +/// took to execute foo. +/// The metric will be emitted regardless of the value of the profiling configuration, +/// since the config value is false. +#[proc_macro_attribute] +pub fn latency_histogram(attr: TokenStream, input: TokenStream) -> TokenStream { + let mut input_fn = parse_macro_input!(input as ItemFn); + let parts = attr + .to_string() + .split(',') + .map(|s| { + TokenStream::from_str(s) + .expect("Expecting metric name and bool (is for profiling only)") + }) + .collect::>(); + let metric_name_as_tokenstream = parts + .first() + .expect("attribute should include metric name and controll with config boolean") + .clone(); + // TODO: consider naming the input value instead of providing a bool + // TODO: consider adding support for metrics levels (e.g. debug, info, warn, error) instead of + // boolean + let controll_with_config_as_tokenstream = parts + .get(1) + .expect("attribute should include metric name and controll with config boolean") + .clone(); + let metric_name = parse_macro_input!(metric_name_as_tokenstream as ExprLit); + let controll_with_config = parse_macro_input!(controll_with_config_as_tokenstream as LitBool); + let origin_block = &mut input_fn.block; + + // Create a new block with the metric update. + let expanded_block = quote! { + { + let mut start_function_time = None; + if !#controll_with_config || (#controll_with_config && *(papyrus_common::metrics::COLLECT_PROFILING_METRICS.get().unwrap_or(&false))) { + start_function_time=Some(std::time::Instant::now()); + } + let return_value=#origin_block; + if let Some(start_time) = start_function_time { + metrics::histogram!(#metric_name, start_time.elapsed().as_secs_f64()); + } + return_value + } + }; + + // Create a new function with the modified block. + let modified_function = ItemFn { + block: syn::parse2(expanded_block).expect("Parse tokens in latency_histogram attribute."), + ..input_fn + }; + + modified_function.to_token_stream().into() +} diff --git a/crates/papyrus_proc_macros/tests/latency_histogram.rs b/crates/papyrus_proc_macros/tests/latency_histogram.rs new file mode 100644 index 00000000000..1af5f170787 --- /dev/null +++ b/crates/papyrus_proc_macros/tests/latency_histogram.rs @@ -0,0 +1,40 @@ +use metrics_exporter_prometheus::PrometheusBuilder; +use papyrus_common::metrics::COLLECT_PROFILING_METRICS; +use papyrus_proc_macros::latency_histogram; +use prometheus_parse::Value::Untyped; +use test_utils::prometheus_is_contained; + +#[test] +fn latency_histogram_test() { + COLLECT_PROFILING_METRICS.set(false).unwrap(); + + #[latency_histogram("foo_histogram", false)] + fn foo() -> usize { + #[allow(clippy::let_and_return)] + let start_function_time = 1000; + start_function_time + } + + #[latency_histogram("bar_histogram", true)] + fn bar() -> usize { + #[allow(clippy::let_and_return)] + let start_function_time = 1000; + start_function_time + } + + let handle = PrometheusBuilder::new().install_recorder().unwrap(); + + assert!(handle.render().is_empty()); + assert_eq!(bar(), 1000); + assert!(handle.render().is_empty()); + assert_eq!(foo(), 1000); + assert_eq!( + prometheus_is_contained(handle.render(), "foo_histogram_count", &[]), + Some(Untyped(1f64)) + ); + // Test that the "start_function_time" variable from the macro is not shadowed. + assert_ne!( + prometheus_is_contained(handle.render(), "foo_histogram_sum", &[]), + Some(Untyped(1000f64)) + ); +} diff --git a/crates/papyrus_protobuf/Cargo.toml b/crates/papyrus_protobuf/Cargo.toml new file mode 100644 index 00000000000..64659b11653 --- /dev/null +++ b/crates/papyrus_protobuf/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "papyrus_protobuf" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[features] +testing = ["rand", "rand_chacha", "test_utils"] + +[dependencies] +indexmap.workspace = true +lazy_static.workspace = true +primitive-types.workspace = true +prost.workspace = true +rand = { workspace = true, optional = true } +rand_chacha = { workspace = true, optional = true } +starknet_api.workspace = true +starknet-types-core.workspace = true +test_utils = { path = "../test_utils", optional = true } +thiserror.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-dev.2" } + +[dev-dependencies] +rand.workspace = true +rand_chacha.workspace = true +test_utils = { path = "../test_utils" } + +[build-dependencies] +prost-build.workspace = true + +[package.metadata.cargo-machete] +# The `rand` and `rand_chacha` crates are used in the `testing` feature, which is optional. +ignored = ["rand", "rand_chacha"] diff --git a/crates/papyrus_protobuf/build.rs b/crates/papyrus_protobuf/build.rs new file mode 100644 index 00000000000..91475765f32 --- /dev/null +++ b/crates/papyrus_protobuf/build.rs @@ -0,0 +1,41 @@ +use std::env; +use std::io::{Error, ErrorKind, Result}; +use std::process::Command; + +fn main() -> Result<()> { + println!("Building"); + let protoc = env::var("PROTOC").unwrap_or("protoc".to_string()); + + let protoc_version = String::from_utf8_lossy( + &Command::new(protoc).arg("--version").output().expect("Protoc is not installed.").stdout, + ) + .to_string(); + + let parts: Vec<&str> = protoc_version.split_whitespace().collect(); + let protoc_version_str = parts.get(1).expect("Failed to determine protoc version"); + let mut protoc_version_parts = protoc_version_str + .split('.') + .map(|part| part.parse::().expect("Error parsing protoc version")); + let major = protoc_version_parts.next().expect("Protoc version did not have a major number"); + let minor = protoc_version_parts.next().unwrap_or_default(); + + if major < 3 || (major == 3 && minor < 15) { + Err(Error::new( + ErrorKind::Other, + "protoc version is too old. version 3.15.x or greater is needed.", + )) + } else { + prost_build::compile_protos( + &[ + "src/proto/p2p/proto/class.proto", + "src/proto/p2p/proto/event.proto", + "src/proto/p2p/proto/header.proto", + "src/proto/p2p/proto/state.proto", + "src/proto/p2p/proto/transaction.proto", + "src/proto/p2p/proto/consensus.proto", + ], + &["src/proto/"], + )?; + Ok(()) + } +} diff --git a/crates/papyrus_protobuf/src/consensus.rs b/crates/papyrus_protobuf/src/consensus.rs new file mode 100644 index 00000000000..f46717c9c82 --- /dev/null +++ b/crates/papyrus_protobuf/src/consensus.rs @@ -0,0 +1,40 @@ +use starknet_api::block::BlockHash; +use starknet_api::core::ContractAddress; +use starknet_api::transaction::Transaction; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Proposal { + pub height: u64, + pub proposer: ContractAddress, + pub transactions: Vec, + pub block_hash: BlockHash, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum VoteType { + Prevote, + Precommit, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Vote { + pub vote_type: VoteType, + pub height: u64, + pub block_hash: BlockHash, + pub voter: ContractAddress, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum ConsensusMessage { + Proposal(Proposal), + Vote(Vote), +} + +impl ConsensusMessage { + pub fn height(&self) -> u64 { + match self { + ConsensusMessage::Proposal(proposal) => proposal.height, + ConsensusMessage::Vote(vote) => vote.height, + } + } +} diff --git a/crates/papyrus_protobuf/src/converters/class.rs b/crates/papyrus_protobuf/src/converters/class.rs new file mode 100644 index 00000000000..9e16a084839 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/class.rs @@ -0,0 +1,344 @@ +use std::collections::HashMap; +use std::convert::{TryFrom, TryInto}; + +use papyrus_common::pending_classes::ApiContractClass; +use prost::Message; +use starknet_api::core::EntryPointSelector; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::{deprecated_contract_class, state}; +use starknet_types_core::felt::Felt; + +use super::common::volition_domain_to_enum_int; +use super::ProtobufConversionError; +use crate::sync::{ClassQuery, DataOrFin, Query}; +use crate::{auto_impl_into_and_try_from_vec_u8, protobuf}; + +pub const DOMAIN: DataAvailabilityMode = DataAvailabilityMode::L1; + +impl TryFrom for DataOrFin { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ClassesResponse) -> Result { + match value.class_message { + Some(protobuf::classes_response::ClassMessage::Class(class)) => { + Ok(Self(Some(class.try_into()?))) + } + Some(protobuf::classes_response::ClassMessage::Fin(_)) => Ok(Self(None)), + None => Err(ProtobufConversionError::MissingField { + field_description: "ClassesResponse::class_message", + }), + } + } +} +impl From> for protobuf::ClassesResponse { + fn from(value: DataOrFin) -> Self { + match value.0 { + Some(class) => protobuf::ClassesResponse { + class_message: Some(protobuf::classes_response::ClassMessage::Class(class.into())), + }, + None => protobuf::ClassesResponse { + class_message: Some(protobuf::classes_response::ClassMessage::Fin( + protobuf::Fin {}, + )), + }, + } + } +} + +auto_impl_into_and_try_from_vec_u8!(DataOrFin, protobuf::ClassesResponse); + +impl TryFrom for ApiContractClass { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Class) -> Result { + let class = match value.class { + Some(protobuf::class::Class::Cairo0(class)) => { + ApiContractClass::DeprecatedContractClass( + deprecated_contract_class::ContractClass::try_from(class)?, + ) + } + Some(protobuf::class::Class::Cairo1(class)) => { + ApiContractClass::ContractClass(state::ContractClass::try_from(class)?) + } + None => { + return Err(ProtobufConversionError::MissingField { + field_description: "Class::class", + }); + } + }; + Ok(class) + } +} + +impl From for protobuf::Class { + fn from(value: ApiContractClass) -> Self { + let domain = u32::try_from(volition_domain_to_enum_int(DOMAIN)) + .expect("volition_domain_to_enum_int output should be convertible to u32"); + let class = match value { + ApiContractClass::DeprecatedContractClass(class) => { + protobuf::class::Class::Cairo0(class.into()) + } + ApiContractClass::ContractClass(class) => protobuf::class::Class::Cairo1(class.into()), + }; + protobuf::Class { domain, class: Some(class) } + } +} + +impl TryFrom for deprecated_contract_class::ContractClass { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Cairo0Class) -> Result { + let mut entry_points_by_type = HashMap::new(); + + if !value.constructors.is_empty() { + entry_points_by_type.insert( + deprecated_contract_class::EntryPointType::Constructor, + value + .constructors + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + if !value.externals.is_empty() { + entry_points_by_type.insert( + deprecated_contract_class::EntryPointType::External, + value + .externals + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + if !value.l1_handlers.is_empty() { + entry_points_by_type.insert( + deprecated_contract_class::EntryPointType::L1Handler, + value + .l1_handlers + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + // TODO: fill abi + let abi = None; + // TODO: fill program + let program = deprecated_contract_class::Program::default(); + + Ok(Self { program, entry_points_by_type, abi }) + } +} + +impl From for protobuf::Cairo0Class { + fn from(value: deprecated_contract_class::ContractClass) -> Self { + protobuf::Cairo0Class { + constructors: value + .entry_points_by_type + .get(&deprecated_contract_class::EntryPointType::Constructor) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::EntryPoint::from) + .collect(), + externals: value + .entry_points_by_type + .get(&deprecated_contract_class::EntryPointType::External) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::EntryPoint::from) + .collect(), + l1_handlers: value + .entry_points_by_type + .get(&deprecated_contract_class::EntryPointType::L1Handler) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::EntryPoint::from) + .collect(), + // TODO: fill abi and program + abi: "".to_string(), + program: "".to_string(), + } + } +} + +impl TryFrom for state::ContractClass { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Cairo1Class) -> Result { + let abi = value.abi; + + let sierra_program = + value.program.into_iter().map(Felt::try_from).collect::, _>>()?; + + let mut entry_points_by_type = HashMap::new(); + let entry_points = + value.entry_points.clone().ok_or(ProtobufConversionError::MissingField { + field_description: "Cairo1Class::entry_points", + })?; + if !entry_points.constructors.is_empty() { + entry_points_by_type.insert( + state::EntryPointType::Constructor, + entry_points + .constructors + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + if !entry_points.externals.is_empty() { + entry_points_by_type.insert( + state::EntryPointType::External, + entry_points + .externals + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + if !entry_points.l1_handlers.is_empty() { + entry_points_by_type.insert( + state::EntryPointType::L1Handler, + entry_points + .l1_handlers + .into_iter() + .map(|entry_point| entry_point.try_into()) + .collect::, _>>()?, + ); + } + + Ok(state::ContractClass { sierra_program, entry_points_by_type, abi }) + } +} + +impl From for protobuf::Cairo1Class { + fn from(value: state::ContractClass) -> Self { + let abi = value.abi; + + let program = + value.sierra_program.clone().into_iter().map(protobuf::Felt252::from).collect(); + + let entry_points = Some(protobuf::Cairo1EntryPoints { + constructors: value + .entry_points_by_type + .get(&state::EntryPointType::Constructor) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::SierraEntryPoint::from) + .collect(), + + externals: value + .entry_points_by_type + .get(&state::EntryPointType::External) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::SierraEntryPoint::from) + .collect(), + l1_handlers: value + .entry_points_by_type + .get(&state::EntryPointType::L1Handler) + .unwrap_or(&vec![]) + .iter() + .cloned() + .map(protobuf::SierraEntryPoint::from) + .collect(), + }); + + let contract_class_version = format!( + "sierra-v{}.{}.{} cairo-v{}.{}.{}", + value.sierra_program[0], + value.sierra_program[1], + value.sierra_program[2], + value.sierra_program[3], + value.sierra_program[4], + value.sierra_program[5] + ); + + protobuf::Cairo1Class { abi, program, entry_points, contract_class_version } + } +} + +impl TryFrom for deprecated_contract_class::EntryPoint { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::EntryPoint) -> Result { + let selector_felt = + Felt::try_from(value.selector.ok_or(ProtobufConversionError::MissingField { + field_description: "EntryPoint::selector", + })?)?; + let selector = EntryPointSelector(selector_felt); + + let offset = deprecated_contract_class::EntryPointOffset( + value.offset.try_into().expect("Failed converting u64 to usize"), + ); + + Ok(deprecated_contract_class::EntryPoint { selector, offset }) + } +} + +impl From for protobuf::EntryPoint { + fn from(value: deprecated_contract_class::EntryPoint) -> Self { + protobuf::EntryPoint { + selector: Some(value.selector.0.into()), + offset: u64::try_from(value.offset.0).expect("Failed converting usize to u64"), + } + } +} + +impl TryFrom for state::EntryPoint { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::SierraEntryPoint) -> Result { + let selector_felt = + Felt::try_from(value.selector.ok_or(ProtobufConversionError::MissingField { + field_description: "SierraEntryPoint::selector", + })?)?; + let selector = EntryPointSelector(selector_felt); + + let function_idx = + state::FunctionIndex(value.index.try_into().expect("Failed converting u64 to usize")); + + Ok(state::EntryPoint { function_idx, selector }) + } +} + +impl From for protobuf::SierraEntryPoint { + fn from(value: state::EntryPoint) -> Self { + protobuf::SierraEntryPoint { + index: u64::try_from(value.function_idx.0).expect("Failed converting usize to u64"), + selector: Some(value.selector.0.into()), + } + } +} + +impl TryFrom for Query { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ClassesRequest) -> Result { + Ok(ClassQuery::try_from(value)?.0) + } +} + +impl TryFrom for ClassQuery { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ClassesRequest) -> Result { + Ok(ClassQuery( + value + .iteration + .ok_or(ProtobufConversionError::MissingField { + field_description: "ClassesRequest::iteration", + })? + .try_into()?, + )) + } +} + +impl From for protobuf::ClassesRequest { + fn from(value: Query) -> Self { + protobuf::ClassesRequest { iteration: Some(value.into()) } + } +} + +impl From for protobuf::ClassesRequest { + fn from(value: ClassQuery) -> Self { + protobuf::ClassesRequest { iteration: Some(value.0.into()) } + } +} + +auto_impl_into_and_try_from_vec_u8!(ClassQuery, protobuf::ClassesRequest); diff --git a/crates/papyrus_protobuf/src/converters/common.rs b/crates/papyrus_protobuf/src/converters/common.rs new file mode 100644 index 00000000000..ea2eabddb36 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/common.rs @@ -0,0 +1,298 @@ +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::data_availability::{DataAvailabilityMode, L1DataAvailabilityMode}; + +use super::ProtobufConversionError; +use crate::protobuf; +use crate::sync::{BlockHashOrNumber, Direction, Query}; + +#[cfg(test)] +#[allow(dead_code)] +pub const PATRICIA_HEIGHT: u32 = 251; + +impl TryFrom for starknet_types_core::felt::Felt { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Felt252) -> Result { + let mut felt = [0; 32]; + felt.copy_from_slice(&value.elements); + // TODO: use from_bytes_checked once it's available. + Ok(Self::from_bytes_be(&felt)) + // if let Ok(stark_felt) = Self::from_bytes_be(&felt) { + // Ok(stark_felt) + // } else { + // Err(ProtobufConversionError::OutOfRangeValue { + // type_description: "Felt252", + // value_as_str: format!("{felt:?}"), + // }) + // } + } +} + +impl From for protobuf::Felt252 { + fn from(value: starknet_types_core::felt::Felt) -> Self { + Self { elements: value.to_bytes_be().to_vec() } + } +} + +impl From for protobuf::Hash { + fn from(value: starknet_api::block::BlockHash) -> Self { + Self { elements: value.0.to_bytes_be().to_vec() } + } +} + +impl From for protobuf::Hash { + fn from(value: starknet_api::hash::StarkHash) -> Self { + Self { elements: value.to_bytes_be().to_vec() } + } +} + +impl From for protobuf::Address { + fn from(value: starknet_api::core::ContractAddress) -> Self { + Self { elements: value.0.key().to_bytes_be().to_vec() } + } +} + +impl From for protobuf::Uint128 { + fn from(value: u128) -> Self { + Self { high: (value >> 64) as u64, low: value as u64 } + } +} + +impl From for u128 { + fn from(value: protobuf::Uint128) -> Self { + u128::from(value.low) + (u128::from(value.high) << 64) + } +} + +impl TryFrom for starknet_api::hash::StarkHash { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Hash) -> Result { + let mut felt = [0; 32]; + if value.elements.len() != 32 { + return Err(ProtobufConversionError::BytesDataLengthMismatch { + type_description: "Hash", + num_expected: 32, + value: value.elements, + }); + } + felt.copy_from_slice(&value.elements); + // TODO: use from_bytes_checked once it's available. + Ok(Self::from_bytes_be(&felt)) + // if let Ok(stark_hash) = Self::new(felt) { + // Ok(stark_hash) + // } else { + // Err(ProtobufConversionError::OutOfRangeValue { + // type_description: "Hash", + // value_as_str: format!("{felt:?}"), + // }) + // } + } +} + +impl TryFrom for starknet_api::core::ContractAddress { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Address) -> Result { + let mut felt = [0; 32]; + if value.elements.len() != 32 { + return Err(ProtobufConversionError::BytesDataLengthMismatch { + type_description: "Address", + num_expected: 32, + value: value.elements, + }); + } + felt.copy_from_slice(&value.elements); + // TODO: use from_bytes_checked once it's available. + let hash = starknet_types_core::felt::Felt::from_bytes_be(&felt); + // if let Ok(hash) = starknet_api::hash::StarkHash::new(felt) { + if let Ok(stark_felt) = starknet_api::core::PatriciaKey::try_from(hash) { + Ok(starknet_api::core::ContractAddress(stark_felt)) + } else { + Err(ProtobufConversionError::OutOfRangeValue { + type_description: "Address", + value_as_str: format!("{felt:?}"), + }) + } + // } else { + // Err(ProtobufConversionError::OutOfRangeValue { + // type_description: "Address", + // value_as_str: format!("{felt:?}"), + // }) + // } + } +} + +pub(super) fn enum_int_to_l1_data_availability_mode( + value: i32, +) -> Result { + match value { + 0 => Ok(L1DataAvailabilityMode::Calldata), + 1 => Ok(L1DataAvailabilityMode::Blob), + _ => Err(ProtobufConversionError::OutOfRangeValue { + type_description: "DataAvailabilityMode", + value_as_str: format!("{value}"), + }), + } +} + +pub(super) fn l1_data_availability_mode_to_enum_int(value: L1DataAvailabilityMode) -> i32 { + match value { + L1DataAvailabilityMode::Calldata => 0, + L1DataAvailabilityMode::Blob => 1, + } +} + +#[cfg(test)] +#[allow(dead_code)] +pub(crate) trait TestInstance { + fn test_instance() -> Self; +} + +#[cfg(test)] +impl TestInstance for protobuf::Hash { + fn test_instance() -> Self { + Self { elements: [0].repeat(32).to_vec() } + } +} + +#[cfg(test)] +impl TestInstance for protobuf::Address { + fn test_instance() -> Self { + Self { elements: [0].repeat(32).to_vec() } + } +} + +#[cfg(test)] +impl TestInstance for protobuf::Patricia { + fn test_instance() -> Self { + Self { n_leaves: 0, root: Some(protobuf::Hash::test_instance()) } + } +} + +#[cfg(test)] +impl TestInstance for protobuf::Uint128 { + fn test_instance() -> Self { + Self { low: 1, high: 0 } + } +} + +#[cfg(test)] +impl TestInstance for protobuf::ConsensusSignature { + fn test_instance() -> Self { + Self { + r: Some(protobuf::Felt252 { elements: [1].repeat(32).to_vec() }), + s: Some(protobuf::Felt252 { elements: [1].repeat(32).to_vec() }), + } + } +} + +#[allow(dead_code)] +pub(super) fn enum_int_to_volition_domain( + value: i32, +) -> Result { + match value { + 0 => Ok(DataAvailabilityMode::L1), + 1 => Ok(DataAvailabilityMode::L2), + _ => Err(ProtobufConversionError::OutOfRangeValue { + type_description: "VolitionDomain", + value_as_str: format!("{value}"), + }), + } +} + +// TODO(shahak): Internalize this once network doesn't depend on protobuf. +pub fn volition_domain_to_enum_int(value: DataAvailabilityMode) -> i32 { + match value { + DataAvailabilityMode::L1 => 0, + DataAvailabilityMode::L2 => 1, + } +} + +impl TryFrom for Query { + type Error = ProtobufConversionError; + + fn try_from(value: protobuf::Iteration) -> Result { + let start = value.start.ok_or(ProtobufConversionError::MissingField { + field_description: "Iteration::start", + })?; + let start_block = match start { + protobuf::iteration::Start::BlockNumber(block_number) => { + BlockHashOrNumber::Number(BlockNumber(block_number)) + } + protobuf::iteration::Start::Header(protobuf_hash) => { + BlockHashOrNumber::Hash(BlockHash(protobuf_hash.try_into()?)) + } + }; + let direction = match value.direction { + 0 => Direction::Forward, + 1 => Direction::Backward, + direction => { + return Err(ProtobufConversionError::OutOfRangeValue { + type_description: "Direction", + value_as_str: format!("{direction}"), + }); + } + }; + let limit = value.limit; + let step = value.step; + Ok(Query { start_block, direction, limit, step }) + } +} + +impl From for protobuf::Iteration { + fn from(value: Query) -> Self { + let start = match value.start_block { + BlockHashOrNumber::Number(BlockNumber(number)) => { + protobuf::iteration::Start::BlockNumber(number) + } + BlockHashOrNumber::Hash(block_hash) => { + protobuf::iteration::Start::Header(block_hash.into()) + } + }; + Self { + start: Some(start), + direction: match value.direction { + Direction::Forward => 0, + Direction::Backward => 1, + }, + limit: value.limit, + step: value.step, + } + } +} + +// TODO: Consider add this functionality to the Felt itself. +pub(super) fn try_from_starkfelt_to_u128( + felt: starknet_types_core::felt::Felt, +) -> Result { + const COMPLIMENT_OF_U128: usize = 16; // 32 - 16 + let felt_be_bytes = felt.to_bytes_be(); + let (rest, u128_bytes) = felt_be_bytes.split_at(COMPLIMENT_OF_U128); + if rest != [0u8; COMPLIMENT_OF_U128] { + return Err("Value out of range"); + } + + let bytes: [u8; 16] = match u128_bytes.try_into() { + Ok(b) => b, + Err(_) => return Err("Failed to convert bytes to u128"), + }; + + Ok(u128::from_be_bytes(bytes)) +} + +// TODO: Consider add this functionality to the Felt itself. +pub(super) fn try_from_starkfelt_to_u32( + felt: starknet_types_core::felt::Felt, +) -> Result { + const COMPLIMENT_OF_U32: usize = 28; // 32 - 4 + let felt_be_bytes = felt.to_bytes_be(); + let (rest, u32_bytes) = felt_be_bytes.split_at(COMPLIMENT_OF_U32); + if rest != [0u8; COMPLIMENT_OF_U32] { + return Err("Value out of range"); + } + + let bytes: [u8; 4] = match u32_bytes.try_into() { + Ok(b) => b, + Err(_) => return Err("Failed to convert bytes to u32"), + }; + + Ok(u32::from_be_bytes(bytes)) +} diff --git a/crates/papyrus_protobuf/src/converters/consensus.rs b/crates/papyrus_protobuf/src/converters/consensus.rs new file mode 100644 index 00000000000..f4236d60a12 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/consensus.rs @@ -0,0 +1,137 @@ +use std::convert::{TryFrom, TryInto}; + +use prost::Message; +use starknet_api::block::BlockHash; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::Transaction; + +use crate::consensus::{ConsensusMessage, Proposal, Vote, VoteType}; +use crate::converters::ProtobufConversionError; +use crate::{auto_impl_into_and_try_from_vec_u8, protobuf}; + +impl TryFrom for Proposal { + type Error = ProtobufConversionError; + + fn try_from(value: protobuf::Proposal) -> Result { + let transactions = value + .transactions + .into_iter() + .map(|tx| tx.try_into()) + .collect::, ProtobufConversionError>>()?; + + let height = value.height; + let proposer = value + .proposer + .ok_or(ProtobufConversionError::MissingField { field_description: "proposer" })? + .try_into()?; + let block_hash: StarkHash = value + .block_hash + .ok_or(ProtobufConversionError::MissingField { field_description: "block_hash" })? + .try_into()?; + let block_hash = BlockHash(block_hash); + + Ok(Proposal { height, proposer, transactions, block_hash }) + } +} + +impl From for protobuf::Proposal { + fn from(value: Proposal) -> Self { + let transactions = value.transactions.into_iter().map(Into::into).collect(); + + protobuf::Proposal { + height: value.height, + proposer: Some(value.proposer.into()), + transactions, + block_hash: Some(value.block_hash.0.into()), + } + } +} + +impl TryFrom for VoteType { + type Error = ProtobufConversionError; + + fn try_from(value: protobuf::vote::VoteType) -> Result { + match value { + protobuf::vote::VoteType::Prevote => Ok(VoteType::Prevote), + protobuf::vote::VoteType::Precommit => Ok(VoteType::Precommit), + } + } +} + +impl From for protobuf::vote::VoteType { + fn from(value: VoteType) -> Self { + match value { + VoteType::Prevote => protobuf::vote::VoteType::Prevote, + VoteType::Precommit => protobuf::vote::VoteType::Precommit, + } + } +} + +impl TryFrom for Vote { + type Error = ProtobufConversionError; + + fn try_from(value: protobuf::Vote) -> Result { + let vote_type = protobuf::vote::VoteType::try_from(value.vote_type)?.try_into()?; + + let height = value.height; + let block_hash: StarkHash = value + .block_hash + .ok_or(ProtobufConversionError::MissingField { field_description: "block_hash" })? + .try_into()?; + let block_hash = BlockHash(block_hash); + let voter = value + .voter + .ok_or(ProtobufConversionError::MissingField { field_description: "voter" })? + .try_into()?; + + Ok(Vote { vote_type, height, block_hash, voter }) + } +} + +impl From for protobuf::Vote { + fn from(value: Vote) -> Self { + let vote_type = match value.vote_type { + VoteType::Prevote => protobuf::vote::VoteType::Prevote, + VoteType::Precommit => protobuf::vote::VoteType::Precommit, + }; + + protobuf::Vote { + vote_type: vote_type as i32, + height: value.height, + block_hash: Some(value.block_hash.0.into()), + voter: Some(value.voter.into()), + } + } +} + +impl TryFrom for ConsensusMessage { + type Error = ProtobufConversionError; + + fn try_from(value: protobuf::ConsensusMessage) -> Result { + use protobuf::consensus_message::Message; + + let Some(message) = value.message else { + return Err(ProtobufConversionError::MissingField { field_description: "message" }); + }; + + match message { + Message::Proposal(proposal) => Ok(ConsensusMessage::Proposal(proposal.try_into()?)), + Message::Vote(vote) => Ok(ConsensusMessage::Vote(vote.try_into()?)), + } + } +} + +impl From for protobuf::ConsensusMessage { + fn from(value: ConsensusMessage) -> Self { + match value { + ConsensusMessage::Proposal(proposal) => protobuf::ConsensusMessage { + message: Some(protobuf::consensus_message::Message::Proposal(proposal.into())), + }, + ConsensusMessage::Vote(vote) => protobuf::ConsensusMessage { + message: Some(protobuf::consensus_message::Message::Vote(vote.into())), + }, + } + } +} + +auto_impl_into_and_try_from_vec_u8!(ConsensusMessage, protobuf::ConsensusMessage); diff --git a/crates/papyrus_protobuf/src/converters/event.rs b/crates/papyrus_protobuf/src/converters/event.rs new file mode 100644 index 00000000000..41d9f8c5dfe --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/event.rs @@ -0,0 +1,129 @@ +#[cfg(test)] +#[path = "event_test.rs"] +mod event_test; +use prost::Message; +use starknet_api::core::{ContractAddress, PatriciaKey}; +use starknet_api::transaction::{Event, EventContent, EventData, EventKey, TransactionHash}; +use starknet_types_core::felt::Felt; + +use super::ProtobufConversionError; +use crate::sync::{DataOrFin, EventQuery, Query}; +use crate::{auto_impl_into_and_try_from_vec_u8, protobuf}; + +impl TryFrom for DataOrFin<(Event, TransactionHash)> { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::EventsResponse) -> Result { + match value.event_message { + Some(protobuf::events_response::EventMessage::Event(event)) => { + Ok(Self(Some(event.try_into()?))) + } + Some(protobuf::events_response::EventMessage::Fin(_)) => Ok(Self(None)), + None => Err(ProtobufConversionError::MissingField { + field_description: "EventsResponse::event_message", + }), + } + } +} +impl From> for protobuf::EventsResponse { + fn from(value: DataOrFin<(Event, TransactionHash)>) -> Self { + match value.0 { + Some(event_transaction_hash) => protobuf::EventsResponse { + event_message: Some(protobuf::events_response::EventMessage::Event( + event_transaction_hash.into(), + )), + }, + None => protobuf::EventsResponse { + event_message: Some(protobuf::events_response::EventMessage::Fin(protobuf::Fin {})), + }, + } + } +} + +auto_impl_into_and_try_from_vec_u8!(DataOrFin<(Event, TransactionHash)>, protobuf::EventsResponse); + +impl TryFrom for (Event, TransactionHash) { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Event) -> Result { + let transaction_hash = TransactionHash( + value + .transaction_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "Event::transaction_hash", + })? + .try_into()?, + ); + + let from_address_felt = + Felt::try_from(value.from_address.ok_or(ProtobufConversionError::MissingField { + field_description: "Event::from_address", + })?)?; + let from_address = + ContractAddress(PatriciaKey::try_from(from_address_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "PatriciaKey", + value_as_str: format!("{from_address_felt:?}"), + } + })?); + + let keys = value + .keys + .into_iter() + .map(Felt::try_from) + .collect::, _>>()? + .into_iter() + .map(EventKey) + .collect(); + + let data = + EventData(value.data.into_iter().map(Felt::try_from).collect::, _>>()?); + + Ok((Event { from_address, content: EventContent { keys, data } }, transaction_hash)) + } +} + +impl From<(Event, TransactionHash)> for protobuf::Event { + fn from(value: (Event, TransactionHash)) -> Self { + let (event, transaction_hash) = value; + let transaction_hash = Some(transaction_hash.0.into()); + let from_address = Some(Felt::from(event.from_address).into()); + let keys = event.content.keys.into_iter().map(|key| key.0.into()).collect(); + let data = + event.content.data.0.into_iter().map(protobuf::Felt252::from).collect::>(); + Self { transaction_hash, from_address, keys, data } + } +} + +impl TryFrom for Query { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::EventsRequest) -> Result { + Ok(EventQuery::try_from(value)?.0) + } +} + +impl TryFrom for EventQuery { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::EventsRequest) -> Result { + Ok(EventQuery( + value + .iteration + .ok_or(ProtobufConversionError::MissingField { + field_description: "EventsRequest::iteration", + })? + .try_into()?, + )) + } +} + +impl From for protobuf::EventsRequest { + fn from(value: Query) -> Self { + protobuf::EventsRequest { iteration: Some(value.into()) } + } +} + +impl From for protobuf::EventsRequest { + fn from(value: EventQuery) -> Self { + protobuf::EventsRequest { iteration: Some(value.0.into()) } + } +} + +auto_impl_into_and_try_from_vec_u8!(EventQuery, protobuf::EventsRequest); diff --git a/crates/papyrus_protobuf/src/converters/event_test.rs b/crates/papyrus_protobuf/src/converters/event_test.rs new file mode 100644 index 00000000000..1345ae4b3a6 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/event_test.rs @@ -0,0 +1,25 @@ +use starknet_api::transaction::{Event, TransactionHash}; +use test_utils::{get_rng, GetTestInstance}; + +use crate::sync::DataOrFin; + +#[test] +fn convert_event_to_vec_u8_and_back() { + let mut rng = get_rng(); + let event = Event::get_test_instance(&mut rng); + let mut rng = get_rng(); + let transaction_hash = TransactionHash::get_test_instance(&mut rng); + + let data = DataOrFin(Some((event, transaction_hash))); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +#[test] +fn fin_event_to_bytes_and_back() { + let bytes_data = Vec::::from(DataOrFin::<(Event, TransactionHash)>(None)); + + let res_data = DataOrFin::<(Event, TransactionHash)>::try_from(bytes_data).unwrap(); + assert!(res_data.0.is_none()); +} diff --git a/crates/papyrus_protobuf/src/converters/header.rs b/crates/papyrus_protobuf/src/converters/header.rs new file mode 100644 index 00000000000..706e65fec30 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/header.rs @@ -0,0 +1,372 @@ +#[cfg(test)] +#[path = "header_test.rs"] +mod header_test; + +use prost::Message; +use starknet_api::block::{ + BlockHash, + BlockHeader, + BlockNumber, + BlockSignature, + GasPrice, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + EventCommitment, + GlobalRoot, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::crypto::utils::Signature; +use starknet_api::hash::PoseidonHash; + +use super::common::{enum_int_to_l1_data_availability_mode, l1_data_availability_mode_to_enum_int}; +use super::ProtobufConversionError; +use crate::sync::{DataOrFin, HeaderQuery, Query, SignedBlockHeader}; +use crate::{auto_impl_into_and_try_from_vec_u8, protobuf}; + +impl TryFrom for DataOrFin { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::BlockHeadersResponse) -> Result { + Ok(Self(value.try_into()?)) + } +} + +impl TryFrom for Option { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::BlockHeadersResponse) -> Result { + match value.header_message { + Some(protobuf::block_headers_response::HeaderMessage::Header(header)) => { + Ok(Some(header.try_into()?)) + } + Some(protobuf::block_headers_response::HeaderMessage::Fin(_)) => Ok(None), + None => Err(ProtobufConversionError::MissingField { + field_description: "BlockHeadersResponse::header_message", + }), + } + } +} + +impl TryFrom for SignedBlockHeader { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::SignedBlockHeader) -> Result { + let block_hash = value + .block_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::block_hash", + })? + .try_into() + .map(BlockHash)?; + + let parent_hash = value + .parent_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::parent_hash", + })? + .try_into() + .map(BlockHash)?; + + let timestamp = starknet_api::block::BlockTimestamp(value.time); + + let sequencer = value + .sequencer_address + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::sequencer_address", + })? + .try_into() + .map(SequencerContractAddress)?; + + let state_root = value + .state_root + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::state_root", + })? + .try_into() + .map(GlobalRoot)?; + + let n_transactions = value + .transactions + .as_ref() + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::transactions", + })? + .n_leaves + .try_into() + .expect("Failed converting u64 to usize"); + + let transaction_commitment = value + .transactions + .map(|transactions| { + Ok::<_, ProtobufConversionError>(TransactionCommitment( + transactions + .root + .ok_or(ProtobufConversionError::MissingField { + field_description: "Merkle::root", + })? + .try_into()?, + )) + }) + .transpose()?; + + let n_events = value + .events + .as_ref() + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::events", + })? + .n_leaves + .try_into() + .expect("Failed converting u64 to usize"); + + let event_commitment = value + .events + .map(|events| { + Ok::<_, ProtobufConversionError>(EventCommitment( + events + .root + .ok_or(ProtobufConversionError::MissingField { + field_description: "Merkle::root", + })? + .try_into()?, + )) + }) + .transpose()?; + + let state_diff_length = value.state_diff_commitment.as_ref().map(|state_diff_commitment| { + state_diff_commitment + .state_diff_length + .try_into() + .expect("Failed converting u64 to usize") + }); + + let l1_da_mode = enum_int_to_l1_data_availability_mode(value.l1_data_availability_mode)?; + + let starknet_version = StarknetVersion(value.protocol_version); + + let l1_gas_price = GasPricePerToken { + price_in_fri: GasPrice( + value + .gas_price_fri + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::gas_price_fri", + })? + .into(), + ), + price_in_wei: GasPrice( + value + .gas_price_wei + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::gas_price_wei", + })? + .into(), + ), + }; + + let l1_data_gas_price = GasPricePerToken { + price_in_fri: GasPrice( + value + .data_gas_price_fri + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::data_gas_price_fri", + })? + .into(), + ), + price_in_wei: GasPrice( + value + .data_gas_price_wei + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::data_gas_price_wei", + })? + .into(), + ), + }; + + let receipt_commitment = value + .receipts + .map(|receipts| receipts.try_into().map(ReceiptCommitment)) + .transpose()?; + + let state_diff_commitment = value + .state_diff_commitment + .map(|state_diff_commitment| { + Ok::<_, ProtobufConversionError>(StateDiffCommitment(PoseidonHash( + state_diff_commitment + .root + .ok_or(ProtobufConversionError::MissingField { + field_description: "StateDiffCommitment::root", + })? + .try_into()?, + ))) + }) + .transpose()?; + + Ok(SignedBlockHeader { + block_header: BlockHeader { + block_hash, + parent_hash, + block_number: BlockNumber(value.number), + l1_gas_price, + l1_data_gas_price, + state_root, + sequencer, + timestamp, + l1_da_mode, + state_diff_commitment, + state_diff_length, + transaction_commitment, + event_commitment, + n_transactions, + n_events, + receipt_commitment, + starknet_version, + }, + // collect will convert from Vec to Result. + signatures: value + .signatures + .into_iter() + .map(starknet_api::block::BlockSignature::try_from) + .collect::, _>>()?, + }) + } +} + +impl From> for protobuf::BlockHeadersResponse { + fn from(value: DataOrFin) -> Self { + value.0.into() + } +} + +impl From<(BlockHeader, Vec)> for protobuf::SignedBlockHeader { + fn from((header, signatures): (BlockHeader, Vec)) -> Self { + let state_diff_commitment = match (header.state_diff_commitment, header.state_diff_length) { + (Some(state_diff_commitment), Some(state_diff_length)) => { + Some(protobuf::StateDiffCommitment { + state_diff_length: state_diff_length + .try_into() + .expect("Converting usize to u64 failed"), + root: Some(state_diff_commitment.0.0.into()), + }) + } + _ => None, + }; + Self { + block_hash: Some(header.block_hash.into()), + parent_hash: Some(header.parent_hash.into()), + number: header.block_number.0, + time: header.timestamp.0, + sequencer_address: Some(header.sequencer.0.into()), + state_diff_commitment, + state_root: Some(header.state_root.0.into()), + transactions: header.transaction_commitment.map(|transaction_commitment| { + protobuf::Patricia { + n_leaves: header + .n_transactions + .try_into() + .expect("Converting usize to u64 failed"), + root: Some(transaction_commitment.0.into()), + } + }), + events: header.event_commitment.map(|event_commitment| protobuf::Patricia { + n_leaves: header.n_events.try_into().expect("Converting usize to u64 failed"), + root: Some(event_commitment.0.into()), + }), + receipts: header + .receipt_commitment + .map(|receipt_commitment| receipt_commitment.0.into()), + protocol_version: header.starknet_version.0, + gas_price_wei: Some(header.l1_gas_price.price_in_wei.0.into()), + gas_price_fri: Some(header.l1_gas_price.price_in_fri.0.into()), + data_gas_price_wei: Some(header.l1_data_gas_price.price_in_wei.0.into()), + data_gas_price_fri: Some(header.l1_data_gas_price.price_in_fri.0.into()), + l1_data_availability_mode: l1_data_availability_mode_to_enum_int(header.l1_da_mode), + signatures: signatures.iter().map(|signature| (*signature).into()).collect(), + } + } +} + +impl TryFrom for starknet_api::block::BlockSignature { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ConsensusSignature) -> Result { + Ok(Self(Signature { + r: value + .r + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::r", + })? + .try_into()?, + s: value + .s + .ok_or(ProtobufConversionError::MissingField { + field_description: "SignedBlockHeader::s", + })? + .try_into()?, + })) + } +} + +impl From for protobuf::ConsensusSignature { + fn from(value: starknet_api::block::BlockSignature) -> Self { + Self { r: Some(value.0.r.into()), s: Some(value.0.s.into()) } + } +} + +impl From> for protobuf::BlockHeadersResponse { + fn from(data: Option) -> Self { + match data { + Some(SignedBlockHeader { block_header, signatures }) => { + protobuf::BlockHeadersResponse { + header_message: Some(protobuf::block_headers_response::HeaderMessage::Header( + (block_header, signatures).into(), + )), + } + } + None => protobuf::BlockHeadersResponse { + header_message: Some(protobuf::block_headers_response::HeaderMessage::Fin( + protobuf::Fin {}, + )), + }, + } + } +} + +auto_impl_into_and_try_from_vec_u8!(DataOrFin, protobuf::BlockHeadersResponse); + +// TODO(shahak): Erase this once network stops using it. +impl TryFrom for Query { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::BlockHeadersRequest) -> Result { + Ok(HeaderQuery::try_from(value)?.0) + } +} + +impl TryFrom for HeaderQuery { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::BlockHeadersRequest) -> Result { + Ok(HeaderQuery( + value + .iteration + .ok_or(ProtobufConversionError::MissingField { + field_description: "BlockHeadersRequest::iteration", + })? + .try_into()?, + )) + } +} + +// TODO(shahak): Erase this once network stops using it. +impl From for protobuf::BlockHeadersRequest { + fn from(value: Query) -> Self { + protobuf::BlockHeadersRequest { iteration: Some(value.into()) } + } +} + +impl From for protobuf::BlockHeadersRequest { + fn from(value: HeaderQuery) -> Self { + protobuf::BlockHeadersRequest { iteration: Some(value.0.into()) } + } +} + +auto_impl_into_and_try_from_vec_u8!(HeaderQuery, protobuf::BlockHeadersRequest); diff --git a/crates/papyrus_protobuf/src/converters/header_test.rs b/crates/papyrus_protobuf/src/converters/header_test.rs new file mode 100644 index 00000000000..e412fd94e14 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/header_test.rs @@ -0,0 +1,30 @@ +use test_utils::{get_rng, GetTestInstance}; + +use crate::sync::{DataOrFin, HeaderQuery, SignedBlockHeader}; + +#[test] +fn block_header_to_bytes_and_back() { + let mut rng = get_rng(); + let signed_block_header = SignedBlockHeader::get_test_instance(&mut rng); + let data = DataOrFin(Some(signed_block_header.clone())); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(res_data, data); +} + +#[test] +fn fin_to_bytes_and_back() { + let bytes_data = Vec::::from(DataOrFin::(None)); + + let res_data = DataOrFin::::try_from(bytes_data).unwrap(); + assert!(res_data.0.is_none()); +} + +#[test] +fn header_query_to_bytes_and_back() { + let mut rng = get_rng(); + let header_query = HeaderQuery::get_test_instance(&mut rng); + let bytes = Vec::::from(header_query.clone()); + let res_query = HeaderQuery::try_from(bytes).unwrap(); + assert_eq!(header_query, res_query); +} diff --git a/crates/papyrus_protobuf/src/converters/mod.rs b/crates/papyrus_protobuf/src/converters/mod.rs new file mode 100644 index 00000000000..71ee24a452e --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/mod.rs @@ -0,0 +1,51 @@ +// TODO(shahak): Internalize this once network doesn't depend on protobuf. +mod class; +pub mod common; +pub mod consensus; +mod event; +mod header; +mod receipt; +// TODO(shahak): Internalize this once network doesn't depend on protobuf. +pub mod state_diff; +mod transaction; + +use prost::DecodeError; + +#[derive(thiserror::Error, Debug)] +pub enum ProtobufConversionError { + #[error("Type `{type_description}` got out of range value {value_as_str}")] + OutOfRangeValue { type_description: &'static str, value_as_str: String }, + #[error("Missing field `{field_description}`")] + MissingField { field_description: &'static str }, + #[error("Type `{type_description}` should be {num_expected} bytes but it got {value:?}.")] + BytesDataLengthMismatch { type_description: &'static str, num_expected: usize, value: Vec }, + #[error(transparent)] + DecodeError(#[from] DecodeError), +} + +#[macro_export] +macro_rules! auto_impl_into_and_try_from_vec_u8 { + ($T:ty, $ProtobufT:ty) => { + impl From<$T> for Vec { + fn from(value: $T) -> Self { + let protobuf_value = <$ProtobufT>::from(value); + protobuf_value.encode_to_vec() + } + } + $crate::auto_impl_try_from_vec_u8!($T, $ProtobufT); + }; +} + +// TODO(shahak): Remove this macro once all types implement both directions. +#[macro_export] +macro_rules! auto_impl_try_from_vec_u8 { + ($T:ty, $ProtobufT:ty) => { + impl TryFrom> for $T { + type Error = ProtobufConversionError; + fn try_from(value: Vec) -> Result { + let protobuf_value = <$ProtobufT>::decode(&value[..])?; + <$T>::try_from(protobuf_value) + } + } + }; +} diff --git a/crates/papyrus_protobuf/src/converters/receipt.rs b/crates/papyrus_protobuf/src/converters/receipt.rs new file mode 100644 index 00000000000..5f9ae8994a3 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/receipt.rs @@ -0,0 +1,484 @@ +use std::collections::HashMap; + +use starknet_api::core::{ContractAddress, EthAddress, PatriciaKey}; +use starknet_api::transaction::{ + Builtin, + DeclareTransactionOutput, + DeployAccountTransactionOutput, + DeployTransactionOutput, + ExecutionResources, + Fee, + GasVector, + InvokeTransactionOutput, + L1HandlerTransactionOutput, + L2ToL1Payload, + MessageToL1, + RevertedTransactionExecutionStatus, + TransactionExecutionStatus, + TransactionOutput, +}; +use starknet_types_core::felt::Felt; + +use super::common::try_from_starkfelt_to_u128; +use super::ProtobufConversionError; +use crate::protobuf; + +impl TryFrom for TransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Receipt) -> Result { + let receipt = value + .r#type + .ok_or(ProtobufConversionError::MissingField { field_description: "Receipt::type" })?; + match receipt { + protobuf::receipt::Type::Invoke(invoke) => { + Ok(TransactionOutput::Invoke(InvokeTransactionOutput::try_from(invoke)?)) + } + protobuf::receipt::Type::L1Handler(l1_handler) => { + Ok(TransactionOutput::L1Handler(L1HandlerTransactionOutput::try_from(l1_handler)?)) + } + protobuf::receipt::Type::Declare(declare) => { + Ok(TransactionOutput::Declare(DeclareTransactionOutput::try_from(declare)?)) + } + protobuf::receipt::Type::DeprecatedDeploy(deploy) => { + Ok(TransactionOutput::Deploy(DeployTransactionOutput::try_from(deploy)?)) + } + protobuf::receipt::Type::DeployAccount(deploy_account) => { + Ok(TransactionOutput::DeployAccount(DeployAccountTransactionOutput::try_from( + deploy_account, + )?)) + } + } + } +} + +impl From for protobuf::Receipt { + fn from(value: TransactionOutput) -> Self { + match value { + TransactionOutput::Invoke(invoke) => { + protobuf::Receipt { r#type: Some(protobuf::receipt::Type::Invoke(invoke.into())) } + } + TransactionOutput::L1Handler(l1_handler) => protobuf::Receipt { + r#type: Some(protobuf::receipt::Type::L1Handler(l1_handler.into())), + }, + TransactionOutput::Declare(declare) => { + protobuf::Receipt { r#type: Some(protobuf::receipt::Type::Declare(declare.into())) } + } + TransactionOutput::Deploy(deploy) => protobuf::Receipt { + r#type: Some(protobuf::receipt::Type::DeprecatedDeploy(deploy.into())), + }, + TransactionOutput::DeployAccount(deploy_account) => protobuf::Receipt { + r#type: Some(protobuf::receipt::Type::DeployAccount(deploy_account.into())), + }, + } + } +} + +// The output will have an empty events vec +impl TryFrom for DeployAccountTransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::DeployAccount) -> Result { + let (actual_fee, messages_sent, execution_status, execution_resources) = + parse_common_receipt_fields(value.common)?; + + let events = vec![]; + + let contract_address = + value.contract_address.ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccount::contract_address", + })?; + let felt = Felt::try_from(contract_address)?; + let contract_address = ContractAddress(PatriciaKey::try_from(felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "PatriciaKey", + value_as_str: format!("{felt:?}"), + } + })?); + + Ok(Self { + actual_fee, + messages_sent, + events, + contract_address, + execution_status, + execution_resources, + }) + } +} + +impl From for protobuf::receipt::DeployAccount { + /// The returned price_unit isn't correct. + /// It can be fixed by calling set_price_unit_based_on_transaction + fn from(value: DeployAccountTransactionOutput) -> Self { + let common = create_proto_receipt_common_from_txn_output_fields( + value.actual_fee, + value.messages_sent, + value.execution_resources, + value.execution_status, + ); + + protobuf::receipt::DeployAccount { + common: Some(common), + contract_address: Some(Felt::from(value.contract_address).into()), + } + } +} + +// The output will have an empty events vec +impl TryFrom for DeployTransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::Deploy) -> Result { + let (actual_fee, messages_sent, execution_status, execution_resources) = + parse_common_receipt_fields(value.common)?; + + let events = vec![]; + + let contract_address = + value.contract_address.ok_or(ProtobufConversionError::MissingField { + field_description: "Deploy::contract_address", + })?; + let felt = Felt::try_from(contract_address)?; + let contract_address = ContractAddress(PatriciaKey::try_from(felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "PatriciaKey", + value_as_str: format!("{felt:?}"), + } + })?); + + Ok(Self { + actual_fee, + messages_sent, + events, + contract_address, + execution_status, + execution_resources, + }) + } +} + +impl From for protobuf::receipt::Deploy { + /// The returned price_unit isn't correct. + /// It can be fixed by calling set_price_unit_based_on_transaction + fn from(value: DeployTransactionOutput) -> Self { + let common = create_proto_receipt_common_from_txn_output_fields( + value.actual_fee, + value.messages_sent, + value.execution_resources, + value.execution_status, + ); + + protobuf::receipt::Deploy { + common: Some(common), + contract_address: Some(Felt::from(value.contract_address).into()), + } + } +} + +// The output will have an empty events vec +impl TryFrom for DeclareTransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::Declare) -> Result { + let (actual_fee, messages_sent, execution_status, execution_resources) = + parse_common_receipt_fields(value.common)?; + + let events = vec![]; + + Ok(Self { actual_fee, messages_sent, events, execution_status, execution_resources }) + } +} + +impl From for protobuf::receipt::Declare { + /// The returned price_unit isn't correct. + /// It can be fixed by calling set_price_unit_based_on_transaction + fn from(value: DeclareTransactionOutput) -> Self { + let common = create_proto_receipt_common_from_txn_output_fields( + value.actual_fee, + value.messages_sent, + value.execution_resources, + value.execution_status, + ); + + protobuf::receipt::Declare { common: Some(common) } + } +} + +// The output will have an empty events vec +impl TryFrom for InvokeTransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::Invoke) -> Result { + let (actual_fee, messages_sent, execution_status, execution_resources) = + parse_common_receipt_fields(value.common)?; + + let events = vec![]; + + Ok(Self { actual_fee, messages_sent, events, execution_status, execution_resources }) + } +} + +impl From for protobuf::receipt::Invoke { + /// The returned price_unit isn't correct. + /// It can be fixed by calling set_price_unit_based_on_transaction + fn from(value: InvokeTransactionOutput) -> Self { + let common = create_proto_receipt_common_from_txn_output_fields( + value.actual_fee, + value.messages_sent, + value.execution_resources, + value.execution_status, + ); + + protobuf::receipt::Invoke { common: Some(common) } + } +} + +// The output will have an empty events vec +impl TryFrom for L1HandlerTransactionOutput { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::L1Handler) -> Result { + let (actual_fee, messages_sent, execution_status, execution_resources) = + parse_common_receipt_fields(value.common)?; + + let events = vec![]; + + Ok(Self { actual_fee, messages_sent, events, execution_status, execution_resources }) + } +} + +impl From for protobuf::receipt::L1Handler { + /// The returned price_unit isn't correct. + /// It can be fixed by calling set_price_unit_based_on_transaction + fn from(value: L1HandlerTransactionOutput) -> Self { + let common = create_proto_receipt_common_from_txn_output_fields( + value.actual_fee, + value.messages_sent, + value.execution_resources, + value.execution_status, + ); + + protobuf::receipt::L1Handler { common: Some(common), msg_hash: None } + } +} + +type ProtobufBuiltinCounter = protobuf::receipt::execution_resources::BuiltinCounter; + +impl TryFrom for HashMap { + type Error = ProtobufConversionError; + fn try_from(value: ProtobufBuiltinCounter) -> Result { + let mut builtin_instance_counter = HashMap::new(); + builtin_instance_counter.insert(Builtin::RangeCheck, u64::from(value.range_check)); + builtin_instance_counter.insert(Builtin::Pedersen, u64::from(value.pedersen)); + builtin_instance_counter.insert(Builtin::Poseidon, u64::from(value.poseidon)); + builtin_instance_counter.insert(Builtin::EcOp, u64::from(value.ec_op)); + builtin_instance_counter.insert(Builtin::Ecdsa, u64::from(value.ecdsa)); + builtin_instance_counter.insert(Builtin::Bitwise, u64::from(value.bitwise)); + builtin_instance_counter.insert(Builtin::Keccak, u64::from(value.keccak)); + builtin_instance_counter.insert(Builtin::SegmentArena, 0); + Ok(builtin_instance_counter) + } +} + +impl From> for ProtobufBuiltinCounter { + fn from(value: HashMap) -> Self { + let builtin_counter = ProtobufBuiltinCounter { + range_check: u32::try_from(*value.get(&Builtin::RangeCheck).unwrap_or(&0)) + // TODO: should not panic + .expect("Failed to convert u64 to u32"), + pedersen: u32::try_from(*value.get(&Builtin::Pedersen).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + poseidon: u32::try_from(*value.get(&Builtin::Poseidon).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + ec_op: u32::try_from(*value.get(&Builtin::EcOp).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + ecdsa: u32::try_from(*value.get(&Builtin::Ecdsa).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + bitwise: u32::try_from(*value.get(&Builtin::Bitwise).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + keccak: u32::try_from(*value.get(&Builtin::Keccak).unwrap_or(&0)) + .expect("Failed to convert u64 to u32"), + output: 0, + }; + builtin_counter + } +} + +impl TryFrom for ExecutionResources { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::receipt::ExecutionResources) -> Result { + let builtin_instance_counter = value + .builtins + .ok_or(ProtobufConversionError::MissingField { field_description: "builtins" })?; + let builtin_instance_counter = HashMap::::try_from(builtin_instance_counter)?; + + // TODO: remove all non-da gas consumed + let gas_consumed = value + .gas_consumed + .ok_or(ProtobufConversionError::MissingField { + field_description: "ExecutionResources::gas_consumed", + })? + .into(); + let da_gas_consumed = value + .da_gas_consumed + .ok_or(ProtobufConversionError::MissingField { + field_description: "ExecutionResources::da_gas_consumed", + })? + .into(); + + let execution_resources = ExecutionResources { + steps: u64::from(value.steps), + builtin_instance_counter, + memory_holes: u64::from(value.memory_holes), + gas_consumed, + da_gas_consumed, + }; + Ok(execution_resources) + } +} + +impl From for GasVector { + fn from(value: protobuf::receipt::execution_resources::GasVector) -> Self { + GasVector { l1_gas: value.l1_gas, l1_data_gas: value.l1_data_gas } + } +} + +impl From for protobuf::receipt::ExecutionResources { + fn from(value: ExecutionResources) -> Self { + let builtin_instance_counter = ProtobufBuiltinCounter::from(value.builtin_instance_counter); + // TODO: add all l1 gas consumed, not just da + let gas_consumed = value.gas_consumed.into(); + let da_gas_consumed = value.da_gas_consumed.into(); + // TODO: should not panic + let steps = u32::try_from(value.steps).expect("Failed to convert u64 to u32"); + let memory_holes = u32::try_from(value.memory_holes).expect("Failed to convert u64 to u32"); + + protobuf::receipt::ExecutionResources { + builtins: Some(builtin_instance_counter), + steps, + memory_holes, + gas_consumed: Some(gas_consumed), + da_gas_consumed: Some(da_gas_consumed), + } + } +} + +impl From for protobuf::receipt::execution_resources::GasVector { + fn from(value: GasVector) -> Self { + protobuf::receipt::execution_resources::GasVector { + l1_gas: value.l1_gas, + l1_data_gas: value.l1_data_gas, + } + } +} + +impl TryFrom for EthAddress { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::EthereumAddress) -> Result { + let mut felt = [0; 20]; + if value.elements.len() != 20 { + return Err(ProtobufConversionError::BytesDataLengthMismatch { + type_description: "EthereumAddress", + num_expected: 20, + value: value.elements, + }); + } + felt.copy_from_slice(&value.elements); + Ok(EthAddress(primitive_types::H160(felt))) + } +} +impl From for protobuf::EthereumAddress { + fn from(value: EthAddress) -> Self { + let elements = value.0.as_bytes().to_vec(); + protobuf::EthereumAddress { elements } + } +} + +impl TryFrom for MessageToL1 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::MessageToL1) -> Result { + let from_address_felt = + Felt::try_from(value.from_address.ok_or(ProtobufConversionError::MissingField { + field_description: "MessageToL1::from_address", + })?)?; + let from_address = ContractAddress::try_from(from_address_felt) + .expect("Converting ContractAddress from Felt failed"); + + let to_address = EthAddress::try_from(value.to_address.ok_or( + ProtobufConversionError::MissingField { field_description: "MessageToL1::to_address" }, + )?)?; + + let payload = L2ToL1Payload( + value.payload.into_iter().map(Felt::try_from).collect::, _>>()?, + ); + + Ok(MessageToL1 { from_address, to_address, payload }) + } +} + +impl From for protobuf::MessageToL1 { + fn from(value: MessageToL1) -> Self { + let from_address = Felt::from(value.from_address).into(); + let to_address = value.to_address.into(); + let payload = value.payload.0.into_iter().map(protobuf::Felt252::from).collect(); + protobuf::MessageToL1 { + from_address: Some(from_address), + to_address: Some(to_address), + payload, + } + } +} + +fn parse_common_receipt_fields( + common: Option, +) -> Result< + (Fee, Vec, TransactionExecutionStatus, ExecutionResources), + ProtobufConversionError, +> { + let common = + common.ok_or(ProtobufConversionError::MissingField { field_description: "Common" })?; + let actual_fee_felt = + Felt::try_from(common.actual_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "Common::actual_fee", + })?)?; + let actual_fee = Fee(try_from_starkfelt_to_u128(actual_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{actual_fee_felt:?}"), + } + })?); + let messages_sent = common + .messages_sent + .into_iter() + .map(MessageToL1::try_from) + .collect::, _>>()?; + let execution_status = + common.revert_reason.map_or(TransactionExecutionStatus::Succeeded, |revert_reason| { + TransactionExecutionStatus::Reverted(RevertedTransactionExecutionStatus { + revert_reason, + }) + }); + let execution_resources = ExecutionResources::try_from(common.execution_resources.ok_or( + ProtobufConversionError::MissingField { field_description: "Common::execution_resources" }, + )?)?; + Ok((actual_fee, messages_sent, execution_status, execution_resources)) +} + +fn create_proto_receipt_common_from_txn_output_fields( + actual_fee: Fee, + messages_sent: Vec, + execution_resources: ExecutionResources, + execution_status: TransactionExecutionStatus, +) -> protobuf::receipt::Common { + let actual_fee = Felt::from(actual_fee).into(); + let messages_sent = messages_sent.into_iter().map(protobuf::MessageToL1::from).collect(); + let execution_resources = execution_resources.into(); + let revert_reason = + if let TransactionExecutionStatus::Reverted(reverted_status) = execution_status { + Some(reverted_status.revert_reason) + } else { + None + }; + protobuf::receipt::Common { + actual_fee: Some(actual_fee), + price_unit: 0, + messages_sent, + execution_resources: Some(execution_resources), + revert_reason, + } +} diff --git a/crates/papyrus_protobuf/src/converters/state_diff.rs b/crates/papyrus_protobuf/src/converters/state_diff.rs new file mode 100644 index 00000000000..070d85cc82d --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/state_diff.rs @@ -0,0 +1,348 @@ +#[cfg(test)] +#[path = "state_diff_test.rs"] +mod state_diff_test; +use indexmap::IndexMap; +use prost::Message; +use starknet_api::core::{ClassHash, CompiledClassHash, Nonce}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::state::{StorageKey, ThinStateDiff}; +use starknet_types_core::felt::Felt; + +use super::common::volition_domain_to_enum_int; +use super::ProtobufConversionError; +use crate::sync::{ + ContractDiff, + DataOrFin, + DeclaredClass, + DeprecatedDeclaredClass, + Query, + StateDiffChunk, + StateDiffQuery, +}; +use crate::{auto_impl_into_and_try_from_vec_u8, auto_impl_try_from_vec_u8, protobuf}; + +pub const DOMAIN: DataAvailabilityMode = DataAvailabilityMode::L1; + +// TODO(shahak): Remove this once we finish the sync refactor. +impl TryFrom for DataOrFin { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::StateDiffsResponse) -> Result { + match value.state_diff_message { + Some(protobuf::state_diffs_response::StateDiffMessage::ContractDiff(contract_diff)) => { + Ok(DataOrFin(Some(contract_diff.try_into()?))) + } + Some(protobuf::state_diffs_response::StateDiffMessage::DeclaredClass( + declared_class, + )) => Ok(DataOrFin(Some(declared_class.try_into()?))), + Some(protobuf::state_diffs_response::StateDiffMessage::Fin(_)) => Ok(DataOrFin(None)), + None => Err(ProtobufConversionError::MissingField { + field_description: "StateDiffsResponse::state_diff_message", + }), + } + } +} +auto_impl_try_from_vec_u8!(DataOrFin, protobuf::StateDiffsResponse); + +impl TryFrom for DataOrFin { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::StateDiffsResponse) -> Result { + match value.state_diff_message { + Some(protobuf::state_diffs_response::StateDiffMessage::ContractDiff(contract_diff)) => { + Ok(DataOrFin(Some(StateDiffChunk::ContractDiff(contract_diff.try_into()?)))) + } + Some(protobuf::state_diffs_response::StateDiffMessage::DeclaredClass( + declared_class, + )) => match declared_class.compiled_class_hash.as_ref() { + Some(_compiled_class_hash) => { + Ok(DataOrFin(Some(StateDiffChunk::DeclaredClass(declared_class.try_into()?)))) + } + None => Ok(DataOrFin(Some(StateDiffChunk::DeprecatedDeclaredClass( + declared_class.try_into()?, + )))), + }, + Some(protobuf::state_diffs_response::StateDiffMessage::Fin(_)) => Ok(DataOrFin(None)), + None => Err(ProtobufConversionError::MissingField { + field_description: "StateDiffsResponse::state_diff_message", + }), + } + } +} + +impl From> for protobuf::StateDiffsResponse { + fn from(value: DataOrFin) -> Self { + let state_diff_message = match value.0 { + Some(StateDiffChunk::ContractDiff(contract_diff)) => { + protobuf::state_diffs_response::StateDiffMessage::ContractDiff(contract_diff.into()) + } + Some(StateDiffChunk::DeclaredClass(declared_class)) => { + protobuf::state_diffs_response::StateDiffMessage::DeclaredClass( + declared_class.into(), + ) + } + Some(StateDiffChunk::DeprecatedDeclaredClass(deprecated_declared_class)) => { + protobuf::state_diffs_response::StateDiffMessage::DeclaredClass( + deprecated_declared_class.into(), + ) + } + None => protobuf::state_diffs_response::StateDiffMessage::Fin(protobuf::Fin {}), + }; + protobuf::StateDiffsResponse { state_diff_message: Some(state_diff_message) } + } +} + +auto_impl_into_and_try_from_vec_u8!(DataOrFin, protobuf::StateDiffsResponse); + +impl TryFrom for ThinStateDiff { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ContractDiff) -> Result { + let contract_address = value + .address + .ok_or(ProtobufConversionError::MissingField { + field_description: "ContractDiff::address", + })? + .try_into()?; + + let deployed_contracts = value + .class_hash + .map(|hash| { + Ok::<_, ProtobufConversionError>(IndexMap::from_iter([( + contract_address, + ClassHash(hash.try_into()?), + )])) + }) + .transpose()? + .unwrap_or_default(); + + let storage_diffs = if value.values.is_empty() { + IndexMap::new() + } else { + let storage_values = value + .values + .into_iter() + .map(|stored_value| stored_value.try_into()) + .collect::, _>>()?; + IndexMap::from_iter([(contract_address, storage_values)]) + }; + + let nonces = value + .nonce + .map(|nonce| { + Ok::<_, ProtobufConversionError>(IndexMap::from_iter([( + contract_address, + Nonce(nonce.try_into()?), + )])) + }) + .transpose()? + .unwrap_or_default(); + + // TODO(shahak): Use the domain field once Starknet supports volition. + + Ok(ThinStateDiff { + deployed_contracts, + storage_diffs, + nonces, + // These two fields come from DeclaredClass messages. + declared_classes: Default::default(), + deprecated_declared_classes: Default::default(), + // The p2p specs doesn't separate replaced classes from deployed contracts. In RPC v0.8 + // the node will stop separating them as well. Until then nodes syncing from + // P2P won't be able to separate replaced classes from deployed contracts correctly + replaced_classes: Default::default(), + }) + } +} + +impl TryFrom for ThinStateDiff { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::DeclaredClass) -> Result { + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclaredClass::class_hash", + })? + .try_into()?, + ); + + // According to the P2P specs, if compiled_class_hash is missing, the declared class is a + // cairo-0 class. + match value.compiled_class_hash { + Some(compiled_class_hash) => Ok(ThinStateDiff { + declared_classes: IndexMap::from_iter([( + class_hash, + CompiledClassHash(compiled_class_hash.try_into()?), + )]), + ..Default::default() + }), + None => Ok(ThinStateDiff { + deprecated_declared_classes: vec![class_hash], + ..Default::default() + }), + } + } +} + +impl TryFrom for (StorageKey, Felt) { + type Error = ProtobufConversionError; + fn try_from(entry: protobuf::ContractStoredValue) -> Result { + let key_felt = Felt::try_from(entry.key.ok_or(ProtobufConversionError::MissingField { + field_description: "ContractStoredValue::key", + })?)?; + let key = StorageKey(key_felt.try_into().map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + // TODO(shahak): Check if the type in the protobuf of the field + // ContractStoredValue::key should be changed into a PatriciaKey which has a + // slightly lower bound than Felt. + type_description: "Felt252", + value_as_str: format!("{key_felt:?}"), + } + })?); + let value = Felt::try_from(entry.value.ok_or(ProtobufConversionError::MissingField { + field_description: "ContractStoredValue::value", + })?)?; + Ok((key, value)) + } +} + +// TODO(shahak): Erase this once network stops using it. +impl TryFrom for Query { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::StateDiffsRequest) -> Result { + Ok(StateDiffQuery::try_from(value)?.0) + } +} + +impl TryFrom for StateDiffQuery { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::StateDiffsRequest) -> Result { + Ok(StateDiffQuery( + value + .iteration + .ok_or(ProtobufConversionError::MissingField { + field_description: "StateDiffsRequest::iteration", + })? + .try_into()?, + )) + } +} + +// TODO(shahak): Erase this once network stops using it. +impl From for protobuf::StateDiffsRequest { + fn from(value: Query) -> Self { + protobuf::StateDiffsRequest { iteration: Some(value.into()) } + } +} + +impl From for protobuf::StateDiffsRequest { + fn from(value: StateDiffQuery) -> Self { + protobuf::StateDiffsRequest { iteration: Some(value.0.into()) } + } +} + +auto_impl_into_and_try_from_vec_u8!(StateDiffQuery, protobuf::StateDiffsRequest); + +impl TryFrom for ContractDiff { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ContractDiff) -> Result { + let contract_address = value + .address + .ok_or(ProtobufConversionError::MissingField { + field_description: "ContractDiff::address", + })? + .try_into()?; + + // class_hash can be None if the contract wasn't deployed in this block + let class_hash = value + .class_hash + .map(|class_hash| Ok::<_, ProtobufConversionError>(ClassHash(class_hash.try_into()?))) + .transpose()?; + + // nonce can be None if it wasn't updated in this block + let nonce = value + .nonce + .map(|nonce| Ok::<_, ProtobufConversionError>(Nonce(nonce.try_into()?))) + .transpose()?; + + let storage_diffs = value + .values + .into_iter() + .map(|stored_value| stored_value.try_into()) + .collect::, _>>()?; + + Ok(ContractDiff { contract_address, class_hash, nonce, storage_diffs }) + } +} + +impl From for protobuf::ContractDiff { + fn from(value: ContractDiff) -> Self { + let contract_address = Some(value.contract_address.into()); + let class_hash = value.class_hash.map(|hash| hash.0.into()); + let nonce = value.nonce.map(|nonce| nonce.0.into()); + let values = value + .storage_diffs + .into_iter() + .map(|(key, value)| protobuf::ContractStoredValue { + key: Some((*key.0.key()).into()), + value: Some(value.into()), + }) + .collect(); + let domain = volition_domain_to_enum_int(DOMAIN); + protobuf::ContractDiff { address: contract_address, class_hash, nonce, values, domain } + } +} +impl TryFrom for DeclaredClass { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::DeclaredClass) -> Result { + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclaredClass::class_hash", + })? + .try_into()?, + ); + let compiled_class_hash = CompiledClassHash( + value + .compiled_class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclaredClass::compiled_class_hash", + })? + .try_into()?, + ); + Ok(DeclaredClass { class_hash, compiled_class_hash }) + } +} + +impl From for protobuf::DeclaredClass { + fn from(value: DeclaredClass) -> Self { + protobuf::DeclaredClass { + class_hash: Some(value.class_hash.0.into()), + compiled_class_hash: Some(value.compiled_class_hash.0.into()), + } + } +} + +impl TryFrom for DeprecatedDeclaredClass { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::DeclaredClass) -> Result { + Ok(DeprecatedDeclaredClass { + class_hash: ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclaredClass::class_hash", + })? + .try_into()?, + ), + }) + } +} + +impl From for protobuf::DeclaredClass { + fn from(value: DeprecatedDeclaredClass) -> Self { + protobuf::DeclaredClass { + class_hash: Some(value.class_hash.0.into()), + compiled_class_hash: None, + } + } +} diff --git a/crates/papyrus_protobuf/src/converters/state_diff_test.rs b/crates/papyrus_protobuf/src/converters/state_diff_test.rs new file mode 100644 index 00000000000..5af6876741a --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/state_diff_test.rs @@ -0,0 +1,64 @@ +use test_utils::{get_rng, GetTestInstance}; + +use crate::sync::{ + ContractDiff, + DataOrFin, + DeclaredClass, + DeprecatedDeclaredClass, + StateDiffChunk, + StateDiffQuery, +}; + +#[test] +fn convert_state_diff_chunk_contract_diff_to_vec_u8_and_back() { + let mut rng = get_rng(); + let state_diff_chunk = StateDiffChunk::ContractDiff(ContractDiff::get_test_instance(&mut rng)); + + let data = DataOrFin(Some(state_diff_chunk)); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +#[test] +fn convert_state_diff_chunk_declared_class_to_vec_u8_and_back() { + let mut rng = get_rng(); + let state_diff_chunk = + StateDiffChunk::DeclaredClass(DeclaredClass::get_test_instance(&mut rng)); + + let data = DataOrFin(Some(state_diff_chunk)); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +#[test] +fn convert_state_diff_chunk_deprecated_declared_class_to_vec_u8_and_back() { + let mut rng = get_rng(); + let state_diff_chunk = StateDiffChunk::DeprecatedDeclaredClass( + DeprecatedDeclaredClass::get_test_instance(&mut rng), + ); + + let data = DataOrFin(Some(state_diff_chunk)); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +#[test] +fn convert_fin_state_diff_chunk_to_vec_u8_and_back() { + let data = DataOrFin::(None); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +#[test] +fn convert_state_diff_query_to_vec_u8_and_back() { + let mut rng = get_rng(); + let state_diff_query = StateDiffQuery::get_test_instance(&mut rng); + + let bytes_data = Vec::::from(state_diff_query.clone()); + let res_data = StateDiffQuery::try_from(bytes_data).unwrap(); + assert_eq!(state_diff_query, res_data); +} diff --git a/crates/papyrus_protobuf/src/converters/transaction.rs b/crates/papyrus_protobuf/src/converters/transaction.rs new file mode 100644 index 00000000000..c42fdb43a7a --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/transaction.rs @@ -0,0 +1,1226 @@ +#[cfg(test)] +#[path = "transaction_test.rs"] +mod transaction_test; +use std::convert::{TryFrom, TryInto}; + +use prost::Message; +use starknet_api::core::{ClassHash, CompiledClassHash, EntryPointSelector, Nonce}; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + DeclareTransaction, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeclareTransactionV3, + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + DeployTransaction, + Fee, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + L1HandlerTransaction, + PaymasterData, + Resource, + ResourceBounds, + ResourceBoundsMapping, + Tip, + Transaction, + TransactionOutput, + TransactionSignature, + TransactionVersion, +}; +use starknet_types_core::felt::Felt; + +use super::common::{ + enum_int_to_volition_domain, + try_from_starkfelt_to_u128, + try_from_starkfelt_to_u32, + volition_domain_to_enum_int, +}; +use super::ProtobufConversionError; +use crate::sync::{DataOrFin, Query, TransactionQuery}; +use crate::{auto_impl_into_and_try_from_vec_u8, protobuf}; + +impl TryFrom for DataOrFin<(Transaction, TransactionOutput)> { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::TransactionsResponse) -> Result { + let Some(transaction_message) = value.transaction_message else { + return Err(ProtobufConversionError::MissingField { + field_description: "TransactionsResponse::transaction_message", + }); + }; + + match transaction_message { + protobuf::transactions_response::TransactionMessage::TransactionWithReceipt( + tx_with_receipt, + ) => { + let result: (Transaction, TransactionOutput) = tx_with_receipt.try_into()?; + Ok(DataOrFin(Some(result))) + } + protobuf::transactions_response::TransactionMessage::Fin(_) => Ok(DataOrFin(None)), + } + } +} +impl From> for protobuf::TransactionsResponse { + fn from(value: DataOrFin<(Transaction, TransactionOutput)>) -> Self { + match value.0 { + Some((transaction, output)) => protobuf::TransactionsResponse { + transaction_message: Some( + protobuf::transactions_response::TransactionMessage::TransactionWithReceipt( + protobuf::TransactionWithReceipt::from((transaction, output)), + ), + ), + }, + None => protobuf::TransactionsResponse { + transaction_message: Some( + protobuf::transactions_response::TransactionMessage::Fin(protobuf::Fin {}), + ), + }, + } + } +} + +auto_impl_into_and_try_from_vec_u8!( + DataOrFin<(Transaction, TransactionOutput)>, + protobuf::TransactionsResponse +); + +impl TryFrom for (Transaction, TransactionOutput) { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::TransactionWithReceipt) -> Result { + let transaction = Transaction::try_from(value.transaction.ok_or( + ProtobufConversionError::MissingField { + field_description: "TransactionWithReceipt::transaction", + }, + )?)?; + + let output = TransactionOutput::try_from(value.receipt.ok_or( + ProtobufConversionError::MissingField { + field_description: "TransactionWithReceipt::output", + }, + )?)?; + Ok((transaction, output)) + } +} + +impl From<(Transaction, TransactionOutput)> for protobuf::TransactionWithReceipt { + fn from(value: (Transaction, TransactionOutput)) -> Self { + let transaction = value.0.into(); + let mut receipt = value.1.into(); + set_price_unit_based_on_transaction(&mut receipt, &transaction); + Self { transaction: Some(transaction), receipt: Some(receipt) } + } +} + +impl TryFrom for Transaction { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::Transaction) -> Result { + let txn = value.txn.ok_or(ProtobufConversionError::MissingField { + field_description: "Transaction::txn", + })?; + + Ok(match txn { + protobuf::transaction::Txn::DeclareV0(declare_v0) => Transaction::Declare( + DeclareTransaction::V0(DeclareTransactionV0V1::try_from(declare_v0)?), + ), + protobuf::transaction::Txn::DeclareV1(declare_v1) => Transaction::Declare( + DeclareTransaction::V1(DeclareTransactionV0V1::try_from(declare_v1)?), + ), + protobuf::transaction::Txn::DeclareV2(declare_v2) => Transaction::Declare( + DeclareTransaction::V2(DeclareTransactionV2::try_from(declare_v2)?), + ), + protobuf::transaction::Txn::DeclareV3(declare_v3) => Transaction::Declare( + DeclareTransaction::V3(DeclareTransactionV3::try_from(declare_v3)?), + ), + protobuf::transaction::Txn::Deploy(deploy) => { + Transaction::Deploy(DeployTransaction::try_from(deploy)?) + } + protobuf::transaction::Txn::DeployAccountV1(deploy_account_v1) => { + Transaction::DeployAccount(DeployAccountTransaction::V1( + DeployAccountTransactionV1::try_from(deploy_account_v1)?, + )) + } + protobuf::transaction::Txn::DeployAccountV3(deploy_account_v3) => { + Transaction::DeployAccount(DeployAccountTransaction::V3( + DeployAccountTransactionV3::try_from(deploy_account_v3)?, + )) + } + protobuf::transaction::Txn::InvokeV0(invoke_v0) => Transaction::Invoke( + InvokeTransaction::V0(InvokeTransactionV0::try_from(invoke_v0)?), + ), + protobuf::transaction::Txn::InvokeV1(invoke_v1) => Transaction::Invoke( + InvokeTransaction::V1(InvokeTransactionV1::try_from(invoke_v1)?), + ), + protobuf::transaction::Txn::InvokeV3(invoke_v3) => Transaction::Invoke( + InvokeTransaction::V3(InvokeTransactionV3::try_from(invoke_v3)?), + ), + protobuf::transaction::Txn::L1Handler(l1_handler) => { + Transaction::L1Handler(L1HandlerTransaction::try_from(l1_handler)?) + } + }) + } +} + +impl From for protobuf::Transaction { + fn from(value: Transaction) -> Self { + match value { + Transaction::Declare(DeclareTransaction::V0(declare_v0)) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeclareV0(declare_v0.into())), + }, + Transaction::Declare(DeclareTransaction::V1(declare_v1)) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeclareV1(declare_v1.into())), + }, + Transaction::Declare(DeclareTransaction::V2(declare_v2)) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeclareV2(declare_v2.into())), + }, + Transaction::Declare(DeclareTransaction::V3(declare_v3)) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeclareV3(declare_v3.into())), + }, + Transaction::Deploy(deploy) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::Deploy(deploy.into())), + }, + Transaction::DeployAccount(deploy_account) => match deploy_account { + DeployAccountTransaction::V1(deploy_account_v1) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeployAccountV1( + deploy_account_v1.into(), + )), + }, + DeployAccountTransaction::V3(deploy_account_v3) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::DeployAccountV3( + deploy_account_v3.into(), + )), + }, + }, + Transaction::Invoke(invoke) => match invoke { + InvokeTransaction::V0(invoke_v0) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::InvokeV0(invoke_v0.into())), + }, + InvokeTransaction::V1(invoke_v1) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::InvokeV1(invoke_v1.into())), + }, + InvokeTransaction::V3(invoke_v3) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::InvokeV3(invoke_v3.into())), + }, + }, + Transaction::L1Handler(l1_handler) => protobuf::Transaction { + txn: Some(protobuf::transaction::Txn::L1Handler(l1_handler.into())), + }, + } + } +} + +impl TryFrom for DeployAccountTransactionV1 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeployAccountV1) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV1::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV1::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV1::nonce", + })? + .try_into()?, + ); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV1::class_hash", + })? + .try_into()?, + ); + + let contract_address_salt = ContractAddressSalt( + value + .address_salt + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV1::address_salt", + })? + .try_into()?, + ); + + let constructor_calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let constructor_calldata = Calldata(constructor_calldata.into()); + + Ok(Self { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + }) + } +} + +impl From for protobuf::transaction::DeployAccountV1 { + fn from(value: DeployAccountTransactionV1) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|stark_felt| stark_felt.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + class_hash: Some(value.class_hash.0.into()), + address_salt: Some(value.contract_address_salt.0.into()), + calldata: value + .constructor_calldata + .0 + .iter() + .map(|calldata| (*calldata).into()) + .collect(), + } + } +} + +impl TryFrom for DeployAccountTransactionV3 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeployAccountV3) -> Result { + let resource_bounds = ResourceBoundsMapping::try_from(value.resource_bounds.ok_or( + ProtobufConversionError::MissingField { + field_description: "DeployAccountV3::resource_bounds", + }, + )?)?; + + let tip = Tip(value.tip); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV3::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV3::nonce", + })? + .try_into()?, + ); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV3::class_hash", + })? + .try_into()?, + ); + + let contract_address_salt = ContractAddressSalt( + value + .address_salt + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeployAccountV3::address_salt", + })? + .try_into()?, + ); + + let constructor_calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let constructor_calldata = Calldata(constructor_calldata.into()); + + let nonce_data_availability_mode = + enum_int_to_volition_domain(value.nonce_data_availability_mode)?; + + let fee_data_availability_mode = + enum_int_to_volition_domain(value.fee_data_availability_mode)?; + + let paymaster_data = PaymasterData( + value.paymaster_data.into_iter().map(Felt::try_from).collect::, _>>()?, + ); + + Ok(Self { + resource_bounds, + tip, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + }) + } +} + +impl From for protobuf::transaction::DeployAccountV3 { + fn from(value: DeployAccountTransactionV3) -> Self { + Self { + resource_bounds: Some(protobuf::ResourceBounds::from(value.resource_bounds)), + tip: value.tip.0, + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|stark_felt| stark_felt.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + class_hash: Some(value.class_hash.0.into()), + address_salt: Some(value.contract_address_salt.0.into()), + calldata: value + .constructor_calldata + .0 + .iter() + .map(|calldata| (*calldata).into()) + .collect(), + nonce_data_availability_mode: volition_domain_to_enum_int( + value.nonce_data_availability_mode, + ), + fee_data_availability_mode: volition_domain_to_enum_int( + value.fee_data_availability_mode, + ), + paymaster_data: value + .paymaster_data + .0 + .iter() + .map(|paymaster_data| (*paymaster_data).into()) + .collect(), + } + } +} + +impl TryFrom for ResourceBoundsMapping { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::ResourceBounds) -> Result { + let mut resource_bounds = ResourceBoundsMapping::default(); + let Some(l1_gas) = value.l1_gas else { + return Err(ProtobufConversionError::MissingField { + field_description: "ResourceBounds::l1_gas", + }); + }; + let max_amount = l1_gas.max_amount; + let max_price_per_unit_felt = Felt::try_from(l1_gas.max_price_per_unit.ok_or( + ProtobufConversionError::MissingField { + field_description: "ResourceBounds::l1_gas::max_price_per_unit", + }, + )?)?; + let max_price_per_unit = + try_from_starkfelt_to_u128(max_price_per_unit_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_price_per_unit_felt:?}"), + } + })?; + + resource_bounds + .0 + .insert(Resource::L1Gas, ResourceBounds { max_amount, max_price_per_unit }); + let Some(l2_gas) = value.l2_gas else { + return Err(ProtobufConversionError::MissingField { + field_description: "ResourceBounds::l2_gas", + }); + }; + let max_amount = l2_gas.max_amount; + let max_price_per_unit_felt = Felt::try_from(l2_gas.max_price_per_unit.ok_or( + ProtobufConversionError::MissingField { + field_description: "ResourceBounds::l2_gas::max_price_per_unit", + }, + )?)?; + let max_price_per_unit = + try_from_starkfelt_to_u128(max_price_per_unit_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_price_per_unit_felt:?}"), + } + })?; + resource_bounds + .0 + .insert(Resource::L2Gas, ResourceBounds { max_amount, max_price_per_unit }); + Ok(resource_bounds) + } +} + +impl From for protobuf::ResourceBounds { + fn from(value: ResourceBoundsMapping) -> Self { + let mut res = protobuf::ResourceBounds::default(); + + let resource_bounds_default = ResourceBounds::default(); + let resource_bounds_l1 = value.0.get(&Resource::L1Gas).unwrap_or(&resource_bounds_default); + + let resource_limits_l1 = protobuf::ResourceLimits { + max_amount: resource_bounds_l1.max_amount, + max_price_per_unit: Some(Felt::from(resource_bounds_l1.max_price_per_unit).into()), + }; + res.l1_gas = Some(resource_limits_l1); + + let resource_bounds_default = ResourceBounds::default(); + let resource_bounds_l2 = value.0.get(&Resource::L2Gas).unwrap_or(&resource_bounds_default); + + let resource_limits_l2 = protobuf::ResourceLimits { + max_amount: resource_bounds_l2.max_amount, + max_price_per_unit: Some(Felt::from(resource_bounds_l2.max_price_per_unit).into()), + }; + res.l2_gas = Some(resource_limits_l2); + + res + } +} + +impl TryFrom for InvokeTransactionV0 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::InvokeV0) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV0::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV0::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let contract_address = value + .address + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV0::address", + })? + .try_into()?; + + let entry_point_selector_felt = Felt::try_from(value.entry_point_selector.ok_or( + ProtobufConversionError::MissingField { + field_description: "InvokeV0::entry_point_selector", + }, + )?)?; + let entry_point_selector = EntryPointSelector(entry_point_selector_felt); + + let calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let calldata = Calldata(calldata.into()); + + Ok(Self { max_fee, signature, contract_address, entry_point_selector, calldata }) + } +} + +impl From for protobuf::transaction::InvokeV0 { + fn from(value: InvokeTransactionV0) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|stark_felt| stark_felt.into()).collect(), + }), + address: Some(value.contract_address.into()), + entry_point_selector: Some(value.entry_point_selector.0.into()), + calldata: value.calldata.0.iter().map(|calldata| (*calldata).into()).collect(), + } + } +} + +impl TryFrom for InvokeTransactionV1 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::InvokeV1) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV1::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV1::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { field_description: "InvokeV1::sender" })? + .try_into()?; + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV1::nonce", + })? + .try_into()?, + ); + + let calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let calldata = Calldata(calldata.into()); + + Ok(Self { max_fee, signature, nonce, sender_address, calldata }) + } +} + +impl From for protobuf::transaction::InvokeV1 { + fn from(value: InvokeTransactionV1) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|signature| signature.into()).collect(), + }), + sender: Some(value.sender_address.into()), + nonce: Some(value.nonce.0.into()), + calldata: value.calldata.0.iter().map(|calldata| (*calldata).into()).collect(), + } + } +} + +impl TryFrom for InvokeTransactionV3 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::InvokeV3) -> Result { + let resource_bounds = ResourceBoundsMapping::try_from(value.resource_bounds.ok_or( + ProtobufConversionError::MissingField { + field_description: "InvokeV3::resource_bounds", + }, + )?)?; + + let tip = Tip(value.tip); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV3::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "InvokeV3::nonce", + })? + .try_into()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { field_description: "InvokeV3::sender" })? + .try_into()?; + + let calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let calldata = Calldata(calldata.into()); + + let nonce_data_availability_mode = + enum_int_to_volition_domain(value.nonce_data_availability_mode)?; + + let fee_data_availability_mode = + enum_int_to_volition_domain(value.fee_data_availability_mode)?; + + let paymaster_data = PaymasterData( + value.paymaster_data.into_iter().map(Felt::try_from).collect::, _>>()?, + ); + + let account_deployment_data = AccountDeploymentData( + value + .account_deployment_data + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + Ok(Self { + resource_bounds, + tip, + signature, + nonce, + sender_address, + calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }) + } +} + +impl From for protobuf::transaction::InvokeV3 { + fn from(value: InvokeTransactionV3) -> Self { + Self { + resource_bounds: Some(protobuf::ResourceBounds::from(value.resource_bounds)), + tip: value.tip.0, + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|signature| signature.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + sender: Some(value.sender_address.into()), + calldata: value.calldata.0.iter().map(|calldata| (*calldata).into()).collect(), + nonce_data_availability_mode: volition_domain_to_enum_int( + value.nonce_data_availability_mode, + ), + fee_data_availability_mode: volition_domain_to_enum_int( + value.fee_data_availability_mode, + ), + paymaster_data: value + .paymaster_data + .0 + .iter() + .map(|paymaster_data| (*paymaster_data).into()) + .collect(), + account_deployment_data: value + .account_deployment_data + .0 + .iter() + .map(|account_deployment_data| (*account_deployment_data).into()) + .collect(), + } + } +} + +impl TryFrom for DeclareTransactionV0V1 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeclareV0) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV0::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV0::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + // V0 transactions don't have a nonce, but the StarkNet API adds one to them + let nonce = Nonce::default(); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV0::class_hash", + })? + .try_into()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV0::sender", + })? + .try_into()?; + + Ok(Self { max_fee, signature, nonce, class_hash, sender_address }) + } +} + +impl From for protobuf::transaction::DeclareV0 { + fn from(value: DeclareTransactionV0V1) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|stark_felt| stark_felt.into()).collect(), + }), + sender: Some(value.sender_address.into()), + class_hash: Some(value.class_hash.0.into()), + } + } +} + +impl TryFrom for DeclareTransactionV0V1 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeclareV1) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV1::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV1::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV1::nonce", + })? + .try_into()?, + ); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV1::class_hash", + })? + .try_into()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV1::sender", + })? + .try_into()?; + + Ok(Self { max_fee, signature, nonce, class_hash, sender_address }) + } +} + +impl From for protobuf::transaction::DeclareV1 { + fn from(value: DeclareTransactionV0V1) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|stark_felt| stark_felt.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + class_hash: Some(value.class_hash.0.into()), + sender: Some(value.sender_address.into()), + } + } +} + +impl TryFrom for DeclareTransactionV2 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeclareV2) -> Result { + let max_fee_felt = + Felt::try_from(value.max_fee.ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::max_fee", + })?)?; + let max_fee = Fee(try_from_starkfelt_to_u128(max_fee_felt).map_err(|_| { + ProtobufConversionError::OutOfRangeValue { + type_description: "u128", + value_as_str: format!("{max_fee_felt:?}"), + } + })?); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::nonce", + })? + .try_into()?, + ); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::class_hash", + })? + .try_into()?, + ); + + let compiled_class_hash = CompiledClassHash( + value + .compiled_class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::compiled_class_hash", + })? + .try_into()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV2::sender", + })? + .try_into()?; + + Ok(Self { max_fee, signature, nonce, class_hash, compiled_class_hash, sender_address }) + } +} + +impl From for protobuf::transaction::DeclareV2 { + fn from(value: DeclareTransactionV2) -> Self { + Self { + max_fee: Some(Felt::from(value.max_fee.0).into()), + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|signature| signature.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + class_hash: Some(value.class_hash.0.into()), + compiled_class_hash: Some(value.compiled_class_hash.0.into()), + sender: Some(value.sender_address.into()), + } + } +} + +impl TryFrom for DeclareTransactionV3 { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::DeclareV3) -> Result { + let resource_bounds = ResourceBoundsMapping::try_from(value.resource_bounds.ok_or( + ProtobufConversionError::MissingField { + field_description: "DeclareV3::resource_bounds", + }, + )?)?; + + let tip = Tip(value.tip); + + let signature = TransactionSignature( + value + .signature + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV3::signature", + })? + .parts + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV3::nonce", + })? + .try_into()?, + ); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV3::class_hash", + })? + .try_into()?, + ); + + let compiled_class_hash = CompiledClassHash( + value + .compiled_class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV3::compiled_class_hash", + })? + .try_into()?, + ); + + let sender_address = value + .sender + .ok_or(ProtobufConversionError::MissingField { + field_description: "DeclareV3::sender", + })? + .try_into()?; + + let nonce_data_availability_mode = + enum_int_to_volition_domain(value.nonce_data_availability_mode)?; + + let fee_data_availability_mode = + enum_int_to_volition_domain(value.fee_data_availability_mode)?; + + let paymaster_data = PaymasterData( + value.paymaster_data.into_iter().map(Felt::try_from).collect::, _>>()?, + ); + + let account_deployment_data = AccountDeploymentData( + value + .account_deployment_data + .into_iter() + .map(Felt::try_from) + .collect::, _>>()?, + ); + + Ok(Self { + resource_bounds, + tip, + signature, + nonce, + class_hash, + compiled_class_hash, + sender_address, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }) + } +} + +impl From for protobuf::transaction::DeclareV3 { + fn from(value: DeclareTransactionV3) -> Self { + Self { + resource_bounds: Some(protobuf::ResourceBounds::from(value.resource_bounds)), + tip: value.tip.0, + signature: Some(protobuf::AccountSignature { + parts: value.signature.0.into_iter().map(|signature| signature.into()).collect(), + }), + nonce: Some(value.nonce.0.into()), + class_hash: Some(value.class_hash.0.into()), + compiled_class_hash: Some(value.compiled_class_hash.0.into()), + sender: Some(value.sender_address.into()), + nonce_data_availability_mode: volition_domain_to_enum_int( + value.nonce_data_availability_mode, + ), + fee_data_availability_mode: volition_domain_to_enum_int( + value.fee_data_availability_mode, + ), + paymaster_data: value + .paymaster_data + .0 + .iter() + .map(|paymaster_data| (*paymaster_data).into()) + .collect(), + account_deployment_data: value + .account_deployment_data + .0 + .iter() + .map(|account_deployment_data| (*account_deployment_data).into()) + .collect(), + } + } +} + +impl TryFrom for DeployTransaction { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::Deploy) -> Result { + let version = TransactionVersion(Felt::from(value.version)); + + let class_hash = ClassHash( + value + .class_hash + .ok_or(ProtobufConversionError::MissingField { + field_description: "Deploy::class_hash", + })? + .try_into()?, + ); + + let contract_address_salt = ContractAddressSalt( + value + .address_salt + .ok_or(ProtobufConversionError::MissingField { + field_description: "Deploy::address_salt", + })? + .try_into()?, + ); + + let constructor_calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let constructor_calldata = Calldata(constructor_calldata.into()); + + Ok(Self { version, class_hash, contract_address_salt, constructor_calldata }) + } +} + +impl From for protobuf::transaction::Deploy { + fn from(value: DeployTransaction) -> Self { + Self { + version: try_from_starkfelt_to_u32(value.version.0).unwrap_or_default(), + class_hash: Some(value.class_hash.0.into()), + address_salt: Some(value.contract_address_salt.0.into()), + calldata: value + .constructor_calldata + .0 + .iter() + .map(|calldata| (*calldata).into()) + .collect(), + } + } +} + +impl TryFrom for L1HandlerTransaction { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::transaction::L1HandlerV0) -> Result { + let version = TransactionVersion(Felt::ZERO); + + let nonce = Nonce( + value + .nonce + .ok_or(ProtobufConversionError::MissingField { + field_description: "L1HandlerV0::nonce", + })? + .try_into()?, + ); + + let contract_address = value + .address + .ok_or(ProtobufConversionError::MissingField { + field_description: "L1HandlerV0::address", + })? + .try_into()?; + + let entry_point_selector_felt = Felt::try_from(value.entry_point_selector.ok_or( + ProtobufConversionError::MissingField { + field_description: "L1HandlerV0::entry_point_selector", + }, + )?)?; + let entry_point_selector = EntryPointSelector(entry_point_selector_felt); + + let calldata = + value.calldata.into_iter().map(Felt::try_from).collect::, _>>()?; + + let calldata = Calldata(calldata.into()); + + Ok(Self { version, nonce, contract_address, entry_point_selector, calldata }) + } +} + +impl From for protobuf::transaction::L1HandlerV0 { + fn from(value: L1HandlerTransaction) -> Self { + Self { + nonce: Some(value.nonce.0.into()), + address: Some(value.contract_address.into()), + entry_point_selector: Some(value.entry_point_selector.0.into()), + calldata: value.calldata.0.iter().map(|calldata| (*calldata).into()).collect(), + } + } +} + +impl TryFrom for Query { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::TransactionsRequest) -> Result { + Ok(TransactionQuery::try_from(value)?.0) + } +} + +impl TryFrom for TransactionQuery { + type Error = ProtobufConversionError; + fn try_from(value: protobuf::TransactionsRequest) -> Result { + Ok(TransactionQuery( + value + .iteration + .ok_or(ProtobufConversionError::MissingField { + field_description: "TransactionsRequest::iteration", + })? + .try_into()?, + )) + } +} + +impl From for protobuf::TransactionsRequest { + fn from(value: Query) -> Self { + protobuf::TransactionsRequest { iteration: Some(value.into()) } + } +} + +impl From for protobuf::TransactionsRequest { + fn from(value: TransactionQuery) -> Self { + protobuf::TransactionsRequest { iteration: Some(value.0.into()) } + } +} + +auto_impl_into_and_try_from_vec_u8!(TransactionQuery, protobuf::TransactionsRequest); + +pub fn set_price_unit_based_on_transaction( + receipt: &mut protobuf::Receipt, + transaction: &protobuf::Transaction, +) { + let price_unit = match &transaction.txn { + Some(protobuf::transaction::Txn::DeclareV1(_)) => protobuf::PriceUnit::Wei, + Some(protobuf::transaction::Txn::DeclareV2(_)) => protobuf::PriceUnit::Wei, + Some(protobuf::transaction::Txn::DeclareV3(_)) => protobuf::PriceUnit::Fri, + Some(protobuf::transaction::Txn::Deploy(_)) => protobuf::PriceUnit::Wei, + Some(protobuf::transaction::Txn::DeployAccountV1(_)) => protobuf::PriceUnit::Wei, + Some(protobuf::transaction::Txn::DeployAccountV3(_)) => protobuf::PriceUnit::Fri, + Some(protobuf::transaction::Txn::InvokeV1(_)) => protobuf::PriceUnit::Wei, + Some(protobuf::transaction::Txn::InvokeV3(_)) => protobuf::PriceUnit::Fri, + Some(protobuf::transaction::Txn::L1Handler(_)) => protobuf::PriceUnit::Wei, + _ => return, + }; + let Some(ref mut receipt_type) = receipt.r#type else { + return; + }; + + let common = match receipt_type { + protobuf::receipt::Type::Invoke(invoke) => invoke.common.as_mut(), + protobuf::receipt::Type::L1Handler(l1_handler) => l1_handler.common.as_mut(), + protobuf::receipt::Type::Declare(declare) => declare.common.as_mut(), + protobuf::receipt::Type::DeprecatedDeploy(deploy) => deploy.common.as_mut(), + protobuf::receipt::Type::DeployAccount(deploy_account) => deploy_account.common.as_mut(), + }; + + if let Some(common) = common { + common.price_unit = price_unit.into(); + } +} diff --git a/crates/papyrus_protobuf/src/converters/transaction_test.rs b/crates/papyrus_protobuf/src/converters/transaction_test.rs new file mode 100644 index 00000000000..848295d0c03 --- /dev/null +++ b/crates/papyrus_protobuf/src/converters/transaction_test.rs @@ -0,0 +1,202 @@ +use lazy_static::lazy_static; +use starknet_api::transaction::{ + Builtin, + DeclareTransaction, + DeclareTransactionOutput, + DeployAccountTransaction, + DeployAccountTransactionOutput, + DeployTransactionOutput, + ExecutionResources, + GasVector, + InvokeTransaction, + InvokeTransactionOutput, + L1HandlerTransactionOutput, + Resource, + ResourceBounds, + ResourceBoundsMapping, + Transaction as StarknetApiTransaction, + TransactionOutput, +}; +use test_utils::{get_rng, GetTestInstance}; + +use crate::sync::DataOrFin; + +macro_rules! create_transaction_output { + ($tx_output_type:ty, $tx_output_enum_variant:ident) => {{ + let mut rng = get_rng(); + let mut transaction_output = <$tx_output_type>::get_test_instance(&mut rng); + transaction_output.execution_resources = EXECUTION_RESOURCES.clone(); + transaction_output.events = vec![]; + TransactionOutput::$tx_output_enum_variant(transaction_output) + }}; +} + +#[test] +fn convert_l1_handler_transaction_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = starknet_api::transaction::L1HandlerTransaction::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::L1Handler(transaction); + + let transaction_output = create_transaction_output!(L1HandlerTransactionOutput, L1Handler); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_deploy_transaction_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = starknet_api::transaction::DeployTransaction::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Deploy(transaction); + + let transaction_output = create_transaction_output!(DeployTransactionOutput, Deploy); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_declare_transaction_v0_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = + starknet_api::transaction::DeclareTransactionV0V1::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Declare(DeclareTransaction::V0(transaction)); + + let transaction_output = create_transaction_output!(DeclareTransactionOutput, Declare); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_declare_transaction_v1_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = + starknet_api::transaction::DeclareTransactionV0V1::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Declare(DeclareTransaction::V1(transaction)); + + let transaction_output = create_transaction_output!(DeclareTransactionOutput, Declare); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_declare_transaction_v2_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = starknet_api::transaction::DeclareTransactionV2::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Declare(DeclareTransaction::V2(transaction)); + + let transaction_output = create_transaction_output!(DeclareTransactionOutput, Declare); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_declare_transaction_v3_to_vec_u8_and_back() { + let mut rng = get_rng(); + let mut transaction = + starknet_api::transaction::DeclareTransactionV3::get_test_instance(&mut rng); + transaction.resource_bounds = RESOURCE_BOUNDS_MAPPING.clone(); + let transaction = StarknetApiTransaction::Declare(DeclareTransaction::V3(transaction)); + + let transaction_output = create_transaction_output!(DeclareTransactionOutput, Declare); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_invoke_transaction_v0_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = starknet_api::transaction::InvokeTransactionV0::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Invoke(InvokeTransaction::V0(transaction)); + + let transaction_output = create_transaction_output!(InvokeTransactionOutput, Invoke); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_invoke_transaction_v1_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = starknet_api::transaction::InvokeTransactionV1::get_test_instance(&mut rng); + let transaction = StarknetApiTransaction::Invoke(InvokeTransaction::V1(transaction)); + + let transaction_output = create_transaction_output!(InvokeTransactionOutput, Invoke); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_invoke_transaction_v3_to_vec_u8_and_back() { + let mut rng = get_rng(); + let mut transaction = + starknet_api::transaction::InvokeTransactionV3::get_test_instance(&mut rng); + transaction.resource_bounds = RESOURCE_BOUNDS_MAPPING.clone(); + let transaction = StarknetApiTransaction::Invoke(InvokeTransaction::V3(transaction)); + + let transaction_output = create_transaction_output!(InvokeTransactionOutput, Invoke); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_deploy_account_transaction_v1_to_vec_u8_and_back() { + let mut rng = get_rng(); + let transaction = + starknet_api::transaction::DeployAccountTransactionV1::get_test_instance(&mut rng); + let transaction = + StarknetApiTransaction::DeployAccount(DeployAccountTransaction::V1(transaction)); + + let transaction_output = + create_transaction_output!(DeployAccountTransactionOutput, DeployAccount); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn convert_deploy_account_transaction_v3_to_vec_u8_and_back() { + let mut rng = get_rng(); + let mut transaction = + starknet_api::transaction::DeployAccountTransactionV3::get_test_instance(&mut rng); + transaction.resource_bounds = RESOURCE_BOUNDS_MAPPING.clone(); + let transaction = + StarknetApiTransaction::DeployAccount(DeployAccountTransaction::V3(transaction)); + + let transaction_output = + create_transaction_output!(DeployAccountTransactionOutput, DeployAccount); + convert_transaction_to_vec_u8_and_back(transaction, transaction_output); +} + +#[test] +fn fin_transaction_to_bytes_and_back() { + let bytes_data = + Vec::::from(DataOrFin::<(StarknetApiTransaction, TransactionOutput)>(None)); + + let res_data = + DataOrFin::<(StarknetApiTransaction, TransactionOutput)>::try_from(bytes_data).unwrap(); + assert!(res_data.0.is_none()); +} + +fn convert_transaction_to_vec_u8_and_back( + transaction: StarknetApiTransaction, + transaction_output: TransactionOutput, +) { + let data = DataOrFin(Some((transaction, transaction_output))); + let bytes_data = Vec::::from(data.clone()); + let res_data = DataOrFin::try_from(bytes_data).unwrap(); + assert_eq!(data, res_data); +} + +lazy_static! { + static ref EXECUTION_RESOURCES: ExecutionResources = ExecutionResources { + steps: 0, + builtin_instance_counter: std::collections::HashMap::from([ + (Builtin::RangeCheck, 1), + (Builtin::Pedersen, 2), + (Builtin::Poseidon, 3), + (Builtin::EcOp, 4), + (Builtin::Ecdsa, 5), + (Builtin::Bitwise, 6), + (Builtin::Keccak, 7), + (Builtin::SegmentArena, 0), + ]), + memory_holes: 0, + da_gas_consumed: GasVector::default(), + gas_consumed: GasVector::default(), + }; + static ref RESOURCE_BOUNDS_MAPPING: ResourceBoundsMapping = ResourceBoundsMapping( + [ + (Resource::L1Gas, ResourceBounds { max_amount: 0x5, max_price_per_unit: 0x6 }), + (Resource::L2Gas, ResourceBounds { max_amount: 0x5, max_price_per_unit: 0x6 }), + ] + .into_iter() + .collect(), + ); +} diff --git a/crates/papyrus_protobuf/src/lib.rs b/crates/papyrus_protobuf/src/lib.rs new file mode 100644 index 00000000000..05003d81ca1 --- /dev/null +++ b/crates/papyrus_protobuf/src/lib.rs @@ -0,0 +1,6 @@ +// TODO(shahak): Internalize this once network doesn't depend on protobuf. +pub mod converters; +// TODO(shahak): Internalize this once network doesn't depend on protobuf. +pub mod consensus; +pub mod protobuf; +pub mod sync; diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/class.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/class.proto new file mode 100644 index 00000000000..6361d1ee370 --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/class.proto @@ -0,0 +1,55 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; + + +message EntryPoint { + Felt252 selector = 1; + uint64 offset = 2; +} + +message Cairo0Class { + string abi = 1; + repeated EntryPoint externals = 2; + repeated EntryPoint l1_handlers = 3; + repeated EntryPoint constructors = 4; + // Compressed in base64 representation. + string program = 5; +} + +message SierraEntryPoint { + uint64 index = 1; + Felt252 selector = 2; +} + +message Cairo1EntryPoints { + repeated SierraEntryPoint externals = 1; + repeated SierraEntryPoint l1_handlers = 2; + repeated SierraEntryPoint constructors = 3; +} + +message Cairo1Class { + string abi = 1; + Cairo1EntryPoints entry_points = 2; + repeated Felt252 program = 3; + string contract_class_version = 4; +} + +message Class { + oneof class { + Cairo0Class cairo0 = 1; + Cairo1Class cairo1 = 2; + } + uint32 domain = 3; +} + +message ClassesRequest { + Iteration iteration = 1; +} + +// Responses are sent ordered by the order given in the request. +message ClassesResponse { + oneof class_message { + Class class = 1; + Fin fin = 2; // Fin is sent after the peer sent all the data or when it encountered a block that it doesn't have its classes. + } +} \ No newline at end of file diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/common.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/common.proto new file mode 100644 index 00000000000..63376061f2a --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/common.proto @@ -0,0 +1,75 @@ +syntax = "proto3"; + +message Felt252 { + bytes elements = 1; +} + +message Hash { + bytes elements = 1; +} + +message Hashes { + repeated Hash items = 1; +} + +message Address { + bytes elements = 1; +} + +message PeerID { + bytes id = 1; +} + +message Uint128 { + uint64 low = 1; + uint64 high = 2; +} + +message ConsensusSignature { + Felt252 r = 1; + Felt252 s = 2; +} +message Patricia { + uint64 n_leaves = 1; // needed to know the height, so as to how many nodes to expect in a proof. + // and also when receiving all leaves, how many to expect + Hash root = 2; +} + +message StateDiffCommitment { + uint64 state_diff_length = 1; + Hash root = 2; +} + +message BlockID { + uint64 number = 1; + Hash header = 2; +} + +enum L1DataAvailabilityMode { + Calldata = 0; + Blob = 1; +} + +enum VolitionDomain { + L1 = 0; + L2 = 1; +} + +message Iteration { + enum Direction { + Forward = 0; + Backward = 1; + } + oneof start { + uint64 block_number = 1; + Hash header = 2; + } + Direction direction = 3; + uint64 limit = 4; + uint64 step = 5; // to allow interleaving from several nodes + // bool interleave = 6; // return results in any order of blocks, per block the messages should still be in the order specified +} + +// mark the end of a stream of messages +// TBD: may not be required if we open a stream per request. +message Fin {} diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/consensus.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/consensus.proto new file mode 100644 index 00000000000..9a35f5ba09d --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/consensus.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; +import "p2p/proto/transaction.proto"; +import "p2p/proto/common.proto"; + +message Proposal { + uint64 height = 1; + Address proposer = 2; + repeated Transaction transactions = 3; + Hash block_hash = 4; +} + +message Vote { + enum VoteType { + Prevote = 0; + Precommit = 1; + }; + + // We use a type field to distinguish between prevotes and precommits instead of different + // messages, to make sure the data, and therefore the signatures, are unambiguous between + // Prevote and Precommit. + VoteType vote_type = 2; + uint64 height = 3; + // This is optional since a vote can be NIL. + optional Hash block_hash = 4; + Address voter = 5; +} + +message ConsensusMessage { + oneof message { + Proposal proposal = 1; + Vote vote = 2; + } +} \ No newline at end of file diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/event.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/event.proto new file mode 100644 index 00000000000..89e02391736 --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/event.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; + +message Event { + Hash transaction_hash = 1; + Felt252 from_address = 3; + repeated Felt252 keys = 4; + repeated Felt252 data = 5; +} + +message EventsRequest { + Iteration iteration = 1; +} + +// Responses are sent ordered by the order given in the request. +message EventsResponse { + oneof event_message { + Event event = 1; + Fin fin = 2; // Fin is sent after the peer sent all the data or when it encountered a block that it doesn't have its events. + } +} diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/header.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/header.proto new file mode 100644 index 00000000000..a3af9cc1d9d --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/header.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; + +// Note: commitments may change to be for the previous blocks like comet/tendermint +// hash of block header sent to L1 +message SignedBlockHeader { + Hash block_hash = 1; // For the structure of the block hash, see https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/header/#block_hash + Hash parent_hash = 2; + uint64 number = 3; // This can be deduced from context. We can consider removing this field. + uint64 time = 4; // Encoded in Unix time. + Address sequencer_address = 5; + Hash state_root = 6; // Patricia root of contract and class patricia tries. Each of those tries are of height 251. Same as in L1. Later more trees will be included + StateDiffCommitment state_diff_commitment = 7; // The state diff commitment returned by the Starknet Feeder Gateway + // For more info, see https://community.starknet.io/t/introducing-p2p-authentication-and-mismatch-resolution-in-v0-12-2/97993 + // The leaves contain a hash of the transaction hash and transaction signature. + Patricia transactions = 8; // By order of execution. TBD: required? the client can execute (powerful machine) and match state diff + Patricia events = 9; // By order of issuance. TBD: in receipts? + Hash receipts = 10; // By order of issuance. This is a patricia root. No need for length because it's the same length as transactions. + string protocol_version = 11; // Starknet version + Uint128 gas_price_fri = 12; + Uint128 gas_price_wei = 13; + Uint128 data_gas_price_fri = 14; + Uint128 data_gas_price_wei = 15; + L1DataAvailabilityMode l1_data_availability_mode = 16; + // for now, we assume a small consensus, so this fits in 1M. Else, these will be repeated and extracted from this message. + repeated ConsensusSignature signatures = 17; + // can be more explicit here about the signature structure as this is not part of account abstraction +} + +// sent to all peers (except the ones this was received from, if any). +// for a fraction of peers, also send the GetBlockHeaders response (as if they asked for it for this block) +message NewBlock { + oneof maybe_full { + BlockID id = 1; + BlockHeadersResponse header = 2; + } +} + + +message BlockHeadersRequest { + Iteration iteration = 1; +} + +// Responses are sent ordered by the order given in the request. +message BlockHeadersResponse { + oneof header_message { + SignedBlockHeader header = 1; + Fin fin = 2; // Fin is sent after the peer sent all the data or when it encountered a block that it doesn't have its header. + } +} diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/receipt.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/receipt.proto new file mode 100644 index 00000000000..4569e1d2a17 --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/receipt.proto @@ -0,0 +1,83 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; + +message MessageToL1 { + Felt252 from_address = 2; + repeated Felt252 payload = 3; + EthereumAddress to_address = 4; +} + +enum PriceUnit { + Wei = 0; + Fri = 1; +} + +message EthereumAddress { + bytes elements = 1; +} + +message Receipt { + message ExecutionResources { + message BuiltinCounter { + uint32 bitwise = 1; + uint32 ecdsa = 2; + uint32 ec_op = 3; + uint32 pedersen = 4; + uint32 range_check = 5; + uint32 poseidon = 6; + uint32 keccak = 7; + uint32 output = 8; + } + + message GasVector { + uint64 l1_gas = 1; + uint64 l1_data_gas = 2; + } + + BuiltinCounter builtins = 1; + uint32 steps = 2; + uint32 memory_holes = 3; + GasVector da_gas_consumed = 4; + GasVector gas_consumed = 5; + } + + message Common { + Felt252 actual_fee = 2; + PriceUnit price_unit = 3; + repeated MessageToL1 messages_sent = 4; + ExecutionResources execution_resources = 5; + optional string revert_reason = 6; + } + + + message Invoke { + Common common = 1; + } + + message L1Handler { + Common common = 1; + Hash msg_hash = 2; + } + + message Declare { + Common common = 1; + } + + message Deploy { + Common common = 1; + Felt252 contract_address = 2; + } + + message DeployAccount { + Common common = 1; + Felt252 contract_address = 2; + } + + oneof type { + Invoke invoke = 1; + L1Handler l1_handler = 2; + Declare declare = 3; + Deploy deprecated_deploy = 4; + DeployAccount deploy_account = 5; + } +} diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/state.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/state.proto new file mode 100644 index 00000000000..132a4a87128 --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/state.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; + + +// optimized for flat storage, not through a trie (not sharing key prefixes) +message ContractStoredValue { + Felt252 key = 1; + Felt252 value = 2; +} + +message ContractDiff { + Address address = 1; + optional Felt252 nonce = 2; // Present only if the nonce was updated + optional Hash class_hash = 3; // Present only if the contract was deployed or replaced in this block. + repeated ContractStoredValue values = 4; + VolitionDomain domain = 5; +} + +message DeclaredClass { + Hash class_hash = 1; + optional Hash compiled_class_hash = 2; // Present only if the class is Cairo1 +} + +message StateDiffsRequest { + Iteration iteration = 1; +} + +// Responses are sent ordered by the order given in the request. +message StateDiffsResponse { + // All of the messages related to a block need to be sent before a message from the next block is sent. + oneof state_diff_message { + ContractDiff contract_diff = 1; // Multiple contract diffs for the same contract may appear continuously if the diff is too large or if it's more convenient. + DeclaredClass declared_class = 2; + Fin fin = 3; // Fin is sent after the peer sent all the data or when it encountered a block that it doesn't have its state diff. + } +} diff --git a/crates/papyrus_protobuf/src/proto/p2p/proto/transaction.proto b/crates/papyrus_protobuf/src/proto/p2p/proto/transaction.proto new file mode 100644 index 00000000000..2fdaa0c3bf7 --- /dev/null +++ b/crates/papyrus_protobuf/src/proto/p2p/proto/transaction.proto @@ -0,0 +1,162 @@ +syntax = "proto3"; +import "p2p/proto/common.proto"; +import "p2p/proto/receipt.proto"; + +message ResourceLimits { + uint64 max_amount = 1; + Felt252 max_price_per_unit = 2; +} + +message ResourceBounds { + ResourceLimits l1_gas = 1; + ResourceLimits l2_gas = 2; +} + +message AccountSignature { + repeated Felt252 parts = 1; +} + +// This is a transaction that is already accepted in a block. Once we have a mempool, we will define +// a separate message for BroadcastedTransaction. +message Transaction +{ + message DeclareV0 { + Address sender = 1; + Felt252 max_fee = 2; + AccountSignature signature = 3; + Hash class_hash = 4; + } + + message DeclareV1 { + Address sender = 1; + Felt252 max_fee = 2; + AccountSignature signature = 3; + Hash class_hash = 4; + Felt252 nonce = 5; + } + + message DeclareV2 { + Address sender = 1; + Felt252 max_fee = 2; + AccountSignature signature = 3; + Hash class_hash = 4; + Felt252 nonce = 5; + Hash compiled_class_hash = 6; + } + + // see https://external.integration.starknet.io/feeder_gateway/get_transaction?transactionHash=0x41d1f5206ef58a443e7d3d1ca073171ec25fa75313394318fc83a074a6631c3 + message DeclareV3 { + Address sender = 1; + AccountSignature signature = 2; + Hash class_hash = 3; + Felt252 nonce = 4; + Hash compiled_class_hash = 5; + ResourceBounds resource_bounds = 6; + uint64 tip = 7; + repeated Felt252 paymaster_data = 8; + repeated Felt252 account_deployment_data = 9; + VolitionDomain nonce_data_availability_mode = 10; + VolitionDomain fee_data_availability_mode = 11; + } + + message Deploy { + Hash class_hash = 1; + Felt252 address_salt = 2; + repeated Felt252 calldata = 3; + uint32 version = 4; + } + + message DeployAccountV1 { + Felt252 max_fee = 1; + AccountSignature signature = 2; + Hash class_hash = 3; + Felt252 nonce = 4; + Felt252 address_salt = 5; + repeated Felt252 calldata = 6; + } + + // see https://external.integration.starknet.io/feeder_gateway/get_transaction?transactionHash=0x29fd7881f14380842414cdfdd8d6c0b1f2174f8916edcfeb1ede1eb26ac3ef0 + message DeployAccountV3 { + AccountSignature signature = 1; + Hash class_hash = 2; + Felt252 nonce = 3; + Felt252 address_salt = 4; + repeated Felt252 calldata = 5; + ResourceBounds resource_bounds = 6; + uint64 tip = 7; + repeated Felt252 paymaster_data = 8; + VolitionDomain nonce_data_availability_mode = 9; + VolitionDomain fee_data_availability_mode = 10; + } + + message InvokeV0 { + Felt252 max_fee = 1; + AccountSignature signature = 2; + Address address = 3; + Felt252 entry_point_selector = 4; + repeated Felt252 calldata = 5; + } + + message InvokeV1 { + Address sender = 1; + Felt252 max_fee = 2; + AccountSignature signature = 3; + repeated Felt252 calldata = 4; + Felt252 nonce = 5; + } + + // see https://external.integration.starknet.io/feeder_gateway/get_transaction?transactionHash=0x41906f1c314cca5f43170ea75d3b1904196a10101190d2b12a41cc61cfd17c + message InvokeV3 { + Address sender = 1; + AccountSignature signature = 2; + repeated Felt252 calldata = 3; + ResourceBounds resource_bounds = 4; + uint64 tip = 5; + repeated Felt252 paymaster_data = 6; + repeated Felt252 account_deployment_data = 7; + VolitionDomain nonce_data_availability_mode = 8; + VolitionDomain fee_data_availability_mode = 9; + Felt252 nonce = 10; + } + + message L1HandlerV0 { + Felt252 nonce = 1; + Address address = 2; + Felt252 entry_point_selector = 3; + repeated Felt252 calldata = 4; + } + + oneof txn { + DeclareV0 declare_v0 = 1; + DeclareV1 declare_v1 = 2; + DeclareV2 declare_v2 = 3; + DeclareV3 declare_v3 = 4; + Deploy deploy = 5; + DeployAccountV1 deploy_account_v1 = 6; + DeployAccountV3 deploy_account_v3 = 7; + InvokeV0 invoke_v0 = 8; + InvokeV1 invoke_v1 = 9; + InvokeV3 invoke_v3 = 10; + L1HandlerV0 l1_handler = 11; + } +} + +message TransactionWithReceipt { + Transaction transaction = 1; + Receipt receipt = 2; +} + +// TBD: can support a flag to return tx hashes only, good for standalone mempool to remove them, +// or any node that keeps track of transaction streaming in the consensus. +message TransactionsRequest { + Iteration iteration = 1; +} + +// Responses are sent ordered by the order given in the request. The order inside each block is +// according to the execution order. +message TransactionsResponse { + oneof transaction_message { + TransactionWithReceipt transaction_with_receipt = 1; + Fin fin = 2; // Fin is sent after the peer sent all the data or when it encountered a block that it doesn't have its transactions. + } +} diff --git a/crates/papyrus_protobuf/src/protobuf.rs b/crates/papyrus_protobuf/src/protobuf.rs new file mode 100644 index 00000000000..3e6d84c3336 --- /dev/null +++ b/crates/papyrus_protobuf/src/protobuf.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/_.rs")); diff --git a/crates/papyrus_protobuf/src/sync.rs b/crates/papyrus_protobuf/src/sync.rs new file mode 100644 index 00000000000..d995d44eac3 --- /dev/null +++ b/crates/papyrus_protobuf/src/sync.rs @@ -0,0 +1,159 @@ +use std::fmt::Debug; + +use indexmap::IndexMap; +use starknet_api::block::{BlockHash, BlockHeader, BlockNumber, BlockSignature}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::state::StorageKey; +use starknet_types_core::felt::Felt; +#[cfg(any(feature = "testing", test))] +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, GetTestInstance}; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Hash)] +pub enum Direction { + #[default] + Forward, + Backward, +} + +/// This struct represents a query that can be sent to a peer. +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct Query { + pub start_block: BlockHashOrNumber, + pub direction: Direction, + pub limit: u64, + pub step: u64, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum BlockHashOrNumber { + Hash(BlockHash), + Number(BlockNumber), +} + +impl Default for BlockHashOrNumber { + fn default() -> Self { + Self::Number(BlockNumber::default()) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DataOrFin(pub Option); + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct HeaderQuery(pub Query); + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct StateDiffQuery(pub Query); + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct TransactionQuery(pub Query); + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct ClassQuery(pub Query); + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct EventQuery(pub Query); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SignedBlockHeader { + pub block_header: BlockHeader, + pub signatures: Vec, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct ContractDiff { + pub contract_address: ContractAddress, + // Has value only if the contract was deployed or replaced in this block. + pub class_hash: Option, + // Has value only if the nonce was updated in this block. + pub nonce: Option, + pub storage_diffs: IndexMap, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct DeclaredClass { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct DeprecatedDeclaredClass { + pub class_hash: ClassHash, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum StateDiffChunk { + ContractDiff(ContractDiff), + DeclaredClass(DeclaredClass), + DeprecatedDeclaredClass(DeprecatedDeclaredClass), +} + +impl StateDiffChunk { + pub fn len(&self) -> usize { + match self { + StateDiffChunk::ContractDiff(contract_diff) => { + let mut result = contract_diff.storage_diffs.len(); + if contract_diff.class_hash.is_some() { + result += 1; + } + if contract_diff.nonce.is_some() { + result += 1; + } + result + } + StateDiffChunk::DeclaredClass(_) => 1, + StateDiffChunk::DeprecatedDeclaredClass(_) => 1, + } + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} +impl Default for StateDiffChunk { + fn default() -> Self { + Self::ContractDiff(ContractDiff::default()) + } +} + +#[cfg(any(feature = "testing", test))] +auto_impl_get_test_instance! { + pub enum StateDiffChunk{ + ContractDiff(ContractDiff) = 0, + DeclaredClass(DeclaredClass) = 1, + DeprecatedDeclaredClass(DeprecatedDeclaredClass) = 2, + } + pub struct ContractDiff{ + pub contract_address: ContractAddress, + pub class_hash: Option, + pub nonce: Option, + pub storage_diffs: IndexMap, + } + pub struct DeclaredClass { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + } + pub struct DeprecatedDeclaredClass { + pub class_hash: ClassHash, + } + pub struct StateDiffQuery(pub Query); + pub struct Query { + pub start_block: BlockHashOrNumber, + pub direction: Direction, + pub limit: u64, + pub step: u64, + } + pub enum BlockHashOrNumber { + Hash(BlockHash)=0, + Number(BlockNumber)=1, + } + pub enum Direction { + Forward=0, + Backward=1, + } + pub struct HeaderQuery(pub Query); + pub struct SignedBlockHeader { + pub block_header: BlockHeader, + pub signatures: Vec, + } +} diff --git a/crates/papyrus_rpc/Cargo.toml b/crates/papyrus_rpc/Cargo.toml new file mode 100644 index 00000000000..604f66a41c9 --- /dev/null +++ b/crates/papyrus_rpc/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "papyrus_rpc" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[dependencies] +anyhow.workspace = true +async-trait.workspace = true +base64.workspace = true +cairo-lang-starknet-classes.workspace = true +ethers.workspace = true +flate2.workspace = true +futures-util.workspace = true +hex.workspace = true +hyper = { workspace = true, features = ["full"] } +jsonrpsee = { workspace = true, features = ["full"] } +lazy_static.workspace = true +metrics.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_execution = { path = "../papyrus_execution", version = "0.4.0-rc.0" } +papyrus_proc_macros = { path = "../papyrus_proc_macros", version = "0.4.0-rc.0" } +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +starknet_client = { path = "../starknet_client", version = "0.4.0-rc.0" } +regex = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +starknet_api.workspace = true +starknet-types-core.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tower = { workspace = true, features = ["full"] } +tracing.workspace = true +validator = { workspace = true, features = ["derive"] } + +[dev-dependencies] +assert_matches.workspace = true +cairo-lang-casm.workspace = true +cairo-lang-starknet-classes.workspace = true +camelpaste.workspace = true +derive_more.workspace = true +enum-iterator.workspace = true +insta = { workspace = true, features = ["json"] } +itertools.workspace = true +jsonschema.workspace = true +lazy_static.workspace = true +metrics-exporter-prometheus.workspace = true +mockall.workspace = true +papyrus_execution = { path = "../papyrus_execution", features = ["testing"] } +papyrus_storage = { path = "../papyrus_storage", features = ["testing"] } +pretty_assertions.workspace = true +prometheus-parse.workspace = true +rand_chacha.workspace = true +reqwest.workspace = true +test_utils = { path = "../test_utils" } +starknet_api = { workspace = true, features = ["testing"] } +starknet_client = { path = "../starknet_client", features = ["testing"] } +starknet-core.workspace = true +strum.workspace = true +strum_macros.workspace = true +indexmap = { workspace = true, features = ["serde"] } +rand.workspace = true diff --git a/crates/papyrus_rpc/resources/V0_6/starknet_api_openrpc.json b/crates/papyrus_rpc/resources/V0_6/starknet_api_openrpc.json new file mode 100644 index 00000000000..27d56ddb022 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_6/starknet_api_openrpc.json @@ -0,0 +1,3944 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.6.0", + "title": "StarkNet Node API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_specVersion", + "summary": "Returns the version of the Starknet JSON-RPC specification being used", + "params": [], + "result": { + "name": "result", + "description": "Semver of Starknet's JSON-RPC spec being used", + "required": true, + "schema": { + "title": "JSON-RPC spec version", + "type": "string" + } + } + }, + { + "name": "starknet_getBlockWithTxHashes", + "summary": "Get block information with transaction hashes given the block id", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The resulting block information with transaction hashes", + "schema": { + "title": "Starknet get block hash with tx hashes result", + "oneOf": [ + { + "title": "Block with transaction hashes", + "$ref": "#/components/schemas/BLOCK_WITH_TX_HASHES" + }, + { + "title": "Pending block with transaction hashes", + "$ref": "#/components/schemas/PENDING_BLOCK_WITH_TX_HASHES" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getBlockWithTxs", + "summary": "Get block information with full transactions given the block id", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The resulting block information with full transactions", + "schema": { + "title": "Starknet get block with txs result", + "oneOf": [ + { + "title": "Block with transactions", + "$ref": "#/components/schemas/BLOCK_WITH_TXS" + }, + { + "title": "Pending block with transactions", + "$ref": "#/components/schemas/PENDING_BLOCK_WITH_TXS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getStateUpdate", + "summary": "Get the information about the result of executing the requested block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The information about the state update of the requested block", + "schema": { + "title": "Starknet get state update result", + "oneOf": [ + { + "title": "State update", + "$ref": "#/components/schemas/STATE_UPDATE" + }, + { + "title": "Pending state update", + "$ref": "#/components/schemas/PENDING_STATE_UPDATE" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getStorageAt", + "summary": "Get the value of the storage at the given address and key", + "params": [ + { + "name": "contract_address", + "description": "The address of the contract to read from", + "summary": "The address of the contract to read from", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + }, + { + "name": "key", + "description": "The key to the storage value for the given contract", + "summary": "The key to the storage value for the given contract", + "required": true, + "schema": { + "title": "Storage key", + "$ref": "#/components/schemas/STORAGE_KEY" + } + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The value at the given key for the given contract. 0 if no value is found", + "summary": "The value at the given key for the given contract.", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionStatus", + "summary": "Gets the transaction status (possibly reflecting that the tx is still in the mempool, or dropped from it)", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "title": "Transaction status", + "type": "object", + "properties": { + "finality_status": { + "title": "finality status", + "$ref": "#/components/schemas/TXN_STATUS" + }, + "execution_status": { + "title": "execution status", + "$ref": "#/components/schemas/TXN_EXECUTION_STATUS" + } + }, + "required": [ + "finality_status" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionByHash", + "summary": "Get the details and status of a submitted transaction", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "title": "Transaction", + "allOf": [ + { + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionByBlockIdAndIndex", + "summary": "Get the details of a transaction by a given block id and index", + "description": "Get the details of the transaction given by the identified block and index in that block. If no transaction is found, null is returned.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "index", + "summary": "The index in the block to search for the transaction", + "required": true, + "schema": { + "title": "Index", + "type": "integer", + "minimum": 0 + } + } + ], + "result": { + "name": "transactionResult", + "schema": { + "title": "Transaction", + "allOf": [ + { + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/INVALID_TXN_INDEX" + } + ] + }, + { + "name": "starknet_getTransactionReceipt", + "summary": "Get the transaction receipt by the transaction hash", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "oneOf": [ + { + "title": "Transaction receipt", + "$ref": "#/components/schemas/TXN_RECEIPT" + }, + { + "title": "Pending transaction receipt", + "$ref": "#/components/schemas/PENDING_TXN_RECEIPT" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClass", + "summary": "Get the contract class definition in the given block associated with the given hash", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "class_hash", + "description": "The hash of the requested contract class", + "required": true, + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + } + ], + "result": { + "name": "result", + "description": "The contract class, if found", + "schema": { + "title": "Starknet get class result", + "oneOf": [ + { + "title": "Deprecated contract class", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + }, + { + "title": "Contract class", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CLASS_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClassHashAt", + "summary": "Get the contract class hash in the given block for the contract deployed at the given address", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose class hash will be returned", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The class hash of the given contract", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClassAt", + "summary": "Get the contract class definition in the given block at the given address", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose class definition will be returned", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The contract class", + "schema": { + "title": "Starknet get class at result", + "oneOf": [ + { + "title": "Deprecated contract class", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + }, + { + "title": "Contract class", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getBlockTransactionCount", + "summary": "Get the number of transactions in a block given a block id", + "description": "Returns the number of transactions in the designated block.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The number of transactions in the designated block", + "summary": "The number of transactions in the designated block", + "schema": { + "title": "Block transaction count", + "type": "integer", + "minimum": 0 + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_call", + "summary": "call a starknet function without creating a StarkNet transaction", + "description": "Calls a function in a contract and returns the return value. Using this call will not create a transaction; hence, will not change the state", + "params": [ + { + "name": "request", + "summary": "The details of the function call", + "schema": { + "title": "Function call", + "$ref": "#/components/schemas/FUNCTION_CALL" + }, + "required": true + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "summary": "The function's return value", + "description": "The function's return value, as defined in the Cairo output", + "schema": { + "type": "array", + "title": "Field element", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_estimateFee", + "summary": "estimate the fee for of StarkNet transactions", + "description": "Estimates the resources required by a given sequence of transactions when applied on a given state. If one of the transactions reverts or fails due to any reason (e.g. validation failure or an internal error), a TRANSACTION_EXECUTION_ERROR is returned. For v0-2 transactions the estimate is given in wei, and for v3 transactions it is given in fri.", + "params": [ + { + "name": "request", + "summary": "The transaction to estimate", + "schema": { + "type": "array", + "description": "a sequence of transactions to estimate, running each transaction on the state resulting from applying all the previous ones", + "title": "Transaction", + "items": { + "$ref": "#/components/schemas/BROADCASTED_TXN" + } + }, + "required": true + }, + { + "name": "simulation_flags", + "description": "describes what parts of the transaction should be executed", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SIMULATION_FLAG_FOR_ESTIMATE_FEE" + } + } + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "the fee estimations", + "schema": { + "title": "Estimation", + "type": "array", + "description": "a sequence of fee estimatione where the i'th estimate corresponds to the i'th transaction", + "items": { + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/TRANSACTION_EXECUTION_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_estimateMessageFee", + "summary": "estimate the L2 fee of a message sent on L1", + "description": "estimates the resources required by the l1_handler transaction induced by the message", + "params": [ + { + "name": "message", + "description": "the message's parameters", + "schema": { + "$ref": "#/components/schemas/MSG_FROM_L1" + }, + "required": true + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "the fee estimation", + "schema": { + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_blockNumber", + "summary": "Get the most recent accepted block number", + "params": [], + "result": { + "name": "result", + "description": "The latest block number", + "schema": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "errors": [ + { + "$ref": "#/components/errors/NO_BLOCKS" + } + ] + }, + { + "name": "starknet_blockHashAndNumber", + "summary": "Get the most recent accepted block hash and number", + "params": [], + "result": { + "name": "result", + "description": "The latest block hash and number", + "schema": { + "title": "Starknet block hash and number result", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "block_hash", + "block_number" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/NO_BLOCKS" + } + ] + }, + { + "name": "starknet_chainId", + "summary": "Return the currently configured StarkNet chain id", + "params": [], + "result": { + "name": "result", + "description": "The chain id this node is connected to", + "schema": { + "title": "Chain id", + "$ref": "#/components/schemas/CHAIN_ID" + } + } + }, + { + "name": "starknet_syncing", + "summary": "Returns an object about the sync status, or false if the node is not synching", + "params": [], + "result": { + "name": "syncing", + "summary": "The state of the synchronization, or false if the node is not synchronizing", + "description": "The status of the node, if it is currently synchronizing state. FALSE otherwise", + "schema": { + "title": "SyncingStatus", + "oneOf": [ + { + "type": "boolean", + "title": "False", + "description": "only legal value is FALSE here" + }, + { + "title": "Sync status", + "$ref": "#/components/schemas/SYNC_STATUS" + } + ] + } + } + }, + { + "name": "starknet_getEvents", + "summary": "Returns all events matching the given filter", + "description": "Returns all event objects matching the conditions in the provided filter", + "params": [ + { + "name": "filter", + "summary": "The conditions used to filter the returned events", + "required": true, + "schema": { + "title": "Events request", + "allOf": [ + { + "title": "Event filter", + "$ref": "#/components/schemas/EVENT_FILTER" + }, + { + "title": "Result page request", + "$ref": "#/components/schemas/RESULT_PAGE_REQUEST" + } + ] + } + } + ], + "result": { + "name": "events", + "description": "All the event objects matching the filter", + "schema": { + "title": "Events chunk", + "$ref": "#/components/schemas/EVENTS_CHUNK" + } + }, + "errors": [ + { + "$ref": "#/components/errors/PAGE_SIZE_TOO_BIG" + }, + { + "$ref": "#/components/errors/INVALID_CONTINUATION_TOKEN" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/TOO_MANY_KEYS_IN_FILTER" + } + ] + }, + { + "name": "starknet_getNonce", + "summary": "Get the nonce associated with the given address in the given block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose nonce we're seeking", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The contract's nonce at the requested state", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "EVENTS_CHUNK": { + "title": "Events chunk", + "type": "object", + "properties": { + "events": { + "type": "array", + "title": "Matching Events", + "items": { + "$ref": "#/components/schemas/EMITTED_EVENT" + } + }, + "continuation_token": { + "title": "Continuation token", + "description": "Use this token in a subsequent query to obtain the next page. Should not appear if there are no more pages.", + "type": "string" + } + }, + "required": [ + "events" + ] + }, + "RESULT_PAGE_REQUEST": { + "title": "Result page request", + "type": "object", + "properties": { + "continuation_token": { + "title": "Continuation token", + "description": "The token returned from the previous query. If no token is provided the first page is returned.", + "type": "string" + }, + "chunk_size": { + "title": "Chunk size", + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "chunk_size" + ] + }, + "EMITTED_EVENT": { + "title": "Emitted event", + "description": "Event information decorated with metadata on where it was emitted / An event emitted as a result of transaction execution", + "allOf": [ + { + "title": "Event", + "description": "The event information", + "$ref": "#/components/schemas/EVENT" + }, + { + "title": "Event context", + "description": "The event emission information", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "description": "The hash of the block in which the event was emitted", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "description": "The number of the block in which the event was emitted", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "transaction_hash": { + "title": "Transaction hash", + "description": "The transaction that emitted the event", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + }, + "EVENT": { + "title": "Event", + "description": "A StarkNet event", + "allOf": [ + { + "title": "Event emitter", + "type": "object", + "properties": { + "from_address": { + "title": "From address", + "$ref": "#/components/schemas/ADDRESS" + } + }, + "required": [ + "from_address" + ] + }, + { + "title": "Event content", + "$ref": "#/components/schemas/EVENT_CONTENT" + } + ] + }, + "EVENT_CONTENT": { + "title": "Event content", + "description": "The content of an event", + "type": "object", + "properties": { + "keys": { + "type": "array", + "title": "Keys", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "data": { + "type": "array", + "title": "Data", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "keys", + "data" + ] + }, + "EVENT_FILTER": { + "title": "Event filter", + "description": "An event filter/query", + "type": "object", + "properties": { + "from_block": { + "title": "from block", + "$ref": "#/components/schemas/BLOCK_ID" + }, + "to_block": { + "title": "to block", + "$ref": "#/components/schemas/BLOCK_ID" + }, + "address": { + "title": "from contract", + "$ref": "#/components/schemas/ADDRESS" + }, + "keys": { + "title": "Keys", + "description": "The values used to filter the events", + "type": "array", + "items": { + "title": "Keys", + "description": "Per key (by position), designate the possible values to be matched for events to be returned. Empty array designates 'any' value", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "required": [] + }, + "BLOCK_ID": { + "title": "Block id", + "description": "Block hash, number or tag", + "oneOf": [ + { + "title": "Block hash", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + } + }, + "required": [ + "block_hash" + ] + }, + { + "title": "Block number", + "type": "object", + "properties": { + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "block_number" + ] + }, + { + "title": "Block tag", + "$ref": "#/components/schemas/BLOCK_TAG" + } + ] + }, + "BLOCK_TAG": { + "title": "Block tag", + "type": "string", + "description": "A tag specifying a dynamic reference to a block", + "enum": [ + "latest", + "pending" + ] + }, + "SYNC_STATUS": { + "title": "Sync status", + "type": "object", + "description": "An object describing the node synchronization status", + "properties": { + "starting_block_hash": { + "title": "Starting block hash", + "description": "The hash of the block from which the sync started", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "starting_block_num": { + "title": "Starting block number", + "description": "The number (height) of the block from which the sync started", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "current_block_hash": { + "title": "Current block hash", + "description": "The hash of the current block being synchronized", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "current_block_num": { + "title": "Current block number", + "description": "The number (height) of the current block being synchronized", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "highest_block_hash": { + "title": "Highest block hash", + "description": "The hash of the estimated highest block to be synchronized", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "highest_block_num": { + "title": "Highest block number", + "description": "The number (height) of the estimated highest block to be synchronized", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "starting_block_hash", + "starting_block_num", + "current_block_hash", + "current_block_num", + "highest_block_hash", + "highest_block_num" + ] + }, + "NUM_AS_HEX": { + "title": "Number as hex", + "description": "An integer number in hex format (0x...)", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "u64": { + "type": "string", + "title": "u64", + "description": "64 bit integers, represented by hex string of length at most 16", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,15})$" + }, + "u128": { + "type": "string", + "title": "u128", + "description": "64 bit integers, represented by hex string of length at most 32", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,31})$" + }, + "CHAIN_ID": { + "title": "Chain id", + "description": "StarkNet chain id, given in hex representation.", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "STATE_DIFF": { + "description": "The change in state applied in this block, given as a mapping of addresses to the new values and/or new contracts", + "type": "object", + "properties": { + "storage_diffs": { + "title": "Storage diffs", + "type": "array", + "items": { + "description": "The changes in the storage per contract address", + "$ref": "#/components/schemas/CONTRACT_STORAGE_DIFF_ITEM" + } + }, + "deprecated_declared_classes": { + "title": "Deprecated declared classes", + "type": "array", + "items": { + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "declared_classes": { + "title": "Declared classes", + "type": "array", + "items": { + "title": "New classes", + "type": "object", + "description": "The declared class hash and compiled class hash", + "properties": { + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The Cairo assembly hash corresponding to the declared class", + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "deployed_contracts": { + "title": "Deployed contracts", + "type": "array", + "items": { + "description": "A new contract deployed as part of the state update", + "$ref": "#/components/schemas/DEPLOYED_CONTRACT_ITEM" + } + }, + "replaced_classes": { + "title": "Replaced classes", + "type": "array", + "items": { + "description": "The list of contracts whose class was replaced", + "title": "Replaced class", + "type": "object", + "properties": { + "contract_address": { + "title": "Contract address", + "description": "The address of the contract whose class was replaced", + "$ref": "#/components/schemas/ADDRESS" + }, + "class_hash": { + "title": "Class hash", + "description": "The new class hash", + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "nonces": { + "title": "Nonces", + "type": "array", + "items": { + "title": "Nonce update", + "description": "The updated nonce per contract address", + "type": "object", + "properties": { + "contract_address": { + "title": "Contract address", + "description": "The address of the contract", + "$ref": "#/components/schemas/ADDRESS" + }, + "nonce": { + "title": "Nonce", + "description": "The nonce for the given address at the end of the block", + "$ref": "#/components/schemas/FELT" + } + } + } + } + }, + "required": [ + "storage_diffs", + "deprecated_declared_classes", + "declared_classes", + "replaced_classes", + "deployed_contracts", + "nonces" + ] + }, + "PENDING_STATE_UPDATE": { + "title": "Pending state update", + "description": "Pending state update", + "type": "object", + "properties": { + "old_root": { + "title": "Old root", + "description": "The previous global state root", + "$ref": "#/components/schemas/FELT" + }, + "state_diff": { + "title": "State diff", + "$ref": "#/components/schemas/STATE_DIFF" + } + }, + "required": [ + "old_root", + "state_diff" + ], + "additionalProperties": false + }, + "STATE_UPDATE": { + "title": "State update", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "old_root": { + "title": "Old root", + "description": "The previous global state root", + "$ref": "#/components/schemas/FELT" + }, + "new_root": { + "title": "New root", + "description": "The new global state root", + "$ref": "#/components/schemas/FELT" + }, + "state_diff": { + "title": "State diff", + "$ref": "#/components/schemas/STATE_DIFF" + } + }, + "required": [ + "state_diff", + "block_hash", + "old_root", + "new_root" + ] + }, + "ADDRESS": { + "title": "Address", + "$ref": "#/components/schemas/FELT" + }, + "STORAGE_KEY": { + "type": "string", + "title": "Storage key", + "$comment": "A storage key, represented as a string of hex digits", + "description": "A storage key. Represented as up to 62 hex digits, 3 bits, and 5 leading zeroes.", + "pattern": "^0x(0|[0-7]{1}[a-fA-F0-9]{0,62}$)" + }, + "ETH_ADDRESS": { + "title": "Ethereum address", + "type": "string", + "$comment": "An ethereum address", + "description": "an ethereum address represented as 40 hex digits", + "pattern": "^0x[a-fA-F0-9]{40}$" + }, + "TXN_HASH": { + "$ref": "#/components/schemas/FELT", + "description": "The transaction hash, as assigned in StarkNet", + "title": "Transaction hash" + }, + "FELT": { + "type": "string", + "title": "Field element", + "description": "A field element. represented by at most 63 hex digits", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,62})$" + }, + "BLOCK_NUMBER": { + "title": "Block number", + "description": "The block's number (its height)", + "type": "integer", + "minimum": 0 + }, + "BLOCK_HASH": { + "title": "Block hash", + "$ref": "#/components/schemas/FELT" + }, + "BLOCK_BODY_WITH_TX_HASHES": { + "title": "Block body with transaction hashes", + "type": "object", + "properties": { + "transactions": { + "title": "Transaction hashes", + "description": "The hashes of the transactions included in this block", + "type": "array", + "items": { + "description": "The hash of a single transaction", + "$ref": "#/components/schemas/TXN_HASH" + } + } + }, + "required": [ + "transactions" + ] + }, + "BLOCK_BODY_WITH_TXS": { + "title": "Block body with transactions", + "type": "object", + "properties": { + "transactions": { + "title": "Transactions", + "description": "The transactions in this block", + "type": "array", + "items": { + "title": "transactions in block", + "type": "object", + "allOf": [ + { + "title": "transaction", + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + } + }, + "required": [ + "transactions" + ] + }, + "BLOCK_HEADER": { + "title": "Block header", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "parent_hash": { + "title": "Parent hash", + "description": "The hash of this block's parent", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "description": "The block number (its height)", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "new_root": { + "title": "New root", + "description": "The new global state root", + "$ref": "#/components/schemas/FELT" + }, + "timestamp": { + "title": "Timestamp", + "description": "The time in which the block was created, encoded in Unix time", + "type": "integer", + "minimum": 0 + }, + "sequencer_address": { + "title": "Sequencer address", + "description": "The StarkNet identity of the sequencer submitting this block", + "$ref": "#/components/schemas/FELT" + }, + "l1_gas_price": { + "title": "L1 gas price", + "descritpion": "The price of l1 gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "starknet_version": { + "title": "Starknet version", + "description": "Semver of the current Starknet protocol", + "type": "string" + } + }, + "required": [ + "block_hash", + "parent_hash", + "block_number", + "new_root", + "timestamp", + "sequencer_address", + "l1_gas_price", + "starknet_version" + ] + }, + "PENDING_BLOCK_HEADER": { + "title": "Pending block header", + "type": "object", + "properties": { + "parent_hash": { + "title": "Parent hash", + "description": "The hash of this block's parent", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "timestamp": { + "title": "Timestamp", + "description": "The time in which the block was created, encoded in Unix time", + "type": "integer", + "minimum": 0 + }, + "sequencer_address": { + "title": "Sequencer address", + "description": "The StarkNet identity of the sequencer submitting this block", + "$ref": "#/components/schemas/FELT" + }, + "l1_gas_price": { + "title": "L1 gas price", + "descritpion": "The price of l1 gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "starknet_version": { + "title": "Starknet version", + "description": "Semver of the current Starknet protocol", + "type": "string" + } + }, + "required": [ + "parent_hash", + "timestamp", + "sequencer_address", + "l1_gas_price", + "starknet_version" + ], + "not": { + "required": [ + "block_hash", + "block_number", + "new_root" + ] + } + }, + "BLOCK_WITH_TX_HASHES": { + "title": "Block with transaction hashes", + "description": "The block object", + "allOf": [ + { + "title": "Block status", + "type": "object", + "properties": { + "status": { + "title": "Status", + "$ref": "#/components/schemas/BLOCK_STATUS" + } + }, + "required": [ + "status" + ] + }, + { + "title": "Block header", + "$ref": "#/components/schemas/BLOCK_HEADER" + }, + { + "title": "Block body with transaction hashes", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TX_HASHES" + } + ] + }, + "BLOCK_WITH_TXS": { + "title": "Block with transactions", + "description": "The block object", + "allOf": [ + { + "title": "block with txs", + "type": "object", + "properties": { + "status": { + "title": "Status", + "$ref": "#/components/schemas/BLOCK_STATUS" + } + }, + "required": [ + "status" + ] + }, + { + "title": "Block header", + "$ref": "#/components/schemas/BLOCK_HEADER" + }, + { + "title": "Block body with transactions", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TXS" + } + ] + }, + "PENDING_BLOCK_WITH_TX_HASHES": { + "title": "Pending block with transaction hashes", + "description": "The dynamic block being constructed by the sequencer. Note that this object will be deprecated upon decentralization.", + "allOf": [ + { + "title": "Block body with transactions hashes", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TX_HASHES" + }, + { + "title": "Pending block header", + "$ref": "#/components/schemas/PENDING_BLOCK_HEADER" + } + ] + }, + "PENDING_BLOCK_WITH_TXS": { + "title": "Pending block with transactions", + "description": "The dynamic block being constructed by the sequencer. Note that this object will be deprecated upon decentralization.", + "allOf": [ + { + "title": "Block body with transactions", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TXS" + }, + { + "title": "Pending block header", + "$ref": "#/components/schemas/PENDING_BLOCK_HEADER" + } + ] + }, + "DEPLOYED_CONTRACT_ITEM": { + "title": "Deployed contract item", + "type": "object", + "properties": { + "address": { + "title": "Address", + "description": "The address of the contract", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the contract code", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "address", + "class_hash" + ] + }, + "CONTRACT_STORAGE_DIFF_ITEM": { + "title": "Contract storage diff item", + "type": "object", + "properties": { + "address": { + "title": "Address", + "description": "The contract address for which the storage changed", + "$ref": "#/components/schemas/FELT" + }, + "storage_entries": { + "title": "Storage entries", + "description": "The changes in the storage of the contract", + "type": "array", + "items": { + "title": "Storage diff item", + "type": "object", + "properties": { + "key": { + "title": "Key", + "description": "The key of the changed value", + "$ref": "#/components/schemas/FELT" + }, + "value": { + "title": "Value", + "description": "The new value applied to the given address", + "$ref": "#/components/schemas/FELT" + } + } + } + } + }, + "required": [ + "address", + "storage_entries" + ] + }, + "TXN": { + "title": "Transaction", + "description": "The transaction schema, as it appears inside a block", + "oneOf": [ + { + "title": "Invoke transaction", + "$ref": "#/components/schemas/INVOKE_TXN" + }, + { + "title": "L1 handler transaction", + "$ref": "#/components/schemas/L1_HANDLER_TXN" + }, + { + "title": "Declare transaction", + "$ref": "#/components/schemas/DECLARE_TXN" + }, + { + "title": "Deploy transaction", + "$ref": "#/components/schemas/DEPLOY_TXN" + }, + { + "title": "Deploy account transaction", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN" + } + ] + }, + "SIGNATURE": { + "title": "Signature", + "description": "A transaction signature", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "DECLARE_TXN": { + "title": "Declare transaction", + "oneOf": [ + { + "title": "Declare transaction V0", + "$ref": "#/components/schemas/DECLARE_TXN_V0" + }, + { + "title": "Declare transaction V1", + "$ref": "#/components/schemas/DECLARE_TXN_V1" + }, + { + "title": "Declare transaction V2", + "$ref": "#/components/schemas/DECLARE_TXN_V2" + }, + { + "title": "Declare transaction V3", + "$ref": "#/components/schemas/DECLARE_TXN_V3" + } + ] + }, + "DECLARE_TXN_V0": { + "title": "Declare Contract Transaction V0", + "description": "Declare Contract Transaction V0", + "allOf": [ + { + "type": "object", + "title": "Declare txn v0", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x0", + "0x100000000000000000000000000000000" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V1": { + "title": "Declare Contract Transaction V1", + "description": "Declare Contract Transaction V1", + "allOf": [ + { + "type": "object", + "title": "Declare txn v1", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "nonce", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V2": { + "title": "Declare Transaction V2", + "description": "Declare Contract Transaction V2", + "allOf": [ + { + "type": "object", + "title": "Declare txn v2", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x2", + "0x100000000000000000000000000000002" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "max_fee", + "version", + "signature", + "nonce", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V3": { + "title": "Declare Transaction V3", + "description": "Declare Contract Transaction V3", + "allOf": [ + { + "type": "object", + "title": "Declare txn v3", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "version", + "signature", + "nonce", + "class_hash", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "BROADCASTED_TXN": { + "oneOf": [ + { + "$ref": "#/components/schemas/BROADCASTED_INVOKE_TXN" + }, + { + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN" + }, + { + "$ref": "#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + } + ] + }, + "BROADCASTED_INVOKE_TXN": { + "title": "Broadcasted invoke transaction", + "$ref": "#/components/schemas/INVOKE_TXN" + }, + "BROADCASTED_DEPLOY_ACCOUNT_TXN": { + "title": "Broadcasted deploy account transaction", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN" + }, + "BROADCASTED_DECLARE_TXN": { + "title": "Broadcasted declare transaction", + "oneOf": [ + { + "title": "Broadcasted declare transaction V1", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V1" + }, + { + "title": "Broadcasted declare transaction V2", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V2" + }, + { + "title": "Broadcasted declare transaction V3", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V3" + } + ] + }, + "BROADCASTED_DECLARE_TXN_V1": { + "title": "Broadcasted declare contract transaction V1", + "allOf": [ + { + "type": "object", + "title": "Declare txn v1", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "nonce", + "contract_class" + ] + } + ] + }, + "BROADCASTED_DECLARE_TXN_V2": { + "title": "Broadcasted declare Transaction V2", + "description": "Broadcasted declare Contract Transaction V2", + "allOf": [ + { + "type": "object", + "title": "Declare txn v2", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x2", + "0x100000000000000000000000000000002" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "max_fee", + "version", + "signature", + "nonce", + "contract_class" + ] + } + ] + }, + "BROADCASTED_DECLARE_TXN_V3": { + "title": "Broadcasted declare Transaction V3", + "description": "Broadcasted declare Contract Transaction V3", + "allOf": [ + { + "type": "object", + "title": "Declare txn v3", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/CONTRACT_CLASS" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "version", + "signature", + "nonce", + "contract_class", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "DEPLOY_ACCOUNT_TXN": { + "title": "Deploy account transaction", + "description": "deploys a new account contract", + "oneOf": [ + { + "title": "Deploy account V1", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_V1" + }, + { + "title": "Deploy account V3", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_V3" + } + ] + }, + "DEPLOY_ACCOUNT_TXN_V1": { + "title": "Deploy account transaction", + "description": "Deploys an account contract, charges fee from the pre-funded account addresses", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_address_salt": { + "title": "Contract address salt", + "description": "The salt for the address of the deployed contract", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "description": "The parameters passed to the constructor", + "title": "Constructor calldata", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "max_fee", + "version", + "signature", + "nonce", + "type", + "contract_address_salt", + "constructor_calldata", + "class_hash" + ] + }, + "DEPLOY_ACCOUNT_TXN_V3": { + "title": "Deploy account transaction", + "description": "Deploys an account contract, charges fee from the pre-funded account addresses", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_address_salt": { + "title": "Contract address salt", + "description": "The salt for the address of the deployed contract", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "description": "The parameters passed to the constructor", + "title": "Constructor calldata", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "version", + "signature", + "nonce", + "type", + "contract_address_salt", + "constructor_calldata", + "class_hash", + "resource_bounds", + "tip", + "paymaster_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + }, + "DEPLOY_TXN": { + "title": "Deploy Contract Transaction", + "description": "The structure of a deploy transaction. Note that this transaction type is deprecated and will no longer be supported in future versions", + "allOf": [ + { + "type": "object", + "title": "Deploy txn", + "properties": { + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "$ref": "#/components/schemas/FELT" + }, + "type": { + "title": "Deploy", + "type": "string", + "enum": [ + "DEPLOY" + ] + }, + "contract_address_salt": { + "description": "The salt for the address of the deployed contract", + "title": "Contract address salt", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "title": "Constructor calldata", + "description": "The parameters passed to the constructor", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "version", + "type", + "constructor_calldata", + "contract_address_salt", + "class_hash" + ] + } + ] + }, + "INVOKE_TXN_V0": { + "title": "Invoke transaction V0", + "description": "invokes a specific function in the desired contract (not necessarily an account)", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x0", + "0x100000000000000000000000000000000" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "contract_address": { + "title": "Contract address", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Entry point selector", + "$ref": "#/components/schemas/FELT" + }, + "calldata": { + "title": "Calldata", + "type": "array", + "description": "The parameters passed to the function", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "type", + "contract_address", + "entry_point_selector", + "calldata", + "max_fee", + "version", + "signature" + ] + }, + "INVOKE_TXN_V1": { + "title": "Invoke transaction V1", + "description": "initiates a transaction from a given account", + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "sender_address": { + "title": "sender address", + "$ref": "#/components/schemas/ADDRESS" + }, + "calldata": { + "type": "array", + "title": "calldata", + "description": "The data expected by the account's `execute` function (in most usecases, this includes the called contract address and a function selector)", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "calldata", + "max_fee", + "version", + "signature", + "nonce" + ] + } + ] + }, + "INVOKE_TXN_V3": { + "title": "Invoke transaction V3", + "description": "initiates a transaction from a given account", + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "sender_address": { + "title": "sender address", + "$ref": "#/components/schemas/ADDRESS" + }, + "calldata": { + "type": "array", + "title": "calldata", + "description": "The data expected by the account's `execute` function (in most usecases, this includes the called contract address and a function selector)", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "calldata", + "version", + "signature", + "nonce", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "INVOKE_TXN": { + "title": "Invoke transaction", + "description": "Initiate a transaction from an account", + "oneOf": [ + { + "title": "Invoke transaction V0", + "$ref": "#/components/schemas/INVOKE_TXN_V0" + }, + { + "title": "Invoke transaction V1", + "$ref": "#/components/schemas/INVOKE_TXN_V1" + }, + { + "title": "Invoke transaction V3", + "$ref": "#/components/schemas/INVOKE_TXN_V3" + } + ] + }, + "L1_HANDLER_TXN": { + "title": "L1 Handler transaction", + "allOf": [ + { + "type": "object", + "title": "L1 handler transaction", + "description": "a call to an l1_handler on an L2 contract induced by a message from L1", + "properties": { + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "$ref": "#/components/schemas/FELT" + }, + "type": { + "title": "type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + }, + "nonce": { + "title": "Nonce", + "description": "The L1->L2 message nonce field of the SN Core L1 contract at the time the transaction was sent", + "$ref": "#/components/schemas/NUM_AS_HEX" + } + }, + "required": [ + "version", + "type", + "nonce" + ] + }, + { + "title": "Function call", + "$ref": "#/components/schemas/FUNCTION_CALL" + } + ] + }, + "COMMON_RECEIPT_PROPERTIES": { + "title": "Common receipt properties", + "description": "Common properties for a transaction receipt", + "type": "object", + "properties": { + "transaction_hash": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH", + "description": "The hash identifying the transaction" + }, + "actual_fee": { + "title": "Actual fee", + "$ref": "#/components/schemas/FEE_PAYMENT", + "description": "The fee that was charged by the sequencer" + }, + "execution_status": { + "title": "Execution status", + "$ref": "#/components/schemas/TXN_EXECUTION_STATUS" + }, + "finality_status": { + "title": "Finality status", + "$ref": "#/components/schemas/TXN_FINALITY_STATUS" + }, + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "messages_sent": { + "type": "array", + "title": "Messages sent", + "items": { + "$ref": "#/components/schemas/MSG_TO_L1" + } + }, + "revert_reason": { + "title": "Revert reason", + "name": "revert reason", + "description": "the revert reason for the failed execution", + "type": "string" + }, + "events": { + "description": "The events emitted as part of this transaction", + "title": "Events", + "type": "array", + "items": { + "$ref": "#/components/schemas/EVENT" + } + }, + "execution_resources": { + "title": "Execution resources", + "description": "The resources consumed by the transaction", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + } + }, + "required": [ + "transaction_hash", + "actual_fee", + "finality_status", + "execution_status", + "block_hash", + "block_number", + "messages_sent", + "events", + "execution_resources" + ] + }, + "INVOKE_TXN_RECEIPT": { + "title": "Invoke Transaction Receipt", + "allOf": [ + { + "title": "Type", + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "PENDING_INVOKE_TXN_RECEIPT": { + "title": "Invoke Transaction Receipt", + "allOf": [ + { + "title": "Type", + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/PENDING_COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "DECLARE_TXN_RECEIPT": { + "title": "Declare Transaction Receipt", + "allOf": [ + { + "title": "Declare txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "PENDING_DECLARE_TXN_RECEIPT": { + "title": "Declare Transaction Receipt", + "allOf": [ + { + "title": "Declare txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/PENDING_COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "DEPLOY_ACCOUNT_TXN_RECEIPT": { + "title": "Deploy Account Transaction Receipt", + "allOf": [ + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + }, + { + "title": "DeployAccount txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "contract_address": { + "title": "Contract address", + "description": "The address of the deployed contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "contract_address" + ] + } + ] + }, + "PENDING_DEPLOY_ACCOUNT_TXN_RECEIPT": { + "title": "Deploy Account Transaction Receipt", + "allOf": [ + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/PENDING_COMMON_RECEIPT_PROPERTIES" + }, + { + "title": "DeployAccount txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "contract_address": { + "title": "Contract address", + "description": "The address of the deployed contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "contract_address" + ] + } + ] + }, + "DEPLOY_TXN_RECEIPT": { + "title": "Deploy Transaction Receipt", + "allOf": [ + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + }, + { + "title": "Deploy txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Deploy", + "type": "string", + "enum": [ + "DEPLOY" + ] + }, + "contract_address": { + "title": "Contract address", + "description": "The address of the deployed contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "contract_address" + ] + } + ] + }, + "L1_HANDLER_TXN_RECEIPT": { + "title": "L1 Handler Transaction Receipt", + "description": "receipt for l1 handler transaction", + "allOf": [ + { + "title": "Transaction type", + "type": "object", + "properties": { + "type": { + "title": "type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + }, + "message_hash": { + "title": "Message hash", + "description": "The message hash as it appears on the L1 core contract", + "$ref": "#/components/schemas/NUM_AS_HEX" + } + }, + "required": [ + "type", + "message_hash" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "PENDING_L1_HANDLER_TXN_RECEIPT": { + "title": "L1 Handler Transaction Receipt", + "description": "receipt for l1 handler transaction", + "allOf": [ + { + "title": "Transaction type", + "type": "object", + "properties": { + "type": { + "title": "type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + }, + "message_hash": { + "title": "Message hash", + "description": "The message hash as it appears on the L1 core contract", + "$ref": "#/components/schemas/NUM_AS_HEX" + } + }, + "required": [ + "type", + "message_hash" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/PENDING_COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "TXN_RECEIPT": { + "title": "Transaction Receipt", + "oneOf": [ + { + "title": "Invoke transaction receipt", + "$ref": "#/components/schemas/INVOKE_TXN_RECEIPT" + }, + { + "title": "L1 handler transaction receipt", + "$ref": "#/components/schemas/L1_HANDLER_TXN_RECEIPT" + }, + { + "title": "Declare transaction receipt", + "$ref": "#/components/schemas/DECLARE_TXN_RECEIPT" + }, + { + "title": "Deploy transaction receipt", + "$ref": "#/components/schemas/DEPLOY_TXN_RECEIPT" + }, + { + "title": "Deploy account transaction receipt", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_RECEIPT" + } + ] + }, + "PENDING_TXN_RECEIPT": { + "title": "Transaction Receipt", + "oneOf": [ + { + "title": "Pending Invoke transaction receipt", + "$ref": "#/components/schemas/PENDING_INVOKE_TXN_RECEIPT" + }, + { + "title": "Pending L1 handler transaction receipt", + "$ref": "#/components/schemas/PENDING_L1_HANDLER_TXN_RECEIPT" + }, + { + "title": "Pending Declare transaction receipt", + "$ref": "#/components/schemas/PENDING_DECLARE_TXN_RECEIPT" + }, + { + "title": "Pending Deploy account transaction receipt", + "$ref": "#/components/schemas/PENDING_DEPLOY_ACCOUNT_TXN_RECEIPT" + } + ], + "not": { + "$ref": "#/components/schemas/TXN_RECEIPT" + } + }, + "PENDING_COMMON_RECEIPT_PROPERTIES": { + "title": "Pending common receipt properties", + "description": "Common properties for a pending transaction receipt", + "type": "object", + "properties": { + "transaction_hash": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH", + "description": "The hash identifying the transaction" + }, + "actual_fee": { + "title": "Actual fee", + "$ref": "#/components/schemas/FEE_PAYMENT", + "description": "The fee that was charged by the sequencer" + }, + "messages_sent": { + "type": "array", + "title": "Messages sent", + "items": { + "$ref": "#/components/schemas/MSG_TO_L1" + } + }, + "events": { + "description": "The events emitted as part of this transaction", + "title": "Events", + "type": "array", + "items": { + "$ref": "#/components/schemas/EVENT" + } + }, + "revert_reason": { + "title": "Revert reason", + "name": "revert reason", + "description": "the revert reason for the failed execution", + "type": "string" + }, + "finality_status": { + "title": "Finality status", + "type": "string", + "enum": [ + "ACCEPTED_ON_L2" + ], + "description": "The finality status of the transaction" + }, + "execution_status": { + "title": "Execution status", + "$ref": "#/components/schemas/TXN_EXECUTION_STATUS" + }, + "execution_resources": { + "title": "Execution resources", + "description": "The resources consumed by the transaction", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + } + }, + "required": [ + "transaction_hash", + "actual_fee", + "messages_sent", + "events", + "finality_status", + "execution_status", + "execution_resources" + ] + }, + "MSG_TO_L1": { + "title": "Message to L1", + "type": "object", + "properties": { + "from_address": { + "description": "The address of the L2 contract sending the message", + "$ref": "#/components/schemas/FELT" + }, + "to_address": { + "title": "To address", + "description": "The target L1 address the message is sent to", + "$ref": "#/components/schemas/FELT" + }, + "payload": { + "description": "The payload of the message", + "title": "Payload", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "from_address", + "to_address", + "payload" + ] + }, + "MSG_FROM_L1": { + "title": "Message from L1", + "type": "object", + "properties": { + "from_address": { + "description": "The address of the L1 contract sending the message", + "$ref": "#/components/schemas/ETH_ADDRESS" + }, + "to_address": { + "title": "To address", + "description": "The target L2 address the message is sent to", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Selector", + "description": "The selector of the l1_handler in invoke in the target contract", + "$ref": "#/components/schemas/FELT" + }, + "payload": { + "description": "The payload of the message", + "title": "Payload", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "from_address", + "to_address", + "payload", + "entry_point_selector" + ] + }, + "TXN_STATUS": { + "title": "Transaction status", + "type": "string", + "enum": [ + "RECEIVED", + "REJECTED", + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1" + ], + "description": "The finality status of the transaction, including the case the txn is still in the mempool or failed validation during the block construction phase" + }, + "TXN_FINALITY_STATUS": { + "title": "Finality status", + "type": "string", + "enum": [ + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1" + ], + "description": "The finality status of the transaction" + }, + "TXN_EXECUTION_STATUS": { + "title": "Execution status", + "type": "string", + "enum": [ + "SUCCEEDED", + "REVERTED" + ], + "description": "The execution status of the transaction" + }, + "TXN_TYPE": { + "title": "Transaction type", + "type": "string", + "enum": [ + "DECLARE", + "DEPLOY", + "DEPLOY_ACCOUNT", + "INVOKE", + "L1_HANDLER" + ], + "description": "The type of the transaction" + }, + "BLOCK_STATUS": { + "title": "Block status", + "type": "string", + "enum": [ + "PENDING", + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1", + "REJECTED" + ], + "description": "The status of the block" + }, + "FUNCTION_CALL": { + "title": "Function call", + "type": "object", + "description": "Function call information", + "properties": { + "contract_address": { + "title": "Contract address", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Entry point selector", + "$ref": "#/components/schemas/FELT" + }, + "calldata": { + "title": "Calldata", + "type": "array", + "description": "The parameters passed to the function", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "contract_address", + "entry_point_selector", + "calldata" + ] + }, + "CONTRACT_CLASS": { + "title": "Contract class", + "type": "object", + "properties": { + "sierra_program": { + "title": "Sierra program", + "type": "array", + "description": "The list of Sierra instructions of which the program consists", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "contract_class_version": { + "title": "Contract class version", + "type": "string", + "description": "The version of the contract class object. Currently, the Starknet OS supports version 0.1.0" + }, + "entry_points_by_type": { + "title": "Entry points by type", + "type": "object", + "properties": { + "CONSTRUCTOR": { + "type": "array", + "title": "Constructor", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + }, + "EXTERNAL": { + "title": "External", + "type": "array", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + }, + "L1_HANDLER": { + "title": "L1 handler", + "type": "array", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + } + }, + "required": [ + "CONSTRUCTOR", + "EXTERNAL", + "L1_HANDLER" + ] + }, + "abi": { + "title": "ABI", + "type": "string", + "description": "The class ABI, as supplied by the user declaring the class" + } + }, + "required": [ + "sierra_program", + "contract_class_version", + "entry_points_by_type" + ] + }, + "DEPRECATED_CONTRACT_CLASS": { + "title": "Deprecated contract class", + "description": "The definition of a StarkNet contract class", + "type": "object", + "properties": { + "program": { + "type": "string", + "title": "Program", + "description": "A base64 representation of the compressed program code", + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" + }, + "entry_points_by_type": { + "type": "object", + "title": "Deprecated entry points by type", + "properties": { + "CONSTRUCTOR": { + "type": "array", + "title": "Deprecated constructor", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + }, + "EXTERNAL": { + "type": "array", + "title": "Deprecated external", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + }, + "L1_HANDLER": { + "type": "array", + "title": "Deprecated L1 handler", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + } + } + }, + "abi": { + "title": "Contract ABI", + "$ref": "#/components/schemas/CONTRACT_ABI" + } + }, + "required": [ + "program", + "entry_points_by_type" + ] + }, + "DEPRECATED_CAIRO_ENTRY_POINT": { + "title": "Deprecated Cairo entry point", + "type": "object", + "properties": { + "offset": { + "title": "Offset", + "description": "The offset of the entry point in the program", + "$ref": "#/components/schemas/NUM_AS_HEX" + }, + "selector": { + "title": "Selector", + "description": "A unique identifier of the entry point (function) in the program", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "offset", + "selector" + ] + }, + "SIERRA_ENTRY_POINT": { + "title": "Sierra entry point", + "type": "object", + "properties": { + "selector": { + "title": "Selector", + "description": "A unique identifier of the entry point (function) in the program", + "$ref": "#/components/schemas/FELT" + }, + "function_idx": { + "title": "Function index", + "description": "The index of the function in the program", + "type": "integer" + } + }, + "required": [ + "selector", + "function_idx" + ] + }, + "CONTRACT_ABI": { + "title": "Contract ABI", + "type": "array", + "items": { + "$ref": "#/components/schemas/CONTRACT_ABI_ENTRY" + } + }, + "CONTRACT_ABI_ENTRY": { + "title": "Contract ABI entry", + "oneOf": [ + { + "title": "Function ABI entry", + "$ref": "#/components/schemas/FUNCTION_ABI_ENTRY" + }, + { + "title": "Event ABI entry", + "$ref": "#/components/schemas/EVENT_ABI_ENTRY" + }, + { + "title": "Struct ABI entry", + "$ref": "#/components/schemas/STRUCT_ABI_ENTRY" + } + ] + }, + "STRUCT_ABI_TYPE": { + "title": "Struct ABI type", + "type": "string", + "enum": [ + "struct" + ] + }, + "EVENT_ABI_TYPE": { + "title": "Event ABI type", + "type": "string", + "enum": [ + "event" + ] + }, + "FUNCTION_ABI_TYPE": { + "title": "Function ABI type", + "type": "string", + "enum": [ + "function", + "l1_handler", + "constructor" + ] + }, + "STRUCT_ABI_ENTRY": { + "title": "Struct ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Struct ABI type", + "$ref": "#/components/schemas/STRUCT_ABI_TYPE" + }, + "name": { + "title": "Struct name", + "description": "The struct name", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer", + "minimum": 1 + }, + "members": { + "type": "array", + "title": "Members", + "items": { + "$ref": "#/components/schemas/STRUCT_MEMBER" + } + } + }, + "required": [ + "type", + "name", + "size", + "members" + ] + }, + "STRUCT_MEMBER": { + "title": "Struct member", + "allOf": [ + { + "title": "Typed parameter", + "$ref": "#/components/schemas/TYPED_PARAMETER" + }, + { + "type": "object", + "title": "Offset", + "properties": { + "offset": { + "title": "Offset", + "description": "offset of this property within the struct", + "type": "integer" + } + } + } + ] + }, + "EVENT_ABI_ENTRY": { + "title": "Event ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Event ABI type", + "$ref": "#/components/schemas/EVENT_ABI_TYPE" + }, + "name": { + "title": "Event name", + "description": "The event name", + "type": "string" + }, + "keys": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "data": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + } + }, + "required": [ + "type", + "name", + "keys", + "data" + ] + }, + "FUNCTION_STATE_MUTABILITY": { + "title": "Function state mutability type", + "type": "string", + "enum": [ + "view" + ] + }, + "FUNCTION_ABI_ENTRY": { + "title": "Function ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Function ABI type", + "$ref": "#/components/schemas/FUNCTION_ABI_TYPE" + }, + "name": { + "title": "Function name", + "description": "The function name", + "type": "string" + }, + "inputs": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "outputs": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "stateMutability": { + "title": "Function state mutability", + "$ref": "#/components/schemas/FUNCTION_STATE_MUTABILITY" + } + }, + "required": [ + "type", + "name", + "inputs", + "outputs" + ] + }, + "TYPED_PARAMETER": { + "title": "Typed parameter", + "type": "object", + "properties": { + "name": { + "title": "Parameter name", + "description": "The parameter's name", + "type": "string" + }, + "type": { + "title": "Parameter type", + "description": "The parameter's type", + "type": "string" + } + }, + "required": [ + "name", + "type" + ] + }, + "SIMULATION_FLAG_FOR_ESTIMATE_FEE": { + "type": "string", + "enum": [ + "SKIP_VALIDATE" + ], + "description": "Flags that indicate how to simulate a given transaction. By default, the sequencer behavior is replicated locally" + }, + "PRICE_UNIT": { + "title": "price unit", + "type": "string", + "enum": [ + "WEI", + "FRI" + ] + }, + "FEE_ESTIMATE": { + "title": "Fee estimation", + "type": "object", + "properties": { + "gas_consumed": { + "title": "Gas consumed", + "description": "The Ethereum gas cost of the transaction (see https://docs.starknet.io/docs/Fees/fee-mechanism for more info)", + "$ref": "#/components/schemas/FELT" + }, + "gas_price": { + "title": "Gas price", + "description": "The gas price (in gwei or fri, depending on the tx version) that was used in the cost estimation", + "$ref": "#/components/schemas/FELT" + }, + "overall_fee": { + "title": "Overall fee", + "description": "The estimated fee for the transaction (in gwei or fri, depending on the tx version), product of gas_consumed and gas_price", + "$ref": "#/components/schemas/FELT" + }, + "unit": { + "title": "Fee unit", + "description": "units in which the fee is given", + "$ref": "#/components/schemas/PRICE_UNIT" + } + }, + "required": [ + "gas_consumed", + "gas_price", + "overall_fee", + "unit" + ] + }, + "FEE_PAYMENT": { + "title": "Fee Payment", + "description": "fee payment info as it appears in receipts", + "type": "object", + "properties": { + "amount": { + "title": "Amunt", + "description": "amount paid", + "$ref": "#/components/schemas/FELT" + }, + "unit": { + "title": "Fee unit", + "description": "units in which the fee is given", + "$ref": "#/components/schemas/PRICE_UNIT" + } + }, + "required": [ + "amount", + "unit" + ] + }, + "DA_MODE": { + "title": "DA mode", + "type": "string", + "description": "Specifies a storage domain in Starknet. Each domain has different gurantess regarding availability", + "enum": [ + "L1", + "L2" + ] + }, + "RESOURCE_BOUNDS_MAPPING": { + "type": "object", + "properties": { + "l1_gas": { + "title": "L1 Gas", + "description": "The max amount and max price per unit of L1 gas used in this tx", + "$ref": "#/components/schemas/RESOURCE_BOUNDS" + }, + "l2_gas": { + "title": "L2 Gas", + "description": "The max amount and max price per unit of L2 gas used in this tx", + "$ref": "#/components/schemas/RESOURCE_BOUNDS" + } + }, + "required": [ + "l1_gas", + "l2_gas" + ] + }, + "RESOURCE_BOUNDS": { + "type": "object", + "properties": { + "max_amount": { + "title": "max amount", + "description": "the max amount of the resource that can be used in the tx", + "$ref": "#/components/schemas/u64" + }, + "max_price_per_unit": { + "title": "max price", + "description": "the max price per unit of this resource for this tx", + "$ref": "#/components/schemas/u128" + } + }, + "required": [ + "max_amount", + "max_price_per_unit" + ] + }, + "RESOURCE_PRICE": { + "type": "object", + "properties": { + "price_in_fri": { + "title": "price in fri", + "description": "the price of one unit of the given resource, denominated in fri (10^-18 strk)", + "$ref": "#/components/schemas/FELT" + }, + "price_in_wei": { + "title": "price in wei", + "description": "the price of one unit of the given resource, denominated in wei", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "price_in_wei", + "price_in_fri" + ] + }, + "EXECUTION_RESOURCES": { + "title": "Execution resources", + "description": "The resources consumed by the VM", + "type": "object", + "properties": { + "steps": { + "title": "Steps", + "description": "The number of Cairo steps used", + "type": "integer", + "not": { + "const": 0 + } + }, + "memory_holes": { + "title": "Memory holes", + "description": "The number of unused memory cells (each cell is roughly equivalent to a step)", + "type": "integer", + "not": { + "const": 0 + } + }, + "range_check_builtin_applications": { + "title": "Range check applications", + "description": "The number of RANGE_CHECK builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "pedersen_builtin_applications": { + "title": "Pedersen applications", + "description": "The number of Pedersen builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "poseidon_builtin_applications": { + "title": "Poseidon applications", + "description": "The number of Poseidon builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "ec_op_builtin_applications": { + "title": "EC_OP applications", + "description": "the number of EC_OP builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "ecdsa_builtin_applications": { + "title": "ECDSA applications", + "description": "the number of ECDSA builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "bitwise_builtin_applications": { + "title": "BITWISE applications", + "description": "the number of BITWISE builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "keccak_builtin_applications": { + "title": "Keccak applications", + "description": "The number of KECCAK builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "segment_arena_builtin": { + "title": "Segment arena", + "description": "The number of accesses to the segment arena", + "type": "integer", + "not": { + "const": 0 + } + } + }, + "required": [ + "steps" + ] + } + }, + "errors": { + "FAILED_TO_RECEIVE_TXN": { + "code": 1, + "message": "Failed to write transaction" + }, + "CONTRACT_NOT_FOUND": { + "code": 20, + "message": "Contract not found" + }, + "BLOCK_NOT_FOUND": { + "code": 24, + "message": "Block not found" + }, + "INVALID_TXN_INDEX": { + "code": 27, + "message": "Invalid transaction index in a block" + }, + "CLASS_HASH_NOT_FOUND": { + "code": 28, + "message": "Class hash not found" + }, + "TXN_HASH_NOT_FOUND": { + "code": 29, + "message": "Transaction hash not found" + }, + "PAGE_SIZE_TOO_BIG": { + "code": 31, + "message": "Requested page size is too big" + }, + "NO_BLOCKS": { + "code": 32, + "message": "There are no blocks" + }, + "INVALID_CONTINUATION_TOKEN": { + "code": 33, + "message": "The supplied continuation token is invalid or unknown" + }, + "TOO_MANY_KEYS_IN_FILTER": { + "code": 34, + "message": "Too many keys provided in a filter" + }, + "CONTRACT_ERROR": { + "code": 40, + "message": "Contract error", + "data": { + "type": "object", + "description": "More data about the execution failure", + "properties": { + "revert_error": { + "title": "revert error", + "description": "a string encoding the execution trace up to the point of failure", + "type": "string" + } + }, + "required": "revert_error" + } + }, + "TRANSACTION_EXECUTION_ERROR": { + "code": 41, + "message": "Transaction execution error", + "data": { + "type": "object", + "description": "More data about the execution failure", + "properties": { + "transaction_index": { + "title": "Transaction index", + "description": "The index of the first transaction failing in a sequence of given transactions", + "type": "integer" + }, + "execution_error": { + "title": "revert error", + "description": "a string encoding the execution trace up to the point of failure", + "type": "string" + } + }, + "required": [ + "transaction_index", + "execution_error" + ] + } + } + } + } +} diff --git a/crates/papyrus_rpc/resources/V0_6/starknet_trace_api_openrpc.json b/crates/papyrus_rpc/resources/V0_6/starknet_trace_api_openrpc.json new file mode 100644 index 00000000000..f08efd04725 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_6/starknet_trace_api_openrpc.json @@ -0,0 +1,494 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.5.1", + "title": "StarkNet Trace API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_traceTransaction", + "summary": "For a given executed transaction, return the trace of its execution, including internal calls", + "description": "Returns the execution trace of the transaction designated by the input hash", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the transaction to trace", + "required": true, + "schema": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "trace", + "description": "The function call trace of the transaction designated by the given hash", + "schema": { + "$ref": "#/components/schemas/TRANSACTION_TRACE" + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + }, + { + "$ref": "#/components/errors/NO_TRACE_AVAILABLE" + } + ] + }, + { + "name": "starknet_simulateTransactions", + "summary": "Simulate a given sequence of transactions on the requested state, and generate the execution traces. Note that some of the transactions may revert, in which case no error is thrown, but revert details can be seen on the returned trace object. . Note that some of the transactions may revert, this will be reflected by the revert_error property in the trace. Other types of failures (e.g. unexpected error or failure in the validation phase) will result in TRANSACTION_EXECUTION_ERROR.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "transactions", + "description": "The transactions to simulate", + "required": true, + "schema": { + "type": "array", + "description": "a sequence of transactions to simulate, running each transaction on the state resulting from applying all the previous ones", + "items": { + "$ref": "#/components/schemas/BROADCASTED_TXN" + } + } + }, + { + "name": "simulation_flags", + "description": "describes what parts of the transaction should be executed", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SIMULATION_FLAG" + } + } + } + ], + "result": { + "name": "simulated_transactions", + "description": "The execution trace and consuemd resources of the required transactions", + "schema": { + "type": "array", + "items": { + "schema": { + "type": "object", + "properties": { + "transaction_trace": { + "title": "the transaction's trace", + "$ref": "#/components/schemas/TRANSACTION_TRACE" + }, + "fee_estimation": { + "title": "the transaction's resources and fee", + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + } + } + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/TRANSACTION_EXECUTION_ERROR" + } + ] + }, + { + "name": "starknet_traceBlockTransactions", + "summary": "Retrieve traces for all transactions in the given block", + "description": "Returns the execution traces of all transactions included in the given block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "traces", + "description": "The traces of all transactions in the block", + "schema": { + "type": "array", + "items": { + "type": "object", + "description": "A single pair of transaction hash and corresponding trace", + "properties": { + "transaction_hash": { + "$ref": "#/components/schemas/FELT" + }, + "trace_root": { + "$ref": "#/components/schemas/TRANSACTION_TRACE" + } + } + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "TRANSACTION_TRACE": { + "oneOf": [ + { + "name": "INVOKE_TXN_TRACE", + "type": "object", + "description": "the execution trace of an invoke transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "execute_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "oneOf": [ + { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + { + "type": "object", + "properties": { + "revert_reason": { + "name": "revert reason", + "description": "the revert reason for the failed execution", + "type": "string" + } + }, + "required": [ + "revert_reason" + ] + } + ] + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + } + }, + "required": [ + "type", + "execute_invocation" + ] + }, + { + "name": "DECLARE_TXN_TRACE", + "type": "object", + "description": "the execution trace of a declare transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "DECLARE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "name": "DEPLOY_ACCOUNT_TXN_TRACE", + "type": "object", + "description": "the execution trace of a deploy account transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "constructor_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + } + }, + "required": [ + "type", + "constructor_invocation" + ] + }, + { + "name": "L1_HANDLER_TXN_TRACE", + "type": "object", + "description": "the execution trace of an L1 handler transaction", + "properties": { + "function_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + } + }, + "required": [ + "type", + "function_invocation" + ] + } + ] + }, + "SIMULATION_FLAG": { + "type": "string", + "enum": [ + "SKIP_VALIDATE", + "SKIP_FEE_CHARGE" + ], + "description": "Flags that indicate how to simulate a given transaction. By default, the sequencer behavior is replicated locally (enough funds are expected to be in the account, and fee will be deducted from the balance before the simulation of the next transaction). To skip the fee charge, use the SKIP_FEE_CHARGE flag." + }, + "NESTED_CALL": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "FUNCTION_INVOCATION": { + "allOf": [ + { + "$ref": "#/components/schemas/FUNCTION_CALL" + }, + { + "type": "object", + "properties": { + "caller_address": { + "title": "Caller Address", + "description": "The address of the invoking contract. 0 for the root invocation", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the class being called", + "$ref": "#/components/schemas/FELT" + }, + "entry_point_type": { + "$ref": "#/components/schemas/ENTRY_POINT_TYPE" + }, + "call_type": { + "$ref": "#/components/schemas/CALL_TYPE" + }, + "result": { + "title": "Invocation Result", + "description": "The value returned from the function invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "calls": { + "title": "Nested Calls", + "description": "The calls made by this invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/NESTED_CALL" + } + }, + "events": { + "title": "Invocation Events", + "description": "The events emitted in this invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/ORDERED_EVENT" + } + }, + "messages": { + "title": "L1 Messages", + "description": "The messages sent by this invocation to L1", + "type": "array", + "items": { + "$ref": "#/components/schemas/ORDERED_MESSAGE" + } + }, + "execution_resources": { + "title": "Execution resources", + "description": "Resources consumed by the internal call", + "items": { + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + } + } + }, + "required": [ + "caller_address", + "class_hash", + "entry_point_type", + "call_type", + "result", + "calls", + "events", + "messages", + "execution_resources" + ] + } + ] + }, + "ENTRY_POINT_TYPE": { + "type": "string", + "enum": [ + "EXTERNAL", + "L1_HANDLER", + "CONSTRUCTOR" + ] + }, + "CALL_TYPE": { + "type": "string", + "enum": [ + "LIBRARY_CALL", + "CALL", + "DELEGATE" + ] + }, + "ORDERED_EVENT": { + "type": "object", + "title": "orderedEvent", + "description": "an event alongside its order within the transaction", + "allOf": [ + { + "type": "object", + "properties": { + "order": { + "title": "order", + "description": "the order of the event within the transaction", + "type": "integer" + } + } + }, + { + "$ref": "#/components/schemas/EVENT" + } + ] + }, + "ORDERED_MESSAGE": { + "type": "object", + "title": "orderedMessage", + "description": "a message alongside its order within the transaction", + "allOf": [ + { + "type": "object", + "properties": { + "order": { + "title": "order", + "description": "the order of the message within the transaction", + "type": "integer" + } + } + }, + { + "$ref": "#/components/schemas/MSG_TO_L1" + } + ] + }, + "FELT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FELT" + }, + "FUNCTION_CALL": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FUNCTION_CALL" + }, + "EVENT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/EVENT_CONTENT" + }, + "MSG_TO_L1": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/MSG_TO_L1" + }, + "BLOCK_ID": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BLOCK_ID" + }, + "FEE_ESTIMATE": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FEE_ESTIMATE" + }, + "BROADCASTED_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_TXN" + }, + "STATE_DIFF": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/STATE_DIFF" + }, + "EXECUTION_RESOURCES": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/EXECUTION_RESOURCES" + } + }, + "errors": { + "NO_TRACE_AVAILABLE": { + "code": 10, + "message": "No trace available for transaction", + "data": { + "type": "object", + "description": "Extra information on why trace is not available. Either it wasn't executed yet (RECEIVED), or the transaction failed (REJECTED)", + "properties": { + "status": { + "type": "string", + "enum": [ + "RECEIVED", + "REJECTED" + ] + } + } + } + }, + "TXN_HASH_NOT_FOUND": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/TXN_HASH_NOT_FOUND" + }, + "BLOCK_NOT_FOUND": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/BLOCK_NOT_FOUND" + }, + "TRANSACTION_EXECUTION_ERROR": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/TRANSACTION_EXECUTION_ERROR" + } + } + } +} diff --git a/crates/papyrus_rpc/resources/V0_6/starknet_write_api.json b/crates/papyrus_rpc/resources/V0_6/starknet_write_api.json new file mode 100644 index 00000000000..4a3f229e894 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_6/starknet_write_api.json @@ -0,0 +1,299 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.6.0", + "title": "StarkNet Node Write API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_addInvokeTransaction", + "summary": "Submit a new transaction to be added to the chain", + "params": [ + { + "name": "invoke_transaction", + "description": "The information needed to invoke the function (or account, for version 1 transactions)", + "required": true, + "schema": { + "$ref": "#/components/schemas/BROADCASTED_INVOKE_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the invoke transaction", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + }, + { + "name": "starknet_addDeclareTransaction", + "summary": "Submit a new class declaration transaction", + "params": [ + { + "name": "declare_transaction", + "description": "Declare transaction required to declare a new class on Starknet", + "required": true, + "schema": { + "title": "Declare transaction", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the declare transaction", + "$ref": "#/components/schemas/TXN_HASH" + }, + "class_hash": { + "title": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "transaction_hash", + "class_hash" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/CLASS_ALREADY_DECLARED" + }, + { + "$ref": "#/components/errors/COMPILATION_FAILED" + }, + { + "$ref": "#/components/errors/COMPILED_CLASS_HASH_MISMATCH" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/CONTRACT_CLASS_SIZE_IS_TOO_LARGE" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_CONTRACT_CLASS_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + }, + { + "name": "starknet_addDeployAccountTransaction", + "summary": "Submit a new deploy account transaction", + "params": [ + { + "name": "deploy_account_transaction", + "description": "The deploy account transaction", + "required": true, + "schema": { + "$ref": "#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the deploy transaction", + "$ref": "#/components/schemas/TXN_HASH" + }, + "contract_address": { + "title": "The address of the new contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "transaction_hash", + "contract_address" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/CLASS_HASH_NOT_FOUND" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "NUM_AS_HEX": { + "title": "An integer number in hex format (0x...)", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "SIGNATURE": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/SIGNATURE" + }, + "FELT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FELT" + }, + "TXN_HASH": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/TXN_HASH" + }, + "BROADCASTED_INVOKE_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_INVOKE_TXN" + }, + "BROADCASTED_DECLARE_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_DECLARE_TXN" + }, + "BROADCASTED_DEPLOY_ACCOUNT_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + }, + "FUNCTION_CALL": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FUNCTION_CALL" + } + }, + "errors": { + "CLASS_HASH_NOT_FOUND": { + "code": 28, + "message": "Class hash not found" + }, + "CLASS_ALREADY_DECLARED": { + "code": 51, + "message": "Class already declared" + }, + "INVALID_TRANSACTION_NONCE": { + "code": 52, + "message": "Invalid transaction nonce" + }, + "INSUFFICIENT_MAX_FEE": { + "code": 53, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + "INSUFFICIENT_ACCOUNT_BALANCE": { + "code": 54, + "message": "Account balance is smaller than the transaction's max_fee" + }, + "VALIDATION_FAILURE": { + "code": 55, + "message": "Account validation failed", + "data": "string" + }, + "COMPILATION_FAILED": { + "code": 56, + "message": "Compilation failed" + }, + "CONTRACT_CLASS_SIZE_IS_TOO_LARGE": { + "code": 57, + "message": "Contract class size it too large" + }, + "NON_ACCOUNT": { + "code": 58, + "message": "Sender address in not an account contract" + }, + "DUPLICATE_TX": { + "code": 59, + "message": "A transaction with the same hash already exists in the mempool" + }, + "COMPILED_CLASS_HASH_MISMATCH": { + "code": 60, + "message": "the compiled class hash did not match the one supplied in the transaction" + }, + "UNSUPPORTED_TX_VERSION": { + "code": 61, + "message": "the transaction version is not supported" + }, + "UNSUPPORTED_CONTRACT_CLASS_VERSION": { + "code": 62, + "message": "the contract class version is not supported" + }, + "UNEXPECTED_ERROR": { + "code": 63, + "message": "An unexpected error occurred", + "data": "string" + } + } + } +} diff --git a/crates/papyrus_rpc/resources/V0_7/starknet_api_openrpc.json b/crates/papyrus_rpc/resources/V0_7/starknet_api_openrpc.json new file mode 100644 index 00000000000..6bc8657e591 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_7/starknet_api_openrpc.json @@ -0,0 +1,3950 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.7.0", + "title": "StarkNet Node API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_specVersion", + "summary": "Returns the version of the Starknet JSON-RPC specification being used", + "params": [], + "result": { + "name": "result", + "description": "Semver of Starknet's JSON-RPC spec being used", + "required": true, + "schema": { + "title": "JSON-RPC spec version", + "type": "string" + } + } + }, + { + "name": "starknet_getBlockWithTxHashes", + "summary": "Get block information with transaction hashes given the block id", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The resulting block information with transaction hashes", + "schema": { + "title": "Starknet get block hash with tx hashes result", + "oneOf": [ + { + "title": "Block with transaction hashes", + "$ref": "#/components/schemas/BLOCK_WITH_TX_HASHES" + }, + { + "title": "Pending block with transaction hashes", + "$ref": "#/components/schemas/PENDING_BLOCK_WITH_TX_HASHES" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getBlockWithTxs", + "summary": "Get block information with full transactions given the block id", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The resulting block information with full transactions", + "schema": { + "title": "Starknet get block with txs result", + "oneOf": [ + { + "title": "Block with transactions", + "$ref": "#/components/schemas/BLOCK_WITH_TXS" + }, + { + "title": "Pending block with transactions", + "$ref": "#/components/schemas/PENDING_BLOCK_WITH_TXS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getBlockWithReceipts", + "summary": "Get block information with full transactions and receipts given the block id", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The resulting block information with full transactions", + "schema": { + "title": "Starknet get block with txs and receipts result", + "oneOf": [ + { + "title": "Block with transactions", + "$ref": "#/components/schemas/BLOCK_WITH_RECEIPTS" + }, + { + "title": "Pending block with transactions", + "$ref": "#/components/schemas/PENDING_BLOCK_WITH_RECEIPTS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getStateUpdate", + "summary": "Get the information about the result of executing the requested block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The information about the state update of the requested block", + "schema": { + "title": "Starknet get state update result", + "oneOf": [ + { + "title": "State update", + "$ref": "#/components/schemas/STATE_UPDATE" + }, + { + "title": "Pending state update", + "$ref": "#/components/schemas/PENDING_STATE_UPDATE" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getStorageAt", + "summary": "Get the value of the storage at the given address and key", + "params": [ + { + "name": "contract_address", + "description": "The address of the contract to read from", + "summary": "The address of the contract to read from", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + }, + { + "name": "key", + "description": "The key to the storage value for the given contract", + "summary": "The key to the storage value for the given contract", + "required": true, + "schema": { + "title": "Storage key", + "$ref": "#/components/schemas/STORAGE_KEY" + } + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The value at the given key for the given contract. 0 if no value is found", + "summary": "The value at the given key for the given contract.", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionStatus", + "summary": "Gets the transaction status (possibly reflecting that the tx is still in the mempool, or dropped from it)", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "title": "Transaction status", + "type": "object", + "properties": { + "finality_status": { + "title": "finality status", + "$ref": "#/components/schemas/TXN_STATUS" + }, + "execution_status": { + "title": "execution status", + "$ref": "#/components/schemas/TXN_EXECUTION_STATUS" + } + }, + "required": [ + "finality_status" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionByHash", + "summary": "Get the details and status of a submitted transaction", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "title": "Transaction", + "allOf": [ + { + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getTransactionByBlockIdAndIndex", + "summary": "Get the details of a transaction by a given block id and index", + "description": "Get the details of the transaction given by the identified block and index in that block. If no transaction is found, null is returned.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "index", + "summary": "The index in the block to search for the transaction", + "required": true, + "schema": { + "title": "Index", + "type": "integer", + "minimum": 0 + } + } + ], + "result": { + "name": "transactionResult", + "schema": { + "title": "Transaction", + "allOf": [ + { + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/INVALID_TXN_INDEX" + } + ] + }, + { + "name": "starknet_getTransactionReceipt", + "summary": "Get the transaction receipt by the transaction hash", + "paramStructure": "by-name", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the requested transaction", + "required": true, + "schema": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "result", + "schema": { + "title": "Transaction receipt with block info", + "$ref": "#/components/schemas/TXN_RECEIPT_WITH_BLOCK_INFO" + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClass", + "summary": "Get the contract class definition in the given block associated with the given hash", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "class_hash", + "description": "The hash of the requested contract class", + "required": true, + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + } + ], + "result": { + "name": "result", + "description": "The contract class, if found", + "schema": { + "title": "Starknet get class result", + "oneOf": [ + { + "title": "Deprecated contract class", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + }, + { + "title": "Contract class", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CLASS_HASH_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClassHashAt", + "summary": "Get the contract class hash in the given block for the contract deployed at the given address", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose class hash will be returned", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The class hash of the given contract", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getClassAt", + "summary": "Get the contract class definition in the given block at the given address", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose class definition will be returned", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The contract class", + "schema": { + "title": "Starknet get class at result", + "oneOf": [ + { + "title": "Deprecated contract class", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + }, + { + "title": "Contract class", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + }, + { + "name": "starknet_getBlockTransactionCount", + "summary": "Get the number of transactions in a block given a block id", + "description": "Returns the number of transactions in the designated block.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "The number of transactions in the designated block", + "summary": "The number of transactions in the designated block", + "schema": { + "title": "Block transaction count", + "type": "integer", + "minimum": 0 + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_call", + "summary": "call a starknet function without creating a StarkNet transaction", + "description": "Calls a function in a contract and returns the return value. Using this call will not create a transaction; hence, will not change the state", + "params": [ + { + "name": "request", + "summary": "The details of the function call", + "schema": { + "title": "Function call", + "$ref": "#/components/schemas/FUNCTION_CALL" + }, + "required": true + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "summary": "The function's return value", + "description": "The function's return value, as defined in the Cairo output", + "schema": { + "type": "array", + "title": "Field element", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_estimateFee", + "summary": "estimate the fee for of StarkNet transactions", + "description": "Estimates the resources required by a given sequence of transactions when applied on a given state. If one of the transactions reverts or fails due to any reason (e.g. validation failure or an internal error), a TRANSACTION_EXECUTION_ERROR is returned. For v0-2 transactions the estimate is given in wei, and for v3 transactions it is given in fri.", + "params": [ + { + "name": "request", + "summary": "The transaction to estimate", + "schema": { + "type": "array", + "description": "a sequence of transactions to estimate, running each transaction on the state resulting from applying all the previous ones", + "title": "Transaction", + "items": { + "$ref": "#/components/schemas/BROADCASTED_TXN" + } + }, + "required": true + }, + { + "name": "simulation_flags", + "description": "describes what parts of the transaction should be executed", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SIMULATION_FLAG_FOR_ESTIMATE_FEE" + } + } + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "the fee estimations", + "schema": { + "title": "Estimation", + "type": "array", + "description": "a sequence of fee estimatione where the i'th estimate corresponds to the i'th transaction", + "items": { + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/TRANSACTION_EXECUTION_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_estimateMessageFee", + "summary": "estimate the L2 fee of a message sent on L1", + "description": "estimates the resources required by the l1_handler transaction induced by the message", + "params": [ + { + "name": "message", + "description": "the message's parameters", + "schema": { + "$ref": "#/components/schemas/MSG_FROM_L1" + }, + "required": true + }, + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "result", + "description": "the fee estimation", + "schema": { + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + }, + "errors": [ + { + "$ref": "#/components/errors/CONTRACT_ERROR" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + }, + { + "name": "starknet_blockNumber", + "summary": "Get the most recent accepted block number", + "params": [], + "result": { + "name": "result", + "description": "The latest block number", + "schema": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "errors": [ + { + "$ref": "#/components/errors/NO_BLOCKS" + } + ] + }, + { + "name": "starknet_blockHashAndNumber", + "summary": "Get the most recent accepted block hash and number", + "params": [], + "result": { + "name": "result", + "description": "The latest block hash and number", + "schema": { + "title": "Starknet block hash and number result", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "block_hash", + "block_number" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/NO_BLOCKS" + } + ] + }, + { + "name": "starknet_chainId", + "summary": "Return the currently configured StarkNet chain id", + "params": [], + "result": { + "name": "result", + "description": "The chain id this node is connected to", + "schema": { + "title": "Chain id", + "$ref": "#/components/schemas/CHAIN_ID" + } + } + }, + { + "name": "starknet_syncing", + "summary": "Returns an object about the sync status, or false if the node is not synching", + "params": [], + "result": { + "name": "syncing", + "summary": "The state of the synchronization, or false if the node is not synchronizing", + "description": "The status of the node, if it is currently synchronizing state. FALSE otherwise", + "schema": { + "title": "SyncingStatus", + "oneOf": [ + { + "type": "boolean", + "title": "False", + "description": "only legal value is FALSE here" + }, + { + "title": "Sync status", + "$ref": "#/components/schemas/SYNC_STATUS" + } + ] + } + } + }, + { + "name": "starknet_getEvents", + "summary": "Returns all events matching the given filter", + "description": "Returns all event objects matching the conditions in the provided filter", + "params": [ + { + "name": "filter", + "summary": "The conditions used to filter the returned events", + "required": true, + "schema": { + "title": "Events request", + "allOf": [ + { + "title": "Event filter", + "$ref": "#/components/schemas/EVENT_FILTER" + }, + { + "title": "Result page request", + "$ref": "#/components/schemas/RESULT_PAGE_REQUEST" + } + ] + } + } + ], + "result": { + "name": "events", + "description": "All the event objects matching the filter", + "schema": { + "title": "Events chunk", + "$ref": "#/components/schemas/EVENTS_CHUNK" + } + }, + "errors": [ + { + "$ref": "#/components/errors/PAGE_SIZE_TOO_BIG" + }, + { + "$ref": "#/components/errors/INVALID_CONTINUATION_TOKEN" + }, + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/TOO_MANY_KEYS_IN_FILTER" + } + ] + }, + { + "name": "starknet_getNonce", + "summary": "Get the nonce associated with the given address in the given block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "title": "Block id", + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "contract_address", + "description": "The address of the contract whose nonce we're seeking", + "required": true, + "schema": { + "title": "Address", + "$ref": "#/components/schemas/ADDRESS" + } + } + ], + "result": { + "name": "result", + "description": "The contract's nonce at the requested state", + "schema": { + "title": "Field element", + "$ref": "#/components/schemas/FELT" + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/CONTRACT_NOT_FOUND" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "EVENTS_CHUNK": { + "title": "Events chunk", + "type": "object", + "properties": { + "events": { + "type": "array", + "title": "Matching Events", + "items": { + "$ref": "#/components/schemas/EMITTED_EVENT" + } + }, + "continuation_token": { + "title": "Continuation token", + "description": "Use this token in a subsequent query to obtain the next page. Should not appear if there are no more pages.", + "type": "string" + } + }, + "required": [ + "events" + ] + }, + "RESULT_PAGE_REQUEST": { + "title": "Result page request", + "type": "object", + "properties": { + "continuation_token": { + "title": "Continuation token", + "description": "The token returned from the previous query. If no token is provided the first page is returned.", + "type": "string" + }, + "chunk_size": { + "title": "Chunk size", + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "chunk_size" + ] + }, + "EMITTED_EVENT": { + "title": "Emitted event", + "description": "Event information decorated with metadata on where it was emitted / An event emitted as a result of transaction execution", + "allOf": [ + { + "title": "Event", + "description": "The event information", + "$ref": "#/components/schemas/EVENT" + }, + { + "title": "Event context", + "description": "The event emission information", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "description": "The hash of the block in which the event was emitted", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "description": "The number of the block in which the event was emitted", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "transaction_hash": { + "title": "Transaction hash", + "description": "The transaction that emitted the event", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + }, + "EVENT": { + "title": "Event", + "description": "A StarkNet event", + "allOf": [ + { + "title": "Event emitter", + "type": "object", + "properties": { + "from_address": { + "title": "From address", + "$ref": "#/components/schemas/ADDRESS" + } + }, + "required": [ + "from_address" + ] + }, + { + "title": "Event content", + "$ref": "#/components/schemas/EVENT_CONTENT" + } + ] + }, + "EVENT_CONTENT": { + "title": "Event content", + "description": "The content of an event", + "type": "object", + "properties": { + "keys": { + "type": "array", + "title": "Keys", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "data": { + "type": "array", + "title": "Data", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "keys", + "data" + ] + }, + "EVENT_FILTER": { + "title": "Event filter", + "description": "An event filter/query", + "type": "object", + "properties": { + "from_block": { + "title": "from block", + "$ref": "#/components/schemas/BLOCK_ID" + }, + "to_block": { + "title": "to block", + "$ref": "#/components/schemas/BLOCK_ID" + }, + "address": { + "title": "from contract", + "$ref": "#/components/schemas/ADDRESS" + }, + "keys": { + "title": "Keys", + "description": "The values used to filter the events", + "type": "array", + "items": { + "title": "Keys", + "description": "Per key (by position), designate the possible values to be matched for events to be returned. Empty array designates 'any' value", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "required": [] + }, + "BLOCK_ID": { + "title": "Block id", + "description": "Block hash, number or tag", + "oneOf": [ + { + "title": "Block hash", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + } + }, + "required": [ + "block_hash" + ] + }, + { + "title": "Block number", + "type": "object", + "properties": { + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "block_number" + ] + }, + { + "title": "Block tag", + "$ref": "#/components/schemas/BLOCK_TAG" + } + ] + }, + "BLOCK_TAG": { + "title": "Block tag", + "type": "string", + "description": "A tag specifying a dynamic reference to a block", + "enum": [ + "latest", + "pending" + ] + }, + "SYNC_STATUS": { + "title": "Sync status", + "type": "object", + "description": "An object describing the node synchronization status", + "properties": { + "starting_block_hash": { + "title": "Starting block hash", + "description": "The hash of the block from which the sync started", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "starting_block_num": { + "title": "Starting block number", + "description": "The number (height) of the block from which the sync started", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "current_block_hash": { + "title": "Current block hash", + "description": "The hash of the current block being synchronized", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "current_block_num": { + "title": "Current block number", + "description": "The number (height) of the current block being synchronized", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "highest_block_hash": { + "title": "Highest block hash", + "description": "The hash of the estimated highest block to be synchronized", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "highest_block_num": { + "title": "Highest block number", + "description": "The number (height) of the estimated highest block to be synchronized", + "$ref": "#/components/schemas/BLOCK_NUMBER" + } + }, + "required": [ + "starting_block_hash", + "starting_block_num", + "current_block_hash", + "current_block_num", + "highest_block_hash", + "highest_block_num" + ] + }, + "NUM_AS_HEX": { + "title": "Number as hex", + "description": "An integer number in hex format (0x...)", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "u64": { + "type": "string", + "title": "u64", + "description": "64 bit integers, represented by hex string of length at most 16", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,15})$" + }, + "u128": { + "type": "string", + "title": "u128", + "description": "64 bit integers, represented by hex string of length at most 32", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,31})$" + }, + "CHAIN_ID": { + "title": "Chain id", + "description": "StarkNet chain id, given in hex representation.", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "STATE_DIFF": { + "description": "The change in state applied in this block, given as a mapping of addresses to the new values and/or new contracts", + "type": "object", + "properties": { + "storage_diffs": { + "title": "Storage diffs", + "type": "array", + "items": { + "description": "The changes in the storage per contract address", + "$ref": "#/components/schemas/CONTRACT_STORAGE_DIFF_ITEM" + } + }, + "deprecated_declared_classes": { + "title": "Deprecated declared classes", + "type": "array", + "items": { + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "declared_classes": { + "title": "Declared classes", + "type": "array", + "items": { + "title": "New classes", + "type": "object", + "description": "The declared class hash and compiled class hash", + "properties": { + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The Cairo assembly hash corresponding to the declared class", + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "deployed_contracts": { + "title": "Deployed contracts", + "type": "array", + "items": { + "description": "A new contract deployed as part of the state update", + "$ref": "#/components/schemas/DEPLOYED_CONTRACT_ITEM" + } + }, + "replaced_classes": { + "title": "Replaced classes", + "type": "array", + "items": { + "description": "The list of contracts whose class was replaced", + "title": "Replaced class", + "type": "object", + "properties": { + "contract_address": { + "title": "Contract address", + "description": "The address of the contract whose class was replaced", + "$ref": "#/components/schemas/ADDRESS" + }, + "class_hash": { + "title": "Class hash", + "description": "The new class hash", + "$ref": "#/components/schemas/FELT" + } + } + } + }, + "nonces": { + "title": "Nonces", + "type": "array", + "items": { + "title": "Nonce update", + "description": "The updated nonce per contract address", + "type": "object", + "properties": { + "contract_address": { + "title": "Contract address", + "description": "The address of the contract", + "$ref": "#/components/schemas/ADDRESS" + }, + "nonce": { + "title": "Nonce", + "description": "The nonce for the given address at the end of the block", + "$ref": "#/components/schemas/FELT" + } + } + } + } + }, + "required": [ + "storage_diffs", + "deprecated_declared_classes", + "declared_classes", + "replaced_classes", + "deployed_contracts", + "nonces" + ] + }, + "PENDING_STATE_UPDATE": { + "title": "Pending state update", + "description": "Pending state update", + "type": "object", + "properties": { + "old_root": { + "title": "Old root", + "description": "The previous global state root", + "$ref": "#/components/schemas/FELT" + }, + "state_diff": { + "title": "State diff", + "$ref": "#/components/schemas/STATE_DIFF" + } + }, + "required": [ + "old_root", + "state_diff" + ], + "additionalProperties": false + }, + "STATE_UPDATE": { + "title": "State update", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "old_root": { + "title": "Old root", + "description": "The previous global state root", + "$ref": "#/components/schemas/FELT" + }, + "new_root": { + "title": "New root", + "description": "The new global state root", + "$ref": "#/components/schemas/FELT" + }, + "state_diff": { + "title": "State diff", + "$ref": "#/components/schemas/STATE_DIFF" + } + }, + "required": [ + "state_diff", + "block_hash", + "old_root", + "new_root" + ] + }, + "ADDRESS": { + "title": "Address", + "$ref": "#/components/schemas/FELT" + }, + "STORAGE_KEY": { + "type": "string", + "title": "Storage key", + "$comment": "A storage key, represented as a string of hex digits", + "description": "A storage key. Represented as up to 62 hex digits, 3 bits, and 5 leading zeroes.", + "pattern": "^0x(0|[0-7]{1}[a-fA-F0-9]{0,62}$)" + }, + "ETH_ADDRESS": { + "title": "Ethereum address", + "type": "string", + "$comment": "An ethereum address", + "description": "an ethereum address represented as 40 hex digits", + "pattern": "^0x[a-fA-F0-9]{40}$" + }, + "TXN_HASH": { + "$ref": "#/components/schemas/FELT", + "description": "The transaction hash, as assigned in StarkNet", + "title": "Transaction hash" + }, + "FELT": { + "type": "string", + "title": "Field element", + "description": "A field element. represented by at most 63 hex digits", + "pattern": "^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,62})$" + }, + "BLOCK_NUMBER": { + "title": "Block number", + "description": "The block's number (its height)", + "type": "integer", + "minimum": 0 + }, + "BLOCK_HASH": { + "title": "Block hash", + "$ref": "#/components/schemas/FELT" + }, + "BLOCK_BODY_WITH_TX_HASHES": { + "title": "Block body with transaction hashes", + "type": "object", + "properties": { + "transactions": { + "title": "Transaction hashes", + "description": "The hashes of the transactions included in this block", + "type": "array", + "items": { + "description": "The hash of a single transaction", + "$ref": "#/components/schemas/TXN_HASH" + } + } + }, + "required": [ + "transactions" + ] + }, + "BLOCK_BODY_WITH_TXS": { + "title": "Block body with transactions", + "type": "object", + "properties": { + "transactions": { + "title": "Transactions", + "description": "The transactions in this block", + "type": "array", + "items": { + "title": "transactions in block", + "type": "object", + "allOf": [ + { + "title": "transaction", + "$ref": "#/components/schemas/TXN" + }, + { + "type": "object", + "properties": { + "transaction_hash": { + "title": "transaction hash", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + ] + } + } + }, + "required": [ + "transactions" + ] + }, + "BLOCK_BODY_WITH_RECEIPTS": { + "title": "Block body with transactions and receipts", + "type": "object", + "properties": { + "transactions": { + "title": "Transactions", + "description": "The transactions in this block", + "type": "array", + "items": { + "type": "object", + "title": "transaction and receipt", + "properties": { + "transaction": { + "title": "transaction", + "$ref": "#/components/schemas/TXN" + }, + "receipt": { + "title": "receipt", + "$ref": "#/components/schemas/TXN_RECEIPT" + } + }, + "required": [ + "transaction", + "receipt" + ] + } + } + }, + "required": [ + "transactions" + ] + }, + "BLOCK_HEADER": { + "title": "Block header", + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "parent_hash": { + "title": "Parent hash", + "description": "The hash of this block's parent", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "block_number": { + "title": "Block number", + "description": "The block number (its height)", + "$ref": "#/components/schemas/BLOCK_NUMBER" + }, + "new_root": { + "title": "New root", + "description": "The new global state root", + "$ref": "#/components/schemas/FELT" + }, + "timestamp": { + "title": "Timestamp", + "description": "The time in which the block was created, encoded in Unix time", + "type": "integer", + "minimum": 0 + }, + "sequencer_address": { + "title": "Sequencer address", + "description": "The StarkNet identity of the sequencer submitting this block", + "$ref": "#/components/schemas/FELT" + }, + "l1_gas_price": { + "title": "L1 gas price", + "description": "The price of l1 gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "l1_data_gas_price": { + "title": "L1 data gas price", + "description": "The price of l1 data gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "l1_da_mode": { + "title": "L1 da mode", + "type": "string", + "description": "specifies whether the data of this block is published via blob data or calldata", + "enum": [ + "BLOB", + "CALLDATA" + ] + }, + "starknet_version": { + "title": "Starknet version", + "description": "Semver of the current Starknet protocol", + "type": "string" + } + }, + "required": [ + "block_hash", + "parent_hash", + "block_number", + "new_root", + "timestamp", + "sequencer_address", + "l1_gas_price", + "l1_data_gas_price", + "l1_da_mode", + "starknet_version" + ] + }, + "PENDING_BLOCK_HEADER": { + "title": "Pending block header", + "type": "object", + "properties": { + "parent_hash": { + "title": "Parent hash", + "description": "The hash of this block's parent", + "$ref": "#/components/schemas/BLOCK_HASH" + }, + "timestamp": { + "title": "Timestamp", + "description": "The time in which the block was created, encoded in Unix time", + "type": "integer", + "minimum": 0 + }, + "sequencer_address": { + "title": "Sequencer address", + "description": "The StarkNet identity of the sequencer submitting this block", + "$ref": "#/components/schemas/FELT" + }, + "l1_gas_price": { + "title": "L1 gas price", + "description": "The price of l1 gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "l1_data_gas_price": { + "title": "L1 data gas price", + "description": "The price of l1 data gas in the block", + "$ref": "#/components/schemas/RESOURCE_PRICE" + }, + "l1_da_mode": { + "title": "L1 da mode", + "type": "string", + "description": "specifies whether the data of this block is published via blob data or calldata", + "enum": [ + "BLOB", + "CALLDATA" + ] + }, + "starknet_version": { + "title": "Starknet version", + "description": "Semver of the current Starknet protocol", + "type": "string" + } + }, + "required": [ + "parent_hash", + "timestamp", + "sequencer_address", + "l1_gas_price", + "l1_data_gas_price", + "l1_da_mode", + "starknet_version" + ], + "not": { + "required": [ + "block_hash", + "block_number", + "new_root" + ] + } + }, + "BLOCK_WITH_TX_HASHES": { + "title": "Block with transaction hashes", + "description": "The block object", + "allOf": [ + { + "title": "Block status", + "type": "object", + "properties": { + "status": { + "title": "Status", + "$ref": "#/components/schemas/BLOCK_STATUS" + } + }, + "required": [ + "status" + ] + }, + { + "title": "Block header", + "$ref": "#/components/schemas/BLOCK_HEADER" + }, + { + "title": "Block body with transaction hashes", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TX_HASHES" + } + ] + }, + "BLOCK_WITH_TXS": { + "title": "Block with transactions", + "description": "The block object", + "allOf": [ + { + "title": "block with txs", + "type": "object", + "properties": { + "status": { + "title": "Status", + "$ref": "#/components/schemas/BLOCK_STATUS" + } + }, + "required": [ + "status" + ] + }, + { + "title": "Block header", + "$ref": "#/components/schemas/BLOCK_HEADER" + }, + { + "title": "Block body with transactions", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TXS" + } + ] + }, + "BLOCK_WITH_RECEIPTS": { + "title": "Block with transactions and receipts", + "description": "The block object", + "allOf": [ + { + "title": "block with txs", + "type": "object", + "properties": { + "status": { + "title": "Status", + "$ref": "#/components/schemas/BLOCK_STATUS" + } + }, + "required": [ + "status" + ] + }, + { + "title": "Block header", + "$ref": "#/components/schemas/BLOCK_HEADER" + }, + { + "title": "Block body with transactions and receipts", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_RECEIPTS" + } + ] + }, + "PENDING_BLOCK_WITH_TX_HASHES": { + "title": "Pending block with transaction hashes", + "description": "The dynamic block being constructed by the sequencer. Note that this object will be deprecated upon decentralization.", + "allOf": [ + { + "title": "Block body with transactions hashes", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TX_HASHES" + }, + { + "title": "Pending block header", + "$ref": "#/components/schemas/PENDING_BLOCK_HEADER" + } + ] + }, + "PENDING_BLOCK_WITH_TXS": { + "title": "Pending block with transactions", + "description": "The dynamic block being constructed by the sequencer. Note that this object will be deprecated upon decentralization.", + "allOf": [ + { + "title": "Block body with transactions", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_TXS" + }, + { + "title": "Pending block header", + "$ref": "#/components/schemas/PENDING_BLOCK_HEADER" + } + ] + }, + "PENDING_BLOCK_WITH_RECEIPTS": { + "title": "Pending block with transactions and receipts", + "description": "The dynamic block being constructed by the sequencer. Note that this object will be deprecated upon decentralization.", + "allOf": [ + { + "title": "Block body with transactions and receipts", + "$ref": "#/components/schemas/BLOCK_BODY_WITH_RECEIPTS" + }, + { + "title": "Pending block header", + "$ref": "#/components/schemas/PENDING_BLOCK_HEADER" + } + ] + }, + "DEPLOYED_CONTRACT_ITEM": { + "title": "Deployed contract item", + "type": "object", + "properties": { + "address": { + "title": "Address", + "description": "The address of the contract", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the contract code", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "address", + "class_hash" + ] + }, + "CONTRACT_STORAGE_DIFF_ITEM": { + "title": "Contract storage diff item", + "type": "object", + "properties": { + "address": { + "title": "Address", + "description": "The contract address for which the storage changed", + "$ref": "#/components/schemas/FELT" + }, + "storage_entries": { + "title": "Storage entries", + "description": "The changes in the storage of the contract", + "type": "array", + "items": { + "title": "Storage diff item", + "type": "object", + "properties": { + "key": { + "title": "Key", + "description": "The key of the changed value", + "$ref": "#/components/schemas/FELT" + }, + "value": { + "title": "Value", + "description": "The new value applied to the given address", + "$ref": "#/components/schemas/FELT" + } + } + } + } + }, + "required": [ + "address", + "storage_entries" + ] + }, + "TXN": { + "title": "Transaction", + "description": "The transaction schema, as it appears inside a block", + "oneOf": [ + { + "title": "Invoke transaction", + "$ref": "#/components/schemas/INVOKE_TXN" + }, + { + "title": "L1 handler transaction", + "$ref": "#/components/schemas/L1_HANDLER_TXN" + }, + { + "title": "Declare transaction", + "$ref": "#/components/schemas/DECLARE_TXN" + }, + { + "title": "Deploy transaction", + "$ref": "#/components/schemas/DEPLOY_TXN" + }, + { + "title": "Deploy account transaction", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN" + } + ] + }, + "SIGNATURE": { + "title": "Signature", + "description": "A transaction signature", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "DECLARE_TXN": { + "title": "Declare transaction", + "oneOf": [ + { + "title": "Declare transaction V0", + "$ref": "#/components/schemas/DECLARE_TXN_V0" + }, + { + "title": "Declare transaction V1", + "$ref": "#/components/schemas/DECLARE_TXN_V1" + }, + { + "title": "Declare transaction V2", + "$ref": "#/components/schemas/DECLARE_TXN_V2" + }, + { + "title": "Declare transaction V3", + "$ref": "#/components/schemas/DECLARE_TXN_V3" + } + ] + }, + "DECLARE_TXN_V0": { + "title": "Declare Contract Transaction V0", + "description": "Declare Contract Transaction V0", + "allOf": [ + { + "type": "object", + "title": "Declare txn v0", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x0", + "0x100000000000000000000000000000000" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V1": { + "title": "Declare Contract Transaction V1", + "description": "Declare Contract Transaction V1", + "allOf": [ + { + "type": "object", + "title": "Declare txn v1", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "nonce", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V2": { + "title": "Declare Transaction V2", + "description": "Declare Contract Transaction V2", + "allOf": [ + { + "type": "object", + "title": "Declare txn v2", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x2", + "0x100000000000000000000000000000002" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "max_fee", + "version", + "signature", + "nonce", + "class_hash" + ] + } + ] + }, + "DECLARE_TXN_V3": { + "title": "Declare Transaction V3", + "description": "Declare Contract Transaction V3", + "allOf": [ + { + "type": "object", + "title": "Declare txn v3", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "version", + "signature", + "nonce", + "class_hash", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "BROADCASTED_TXN": { + "oneOf": [ + { + "$ref": "#/components/schemas/BROADCASTED_INVOKE_TXN" + }, + { + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN" + }, + { + "$ref": "#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + } + ] + }, + "BROADCASTED_INVOKE_TXN": { + "title": "Broadcasted invoke transaction", + "$ref": "#/components/schemas/INVOKE_TXN" + }, + "BROADCASTED_DEPLOY_ACCOUNT_TXN": { + "title": "Broadcasted deploy account transaction", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN" + }, + "BROADCASTED_DECLARE_TXN": { + "title": "Broadcasted declare transaction", + "oneOf": [ + { + "title": "Broadcasted declare transaction V1", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V1" + }, + { + "title": "Broadcasted declare transaction V2", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V2" + }, + { + "title": "Broadcasted declare transaction V3", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN_V3" + } + ] + }, + "BROADCASTED_DECLARE_TXN_V1": { + "title": "Broadcasted declare contract transaction V1", + "allOf": [ + { + "type": "object", + "title": "Declare txn v1", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/DEPRECATED_CONTRACT_CLASS" + } + }, + "required": [ + "type", + "sender_address", + "max_fee", + "version", + "signature", + "nonce", + "contract_class" + ] + } + ] + }, + "BROADCASTED_DECLARE_TXN_V2": { + "title": "Broadcasted declare Transaction V2", + "description": "Broadcasted declare Contract Transaction V2", + "allOf": [ + { + "type": "object", + "title": "Declare txn v2", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x2", + "0x100000000000000000000000000000002" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/CONTRACT_CLASS" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "max_fee", + "version", + "signature", + "nonce", + "contract_class" + ] + } + ] + }, + "BROADCASTED_DECLARE_TXN_V3": { + "title": "Broadcasted declare Transaction V3", + "description": "Broadcasted declare Contract Transaction V3", + "allOf": [ + { + "type": "object", + "title": "Declare txn v3", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + }, + "sender_address": { + "title": "Sender address", + "description": "The address of the account contract sending the declaration transaction", + "$ref": "#/components/schemas/ADDRESS" + }, + "compiled_class_hash": { + "title": "Compiled class hash", + "description": "The hash of the Cairo assembly resulting from the Sierra compilation", + "$ref": "#/components/schemas/FELT" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_class": { + "title": "Contract class", + "description": "The class to be declared", + "$ref": "#/components/schemas/CONTRACT_CLASS" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "compiled_class_hash", + "version", + "signature", + "nonce", + "contract_class", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "DEPLOY_ACCOUNT_TXN": { + "title": "Deploy account transaction", + "description": "deploys a new account contract", + "oneOf": [ + { + "title": "Deploy account V1", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_V1" + }, + { + "title": "Deploy account V3", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_V3" + } + ] + }, + "DEPLOY_ACCOUNT_TXN_V1": { + "title": "Deploy account transaction", + "description": "Deploys an account contract, charges fee from the pre-funded account addresses", + "type": "object", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_address_salt": { + "title": "Contract address salt", + "description": "The salt for the address of the deployed contract", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "description": "The parameters passed to the constructor", + "title": "Constructor calldata", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "max_fee", + "version", + "signature", + "nonce", + "type", + "contract_address_salt", + "constructor_calldata", + "class_hash" + ] + }, + "DEPLOY_ACCOUNT_TXN_V3": { + "title": "Deploy account transaction", + "description": "Deploys an account contract, charges fee from the pre-funded account addresses", + "type": "object", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "contract_address_salt": { + "title": "Contract address salt", + "description": "The salt for the address of the deployed contract", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "description": "The parameters passed to the constructor", + "title": "Constructor calldata", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "version", + "signature", + "nonce", + "type", + "contract_address_salt", + "constructor_calldata", + "class_hash", + "resource_bounds", + "tip", + "paymaster_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + }, + "DEPLOY_TXN": { + "title": "Deploy Contract Transaction", + "description": "The structure of a deploy transaction. Note that this transaction type is deprecated and will no longer be supported in future versions", + "allOf": [ + { + "type": "object", + "title": "Deploy txn", + "properties": { + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "$ref": "#/components/schemas/FELT" + }, + "type": { + "title": "Deploy", + "type": "string", + "enum": [ + "DEPLOY" + ] + }, + "contract_address_salt": { + "description": "The salt for the address of the deployed contract", + "title": "Contract address salt", + "$ref": "#/components/schemas/FELT" + }, + "constructor_calldata": { + "type": "array", + "title": "Constructor calldata", + "description": "The parameters passed to the constructor", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the deployed contract's class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "version", + "type", + "constructor_calldata", + "contract_address_salt", + "class_hash" + ] + } + ] + }, + "INVOKE_TXN_V0": { + "title": "Invoke transaction V0", + "description": "invokes a specific function in the desired contract (not necessarily an account)", + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x0", + "0x100000000000000000000000000000000" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "contract_address": { + "title": "Contract address", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Entry point selector", + "$ref": "#/components/schemas/FELT" + }, + "calldata": { + "title": "Calldata", + "type": "array", + "description": "The parameters passed to the function", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "type", + "contract_address", + "entry_point_selector", + "calldata", + "max_fee", + "version", + "signature" + ] + }, + "INVOKE_TXN_V1": { + "title": "Invoke transaction V1", + "description": "initiates a transaction from a given account", + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "sender_address": { + "title": "sender address", + "$ref": "#/components/schemas/ADDRESS" + }, + "calldata": { + "type": "array", + "title": "calldata", + "description": "The data expected by the account's `execute` function (in most usecases, this includes the called contract address and a function selector)", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "max_fee": { + "title": "Max fee", + "$ref": "#/components/schemas/FELT", + "description": "The maximal fee that can be charged for including the transaction" + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x1", + "0x100000000000000000000000000000001" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "sender_address", + "calldata", + "max_fee", + "version", + "signature", + "nonce" + ] + } + ] + }, + "INVOKE_TXN_V3": { + "title": "Invoke transaction V3", + "description": "initiates a transaction from a given account", + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + }, + "sender_address": { + "title": "sender address", + "$ref": "#/components/schemas/ADDRESS" + }, + "calldata": { + "type": "array", + "title": "calldata", + "description": "The data expected by the account's `execute` function (in most usecases, this includes the called contract address and a function selector)", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x3", + "0x100000000000000000000000000000003" + ] + }, + "signature": { + "title": "Signature", + "$ref": "#/components/schemas/SIGNATURE" + }, + "nonce": { + "title": "Nonce", + "$ref": "#/components/schemas/FELT" + }, + "resource_bounds": { + "title": "Resource bounds", + "description": "resource bounds for the transaction execution", + "$ref": "#/components/schemas/RESOURCE_BOUNDS_MAPPING" + }, + "tip": { + "title": "Tip", + "$ref": "#/components/schemas/u64", + "description": "the tip for the transaction" + }, + "paymaster_data": { + "title": "Paymaster data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to allow the paymaster to pay for the transaction in native tokens" + }, + "account_deployment_data": { + "title": "Account deployment data", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + }, + "description": "data needed to deploy the account contract from which this tx will be initiated" + }, + "nonce_data_availability_mode": { + "title": "Nonce DA mode", + "description": "The storage domain of the account's nonce (an account has a nonce per DA mode)", + "$ref": "#/components/schemas/DA_MODE" + }, + "fee_data_availability_mode": { + "title": "Fee DA mode", + "description": "The storage domain of the account's balance from which fee will be charged", + "$ref": "#/components/schemas/DA_MODE" + } + }, + "required": [ + "type", + "sender_address", + "calldata", + "version", + "signature", + "nonce", + "resource_bounds", + "tip", + "paymaster_data", + "account_deployment_data", + "nonce_data_availability_mode", + "fee_data_availability_mode" + ] + } + ] + }, + "INVOKE_TXN": { + "title": "Invoke transaction", + "description": "Initiate a transaction from an account", + "oneOf": [ + { + "title": "Invoke transaction V0", + "$ref": "#/components/schemas/INVOKE_TXN_V0" + }, + { + "title": "Invoke transaction V1", + "$ref": "#/components/schemas/INVOKE_TXN_V1" + }, + { + "title": "Invoke transaction V3", + "$ref": "#/components/schemas/INVOKE_TXN_V3" + } + ] + }, + "L1_HANDLER_TXN": { + "title": "L1 Handler transaction", + "allOf": [ + { + "type": "object", + "title": "L1 handler transaction", + "description": "a call to an l1_handler on an L2 contract induced by a message from L1", + "properties": { + "version": { + "title": "Version", + "description": "Version of the transaction scheme", + "type": "string", + "enum": [ + "0x0" + ] + }, + "type": { + "title": "type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + }, + "nonce": { + "title": "Nonce", + "description": "The L1->L2 message nonce field of the SN Core L1 contract at the time the transaction was sent", + "$ref": "#/components/schemas/NUM_AS_HEX" + } + }, + "required": [ + "version", + "type", + "nonce" + ] + }, + { + "title": "Function call", + "$ref": "#/components/schemas/FUNCTION_CALL" + } + ] + }, + "COMMON_RECEIPT_PROPERTIES": { + "title": "Common receipt properties", + "description": "Common properties for a transaction receipt", + "type": "object", + "properties": { + "transaction_hash": { + "title": "Transaction hash", + "$ref": "#/components/schemas/TXN_HASH", + "description": "The hash identifying the transaction" + }, + "actual_fee": { + "title": "Actual fee", + "$ref": "#/components/schemas/FEE_PAYMENT", + "description": "The fee that was charged by the sequencer" + }, + "execution_status": { + "title": "Execution status", + "$ref": "#/components/schemas/TXN_EXECUTION_STATUS" + }, + "finality_status": { + "title": "Finality status", + "description": "finality status of the tx", + "$ref": "#/components/schemas/TXN_FINALITY_STATUS" + }, + "messages_sent": { + "type": "array", + "title": "Messages sent", + "items": { + "$ref": "#/components/schemas/MSG_TO_L1" + } + }, + "revert_reason": { + "title": "Revert reason", + "name": "revert reason", + "description": "the revert reason for the failed execution", + "type": "string" + }, + "events": { + "description": "The events emitted as part of this transaction", + "title": "Events", + "type": "array", + "items": { + "$ref": "#/components/schemas/EVENT" + } + }, + "execution_resources": { + "title": "Execution resources", + "description": "The resources consumed by the transaction", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + } + }, + "required": [ + "transaction_hash", + "actual_fee", + "finality_status", + "execution_status", + "messages_sent", + "events", + "execution_resources" + ] + }, + "INVOKE_TXN_RECEIPT": { + "title": "Invoke Transaction Receipt", + "allOf": [ + { + "title": "Type", + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "DECLARE_TXN_RECEIPT": { + "title": "Declare Transaction Receipt", + "allOf": [ + { + "title": "Declare txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Declare", + "type": "string", + "enum": [ + "DECLARE" + ] + } + }, + "required": [ + "type" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "DEPLOY_ACCOUNT_TXN_RECEIPT": { + "title": "Deploy Account Transaction Receipt", + "allOf": [ + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + }, + { + "title": "DeployAccount txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Deploy account", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + }, + "contract_address": { + "title": "Contract address", + "description": "The address of the deployed contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "contract_address" + ] + } + ] + }, + "DEPLOY_TXN_RECEIPT": { + "title": "Deploy Transaction Receipt", + "allOf": [ + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + }, + { + "title": "Deploy txn receipt", + "type": "object", + "properties": { + "type": { + "title": "Deploy", + "type": "string", + "enum": [ + "DEPLOY" + ] + }, + "contract_address": { + "title": "Contract address", + "description": "The address of the deployed contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "type", + "contract_address" + ] + } + ] + }, + "L1_HANDLER_TXN_RECEIPT": { + "title": "L1 Handler Transaction Receipt", + "description": "receipt for l1 handler transaction", + "allOf": [ + { + "title": "Transaction type", + "type": "object", + "properties": { + "type": { + "title": "type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + }, + "message_hash": { + "title": "Message hash", + "description": "The message hash as it appears on the L1 core contract", + "$ref": "#/components/schemas/NUM_AS_HEX" + } + }, + "required": [ + "type", + "message_hash" + ] + }, + { + "title": "Common receipt properties", + "$ref": "#/components/schemas/COMMON_RECEIPT_PROPERTIES" + } + ] + }, + "TXN_RECEIPT": { + "title": "Transaction Receipt", + "oneOf": [ + { + "title": "Invoke transaction receipt", + "$ref": "#/components/schemas/INVOKE_TXN_RECEIPT" + }, + { + "title": "L1 handler transaction receipt", + "$ref": "#/components/schemas/L1_HANDLER_TXN_RECEIPT" + }, + { + "title": "Declare transaction receipt", + "$ref": "#/components/schemas/DECLARE_TXN_RECEIPT" + }, + { + "title": "Deploy transaction receipt", + "$ref": "#/components/schemas/DEPLOY_TXN_RECEIPT" + }, + { + "title": "Deploy account transaction receipt", + "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TXN_RECEIPT" + } + ] + }, + "TXN_RECEIPT_WITH_BLOCK_INFO": { + "title": "Transaction receipt with block info", + "allOf": [ + { + "title": "Transaction receipt", + "$ref": "#/components/schemas/TXN_RECEIPT" + }, + { + "type": "object", + "properties": { + "block_hash": { + "title": "Block hash", + "$ref": "#/components/schemas/BLOCK_HASH", + "description": "If this field is missing, it means the receipt belongs to the pending block" + }, + "block_number": { + "title": "Block number", + "$ref": "#/components/schemas/BLOCK_NUMBER", + "description": "If this field is missing, it means the receipt belongs to the pending block" + } + } + } + ] + }, + "MSG_TO_L1": { + "title": "Message to L1", + "type": "object", + "properties": { + "from_address": { + "description": "The address of the L2 contract sending the message", + "$ref": "#/components/schemas/FELT" + }, + "to_address": { + "title": "To address", + "description": "The target L1 address the message is sent to", + "$ref": "#/components/schemas/FELT" + }, + "payload": { + "description": "The payload of the message", + "title": "Payload", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "from_address", + "to_address", + "payload" + ] + }, + "MSG_FROM_L1": { + "title": "Message from L1", + "type": "object", + "properties": { + "from_address": { + "description": "The address of the L1 contract sending the message", + "$ref": "#/components/schemas/ETH_ADDRESS" + }, + "to_address": { + "title": "To address", + "description": "The target L2 address the message is sent to", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Selector", + "description": "The selector of the l1_handler in invoke in the target contract", + "$ref": "#/components/schemas/FELT" + }, + "payload": { + "description": "The payload of the message", + "title": "Payload", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "from_address", + "to_address", + "payload", + "entry_point_selector" + ] + }, + "TXN_STATUS": { + "title": "Transaction status", + "type": "string", + "enum": [ + "RECEIVED", + "REJECTED", + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1" + ], + "description": "The finality status of the transaction, including the case the txn is still in the mempool or failed validation during the block construction phase" + }, + "TXN_FINALITY_STATUS": { + "title": "Finality status", + "type": "string", + "enum": [ + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1" + ], + "description": "The finality status of the transaction" + }, + "TXN_EXECUTION_STATUS": { + "title": "Execution status", + "type": "string", + "enum": [ + "SUCCEEDED", + "REVERTED" + ], + "description": "The execution status of the transaction" + }, + "TXN_TYPE": { + "title": "Transaction type", + "type": "string", + "enum": [ + "DECLARE", + "DEPLOY", + "DEPLOY_ACCOUNT", + "INVOKE", + "L1_HANDLER" + ], + "description": "The type of the transaction" + }, + "BLOCK_STATUS": { + "title": "Block status", + "type": "string", + "enum": [ + "PENDING", + "ACCEPTED_ON_L2", + "ACCEPTED_ON_L1", + "REJECTED" + ], + "description": "The status of the block" + }, + "FUNCTION_CALL": { + "title": "Function call", + "type": "object", + "description": "Function call information", + "properties": { + "contract_address": { + "title": "Contract address", + "$ref": "#/components/schemas/ADDRESS" + }, + "entry_point_selector": { + "title": "Entry point selector", + "$ref": "#/components/schemas/FELT" + }, + "calldata": { + "title": "Calldata", + "type": "array", + "description": "The parameters passed to the function", + "items": { + "$ref": "#/components/schemas/FELT" + } + } + }, + "required": [ + "contract_address", + "entry_point_selector", + "calldata" + ] + }, + "CONTRACT_CLASS": { + "title": "Contract class", + "type": "object", + "properties": { + "sierra_program": { + "title": "Sierra program", + "type": "array", + "description": "The list of Sierra instructions of which the program consists", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "contract_class_version": { + "title": "Contract class version", + "type": "string", + "description": "The version of the contract class object. Currently, the Starknet OS supports version 0.1.0" + }, + "entry_points_by_type": { + "title": "Entry points by type", + "type": "object", + "properties": { + "CONSTRUCTOR": { + "type": "array", + "title": "Constructor", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + }, + "EXTERNAL": { + "title": "External", + "type": "array", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + }, + "L1_HANDLER": { + "title": "L1 handler", + "type": "array", + "items": { + "$ref": "#/components/schemas/SIERRA_ENTRY_POINT" + } + } + }, + "required": [ + "CONSTRUCTOR", + "EXTERNAL", + "L1_HANDLER" + ] + }, + "abi": { + "title": "ABI", + "type": "string", + "description": "The class ABI, as supplied by the user declaring the class" + } + }, + "required": [ + "sierra_program", + "contract_class_version", + "entry_points_by_type" + ] + }, + "DEPRECATED_CONTRACT_CLASS": { + "title": "Deprecated contract class", + "description": "The definition of a StarkNet contract class", + "type": "object", + "properties": { + "program": { + "type": "string", + "title": "Program", + "description": "A base64 representation of the compressed program code", + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" + }, + "entry_points_by_type": { + "type": "object", + "title": "Deprecated entry points by type", + "properties": { + "CONSTRUCTOR": { + "type": "array", + "title": "Deprecated constructor", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + }, + "EXTERNAL": { + "type": "array", + "title": "Deprecated external", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + }, + "L1_HANDLER": { + "type": "array", + "title": "Deprecated L1 handler", + "items": { + "$ref": "#/components/schemas/DEPRECATED_CAIRO_ENTRY_POINT" + } + } + } + }, + "abi": { + "title": "Contract ABI", + "$ref": "#/components/schemas/CONTRACT_ABI" + } + }, + "required": [ + "program", + "entry_points_by_type" + ] + }, + "DEPRECATED_CAIRO_ENTRY_POINT": { + "title": "Deprecated Cairo entry point", + "type": "object", + "properties": { + "offset": { + "title": "Offset", + "description": "The offset of the entry point in the program", + "$ref": "#/components/schemas/NUM_AS_HEX" + }, + "selector": { + "title": "Selector", + "description": "A unique identifier of the entry point (function) in the program", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "offset", + "selector" + ] + }, + "SIERRA_ENTRY_POINT": { + "title": "Sierra entry point", + "type": "object", + "properties": { + "selector": { + "title": "Selector", + "description": "A unique identifier of the entry point (function) in the program", + "$ref": "#/components/schemas/FELT" + }, + "function_idx": { + "title": "Function index", + "description": "The index of the function in the program", + "type": "integer" + } + }, + "required": [ + "selector", + "function_idx" + ] + }, + "CONTRACT_ABI": { + "title": "Contract ABI", + "type": "array", + "items": { + "$ref": "#/components/schemas/CONTRACT_ABI_ENTRY" + } + }, + "CONTRACT_ABI_ENTRY": { + "title": "Contract ABI entry", + "oneOf": [ + { + "title": "Function ABI entry", + "$ref": "#/components/schemas/FUNCTION_ABI_ENTRY" + }, + { + "title": "Event ABI entry", + "$ref": "#/components/schemas/EVENT_ABI_ENTRY" + }, + { + "title": "Struct ABI entry", + "$ref": "#/components/schemas/STRUCT_ABI_ENTRY" + } + ] + }, + "STRUCT_ABI_TYPE": { + "title": "Struct ABI type", + "type": "string", + "enum": [ + "struct" + ] + }, + "EVENT_ABI_TYPE": { + "title": "Event ABI type", + "type": "string", + "enum": [ + "event" + ] + }, + "FUNCTION_ABI_TYPE": { + "title": "Function ABI type", + "type": "string", + "enum": [ + "function", + "l1_handler", + "constructor" + ] + }, + "STRUCT_ABI_ENTRY": { + "title": "Struct ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Struct ABI type", + "$ref": "#/components/schemas/STRUCT_ABI_TYPE" + }, + "name": { + "title": "Struct name", + "description": "The struct name", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer", + "minimum": 1 + }, + "members": { + "type": "array", + "title": "Members", + "items": { + "$ref": "#/components/schemas/STRUCT_MEMBER" + } + } + }, + "required": [ + "type", + "name", + "size", + "members" + ] + }, + "STRUCT_MEMBER": { + "title": "Struct member", + "allOf": [ + { + "title": "Typed parameter", + "$ref": "#/components/schemas/TYPED_PARAMETER" + }, + { + "type": "object", + "title": "Offset", + "properties": { + "offset": { + "title": "Offset", + "description": "offset of this property within the struct", + "type": "integer" + } + } + } + ] + }, + "EVENT_ABI_ENTRY": { + "title": "Event ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Event ABI type", + "$ref": "#/components/schemas/EVENT_ABI_TYPE" + }, + "name": { + "title": "Event name", + "description": "The event name", + "type": "string" + }, + "keys": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "data": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + } + }, + "required": [ + "type", + "name", + "keys", + "data" + ] + }, + "FUNCTION_STATE_MUTABILITY": { + "title": "Function state mutability type", + "type": "string", + "enum": [ + "view" + ] + }, + "FUNCTION_ABI_ENTRY": { + "title": "Function ABI entry", + "type": "object", + "properties": { + "type": { + "title": "Function ABI type", + "$ref": "#/components/schemas/FUNCTION_ABI_TYPE" + }, + "name": { + "title": "Function name", + "description": "The function name", + "type": "string" + }, + "inputs": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "outputs": { + "type": "array", + "title": "Typed parameter", + "items": { + "$ref": "#/components/schemas/TYPED_PARAMETER" + } + }, + "stateMutability": { + "title": "Function state mutability", + "$ref": "#/components/schemas/FUNCTION_STATE_MUTABILITY" + } + }, + "required": [ + "type", + "name", + "inputs", + "outputs" + ] + }, + "TYPED_PARAMETER": { + "title": "Typed parameter", + "type": "object", + "properties": { + "name": { + "title": "Parameter name", + "description": "The parameter's name", + "type": "string" + }, + "type": { + "title": "Parameter type", + "description": "The parameter's type", + "type": "string" + } + }, + "required": [ + "name", + "type" + ] + }, + "SIMULATION_FLAG_FOR_ESTIMATE_FEE": { + "type": "string", + "enum": [ + "SKIP_VALIDATE" + ], + "description": "Flags that indicate how to simulate a given transaction. By default, the sequencer behavior is replicated locally" + }, + "PRICE_UNIT": { + "title": "price unit", + "type": "string", + "enum": [ + "WEI", + "FRI" + ] + }, + "FEE_ESTIMATE": { + "title": "Fee estimation", + "type": "object", + "properties": { + "gas_consumed": { + "title": "Gas consumed", + "description": "The Ethereum gas consumption of the transaction", + "$ref": "#/components/schemas/FELT" + }, + "gas_price": { + "title": "Gas price", + "description": "The gas price (in wei or fri, depending on the tx version) that was used in the cost estimation", + "$ref": "#/components/schemas/FELT" + }, + "data_gas_consumed": { + "title": "Data gas consumed", + "description": "The Ethereum data gas consumption of the transaction", + "$ref": "#/components/schemas/FELT" + }, + "data_gas_price": { + "title": "Data gas price", + "description": "The data gas price (in wei or fri, depending on the tx version) that was used in the cost estimation", + "$ref": "#/components/schemas/FELT" + }, + "overall_fee": { + "title": "Overall fee", + "description": "The estimated fee for the transaction (in wei or fri, depending on the tx version), equals to gas_consumed*gas_price + data_gas_consumed*data_gas_price", + "$ref": "#/components/schemas/FELT" + }, + "unit": { + "title": "Fee unit", + "description": "units in which the fee is given", + "$ref": "#/components/schemas/PRICE_UNIT" + } + }, + "required": [ + "gas_consumed", + "gas_price", + "data_gas_consumed", + "data_gas_price", + "overall_fee", + "unit" + ] + }, + "FEE_PAYMENT": { + "title": "Fee Payment", + "description": "fee payment info as it appears in receipts", + "type": "object", + "properties": { + "amount": { + "title": "Amount", + "description": "amount paid", + "$ref": "#/components/schemas/FELT" + }, + "unit": { + "title": "Fee unit", + "description": "units in which the fee is given", + "$ref": "#/components/schemas/PRICE_UNIT" + } + }, + "required": [ + "amount", + "unit" + ] + }, + "DA_MODE": { + "title": "DA mode", + "type": "string", + "description": "Specifies a storage domain in Starknet. Each domain has different gurantess regarding availability", + "enum": [ + "L1", + "L2" + ] + }, + "RESOURCE_BOUNDS_MAPPING": { + "type": "object", + "properties": { + "l1_gas": { + "title": "L1 Gas", + "description": "The max amount and max price per unit of L1 gas used in this tx", + "$ref": "#/components/schemas/RESOURCE_BOUNDS" + }, + "l2_gas": { + "title": "L2 Gas", + "description": "The max amount and max price per unit of L2 gas used in this tx", + "$ref": "#/components/schemas/RESOURCE_BOUNDS" + } + }, + "required": [ + "l1_gas", + "l2_gas" + ] + }, + "RESOURCE_BOUNDS": { + "type": "object", + "properties": { + "max_amount": { + "title": "max amount", + "description": "the max amount of the resource that can be used in the tx", + "$ref": "#/components/schemas/u64" + }, + "max_price_per_unit": { + "title": "max price", + "description": "the max price per unit of this resource for this tx", + "$ref": "#/components/schemas/u128" + } + }, + "required": [ + "max_amount", + "max_price_per_unit" + ] + }, + "RESOURCE_PRICE": { + "type": "object", + "properties": { + "price_in_fri": { + "title": "price in fri", + "description": "the price of one unit of the given resource, denominated in fri (10^-18 strk)", + "$ref": "#/components/schemas/FELT" + }, + "price_in_wei": { + "title": "price in wei", + "description": "the price of one unit of the given resource, denominated in wei", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "price_in_wei", + "price_in_fri" + ] + }, + "COMPUTATION_RESOURCES": { + "title": "Computation resources", + "description": "The resources consumed by the VM", + "type": "object", + "properties": { + "steps": { + "title": "Steps", + "description": "The number of Cairo steps used", + "type": "integer", + "not": { + "const": 0 + } + }, + "memory_holes": { + "title": "Memory holes", + "description": "The number of unused memory cells (each cell is roughly equivalent to a step)", + "type": "integer", + "not": { + "const": 0 + } + }, + "range_check_builtin_applications": { + "title": "Range check applications", + "description": "The number of RANGE_CHECK builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "pedersen_builtin_applications": { + "title": "Pedersen applications", + "description": "The number of Pedersen builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "poseidon_builtin_applications": { + "title": "Poseidon applications", + "description": "The number of Poseidon builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "ec_op_builtin_applications": { + "title": "EC_OP applications", + "description": "the number of EC_OP builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "ecdsa_builtin_applications": { + "title": "ECDSA applications", + "description": "the number of ECDSA builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "bitwise_builtin_applications": { + "title": "BITWISE applications", + "description": "the number of BITWISE builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "keccak_builtin_applications": { + "title": "Keccak applications", + "description": "The number of KECCAK builtin instances", + "type": "integer", + "not": { + "const": 0 + } + }, + "segment_arena_builtin": { + "title": "Segment arena", + "description": "The number of accesses to the segment arena", + "type": "integer", + "not": { + "const": 0 + } + } + }, + "required": [ + "steps" + ] + }, + "EXECUTION_RESOURCES": { + "type": "object", + "title": "Execution resources", + "description": "the resources consumed by the transaction, includes both computation and data", + "allOf": [ + { + "title": "ComputationResources", + "$ref": "#/components/schemas/COMPUTATION_RESOURCES" + }, + { + "type": "object", + "title": "DataResources", + "description": "the data-availability resources of this transaction", + "properties": { + "data_availability": { + "type": "object", + "properties": { + "l1_gas": { + "title": "L1Gas", + "description": "the gas consumed by this transaction's data, 0 if it uses data gas for DA", + "type": "integer" + }, + "l1_data_gas": { + "title": "L1DataGas", + "description": "the data gas consumed by this transaction's data, 0 if it uses gas for DA", + "type": "integer" + } + }, + "required": [ + "l1_gas", + "l1_data_gas" + ] + } + }, + "required": [ + "data_availability" + ] + } + ] + } + }, + "errors": { + "FAILED_TO_RECEIVE_TXN": { + "code": 1, + "message": "Failed to write transaction" + }, + "CONTRACT_NOT_FOUND": { + "code": 20, + "message": "Contract not found" + }, + "BLOCK_NOT_FOUND": { + "code": 24, + "message": "Block not found" + }, + "INVALID_TXN_INDEX": { + "code": 27, + "message": "Invalid transaction index in a block" + }, + "CLASS_HASH_NOT_FOUND": { + "code": 28, + "message": "Class hash not found" + }, + "TXN_HASH_NOT_FOUND": { + "code": 29, + "message": "Transaction hash not found" + }, + "PAGE_SIZE_TOO_BIG": { + "code": 31, + "message": "Requested page size is too big" + }, + "NO_BLOCKS": { + "code": 32, + "message": "There are no blocks" + }, + "INVALID_CONTINUATION_TOKEN": { + "code": 33, + "message": "The supplied continuation token is invalid or unknown" + }, + "TOO_MANY_KEYS_IN_FILTER": { + "code": 34, + "message": "Too many keys provided in a filter" + }, + "CONTRACT_ERROR": { + "code": 40, + "message": "Contract error", + "data": { + "type": "object", + "description": "More data about the execution failure", + "properties": { + "revert_error": { + "title": "revert error", + "description": "a string encoding the execution trace up to the point of failure", + "type": "string" + } + }, + "required": "revert_error" + } + }, + "TRANSACTION_EXECUTION_ERROR": { + "code": 41, + "message": "Transaction execution error", + "data": { + "type": "object", + "description": "More data about the execution failure", + "properties": { + "transaction_index": { + "title": "Transaction index", + "description": "The index of the first transaction failing in a sequence of given transactions", + "type": "integer" + }, + "execution_error": { + "title": "revert error", + "description": "a string encoding the execution trace up to the point of failure", + "type": "string" + } + }, + "required": [ + "transaction_index", + "execution_error" + ] + } + } + } + } +} diff --git a/crates/papyrus_rpc/resources/V0_7/starknet_trace_api_openrpc.json b/crates/papyrus_rpc/resources/V0_7/starknet_trace_api_openrpc.json new file mode 100644 index 00000000000..0ed195025f2 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_7/starknet_trace_api_openrpc.json @@ -0,0 +1,513 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.7.0", + "title": "StarkNet Trace API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_traceTransaction", + "summary": "For a given executed transaction, return the trace of its execution, including internal calls", + "description": "Returns the execution trace of the transaction designated by the input hash", + "params": [ + { + "name": "transaction_hash", + "summary": "The hash of the transaction to trace", + "required": true, + "schema": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/TXN_HASH" + } + } + ], + "result": { + "name": "trace", + "description": "The function call trace of the transaction designated by the given hash", + "schema": { + "$ref": "#/components/schemas/TRANSACTION_TRACE" + } + }, + "errors": [ + { + "$ref": "#/components/errors/TXN_HASH_NOT_FOUND" + }, + { + "$ref": "#/components/errors/NO_TRACE_AVAILABLE" + } + ] + }, + { + "name": "starknet_simulateTransactions", + "summary": "Simulate a given sequence of transactions on the requested state, and generate the execution traces. Note that some of the transactions may revert, in which case no error is thrown, but revert details can be seen on the returned trace object. . Note that some of the transactions may revert, this will be reflected by the revert_error property in the trace. Other types of failures (e.g. unexpected error or failure in the validation phase) will result in TRANSACTION_EXECUTION_ERROR.", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag, for the block referencing the state or call the transaction on.", + "required": true, + "schema": { + "$ref": "#/components/schemas/BLOCK_ID" + } + }, + { + "name": "transactions", + "description": "The transactions to simulate", + "required": true, + "schema": { + "type": "array", + "description": "a sequence of transactions to simulate, running each transaction on the state resulting from applying all the previous ones", + "items": { + "$ref": "#/components/schemas/BROADCASTED_TXN" + } + } + }, + { + "name": "simulation_flags", + "description": "describes what parts of the transaction should be executed", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SIMULATION_FLAG" + } + } + } + ], + "result": { + "name": "simulated_transactions", + "description": "The execution trace and consuemd resources of the required transactions", + "schema": { + "type": "array", + "items": { + "schema": { + "type": "object", + "properties": { + "transaction_trace": { + "title": "the transaction's trace", + "$ref": "#/components/schemas/TRANSACTION_TRACE" + }, + "fee_estimation": { + "title": "the transaction's resources and fee", + "$ref": "#/components/schemas/FEE_ESTIMATE" + } + } + } + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + }, + { + "$ref": "#/components/errors/TRANSACTION_EXECUTION_ERROR" + } + ] + }, + { + "name": "starknet_traceBlockTransactions", + "summary": "Retrieve traces for all transactions in the given block", + "description": "Returns the execution traces of all transactions included in the given block", + "params": [ + { + "name": "block_id", + "description": "The hash of the requested block, or number (height) of the requested block, or a block tag", + "required": true, + "schema": { + "$ref": "#/components/schemas/BLOCK_ID" + } + } + ], + "result": { + "name": "traces", + "description": "The traces of all transactions in the block", + "schema": { + "type": "array", + "items": { + "type": "object", + "description": "A single pair of transaction hash and corresponding trace", + "properties": { + "transaction_hash": { + "$ref": "#/components/schemas/FELT" + }, + "trace_root": { + "$ref": "#/components/schemas/TRANSACTION_TRACE" + } + } + } + } + }, + "errors": [ + { + "$ref": "#/components/errors/BLOCK_NOT_FOUND" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "TRANSACTION_TRACE": { + "oneOf": [ + { + "name": "INVOKE_TXN_TRACE", + "type": "object", + "description": "the execution trace of an invoke transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "execute_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "oneOf": [ + { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + { + "type": "object", + "properties": { + "revert_reason": { + "name": "revert reason", + "description": "the revert reason for the failed execution", + "type": "string" + } + }, + "required": [ + "revert_reason" + ] + } + ] + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "execution_resources": { + "title": "Execution resources", + "description": "the resources consumed by the transaction, includes both computation and data", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "INVOKE" + ] + } + }, + "required": [ + "type", + "execute_invocation", + "execution_resources" + ] + }, + { + "name": "DECLARE_TXN_TRACE", + "type": "object", + "description": "the execution trace of a declare transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "execution_resources": { + "title": "Execution resources", + "description": "the resources consumed by the transaction, includes both computation and data", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "DECLARE" + ] + } + }, + "required": [ + "type", + "execution_resources" + ] + }, + { + "name": "DEPLOY_ACCOUNT_TXN_TRACE", + "type": "object", + "description": "the execution trace of a deploy account transaction", + "properties": { + "validate_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "constructor_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "fee_transfer_invocation": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "execution_resources": { + "title": "Execution resources", + "description": "the resources consumed by the transaction, includes both computation and data", + "$ref": "#/components/schemas/EXECUTION_RESOURCES" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "DEPLOY_ACCOUNT" + ] + } + }, + "required": [ + "type", + "execution_resources", + "constructor_invocation" + ] + }, + { + "name": "L1_HANDLER_TXN_TRACE", + "type": "object", + "description": "the execution trace of an L1 handler transaction", + "properties": { + "function_invocation": { + "description": "the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions)", + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "state_diff": { + "title": "state_diff", + "description": "the state diffs induced by the transaction", + "$ref": "#/components/schemas/STATE_DIFF" + }, + "type": { + "title": "Type", + "type": "string", + "enum": [ + "L1_HANDLER" + ] + } + }, + "required": [ + "type", + "function_invocation" + ] + } + ] + }, + "SIMULATION_FLAG": { + "type": "string", + "enum": [ + "SKIP_VALIDATE", + "SKIP_FEE_CHARGE" + ], + "description": "Flags that indicate how to simulate a given transaction. By default, the sequencer behavior is replicated locally (enough funds are expected to be in the account, and fee will be deducted from the balance before the simulation of the next transaction). To skip the fee charge, use the SKIP_FEE_CHARGE flag." + }, + "NESTED_CALL": { + "$ref": "#/components/schemas/FUNCTION_INVOCATION" + }, + "FUNCTION_INVOCATION": { + "allOf": [ + { + "$ref": "#/components/schemas/FUNCTION_CALL" + }, + { + "type": "object", + "properties": { + "caller_address": { + "title": "Caller Address", + "description": "The address of the invoking contract. 0 for the root invocation", + "$ref": "#/components/schemas/FELT" + }, + "class_hash": { + "title": "Class hash", + "description": "The hash of the class being called", + "$ref": "#/components/schemas/FELT" + }, + "entry_point_type": { + "$ref": "#/components/schemas/ENTRY_POINT_TYPE" + }, + "call_type": { + "$ref": "#/components/schemas/CALL_TYPE" + }, + "result": { + "title": "Invocation Result", + "description": "The value returned from the function invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/FELT" + } + }, + "calls": { + "title": "Nested Calls", + "description": "The calls made by this invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/NESTED_CALL" + } + }, + "events": { + "title": "Invocation Events", + "description": "The events emitted in this invocation", + "type": "array", + "items": { + "$ref": "#/components/schemas/ORDERED_EVENT" + } + }, + "messages": { + "title": "L1 Messages", + "description": "The messages sent by this invocation to L1", + "type": "array", + "items": { + "$ref": "#/components/schemas/ORDERED_MESSAGE" + } + }, + "execution_resources": { + "title": "Computation resources", + "description": "Resources consumed by the internal call", + "$ref": "#/components/schemas/COMPUTATION_RESOURCES" + } + }, + "required": [ + "caller_address", + "class_hash", + "entry_point_type", + "call_type", + "result", + "calls", + "events", + "messages", + "execution_resources" + ] + } + ] + }, + "ENTRY_POINT_TYPE": { + "type": "string", + "enum": [ + "EXTERNAL", + "L1_HANDLER", + "CONSTRUCTOR" + ] + }, + "CALL_TYPE": { + "type": "string", + "enum": [ + "LIBRARY_CALL", + "CALL", + "DELEGATE" + ] + }, + "ORDERED_EVENT": { + "type": "object", + "title": "orderedEvent", + "description": "an event alongside its order within the transaction", + "allOf": [ + { + "type": "object", + "properties": { + "order": { + "title": "order", + "description": "the order of the event within the transaction", + "type": "integer" + } + } + }, + { + "$ref": "#/components/schemas/EVENT" + } + ] + }, + "ORDERED_MESSAGE": { + "type": "object", + "title": "orderedMessage", + "description": "a message alongside its order within the transaction", + "allOf": [ + { + "type": "object", + "properties": { + "order": { + "title": "order", + "description": "the order of the message within the transaction", + "type": "integer" + } + } + }, + { + "$ref": "#/components/schemas/MSG_TO_L1" + } + ] + }, + "FELT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FELT" + }, + "FUNCTION_CALL": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FUNCTION_CALL" + }, + "EVENT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/EVENT_CONTENT" + }, + "MSG_TO_L1": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/MSG_TO_L1" + }, + "BLOCK_ID": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BLOCK_ID" + }, + "FEE_ESTIMATE": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FEE_ESTIMATE" + }, + "BROADCASTED_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_TXN" + }, + "STATE_DIFF": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/STATE_DIFF" + }, + "COMPUTATION_RESOURCES": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/COMPUTATION_RESOURCES" + }, + "EXECUTION_RESOURCES": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/EXECUTION_RESOURCES" + } + }, + "errors": { + "NO_TRACE_AVAILABLE": { + "code": 10, + "message": "No trace available for transaction", + "data": { + "type": "object", + "description": "Extra information on why trace is not available. Either it wasn't executed yet (RECEIVED), or the transaction failed (REJECTED)", + "properties": { + "status": { + "type": "string", + "enum": [ + "RECEIVED", + "REJECTED" + ] + } + } + } + }, + "TXN_HASH_NOT_FOUND": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/TXN_HASH_NOT_FOUND" + }, + "BLOCK_NOT_FOUND": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/BLOCK_NOT_FOUND" + }, + "TRANSACTION_EXECUTION_ERROR": { + "$ref": "./api/starknet_api_openrpc.json#/components/errors/TRANSACTION_EXECUTION_ERROR" + } + } + } +} diff --git a/crates/papyrus_rpc/resources/V0_7/starknet_write_api.json b/crates/papyrus_rpc/resources/V0_7/starknet_write_api.json new file mode 100644 index 00000000000..c492fd37f78 --- /dev/null +++ b/crates/papyrus_rpc/resources/V0_7/starknet_write_api.json @@ -0,0 +1,299 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "0.7.0", + "title": "StarkNet Node Write API", + "license": {} + }, + "servers": [], + "methods": [ + { + "name": "starknet_addInvokeTransaction", + "summary": "Submit a new transaction to be added to the chain", + "params": [ + { + "name": "invoke_transaction", + "description": "The information needed to invoke the function (or account, for version 1 transactions)", + "required": true, + "schema": { + "$ref": "#/components/schemas/BROADCASTED_INVOKE_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the invoke transaction", + "$ref": "#/components/schemas/TXN_HASH" + } + }, + "required": [ + "transaction_hash" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + }, + { + "name": "starknet_addDeclareTransaction", + "summary": "Submit a new class declaration transaction", + "params": [ + { + "name": "declare_transaction", + "description": "Declare transaction required to declare a new class on Starknet", + "required": true, + "schema": { + "title": "Declare transaction", + "$ref": "#/components/schemas/BROADCASTED_DECLARE_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the declare transaction", + "$ref": "#/components/schemas/TXN_HASH" + }, + "class_hash": { + "title": "The hash of the declared class", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "transaction_hash", + "class_hash" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/CLASS_ALREADY_DECLARED" + }, + { + "$ref": "#/components/errors/COMPILATION_FAILED" + }, + { + "$ref": "#/components/errors/COMPILED_CLASS_HASH_MISMATCH" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/CONTRACT_CLASS_SIZE_IS_TOO_LARGE" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_CONTRACT_CLASS_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + }, + { + "name": "starknet_addDeployAccountTransaction", + "summary": "Submit a new deploy account transaction", + "params": [ + { + "name": "deploy_account_transaction", + "description": "The deploy account transaction", + "required": true, + "schema": { + "$ref": "#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + } + } + ], + "result": { + "name": "result", + "description": "The result of the transaction submission", + "schema": { + "type": "object", + "properties": { + "transaction_hash": { + "title": "The hash of the deploy transaction", + "$ref": "#/components/schemas/TXN_HASH" + }, + "contract_address": { + "title": "The address of the new contract", + "$ref": "#/components/schemas/FELT" + } + }, + "required": [ + "transaction_hash", + "contract_address" + ] + } + }, + "errors": [ + { + "$ref": "#/components/errors/INSUFFICIENT_ACCOUNT_BALANCE" + }, + { + "$ref": "#/components/errors/INSUFFICIENT_MAX_FEE" + }, + { + "$ref": "#/components/errors/INVALID_TRANSACTION_NONCE" + }, + { + "$ref": "#/components/errors/VALIDATION_FAILURE" + }, + { + "$ref": "#/components/errors/NON_ACCOUNT" + }, + { + "$ref": "#/components/errors/CLASS_HASH_NOT_FOUND" + }, + { + "$ref": "#/components/errors/DUPLICATE_TX" + }, + { + "$ref": "#/components/errors/UNSUPPORTED_TX_VERSION" + }, + { + "$ref": "#/components/errors/UNEXPECTED_ERROR" + } + ] + } + ], + "components": { + "contentDescriptors": {}, + "schemas": { + "NUM_AS_HEX": { + "title": "An integer number in hex format (0x...)", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$" + }, + "SIGNATURE": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/SIGNATURE" + }, + "FELT": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FELT" + }, + "TXN_HASH": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/TXN_HASH" + }, + "BROADCASTED_INVOKE_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_INVOKE_TXN" + }, + "BROADCASTED_DECLARE_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_DECLARE_TXN" + }, + "BROADCASTED_DEPLOY_ACCOUNT_TXN": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/BROADCASTED_DEPLOY_ACCOUNT_TXN" + }, + "FUNCTION_CALL": { + "$ref": "./starknet_api_openrpc.json#/components/schemas/FUNCTION_CALL" + } + }, + "errors": { + "CLASS_HASH_NOT_FOUND": { + "code": 28, + "message": "Class hash not found" + }, + "CLASS_ALREADY_DECLARED": { + "code": 51, + "message": "Class already declared" + }, + "INVALID_TRANSACTION_NONCE": { + "code": 52, + "message": "Invalid transaction nonce" + }, + "INSUFFICIENT_MAX_FEE": { + "code": 53, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + "INSUFFICIENT_ACCOUNT_BALANCE": { + "code": 54, + "message": "Account balance is smaller than the transaction's max_fee" + }, + "VALIDATION_FAILURE": { + "code": 55, + "message": "Account validation failed", + "data": "string" + }, + "COMPILATION_FAILED": { + "code": 56, + "message": "Compilation failed" + }, + "CONTRACT_CLASS_SIZE_IS_TOO_LARGE": { + "code": 57, + "message": "Contract class size it too large" + }, + "NON_ACCOUNT": { + "code": 58, + "message": "Sender address in not an account contract" + }, + "DUPLICATE_TX": { + "code": 59, + "message": "A transaction with the same hash already exists in the mempool" + }, + "COMPILED_CLASS_HASH_MISMATCH": { + "code": 60, + "message": "the compiled class hash did not match the one supplied in the transaction" + }, + "UNSUPPORTED_TX_VERSION": { + "code": 61, + "message": "the transaction version is not supported" + }, + "UNSUPPORTED_CONTRACT_CLASS_VERSION": { + "code": 62, + "message": "the contract class version is not supported" + }, + "UNEXPECTED_ERROR": { + "code": 63, + "message": "An unexpected error occurred", + "data": "string" + } + } + } +} diff --git a/crates/papyrus_rpc/resources/account_class.json b/crates/papyrus_rpc/resources/account_class.json new file mode 100644 index 00000000000..9aa492285ce --- /dev/null +++ b/crates/papyrus_rpc/resources/account_class.json @@ -0,0 +1,2255 @@ +{ + "abi": [ + { + "inputs": [], + "name": "assert_only_self", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "__validate_declare__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + } + ], + "name": "__validate_deploy__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "__validate__", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "__execute__", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + } + ], + "name": "deploy_contract", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": 133, + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad" + }, + { + "offset": 94, + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775" + }, + { + "offset": 175, + "selector": "0x2730079d734ee55315f4f141eaed376bddd8c2133523d223a344c5604e0f7f8" + }, + { + "offset": 61, + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3" + }, + { + "offset": 47, + "selector": "0x2de154d8a89be65c1724e962dc4c65637c05532a6c2825d0a7b7d774169dbba" + }, + { + "offset": 77, + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check" + ], + "compiler_version": "0.11.1.1", + "data": [ + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff9", + "0x400380027ff87ffa", + "0x400380037ff87ffb", + "0x400380047ff87ffc", + "0x400380057ff87ffd", + "0x482680017ff88000", + "0x9", + "0x480280067ff88000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x47657443616c6c657241646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574436f6e747261637441646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff9", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x40127fff7fff7ff9", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x40780017fff7fff", + "0x1", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff84", + "0x48127ffd7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff8c", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6a", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe4", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "7": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.call_contract" + ], + "code": "syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": 0 + } + } + } + ], + "20": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.deploy" + ], + "code": "syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.deploy.syscall_ptr": 1 + } + } + } + ], + "27": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_caller_address" + ], + "code": "syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": 2 + } + } + } + ], + "34": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_contract_address" + ], + "code": "syscall_handler.get_contract_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr": 3 + } + } + } + ], + "51": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.assert_only_self" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 16 + }, + "reference_ids": {} + } + } + ], + "67": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate_declare__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 4 + }, + "reference_ids": {} + } + } + ], + "84": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate_deploy__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 5 + }, + "reference_ids": {} + } + } + ], + "109": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.__validate__" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 11, + "offset": 11 + }, + "reference_ids": {} + } + } + ], + "166": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.deploy_contract_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 15, + "offset": 0 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.__execute__": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 120, + "type": "function" + }, + "__main__.__execute__.Args": { + "full_name": "__main__.__execute__.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.__execute__.ImplicitArgs": { + "full_name": "__main__.__execute__.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.__execute__.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.__execute__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate__": { + "decorators": [ + "external" + ], + "pc": 93, + "type": "function" + }, + "__main__.__validate__.Args": { + "full_name": "__main__.__validate__.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.__validate__.ImplicitArgs": { + "full_name": "__main__.__validate__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate_declare__": { + "decorators": [ + "external" + ], + "pc": 60, + "type": "function" + }, + "__main__.__validate_declare__.Args": { + "full_name": "__main__.__validate_declare__.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.__validate_declare__.ImplicitArgs": { + "full_name": "__main__.__validate_declare__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate_declare__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate_declare__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.__validate_deploy__": { + "decorators": [ + "external" + ], + "pc": 76, + "type": "function" + }, + "__main__.__validate_deploy__.Args": { + "full_name": "__main__.__validate_deploy__.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.__validate_deploy__.ImplicitArgs": { + "full_name": "__main__.__validate_deploy__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.__validate_deploy__.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.__validate_deploy__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.assert_only_self": { + "decorators": [ + "view" + ], + "pc": 38, + "type": "function" + }, + "__main__.assert_only_self.Args": { + "full_name": "__main__.assert_only_self.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.assert_only_self.ImplicitArgs": { + "full_name": "__main__.assert_only_self.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.assert_only_self.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.assert_only_self.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.call_contract": { + "destination": "starkware.starknet.common.syscalls.call_contract", + "type": "alias" + }, + "__main__.deploy": { + "destination": "starkware.starknet.common.syscalls.deploy", + "type": "alias" + }, + "__main__.deploy_contract": { + "decorators": [ + "external" + ], + "pc": 154, + "type": "function" + }, + "__main__.deploy_contract.Args": { + "full_name": "__main__.deploy_contract.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.deploy_contract.ImplicitArgs": { + "full_name": "__main__.deploy_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.deploy_contract.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.deploy_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "__main__.get_contract_address": { + "destination": "starkware.starknet.common.syscalls.get_contract_address", + "type": "alias" + }, + "__wrappers__.__execute__": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 133, + "type": "function" + }, + "__wrappers__.__execute__.Args": { + "full_name": "__wrappers__.__execute__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__execute__.ImplicitArgs": { + "full_name": "__wrappers__.__execute__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__execute__.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__execute__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__execute__.__wrapped_func": { + "destination": "__main__.__execute__", + "type": "alias" + }, + "__wrappers__.__execute___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate__": { + "decorators": [ + "external" + ], + "pc": 94, + "type": "function" + }, + "__wrappers__.__validate__.Args": { + "full_name": "__wrappers__.__validate__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate__.ImplicitArgs": { + "full_name": "__wrappers__.__validate__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate__.__wrapped_func": { + "destination": "__main__.__validate__", + "type": "alias" + }, + "__wrappers__.__validate___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate_declare__": { + "decorators": [ + "external" + ], + "pc": 61, + "type": "function" + }, + "__wrappers__.__validate_declare__.Args": { + "full_name": "__wrappers__.__validate_declare__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_declare__.ImplicitArgs": { + "full_name": "__wrappers__.__validate_declare__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_declare__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate_declare__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate_declare__.__wrapped_func": { + "destination": "__main__.__validate_declare__", + "type": "alias" + }, + "__wrappers__.__validate_declare___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.__validate_deploy__": { + "decorators": [ + "external" + ], + "pc": 77, + "type": "function" + }, + "__wrappers__.__validate_deploy__.Args": { + "full_name": "__wrappers__.__validate_deploy__.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_deploy__.ImplicitArgs": { + "full_name": "__wrappers__.__validate_deploy__.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.__validate_deploy__.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.__validate_deploy__.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.__validate_deploy__.__wrapped_func": { + "destination": "__main__.__validate_deploy__", + "type": "alias" + }, + "__wrappers__.__validate_deploy___encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.assert_only_self": { + "decorators": [ + "view" + ], + "pc": 47, + "type": "function" + }, + "__wrappers__.assert_only_self.Args": { + "full_name": "__wrappers__.assert_only_self.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.assert_only_self.ImplicitArgs": { + "full_name": "__wrappers__.assert_only_self.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.assert_only_self.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.assert_only_self.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.assert_only_self.__wrapped_func": { + "destination": "__main__.assert_only_self", + "type": "alias" + }, + "__wrappers__.assert_only_self_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.deploy_contract": { + "decorators": [ + "external" + ], + "pc": 175, + "type": "function" + }, + "__wrappers__.deploy_contract.Args": { + "full_name": "__wrappers__.deploy_contract.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract.ImplicitArgs": { + "full_name": "__wrappers__.deploy_contract.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.deploy_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.deploy_contract.__wrapped_func": { + "destination": "__main__.deploy_contract", + "type": "alias" + }, + "__wrappers__.deploy_contract_encode_return": { + "decorators": [], + "pc": 166, + "type": "function" + }, + "__wrappers__.deploy_contract_encode_return.Args": { + "full_name": "__wrappers__.deploy_contract_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.deploy_contract_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.deploy_contract_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.deploy_contract_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.deploy_contract_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.deploy_contract_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.starknet.common.syscalls.call_contract.Args": { + "full_name": "starkware.starknet.common.syscalls.call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.call_contract.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 7, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.deploy": { + "decorators": [], + "pc": 12, + "type": "function" + }, + "starkware.starknet.common.syscalls.deploy.Args": { + "full_name": "starkware.starknet.common.syscalls.deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.deploy.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.deploy.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 20, + "value": "cast([fp + (-8)] + 9, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_caller_address": { + "decorators": [], + "pc": 24, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_caller_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.Return": { + "cairo_type": "(caller_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 1 + }, + "pc": 27, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_contract_address": { + "decorators": [], + "pc": 31, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_contract_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_contract_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_contract_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 31, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 1 + }, + "pc": 34, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 31, + "value": "[cast(fp + (-3), felt**)]" + } + ] + } + } +} diff --git a/crates/papyrus_rpc/resources/base64_compressed_program.txt b/crates/papyrus_rpc/resources/base64_compressed_program.txt new file mode 100644 index 00000000000..009251afc0c --- /dev/null +++ b/crates/papyrus_rpc/resources/base64_compressed_program.txt @@ -0,0 +1 @@ +H4sICBLB2GQAA29yaWdpbmFsX3Byb2dyYW0uanNvbgDtXQmP2ziy/iuGF4tJsr0N3Uew84BO0jMTbK7X3dnjTQaCLMsdI27Ja7knyQ7y3x+pwyYlkiqSkrp7dzKYxJbJYlXxq4OnfpvH+/1uvbjdp8X86c+/nMwXt+vNfp3hb/Ntukx3RZrNT+a7OLtOo+RjmnxC3xbr/ed1kc5R+SS/2a436S76FRVd59n86dw4Nc1T9B8quIz3MaZkfHEMww4Mw/BXqwX6P0E/Hh6a9cNl9TCwvOYhrlE+tOufDAs9sqifLCPAlVf1/yn/oWkaDqZc/19Vxx8Of1AJyT8Ny07NcsohbKwk//DFQE01ClodWnNsz/QSL0H/rrzUd3wLfbd9p9GzVSs/9BvahPLxw5h8aNUPF+RDu35I9Z1TP+z0XXhgzSf7zqV+qh961EMJoRMv9Cwsqm/5YaOC/2yRHc/1DSTmyg/bggYsQfHDsC1o0Jberh8u2oIGbend+mFH+uDAY9gWNFAQ1EXgRUJiGPue61qeiz514JywRE5Y7CV8X5Los+ejTyF64rYZXLAY7HhAC+oBJRi0aqAgN+C5yDbQJ9/27SE0aEnyYgNcXd0fdENOYBsNpWMTxrHn/J7qjtNhptfFk/QMmp5hm420EIyxNWT4DU8H7s26uNf95cBO3MhLiHdoeXkUTy6EmYYJjY2SISxd8gExTNA1rbojKJUEjTpk4r6sbP7gHTAAVhJunZjfFb6c5LQajsbHROcUXbEMajvpSh1w9bEQsV0+XNI+Y3i2Ba2BoWCNxFxwSBj8Dl4M1k8m+RPLLiVFqtUSs3oG0F2E816I+9BajKTCQ3Zm2jz26PjuGFZIlDRJXS5a1U2rowc1BbcJs2LeNPbgeWMRjkEdQQZ5y+1Ae5ju0EM1G8A+yUQ7GDI7uSw5dn+mYa8eOiI34FuyOmg5IrPOks+sRdlQFWLd3u5UdOgNzBgZ5SApk2HbdXuLPpRAZUMp+qF7CBuqvtSlD93ePEzaJZtBR5NPHOZTCP/N/8km6WN0x4TqyTxpoY+VVcDv0uGRGS9FfcS3+TvJaRZjDSWW8aQ6p0KkD9I5a4LAdRzTtZyFkzqu67grx3ZWToo+WY7p2OUT00F/0HcXlbbH6hVvUgzYZGvh2K0JvNXYxsg0scXYAocjEU4o0Af9oB8hUyOTrNRksdAOPYyHooyjE+MYU1WhGQfByl7EyzQJPNdYOMvAdr3UDMpZyDBNQ99N3SA1DM+IY8P37NBLUmNhLpNkMaWpGbYIjpN0mWtP3mV3Ft1WwsxoEnVbFr+1+qELfqg5YAF0zAijCspLhf19MBE2zAXJgsfiywOr+/5A3hQuOjDmPuvuMayGu84EPT0nc5eDvlWzVsMfhrEBxZi7Ya1L1w/t9sNuzKFwEvfjhDOctBaE0pdjaW3VqzV+P9+p1sgpy6OChNMUrNl9EMJHxW38YHtgiLmReh9JLWBC9VTzA60M1pyFFRBEjtzVD3rluJ/AsPidOkJr8mBjTp4ywcZAlJShg7caMVB9WAw/aJHoSMbCvDt4jOyY3t3FyGa7wGi+ho2JIby9wIN0V7UOW1a6udaQLoDpaUf3C96AncgYOoweMO5NQpwGggWMEVpT2kVybyPkQxocpNQetrFjaboiDaM9fLzTWCoyY8ZPJv8ni/+Tzf/JGcAEAvKhWT+k90TWD+k9kQ0iyYdOv1lRq4PDmtU0Y7w0mDSR7Fj7vUkk2dNMWnNiEwUqS7xdlJuLWLSzJaBK+GqGb+/sqSU9drWH0yc3x48RBTitc7kdwXAWIgXzU6c2vg9L3J3cUoBy5mwo/VAjUz64PEu+V7hGBMj7rbZKQBsCRlqIXh4846HN1TDIOYxSzWaDRkdZ7TU5Cd/EWJ3mR54RtJaSkOxswYLD467c6TL1hRLwUqQHmbmLpwRVgoMjIHLHwYHJEleEEZbdBQfbeBvcG9dzVNhoW/jJ5d2VAwldv6dmPX+WsXhn5O+p2e+pWd9G2SlguhCeQFVeAJl+9tPvi7r3dZlXP++7X44vEDm+B5sUTeaWWWOOQWxuEI+NeaspH481j7ATWNghd54vUR7lHuZLqs5Aeq7XH0fDqRP08TN8m3azfsY4ckkfv2HuwQQ8hE/2ysySTrN00b8bRUs1o4fX9v7+/6yYmwpOTvwec0eKuUyeuQOJdliaJEb7Y8bo5rT5JHuiU+EeBmYgnijm/r5NU9Yt/3IyX6aL2+tona3y+dPsdrM5mX9cZ/ti/vS3OVLS/OnPv83jJEmLYr3YpFGR5Nvy5qp5sY93nz7Hu/S0/JSl+9Mkv7nJM/Q938XXWPu9ZU6zfHcTb9b/TqN4udyhVqorrlDW+XS+Xhan6yKyXGP2/cycrVcz/ASXm/1lZj15gn9IN0U6w8KtNvnnaL+Lk0/r7DqqrsFCnG8Pz/DX611+u50/NY2Teb5aFel+/tT6djLfpat0l2ZJGqEGcDkFvku+5k9DJaFrMRFn5rdv35AGzFBJ8V+LJN5sCrHm60Kn+O8oyTOsoD2h9rpA9DHOlpt0R5d7VKTXNynCx/fNh5NZU2G7332Pe4j4/liyZ+xjx5iSHcMUi+Rl/tSolGsbLl+7UXQTr7MoQoxTHz/v4u023RWdr4iBrNjvbhPUuYQWb9KbfPf153j7CwJvoysMkkeyOrF8Qik2Qyu1VOb4kNmsF7t49zXC3wSIIYuNDBhHHzAktzRezEazAmuUx8vn9f5jfruP4t31OHgJxd6tFsoOhhZqNIls8yiRw5cIO9DhJNql+9tdFiH3fLvZR6g1JFVUPRxHSML3GXwhQ4GZywtZ3ysZIcMdRyjvKFTAFcoxbHmhqo+nxb92ZPBa7fKb2dHot1+RrWWnNzFC5+1+vSlm65ttvtvP1rjeh+zXeHObIiGxF6o+/3H27uLl6/MPWVwUKSpYPUX5xuzJkxmK0Sez1Yd5+fD738p/viFaM2TPxXqZzvLVbP8xnZWXd85+RoWrNOXx6Yf5gWJDCRGtm8Kt7/J8jxnBfD0qCUvr2u/xhZTOygZxQGnpslID+sGq+8YU5IDygGt114BIC47S+3yk2QpI40uzT4t9VGd1yDfES/Tjep9O4C0cA+ItHLX8XSonWKbbTf5VkA1UBUbOA1z9PKDik84AGiPwB/W6JWw2ORIKIQTLNQVgQOHFtcYHDGkvAtiQxUYGj6cPHpJbGkJ2rVlv0HyrhFCG/kqXEZnAToGkAIIkb4LhSKP00ukCoFSWGxlLfUFYViwaTE6tXJGdKoJph9xfjPhMNjE1CzMccFxydM9STi3cCM628u0TGIfrgoxD4AuGMg5ef7aNgyo3snEE+sZBsUsbh1spVwSfYwNJvN7lDXU8PqC02vn1tEre8SxdhAZN/BFHpyY97oiLaJ2hgceH7A+z5/lulyZ75MWLWXnR/+lxQFKVe3QYl5xUY4XH3PEJLvn+3bvzi+jZ2/dvXqBhyncy45PvapbiTXK7iffrPJut8l1ZuGoIPTmtRiof19cfT8r2UM8jVpfrX2/yJckq/nj508sfrmTxEYqNR6KDSi5LwEnUQZyWDlyiSj1a8mro2f5ow4tf43GmF13SKC2P67N8d3jZmmnaZh58AgftmRAHHRiDBthVno8jjAuZ6gu8u1zF+cPsb+luvfra+JLbmy12JsgnZZUvSit/U3xcb2eLdP85TbPaLZ3Mzl68qB3aDIWryvUhN0Q8ruZuiAdtB/moXin6C0nsL99XTZiPS7qPrNmT2aFc7WnLHz5ks/oPURuVnf1PXexk9uFDVei7jhYePZ4lcZbleyTX7LZIlzM8TVpKndwi35/tZ+XiQYz7/7vKu66LqEBUNowlL4ID7WUv2fA72rJXKSzmDWMVMYWiVLZfr9bIcKg5q2fVTOWz6m05+Kcl8iDrrMQOTmvYPrv8EjXv2GlTOZnvv24xSBFbcTH/RsyF/XD26vIc3Mwizzd1FQHNn+Lio6YAJAlBS+S8btlSgroAdUNp8+mXfbrL4nIFZ5vgiUP3QGp1myUlQxxqp2e767JjVrco7criG1yJX/AEO7tF3Zdf8F+VPE1r6WY/p/3x175C5jdUqkAoQi7vwHa1AMdl+uXNdrNO1nsw81QFSoimVJlxtjhVweATSv6DaCZUtIsqVLZZKUNJ/Rn/g0ZAq3W2Fnbt5cv/O3/7Q/Tq7XMEZEyxrl/6KESuznUMsj69iCwANXAZWoBpcp21g+nWIiyGtRWaYlgTdcSw7hSkENGEPAC4aw0OA3CSKxDAuRUocaghFYNTFcCSLWsCliSlAth6uloFqXVVAURxntfrbv0wEOMSURHj8VCA7LhDTxiinsBVQWDpFFRrS7O3MQmVXr5Ou4MLYJ+jb3lx2q7cfcBsQoANau+ECvwoAoKGslvcTejbllAW7t5iGycpp6gYcO1y8lggKEyXBRGNgjDPK68lrqYFEJRUDIGoXmXqLe/UxErXEPukFh0wXI6FqSDzKe3N86Cxpd2YbE93K1GcNq/k1Ej4CLQ+aSUExFs+uQFXITVoi8fDIPJZT2e4DXkwlnQ1EfkRKcYC+wBcuq4Cs/nurISM2+VObcAaL1c3edbmOWBrKxcUoVg+Fp7A2srGZK2tW2kiazPlrQ3PqClmw7aMDnnWWVqPqn2WlDXtk1qpV0lZKAIwu6HXdHUarSjAWiVaY5ir35OwtwmB7ZUoLW+wAw8nO2zJmjaj1n+1bVf6GC79q+ipmDS9FKxiUzQFgU1Ru2YBU49Oj2lR9MR2xShK4Q+pcqgoSDcFMhRBFfnhBU1MkN2hn6UCCE1YBWvlBs/efneMnrm5ciuqUKHHElQvg3witJ/LNkDd2y1JcSXpnaT40/QwJQ1gT5uditUuYrY0fEWVtYgFqKJaoNx2V7I4e5srDNkHxuY/J3Gxf7TanpRof/L4lzle+az5ObTTFVwIF74AVTVVCYxvhBW0JZj9afboz/ZjGUGmStMmzM2q7QHdxQWmU8HR/3OU3+63t/vGw3iGL/Yw3RbE/oZXnrJz/HvT8cJ8Ap/jagpHm7Rrvox8hTWh2ZciNqJHRbpJm6UTYLroiFwPQx0gR9lXb/S1CAYD/ABa7c7GVKswejKrnz2tzRPmYxltqsRW5p4ZwIKDAzKF9gQ3oBuZVWiDwAljhGdt+oF3Qq7iRXKmxKgINatqWQcl2UCzwifQinjDDXsMQLr9gGyrUsKYhFUf/mQmW0iezbYLSqW/7KaUTZVcaxQZqOdZAAOtz6f0A4IsqGiMxl0ZY2dHIMTSzIMVR3g3bvTvdJf3W7GEddYahdskq8I0ka1ueTzzqBtQNoruOig4p3NCSCCjznP3d1W3+IQZnZRBjpLCUeLDAc6vNg3Mqfanyd+oJtXhTxz7A8yTeD3rsh2aEMR3isvPQHUJSWCHW20IPnhgiBsELJoPSfNh2XyQW23ptq2MCsZJvn5wuDYEHAzSAIxwa6k5R0fSOdrSzhFxKjHGPZnXAkKrWDLpAkt5cPPorT2Nh2WxMeBMM7cNlalIxgHG/qTbgVgPfdysv/MY5ZVTcInOopuFY01QbxqU0QxoTmUzKCp75O6tDoBobfXs6+BQBuCKV+le7ETmcQjHYV/lacDI4GJoj8doQhui+GRg/ySgCZljIEhKgPJQWjF/I+nIY6ZT679v10FHH0M4UpKeCkYPV4L17wLAV5aJsNmQEmOSLjXW2v+hFRBS2aXl7eRAR7NnD3RUe7S5ua6/U82eU2UEtf5+pQqqqa8hAe43ZgW9tgfovYaUVAdyrnzr78TA5nQimyKnI0WFJRTKISPuUEglfR54HUt4+2aSgYxIh1kpOo4cpiqOhw2f8u6YEJ8uPJmpT35xRB0AeKfND8sIo6q7leCAeBKtrO0CbPr0PQKnqHOTrfDMF33PQ1m8qdXTqvypRN4cNptov0UJTyfC0Qw/TgippM8D2KKeqJtU9WgQC1E+l8ihAbYQEmNwrE5oIcBDkbwUkKbUbw4qhyNb1cHw1zkk2SIzQQAZEO3S5zJbdcHoxuDpx9eEaJbd4OwCcA3Z5CwuroY7mW3MsGpD8PGwLEFjxzSXCtg6aDDKILd101Ibxwf08ubIYXQlscyqrLONurrkZh+xJzs7c3iMmQD2tCeQfzWDEhEZwLxa5Lnzm2wratbvyO+aNtNiSGr5B0hzzHgAPe8AyPoFZx6YpdTQADjTICyt0erD8uwyByM6Dr2sDPbjJYgAQJsQ1/ob8Lnzf8JW+g0AshEfDkzpfewSdQfj6IGNhXW3u4tJga2KAWFp0E9ucfK7+z0PamewHf6wajrYltvrLld9SL6U45X8uuId2ajWVvdeapKWCrlMSfIGWc64xncB6RiAvqIFTTzO4e/5VhnxQCTSM+jhR0CQZu5kJARhTHVEBKE9ejwDH4EJADMN/cdgRIU1oAM6/wGppM/DQ0wFVY6McGjIhRTBjY2gN0Rwwofn824vgFCVgu7DDxVMOVQsaaSwwCR+d8GAyY5WCGBSHN3xaxzzcg3ozAHgUEN/FQ3sSOzwh1cdip+HGCnUz1gJKclFjd6LVkVtTW5ncufJAt4OdRFdqGnpnCsTEpM0rSHOlwmJPqyJbM1zakJKkpZFglUW3bDczAHnZnzaCngfOk9zxXma5GFGRvLmSaNeK4WDEhrIQu9NOidgSiupE9AdPeSoHVb1oVNu8AOr4JoaqJI/yylNYWDuHmLep3EQlB2kWATlYhUL5YrWAYtcrse7C1O6CXV7eYBbcICiaBvtSGGrv6W7i179vGkFsX7yo8cy6UPj0KkJyMFxQB0NYMmcCZeoOxhHDzFOaRwuF5OSi0391zELW5vayJTO0ju888r91IHmBjlTL4lw6UPwsgSG5e0hmqDuCXoAPTljZKBbzSiAExw24EgmqAVlM3moSWKvJLq2OlKK2NvQ3WWIvaxpJYi91CcLXbA7Nmzo3GP/PRu9NQbAU/99G+CaA3GjHpAeypY75Vs1RITUAhbGtKQNTGh+EteH2IBUsecKEW5JNWADLwnpraHZ+sNap1K7m4RFAGwPB5ABwTgx/iUuWwFsAu+/cEVUWB2KsItXIJX0eXh4FqF73wtJQ8ouGvDBcTqudXCqLfJ8c/oD0sm5WCmi6lcX7wW1TX5t4eUrbYwr0aDGVV/6RlJY0C/lDSi9L5CzyqL5rr+kU5b8AimK723tLWSK71KFqek8ebvV0jNJgFJy701hWB/bTiFOq2kSbfN1tkftvcP/tjrrXwPQwT0JvttOQMc99ouv0S8VWajVM/gBGj4/tVcDBP1SaXI243DXQ689QexTxj5Yt/7BpPlrmiTxJy2F0CQolawzvF8TCLlPJR00jIj3KU30Ej9qqafeCzo47YC434+1+UVBJ1UTUKT3s6oG/Hd5ka6XeabV120i6r29rSnVgrYI6/e4HH1bvONJSTly3Q7jV63rL9fXqPnbnV7G0aFCh8O0KNDoHzKHu71dRHLvmmbN23KYXq7xsYQkwQcLX6DPZ+VHoMScyiov3c3Sz5yJakZA2O7SX2Gl1Zx+J3rC1MEIurJZpkwUk+jl8iXvrVAOMjNhMAdaF/GGec7iC/uQWi855nAbWOt+dU3FmGgkL1mbEg//Psa7yY6RX0lc7vIK+BLw/jYkhvcCYnWQuUsDIlg4BEogPjpV6Vcn3O52abYHvxEkiz7nu2UxnjHU7F6n+2i1LQfdW8acCofALr1eF3skWqu+iq4JlwVomfByqo1FWIfd7VK1k7QM9kZGGdqyHpNDgAIQ6E015btk0ux6D3hhpSZwCGYVHWoPoXvtW7u889wsLqLpZLuNDepvj3SjLI+28XK5zrqz9rV5mJw7tRWb0baUDq2O0URQgzipisNebXAyL/su3oA8uqWUH/cKPJThcWk+LBskxXiV59tXeRJvBlMMQbEd2YEYkATYOPpWG6r1amdK90e2K7FDR7WJ8ukG9T4mX/rA8Dgbs4kX6UZGAJThbErtc/wr56SRJHktv0rR6LqAsqgMMFnZ8QguoGF7CK/IpPVwvGHD/lRW2bQ3fF6CmeHaCueNZRKkdezkWB+8si9DeQAYd+mMwqkIZUdvwd3lxnQPg+Cy5A6ISQtO9na7jBmnABpU2lqorIjr4JKkoJoNSyUrZpOsjBkZNJKVWiEDGBSL0oOJCjXzPGvFSwN3brE1j2PZbFSghG7DN13OjfEqbehbMEVokjQMDWr3ae8OkmGmjmgZB7NNJsEHZqKNDA/AUhtWRzPYcu8qfpB8jJv1AIbhcq4R1mlrAANmEfw9InP1M5wTEBF+aM6gJctDcAotlvVHhX27j2Bg6d/DRL6n2YAs0xUmZF65sCDWXdh9pfAG1cLpK4V3eBZuXyl8R1Ph9ZXycCm/r5R/xHsAx/tNvP943PsMWv0jtkuDV//KZpo90vBWyhpyjcRFke72keUa0YIxazH/lOWfsyjeRsgssuv0+HJrmdjFaEkmUnGrU+AHbfpR83IsBn56+eNP0bO379+84HsH1za90DTDwDbt0PNsJzQ907WswHJM0zJtP7ANR65ZhXjTS0bnJPFwCuUFCSUnz2rg8qeXP1zxO8t2DNQxtueFlhHagYO6y7Nt3/EM37FN3wss03RcT7JN7TDCovr+3bvziz7wmYERWi4CnmPbtuG5rovwZ1sIh47hY6EC1zMsw7cd2zUNxzCQtIFpm6bnWo7vGibShWN5ruFZkhj9uL7mpoaKeC1J4jPrq3SXZkmKfdNvc+SW8OXJn1A+HzV7Da53+e12/jSkY17js2rdzH9O4mL/6OfVdvan2aM/O49/Qf+aJ/VxoV/m3345YO7QpCTaNvnngXWAKY6pgkHFF3pjRQVUNAdXQa0B+7GyAiA7jmG+GrZ3+Q5TPpWRFL3zKt72JzUbFIRw7e16k+5ON+tFlwY4zeHt+9JmQmYLGUAgcOoFyrz6GwRlYFAyyms0gAZkUh5ZcmPyzUtoUI8iBwQ6m6rQqkbGAQc8Z0oLNqEFbmYQhLaojdbhx3aGxCuH6gRS8NC7ItF7Mtsmo4H5yIsSpstPWbpv4kB9qcbp2YsXvbnzn03D803Dt0KUB7u+7aJPgWsZgWMZZui4toESaZQ6+yhtdiyUWgdB4AaoSugEIYiL12f/iC6v3l6c/Xgevbw6fx1hGQWT0K2BB48sazgPOQnOmAoQBTVe81m+uyl3VfDfpseJapxr8hWa7PEaknSoZAv/MtiAGM4IzKEo0ptk8A/nTXDyQ27zD7zJQb1Ll7wINLo9WdKWGRCZRndEhE1vgBERnOt1gZ3MWDqpqatqxaq1YhodtcSVWszx1FLc1Fe7j6SYir6qaswGMN44mqluhClOkR2+ip6/fXN1cfb8Kro8f3X+HEVKQXA0Ate2fNvxXcsyHN9yAs8MTT9wAqvHag9Nor+fE69dBuqaWb11lcG/blEEFqzVgYhe1GRo60XdukWq6M6zSFOv6ShcTSHFvp5mj0ogt7KjAqBzRngSsykcFfV25r6VK9bbgfumUZr8JSrSTZogcwQtpAHLGtCrXOQ6XrdjDvihoL8HdUx9GSm4X8Cn2bm8v0Au5cezq/Oo9DQAB2Oanu+GjuEhp2JbhhdYthmidN8zHaCDOTT5yox+Onvz4tX5BaRh5NYcNAIJDCv0rcApZ+ZdDw1DwsCz/dA0Aw+xYVlQJt69evtPQLvIkRqW4wUuXhMxgcQPLx6VRNKL5p2Rw7jNitzwDrOh23GV3hGPoSIeKZZVNch2j+X145CzPmbl7irG810k51gZFZWdbFTEsNt/6hctrnb5TfTvdJeD9g/IO1rxPSZQwKh3K8u5kgqHOlqr1VEyTtdUCIbgfVd8DVDXjoCmMrgXj0jMZjTNn79+eRWd/+38DSQLNa3A8I3QRu7aNWzb9Z3QdwJgQzfr/fmvqeg6EUBd+bPXTrNBb5N2x9wMS/2UfmX3ehtmuCCEqDlp6vPj+VX0DI3z/xq9ef/6GSgCm44TGEFoophvu65lG4bp2IFvWLbj4tXzoGdertv01cvX55dXZ6/fQeI/CvROaNi+bXmW5zlugLchIDZc3w/80PLRv66JHsCZwCkPkhzPgp5fXgJ4wAzgZMcPTBuhG42qHMdykVYQ0n3PDUzD8hxbgoFmYAdnwbNMxIVre0ZguE5oOijlQUKHvmEihvAGBTO00FjPCCT4uDz/3/fnb55L6cJ0Q8QKasZGcodoiImU4NqIqcAKUX7omfgnzIiLQQLn5eof0cs3P7yFcGCjRq3QDhH4yk1EiANLQmrU0uXLH9+cXb2/OJeAvxV4CHWOYfhI9yjvtSzfR19CH9p0un+2yZNPb26xg1Lwci0CQyWLNNnhk8Y2/U7yCD6YICmCroaZyaSCp5acF+7Rm75UrFxqgQtE2QGa04h2tb5BCo5vthpSHWkMbRAHyuPZBNHEiGbREWQAbd8T4+gqcBDZ+CayJyE7uox4hindnR3HGvKi0SQGtBGK8Cgm0mphHAthiqGv6bu3D7b2hpCMORgviygMizUErMfieubRIjKkgdCkxzGRdhsjGQlblCE0fg8MhaPDYaTjzFypziKpi3mJFZ0lmuGkQ2VAg2nTHsViuo2MYzI8YQbR+t0bDVeNA8nHMpuiKTWp3Vx9eZmtcjW56roD2khFcRTLaEiPYw804xravHvstxSlJQsL5/sv0bqGnGw3VmSVDjWLuT3c164q7pHAoNZwIDuSSRD0RXahuLjDFkFXw/fBQrp605eKGRNIXPbusTiUhizM6G+yePXy2cXZxT+rPRZSux4c27Ns23Et33XMMDBd3zdc3/Es1/CD0HV91wzLQ7SOZ3quB1z8oPgBLHtYtu8ZlueHjm35hmn6eDe46XnADR+v1otdvPv6vN7QJ9n7ZO2hXAZB8wFuJ2Nwr6XWu9hMJrUX455vI7s4f/fq7Pl59PzVGWjpzHJdw3AM2zJ9x7FtP0Dm7Rl4P5XnAVfKLtLtJk7S51iNCp1PVdfYJKOgY0UXenn+5kX0+vzyEp8SuXqLvSjEe+KF2dAIfC+wDduxw9DwzdAL3NBybB/5UuiiXXM+5eL87AVkrdAwgtDwQtS5Bu5ZD5+NMQIL7DKb9v5+8fIKsjhpuYEVoIZcwwp8x3ANLKHneVbo21AR02z5unrfzlX+yrz8Wig6bA4hCmbb+Osmj5eg25Aw/015iH+RM34Exxy+pfUAY0cRxtWW9Is0Xqpolqg9VCgkaA4fCininUgIPkItw7yWVpmRUGK/84T+kKFZTdFZafWwN8n08fH33Vp0PQCs+vh9dwJTiz68laecWPNNcZLkt9k+UtnHX14EFq2XfWXxDrCb+Eu0SkFeOsvxSZiegj45XgNlo1KjOxxdkD6yIq5STEjqgzfP/orUWu6+BNuG+G4tbl/ivw+dhptj36Ute2aUSV72wKiAiNpgwpYdTFhKm3EVhhT6sZ9WkuJJVgAxel7k+G7xXuXr+3GaK/4B1uNma5XXlEszMsyxVjZtiIK1+pZsQOa4ot093oq9BPN4q9+cViyPK55A6TanIM3wSJe6Sskvb5Pym6OQOichl4czNSz/Z/fdt9FDV9XxkbUVx9HGN8XDJjanorLfBB02KV+0JHnYxNGeYqn1rOk0WVTu0FvW7PDcZLt7NA/9t1od1ifWREdwhgzKMl7Q7XpBu3Nmu/ZWgYQXdLte0HE4XjAovWA4hBfcVLO2pa3zfGHva1VA1FU9YpfGlJmglNe9gxyQ0o6mN+PTukOfRjF1hwkgxcewvo4iPYLH49KX8XtO1+9ZvMtNZLI/p+v3bHP87G9XLVhESbPgwbxzTdnxUeRVPR+DiHJKqGuGNC+ajkZA7A49Dc2V7pXJwGaG9SQ07RFcCb8BGV8SdH2Jx/MljoQvCbq+xAs4vqS6l9gawpfU1wJFu3oRhuVKnL63SIOoq3qSLg2VSW19E6P40HQifFp36EMopngupMTjQIMvqsFhnQlFegRfwqUv40q8ritxggFcidd1Ja4ldCX2kK7kc7NwxfIlrvLcFEVe15kQRNS8CXDZS3+XMM3xQH6HQeweOJ6Kq9GSF7qZcfxNRXtEh9NtQMbj+F2P4/ImgFwJj+MzkhfeQMjV8TjoW16cticDuw86l0m8uzj/4eU/+P2Mr/DwXNt33NA3XAdfn2WFhulYvmEHIfpmG64beq5n26ER+iG+y8UK/cC3TO7FvlBmiTdvVW4TcJ1NhSnWy7uOZiK+0gbKHb5ymbWoyJxtM0O4e9dhAO7/9VuZ+t4s7aWMapYYfiKo3CYAWO1Q2RyqpX7paDdca5O8We9E9mJllXRCSyejL8docacbw6GNUy+GB7to3pvlh3bQrXfLK3BWVh6DK/Lt4gp81dXH44x6h7Iygw2VEflkvTpWnd8WtYH55lz2z2a3k/By3xjQ5rLcXbfOoiLJy8dRVH6NUMHtbl3GCONLYBB/TNOQ+2OSyTUinyHOSh999xtPxlrSGGuJeKy5jrFGNGNN8yq/eWwAsux3ug1LuPW+PDFx9bcOwOnKXU4Ppyv5PoCebWQMGDvGALiwGSNzx7C7hMkL+r99+3+dhf/IHYsBAA== \ No newline at end of file diff --git a/crates/papyrus_rpc/resources/casm.json b/crates/papyrus_rpc/resources/casm.json new file mode 100644 index 00000000000..b031f456333 --- /dev/null +++ b/crates/papyrus_rpc/resources/casm.json @@ -0,0 +1,17050 @@ +{ + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "compiler_version": "2.4.0", + "bytecode": [ + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x85", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x9d6", + "0x20680017fff7ffe", + "0x6c", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0xa09", + "0x20680017fff7ffe", + "0x58", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe87fff8000", + "0x48127fcc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2cfa", + "0x482480017fff8000", + "0x2cf9", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fca", + "0x604a", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe37fff", + "0x10780017fff7fff", + "0x26", + "0x4824800180007fca", + "0x604a", + "0x400080007fe47fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fe67fff8000", + "0x48127ff47fff8000", + "0x1104800180018000", + "0x9ff", + "0x482480017fbf8000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0xa4e", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fe18000", + "0x1", + "0x48127fc57fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffed90", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xa2", + "0x4825800180007ffa", + "0x1270", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x9f7", + "0x20680017fff7ffe", + "0x89", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x96e", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x74", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0xa20", + "0x20680017fff7ffa", + "0x63", + "0x20680017fff7ffd", + "0x53", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2c53", + "0x482480017fff8000", + "0x2c52", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff2", + "0x3458", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x21", + "0x4824800180007ff2", + "0x3458", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0xa36", + "0x482480017fd58000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fed7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffee80", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x9b", + "0x4825800180007ffa", + "0x1180", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x977", + "0x20680017fff7ffa", + "0x87", + "0x20680017fff7ffd", + "0x77", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x40137ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x96b", + "0x20680017fff7ffa", + "0x65", + "0x20680017fff7ffd", + "0x55", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2b9e", + "0x482480017fff8000", + "0x2b9d", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff2", + "0x3584", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x23", + "0x4824800180007ff2", + "0x3584", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0x9b0", + "0x482480017fd38000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fed7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8d", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x62", + "0x48127ffa7fff8000", + "0x480080007ffe8000", + "0x1104800180018000", + "0x960", + "0x20680017fff7ffe", + "0x59", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48307ffe80007fff", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127fe47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2ae7", + "0x482480017fff8000", + "0x2ae6", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fe2", + "0x2422", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff27fff", + "0x10780017fff7fff", + "0x25", + "0x4824800180007fe2", + "0x2422", + "0x400080007ff37fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff37fff8000", + "0x1104800180018000", + "0x957", + "0x482480017fdd8000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x83c", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff08000", + "0x1", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fec7fff8000", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fe77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x3", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff0ca4", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xe0", + "0x4825800180007ffa", + "0xf35c", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x924", + "0x20680017fff7ffc", + "0xc7", + "0x48127ff97fff8000", + "0x48127fa97fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x40137ff97fff8000", + "0x40137ffa7fff8001", + "0x40137ffb7fff8002", + "0x1104800180018000", + "0x995", + "0x20680017fff7feb", + "0xb4", + "0x20680017fff7fee", + "0xa4", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x1104800180018000", + "0x757", + "0x20680017fff7ffe", + "0x90", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x751", + "0x20680017fff7ffe", + "0x7c", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x74b", + "0x20680017fff7ffe", + "0x68", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fb87fff8000", + "0x48127fb87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2a3c", + "0x482480017fff8000", + "0x2a3b", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fb6", + "0xa654", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fb37fff", + "0x10780017fff7fff", + "0x36", + "0x4824800180007fb6", + "0xa654", + "0x400080007fb47fff", + "0x482480017fb48000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fb47fff8000", + "0x48127fc27fff8000", + "0x48127fd07fff8000", + "0x48127fde7fff8000", + "0x1104800180018000", + "0xd11", + "0x20680017fff7ffd", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fb18000", + "0x1", + "0x48127fb17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202335", + "0x400080007ffe7fff", + "0x48127fba7fff8000", + "0x48127fba7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x400080007ffe7fff", + "0x48127fc97fff8000", + "0x48127fc97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x48127fd87fff8000", + "0x48127fd87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fe77fff8000", + "0x48127fe77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127fa77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffed90", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xa2", + "0x4825800180007ffa", + "0x1270", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xdbc", + "0x20680017fff7ffe", + "0x89", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x66e", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x74", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x720", + "0x20680017fff7ffa", + "0x63", + "0x20680017fff7ffd", + "0x53", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2953", + "0x482480017fff8000", + "0x2952", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff2", + "0x3458", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x21", + "0x4824800180007ff2", + "0x3458", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0xdb3", + "0x482480017fd58000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fed7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffef02", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xbd", + "0x4825800180007ffa", + "0x10fe", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xd06", + "0x20680017fff7ffe", + "0xa4", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x5b8", + "0x20680017fff7ffe", + "0x90", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x5b2", + "0x20680017fff7ffe", + "0x7c", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x5ac", + "0x20680017fff7ffe", + "0x68", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x5a6", + "0x20680017fff7ffe", + "0x54", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fbb7fff8000", + "0x48127f9f7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2897", + "0x482480017fff8000", + "0x2896", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007f9d", + "0x69dc", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fb67fff", + "0x10780017fff7fff", + "0x22", + "0x4824800180007f9d", + "0x69dc", + "0x400080007fb77fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fb97fff8000", + "0x48127fc77fff8000", + "0x48127fd57fff8000", + "0x48127fe37fff8000", + "0x48127ff17fff8000", + "0x1104800180018000", + "0xd25", + "0x482480017f888000", + "0x1", + "0x20680017fff7ffc", + "0xa", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fb48000", + "0x1", + "0x48127f987fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202335", + "0x400080007ffe7fff", + "0x48127fbd7fff8000", + "0x48127fa17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x400080007ffe7fff", + "0x48127fcc7fff8000", + "0x48127fb07fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x48127fdb7fff8000", + "0x48127fbf7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x6b", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xc35", + "0x20680017fff7ffe", + "0x52", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127fdb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x27de", + "0x482480017fff8000", + "0x27dd", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd9", + "0x24ea", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff27fff", + "0x10780017fff7fff", + "0x20", + "0x4824800180007fd9", + "0x24ea", + "0x400080007ff37fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x1104800180018000", + "0xcdc", + "0x482480017fdd8000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff08000", + "0x1", + "0x48127fd47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffffd9e", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8e", + "0x4825800180007ffa", + "0x262", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x46e", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x75", + "0x48127fff7fff8000", + "0x48127fee7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x40137ffa7fff8000", + "0x1104800180018000", + "0x51f", + "0x20680017fff7ffa", + "0x64", + "0x20680017fff7ffd", + "0x54", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2752", + "0x482480017fff8000", + "0x2751", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff2", + "0x33f4", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x22", + "0x4824800180007ff2", + "0x33f4", + "0x400080007ff07fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x1104800180018000", + "0xc7c", + "0x482480017fd68000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fed8000", + "0x1", + "0x48127fed7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x4f", + "0x4825800180007ffa", + "0x0", + "0x400280007ff87fff", + "0x48297ffc80007ffd", + "0x482680017ff88000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x26c0", + "0x482480017fff8000", + "0x26bf", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x79e", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x16", + "0x4824800180007ff7", + "0x79e", + "0x400080007ff87fff", + "0x482480017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0xc1d", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x480a7ff97fff8000", + "0x48127ff17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffe3cc", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xb9", + "0x4825800180007ffa", + "0x1c34", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xaac", + "0x20680017fff7ffe", + "0xa0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x35e", + "0x40137ff07fff8000", + "0x20680017fff7ffe", + "0x8b", + "0x48127fec7fff8000", + "0x48127fd07fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff8001", + "0x1104800180018000", + "0x410", + "0x20680017fff7ffa", + "0x7a", + "0x20680017fff7ffd", + "0x6a", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0xbde", + "0x20680017fff7ffe", + "0x56", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fe17fff8000", + "0x48127fe17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x263d", + "0x482480017fff8000", + "0x263c", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fdf", + "0x364c", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fdc7fff", + "0x10780017fff7fff", + "0x24", + "0x4824800180007fdf", + "0x364c", + "0x400080007fdd7fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127fdf7fff8000", + "0x48127fdf7fff8000", + "0x48127ff17fff8000", + "0x1104800180018000", + "0xbe0", + "0x482480017fbf8000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fda8000", + "0x1", + "0x48127fda7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x400080007ffe7fff", + "0x48127fe37fff8000", + "0x48127fe37fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fea7fff8000", + "0x48127fce7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x56", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x258e", + "0x482480017fff8000", + "0x258d", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0xdfe8", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x1f", + "0x4824800180007ff7", + "0xdfe8", + "0x400080007ff87fff", + "0x482480017ff88000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0xb69", + "0x20680017fff7ffd", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x5e", + "0x4825800180007ffa", + "0x0", + "0x400280007ff87fff", + "0x48297ffc80007ffd", + "0x482680017ff88000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x2523", + "0x482480017fff8000", + "0x2522", + "0x480080007fff8000", + "0x480080017fff8000", + "0x484480017fff8000", + "0x8", + "0x482480017fff8000", + "0x578d2", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007ff4", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff47fff", + "0x10780017fff7fff", + "0x21", + "0x48307ffe80007ff4", + "0x400080007ff57fff", + "0x482480017ff58000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0xb8c", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ffa7fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff28000", + "0x1", + "0x480a7ff97fff8000", + "0x48127fee7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x56", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x24b1", + "0x482480017fff8000", + "0x24b0", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x4586c", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x1f", + "0x4824800180007ff7", + "0x4586c", + "0x400080007ff87fff", + "0x482480017ff88000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0xc6b", + "0x20680017fff7ffd", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x78", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x152", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x5f", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x14a", + "0x20680017fff7ffe", + "0x4b", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fec7fff8000", + "0x48127fdb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x243b", + "0x482480017fff8000", + "0x243a", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd9", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe77fff", + "0x10780017fff7fff", + "0x19", + "0x4824800180007fd9", + "0x0", + "0x400080007fe87fff", + "0x48127fe77fff8000", + "0x48127ff67fff8000", + "0x1104800180018000", + "0xd5a", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x195", + "0x482480017fdb8000", + "0x1", + "0x48127ff17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fe58000", + "0x1", + "0x48127fd47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x85", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xc6", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0x6c", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0xbe", + "0x20680017fff7ffe", + "0x58", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127fec7fff8000", + "0x48127fdb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x23af", + "0x482480017fff8000", + "0x23ae", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fd9", + "0x2d78", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fe77fff", + "0x10780017fff7fff", + "0x26", + "0x4824800180007fd9", + "0x2d78", + "0x400080007fe87fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x48127fe57fff8000", + "0x48127ff47fff8000", + "0x1104800180018000", + "0xcce", + "0x482480017fc58000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x103", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017fe58000", + "0x1", + "0x48127fd47fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fdd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fec7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x37", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x8", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x480080007ffa8000", + "0x208b7fff7fff7ffe", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffa", + "0x400280027ffb7ffe", + "0x400380037ffb7ffc", + "0x400380047ffb7ffd", + "0x480280067ffb8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffb8000", + "0x482680017ffb8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffb8000", + "0x482680017ffb8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffb8000", + "0x480280087ffb8000", + "0x1104800180018000", + "0xc12", + "0x20680017fff7ffd", + "0x31", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400080007ff57fff", + "0x400080017ff57ff4", + "0x400080027ff57ffe", + "0x400180037ff57ffc", + "0x480080057ff58000", + "0x20680017fff7fff", + "0xc", + "0x480080047ff48000", + "0x482480017ff38000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080067ff08000", + "0x10780017fff7fff", + "0x9", + "0x480080047ff48000", + "0x482480017ff38000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480080067ff18000", + "0x480080077ff08000", + "0x1104800180018000", + "0xc00", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xd", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffd7ffb", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff7c", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x26", + "0x40780017fff7fff", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x480080007ff68000", + "0x1104800180018000", + "0xb93", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff98000", + "0x480280097ff98000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0xbba", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400280027ff97ffb", + "0x400280037ff97ffc", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xd", + "0x480280067ff98000", + "0x482680017ff98000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0xb00", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x12", + "0x4825800180007ffd", + "0x10000000000000000", + "0x4844800180008002", + "0x8000000000000110000000000000000", + "0x4830800080017ffe", + "0x480280007ffc7fff", + "0x482480017ffe8000", + "0xefffffffffffffdeffffffffffffffff", + "0x480280017ffc7fff", + "0x400280027ffc7ffb", + "0x402480017fff7ffb", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x11", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x482680017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x400280017ffc7fff", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574426c6f636b48617368", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xc", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x6", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x10780017fff7fff", + "0x9", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x1104800180018000", + "0xabb", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x59", + "0x480a7ffb7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff96", + "0x20680017fff7ffe", + "0x4e", + "0x48307ff080007ff1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017fef8000", + "0x1", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fec7fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x29", + "0x48127ff67fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff79", + "0x20680017fff7ffe", + "0x1e", + "0x48127ffd7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8d", + "0x20680017fff7ffe", + "0xb", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fc77fff8000", + "0x48127fdb7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1f", + "0x48127fde7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x2d", + "0x48127fc97fff8000", + "0x48127fd07fff8000", + "0x48127fd07fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x34", + "0x48127fc97fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x42", + "0x480a7ffb7fff8000", + "0x48127fbb7fff8000", + "0x48127fbb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc7", + "0x20680017fff7ffe", + "0x3a4", + "0x480a7ffa7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe43", + "0x40137fe07fff8004", + "0x20680017fff7ffe", + "0x371", + "0x40137fff7fff8003", + "0x48307ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffb8000", + "0x1", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x32c", + "0x48127ff47fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0xa87", + "0x20680017fff7ffe", + "0x323", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x40137ffb7fff8002", + "0x1104800180018000", + "0xaa5", + "0x20680017fff7ffa", + "0x2ef", + "0x20680017fff7ffd", + "0x2c2", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd90", + "0x40137fef7fff8000", + "0x40137ff07fff8001", + "0x20680017fff7ffe", + "0x28f", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd88", + "0x40137ff07fff800e", + "0x20680017fff7ffe", + "0x25d", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd81", + "0x40137ff07fff800d", + "0x20680017fff7ffe", + "0x22b", + "0x48127fcb7fff8000", + "0x48127fcb7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x40137ffb7fff800c", + "0x1104800180018000", + "0xadc", + "0x20680017fff7ffa", + "0x1f7", + "0x20680017fff7ffd", + "0x1ca", + "0x40137ffe7fff800a", + "0x40137fff7fff800b", + "0x48307ffb80007ffc", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffa8000", + "0x1", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff77fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x184", + "0x48127ff17fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0xa3c", + "0x20680017fff7ffe", + "0x17b", + "0x48127ffd7fff8000", + "0x48127fe47fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x40137ffb7fff8009", + "0x1104800180018000", + "0xa5a", + "0x20680017fff7ffa", + "0x147", + "0x20680017fff7ffd", + "0x11a", + "0x40137ffe7fff8007", + "0x40137fff7fff8008", + "0x48307ffb80007ffc", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffa8000", + "0x1", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff77fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0xd4", + "0x48127ff17fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0xae9", + "0x20680017fff7ffe", + "0xcb", + "0x40137fff7fff8006", + "0x48307ff080007ff1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017fef8000", + "0x1", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fec7fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x86", + "0x48127ff67fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0xacb", + "0x20680017fff7ffe", + "0x7d", + "0x48127ffd7fff8000", + "0x48127fce7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x40137ffb7fff8005", + "0x1104800180018000", + "0xa12", + "0x20680017fff7ffa", + "0x49", + "0x20680017fff7ffd", + "0x1c", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x480a80047fff8000", + "0x480a80037fff8000", + "0x480a80027fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a800e7fff8000", + "0x480a800d7fff8000", + "0x480a800c7fff8000", + "0x480a800a7fff8000", + "0x480a800b7fff8000", + "0x480a80097fff8000", + "0x480a80077fff8000", + "0x480a80087fff8000", + "0x480a80067fff8000", + "0x480a80057fff8000", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fe87fff8000", + "0x48127fce7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fe37fff8000", + "0x48127fe37fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xd", + "0x48127fe47fff8000", + "0x48127fe47fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fcb7fff8000", + "0x48127fcb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127fda7fff8000", + "0x48127fda7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xd", + "0x48127fe77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x15", + "0x480a7fe57fff8000", + "0x480a7fe67fff8000", + "0x1104800180018000", + "0x7d5", + "0x40137ffc7fff8001", + "0x20680017fff7ffd", + "0x12e", + "0x480080007fff8000", + "0x480080007fff8000", + "0x480080017ffe8000", + "0x480080027ffd8000", + "0x480080017ffb8000", + "0x400180027ffa8000", + "0x400180037ffa8003", + "0x400180047ffa8002", + "0x48287fe780007ffc", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x2", + "0x10780017fff7fff", + "0x9", + "0x48287fe880007ffc", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x1", + "0x10780017fff7fff", + "0x106", + "0x48287fe980007ffc", + "0x20680017fff7fff", + "0x103", + "0x400180007ffc8004", + "0x400180017ffc8005", + "0x400180027ffc8006", + "0x400180037ffc8007", + "0x400180047ffc8008", + "0x400180057ffc8009", + "0x400180067ffc800a", + "0x400180077ffc800b", + "0x400180087ffc800c", + "0x400180097ffc800d", + "0x4001800a7ffc800e", + "0x4001800b7ffc800f", + "0x4001800c7ffc8010", + "0x4001800d7ffc8011", + "0x4001800e7ffc8012", + "0x4001800f7ffc8013", + "0x400180107ffc8014", + "0x48297fea80008004", + "0x20680017fff7fff", + "0xdd", + "0x48297feb80008005", + "0x20680017fff7fff", + "0xd6", + "0x48297fec80008006", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xd5", + "0x480a7fe47fff8000", + "0x48127fef7fff8000", + "0x480a80077fff8000", + "0x480a80087fff8000", + "0x480a7fed7fff8000", + "0x480a7fee7fff8000", + "0x1104800180018000", + "0x7ba", + "0x20680017fff7ffd", + "0xbd", + "0x20680017fff7fff", + "0x6", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x10780017fff7fff", + "0xc7", + "0x48297fef80008009", + "0x20680017fff7fff", + "0xb0", + "0x48297ff08000800a", + "0x20680017fff7fff", + "0xa9", + "0x48297ff18000800b", + "0x20680017fff7fff", + "0xa2", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a800c7fff8000", + "0x480a800d7fff8000", + "0x480a7ff27fff8000", + "0x480a7ff37fff8000", + "0x1104800180018000", + "0x7ca", + "0x20680017fff7ffd", + "0x90", + "0x20680017fff7fff", + "0x6", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x10780017fff7fff", + "0xae", + "0x48297ff48000800e", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x10780017fff7fff", + "0xa5", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a800f7fff8000", + "0x480a80107fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x1104800180018000", + "0x788", + "0x20680017fff7ffd", + "0x6f", + "0x20680017fff7fff", + "0x6", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x10780017fff7fff", + "0x95", + "0x48297ff780008011", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x10780017fff7fff", + "0x8c", + "0x48297ff880008012", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x10780017fff7fff", + "0x83", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480a80137fff8000", + "0x480a80147fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x766", + "0x20680017fff7ffd", + "0x45", + "0x20680017fff7fff", + "0x6", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x10780017fff7fff", + "0x73", + "0x48297ffb80008000", + "0x20680017fff7fff", + "0x2e", + "0x48297ffc80008003", + "0x20680017fff7fff", + "0x1d", + "0x48297ffd80008002", + "0x20680017fff7fff", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53454c4543544f525f4d49534d41544348", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x434f4e54524143545f4d49534d41544348", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x43414c4c45525f4d49534d41544348", + "0x400080007ffe7fff", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x10780017fff7fff", + "0x1a", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x10780017fff7fff", + "0x16", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x10780017fff7fff", + "0x12", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x40780017fff7fff", + "0x2", + "0x480a7fe47fff8000", + "0x48127fef7fff8000", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x54585f494e464f5f4d49534d41544348", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x424c4f434b5f494e464f5f4d49534d41544348", + "0x400080007ffe7fff", + "0x480a7fe47fff8000", + "0x48127ff07fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7fe47fff8000", + "0x48127ffa7fff8000", + "0x480a80017fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff8b7", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff98000", + "0x480280097ff98000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0x53d", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ff9", + "0x400180017fff7ffb", + "0x480680017fff8000", + "0x2", + "0x400080027ffe7fff", + "0x482680017ffc8000", + "0x1", + "0x400080037ffd7fff", + "0x482680017ffd8000", + "0x1", + "0x400080047ffc7fff", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x5", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff87fff", + "0x400380017ff87ff7", + "0x400380027ff87ff9", + "0x400380037ff87ffa", + "0x400280047ff87ffd", + "0x400280057ff87ffe", + "0x480280077ff88000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff88000", + "0x482680017ff88000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff88000", + "0x480280097ff88000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff88000", + "0x482680017ff88000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff88000", + "0x480280097ff88000", + "0x1104800180018000", + "0x500", + "0x20680017fff7ffd", + "0x36", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ffc", + "0x400180017fff7ffd", + "0x48127fff7fff8000", + "0x482480017ffe8000", + "0x2", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400080007ff37fff", + "0x400080017ff37ff2", + "0x400180027ff37ff9", + "0x400180037ff37ffb", + "0x400080047ff37ffd", + "0x400080057ff37ffe", + "0x480080077ff38000", + "0x20680017fff7fff", + "0xb", + "0x480080067ff28000", + "0x482480017ff18000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480080087fef8000", + "0x480080097fee8000", + "0x10780017fff7fff", + "0x9", + "0x480080067ff28000", + "0x482480017ff18000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480080087fef8000", + "0x480080097fee8000", + "0x1104800180018000", + "0x4da", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf", + "0x48127fe77fff8000", + "0x48127fe77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5265706c616365436c617373", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x1104800180018000", + "0x41e", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x53656e644d657373616765546f4c31", + "0x400280007ffa7fff", + "0x400380017ffa7ff9", + "0x400380027ffa7ffb", + "0x400280037ffa7ffd", + "0x400280047ffa7ffe", + "0x480280067ffa8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x1104800180018000", + "0x3ec", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48027ffd7ffc8000", + "0x48027ffe7ffc8000", + "0x48027fff7ffc8000", + "0x400280007ffc7ffd", + "0x482480017ffe8000", + "0x1", + "0x400280017ffc7fff", + "0x400280027ffc7ffe", + "0x484480017ffd8000", + "0x3", + "0x48307fff7ffb8000", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x3", + "0x480a7ffd7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x5d9", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x15", + "0x480080007ffd8000", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48307ffb80007ffc", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff7", + "0x400380027ff87ff9", + "0x400380037ff87ffa", + "0x400280047ff87ffd", + "0x400280057ff87ffe", + "0x400380067ff87ffd", + "0x480280087ff88000", + "0x20680017fff7fff", + "0xc", + "0x480280077ff88000", + "0x482680017ff88000", + "0xc", + "0x480680017fff8000", + "0x0", + "0x480280097ff88000", + "0x4802800a7ff88000", + "0x4802800b7ff88000", + "0x10780017fff7fff", + "0xb", + "0x480280077ff88000", + "0x482680017ff88000", + "0xb", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480280097ff88000", + "0x4802800a7ff88000", + "0x1104800180018000", + "0x63d", + "0x20680017fff7ffc", + "0xb", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x400080007ffd7ffe", + "0x400080017ffd7fff", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x2", + "0x1104800180018000", + "0x62a", + "0x20680017fff7ffd", + "0x7a", + "0x4824800180007ffe", + "0x587f7cc3722e9654ea3963d5fe8c0748", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e6720686173682076616c7565", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x4824800180007ffe", + "0xa5963aa610cb75ba273817bce5f8c48f", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e6720686173682076616c7565", + "0x400080007ffe7fff", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x1", + "0x400080007ffe7fff", + "0x48127ffe7fff8000", + "0x482480017ffd8000", + "0x1", + "0x480680017fff8000", + "0x4b656363616b", + "0x400080007ff57fff", + "0x400080017ff57ff4", + "0x400080027ff57ffd", + "0x400080037ff57ffe", + "0x480080057ff58000", + "0x20680017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206661696c", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x480080047ff18000", + "0x482480017ff08000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff27fff8000", + "0x480080067ff38000", + "0x480080077ff28000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x630", + "0x480080047fdb8000", + "0x482480017fda8000", + "0x8", + "0x20680017fff7ffb", + "0x1e", + "0x4824800180007ffd", + "0x496e76616c696420696e707574206c656e677468", + "0x20680017fff7fff", + "0xc", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e67206572726f72206d7367", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x536563703235366b314e6577", + "0x400280007ffd7fff", + "0x400380017ffd7ffb", + "0x400280027ffd7ffb", + "0x400280037ffd7ffc", + "0x400280047ffd7ffd", + "0x400280057ffd7ffe", + "0x480280077ffd8000", + "0x20680017fff7fff", + "0xb", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x1104800180018000", + "0x5ef", + "0x20680017fff7ffd", + "0x11f", + "0x20680017fff7ffe", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206265206e6f6e65", + "0x400080007ffe7fff", + "0x480a7ffa7fff8000", + "0x48127ff37fff8000", + "0x480a7ffc7fff8000", + "0x48127ff27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xfffffffffffffffffffffffefffffc2f", + "0x480680017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x536563703235366b314e6577", + "0x400080007ff27fff", + "0x400080017ff27ff1", + "0x400080027ff27ffb", + "0x400080037ff27ffc", + "0x400080047ff27ffd", + "0x400080057ff27ffe", + "0x480080077ff28000", + "0x20680017fff7fff", + "0x12", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206661696c", + "0x400080007ffe7fff", + "0x480a7ffa7fff8000", + "0x480080067fee8000", + "0x480a7ffc7fff8000", + "0x482480017fec8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480080087ff08000", + "0x480080097fef8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x59d", + "0x480080067fd88000", + "0x482480017fd78000", + "0xa", + "0x20680017fff7ffb", + "0xd6", + "0x4824800180007ffd", + "0x496e76616c696420617267756d656e74", + "0x20680017fff7fff", + "0xc3", + "0x480680017fff8000", + "0xe3e70682c2094cac629f6fbed82c07cd", + "0x480680017fff8000", + "0xf728b4fa42485e3a0a5d2f346baa9455", + "0x480680017fff8000", + "0x8e031ab54fc0c4a8f0dc94fad0d0611", + "0x480680017fff8000", + "0x8e182ca967f38e1bd6a49583f43f1876", + "0x480680017fff8000", + "0x536563703235366b314e6577", + "0x400080007ff97fff", + "0x400080017ff97ff8", + "0x400080027ff97ffb", + "0x400080037ff97ffc", + "0x400080047ff97ffd", + "0x400080057ff97ffe", + "0x480080077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480080067ff88000", + "0x482480017ff78000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480080087ff58000", + "0x480080097ff48000", + "0x10780017fff7fff", + "0x9", + "0x480080067ff88000", + "0x482480017ff78000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480080087ff58000", + "0x480080097ff48000", + "0x1104800180018000", + "0x584", + "0x20680017fff7ffd", + "0x93", + "0x20680017fff7ffe", + "0x82", + "0x480680017fff8000", + "0x536563703235366b314765745879", + "0x400080007ff67fff", + "0x400080017ff67ff5", + "0x400080027ff67ffe", + "0x480080047ff68000", + "0x20680017fff7fff", + "0xd", + "0x480080037ff58000", + "0x482480017ff48000", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480080057ff28000", + "0x480080067ff18000", + "0x480080077ff08000", + "0x480080087fef8000", + "0x10780017fff7fff", + "0xd", + "0x480080037ff58000", + "0x482480017ff48000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080057ff08000", + "0x480080067fef8000", + "0x1104800180018000", + "0x56c", + "0x20680017fff7ffb", + "0x57", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127fde7fff8000", + "0x48127fde7fff8000", + "0x1104800180018000", + "0x576", + "0x20680017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x12", + "0x10780017fff7fff", + "0xa", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x48127fce7fff8000", + "0x48127fce7fff8000", + "0x1104800180018000", + "0x56a", + "0x20680017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x556e657870656374656420636f6f7264696e61746573", + "0x400080007ffe7fff", + "0x48127fb37fff8000", + "0x48127fcb7fff8000", + "0x480a7ffc7fff8000", + "0x48127fca7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fb57fff8000", + "0x1104800180018000", + "0x567", + "0x20680017fff7ff3", + "0x26", + "0x48127ff27fff8000", + "0x48127f8f7fff8000", + "0x480a7ffc7fff8000", + "0x48127f8e7fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x48127ff47fff8000", + "0x1104800180018000", + "0x595", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff27fff8000", + "0x48127f8f7fff8000", + "0x480a7ffc7fff8000", + "0x48127f8e7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fd97fff8000", + "0x48127ff17fff8000", + "0x480a7ffc7fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fe77fff8000", + "0x48127ff37fff8000", + "0x480a7ffc7fff8000", + "0x48127ff27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fe97fff8000", + "0x48127ff57fff8000", + "0x480a7ffc7fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e67206572726f72206d7367", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127ffa7fff8000", + "0x480a7ffc7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x48127ff57fff8000", + "0x480a7ffc7fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x5365637032353672314e6577", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffb", + "0x400280037ffd7ffc", + "0x400280047ffd7ffd", + "0x400280057ffd7ffe", + "0x480280077ffd8000", + "0x20680017fff7fff", + "0xb", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x1104800180018000", + "0x542", + "0x20680017fff7ffd", + "0x136", + "0x20680017fff7ffe", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206265206e6f6e65", + "0x400080007ffe7fff", + "0x480a7ffb7fff8000", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xffffffffffffffffffffffff", + "0x480680017fff8000", + "0xffffffff000000010000000000000000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x5365637032353672314e6577", + "0x400080007ff27fff", + "0x400080017ff27ff1", + "0x400080027ff27ffb", + "0x400080037ff27ffc", + "0x400080047ff27ffd", + "0x400080057ff27ffe", + "0x480080077ff28000", + "0x20680017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53686f756c64206661696c", + "0x400080007ffe7fff", + "0x480a7ffb7fff8000", + "0x480080067fee8000", + "0x482480017fed8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480080087ff08000", + "0x480080097fef8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x452", + "0x480080067fd88000", + "0x482480017fd78000", + "0xa", + "0x20680017fff7ffb", + "0xf0", + "0x4824800180007ffd", + "0x496e76616c696420617267756d656e74", + "0x20680017fff7fff", + "0xde", + "0x480680017fff8000", + "0x2d483fe223b12b91047d83258a958b0f", + "0x480680017fff8000", + "0x502a43ce77c6f5c736a82f847fa95f8c", + "0x480680017fff8000", + "0xce729c7704f4ddf2eaaf0b76209fe1b0", + "0x480680017fff8000", + "0xdb0a2e6710c71ba80afeb3abdf69d306", + "0x480680017fff8000", + "0x5365637032353672314e6577", + "0x400080007ff97fff", + "0x400080017ff97ff8", + "0x400080027ff97ffb", + "0x400080037ff97ffc", + "0x400080047ff97ffd", + "0x400080057ff97ffe", + "0x480080077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480080067ff88000", + "0x482480017ff78000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480080087ff58000", + "0x480080097ff48000", + "0x10780017fff7fff", + "0x9", + "0x480080067ff88000", + "0x482480017ff78000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480080087ff58000", + "0x480080097ff48000", + "0x1104800180018000", + "0x4d9", + "0x20680017fff7ffd", + "0xaf", + "0x20680017fff7ffe", + "0x9f", + "0x480680017fff8000", + "0x5365637032353672314765745879", + "0x400080007ff67fff", + "0x400080017ff67ff5", + "0x400080027ff67ffe", + "0x480080047ff68000", + "0x20680017fff7fff", + "0xd", + "0x480080037ff58000", + "0x482480017ff48000", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480080057ff28000", + "0x480080067ff18000", + "0x480080077ff08000", + "0x480080087fef8000", + "0x10780017fff7fff", + "0xd", + "0x480080037ff58000", + "0x482480017ff48000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080057ff08000", + "0x480080067fef8000", + "0x1104800180018000", + "0x421", + "0x20680017fff7ffb", + "0x75", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127fde7fff8000", + "0x48127fde7fff8000", + "0x1104800180018000", + "0x42b", + "0x20680017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x12", + "0x10780017fff7fff", + "0xa", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x48127fce7fff8000", + "0x48127fce7fff8000", + "0x1104800180018000", + "0x41f", + "0x20680017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x556e657870656374656420636f6f7264696e61746573", + "0x400080007ffe7fff", + "0x48127fb37fff8000", + "0x48127fcb7fff8000", + "0x48127fcb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fb57fff8000", + "0x1104800180018000", + "0x49a", + "0x20680017fff7ff3", + "0x46", + "0x48127f907fff8000", + "0x48127f907fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x4ce", + "0x1104800180018000", + "0x482", + "0x20680017fff7ffd", + "0x32", + "0x20680017fff7ffe", + "0x22", + "0x48127fde7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127fdd7fff8000", + "0x48127fdd7fff8000", + "0x48127fdd7fff8000", + "0x48127fdd7fff8000", + "0x48127fdd7fff8000", + "0x48127fdd7fff8000", + "0x48127ff67fff8000", + "0x1104800180018000", + "0x4d8", + "0x20680017fff7ffd", + "0xc", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fdc7fff8000", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fde7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff27fff8000", + "0x48127f8f7fff8000", + "0x48127f8f7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fd97fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fe77fff8000", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fe97fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x57726f6e67206572726f72206d7367", + "0x400080007ffe7fff", + "0x48127ff77fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x482a7ffd7ffc8000", + "0x1104800180018000", + "0x55b", + "0x20680017fff7ffd", + "0xa", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x169b", + "0x482480017fff8000", + "0x169a", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff8", + "0x12a2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff77fff", + "0x10780017fff7fff", + "0x4c", + "0x4825800180007ff8", + "0x12a2", + "0x400280007ff77fff", + "0x482680017ff78000", + "0x1", + "0x20780017fff7ffd", + "0xd", + "0x48127fff7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff370", + "0x20680017fff7ffe", + "0x27", + "0x400280007ffc7fff", + "0x48127ff07fff8000", + "0x48127fee7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x4825800180007ffd", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd1", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff07fff8000", + "0x48127fee7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff78000", + "0x1", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x16", + "0x480280007ffc8003", + "0x480280017ffc8003", + "0x4844800180017ffe", + "0x100000000000000000000000000000000", + "0x483180017ffd7ffd", + "0x482480017fff7ffd", + "0x800000000000010fffffffffffffffff7ffffffffffffef0000000000000001", + "0x20680017fff7ffc", + "0x6", + "0x402480017fff7ffd", + "0xffffffffffffffffffffffffffffffff", + "0x10780017fff7fff", + "0x4", + "0x402480017ffe7ffd", + "0xf7ffffffffffffef0000000000000000", + "0x400280027ffc7ffd", + "0x20680017fff7ffe", + "0xe", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x36", + "0x40780017fff7fff", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x480080007ff68000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff42", + "0x20680017fff7ffa", + "0x1c", + "0x20680017fff7ffd", + "0xd", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x36", + "0x40780017fff7fff", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x480080007ff68000", + "0x1104800180018000", + "0x44a", + "0x20680017fff7ffa", + "0x1c", + "0x20680017fff7ffd", + "0xd", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x12", + "0x4825800180007ffd", + "0x100000000", + "0x4844800180008002", + "0x8000000000000110000000000000000", + "0x4830800080017ffe", + "0x480280007ffc7fff", + "0x482480017ffe8000", + "0xefffffffffffffde00000000ffffffff", + "0x480280017ffc7fff", + "0x400280027ffc7ffb", + "0x402480017fff7ffb", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x11", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x482680017ffd8000", + "0xffffffffffffffffffffffff00000000", + "0x400280017ffc7fff", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574457865637574696f6e496e666f", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x480280037ffd8000", + "0x20680017fff7fff", + "0xc", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280047ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x6", + "0x480680017fff8000", + "0x1", + "0x480280047ffd8000", + "0x480280057ffd8000", + "0x1104800180018000", + "0x443", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffa80007ffb", + "0x48297ffc80007ffd", + "0x48307fff80007ffe", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xb", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x427", + "0x20680017fff7ffa", + "0xa", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffa80007ffb", + "0x48297ffc80007ffd", + "0x4844800180007ffe", + "0x3", + "0x4844800180007ffe", + "0x3", + "0x48307fff80007ffe", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xb", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x4a0", + "0x20680017fff7ffa", + "0xa", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x4", + "0x10780017fff7fff", + "0xb2", + "0x48037ffd7ffc8002", + "0x48037ffe7ffc8003", + "0x48037fff7ffc8004", + "0x480380007ffa8000", + "0x4825800180018003", + "0x1", + "0x4828800080018000", + "0x480280017ffa8000", + "0x4846800180008000", + "0x3", + "0x48327fff80028000", + "0x400180027fff8004", + "0x400180017fff7ffd", + "0x400380007ffc8002", + "0x400380017ffc8003", + "0x4826800180048000", + "0x1", + "0x400280027ffc7fff", + "0x482680017ffa8000", + "0x2", + "0x480080007ffd8000", + "0x480a7ffd7fff8000", + "0x40337ffe80017ffd", + "0x1104800180018000", + "0xf", + "0x48307fff80007ffe", + "0x48317fff80008001", + "0x4844800180007fff", + "0x3", + "0x484480017fff8000", + "0xfd2", + "0x48127ff97fff8000", + "0x48327ffe7ffb8000", + "0x482680017ffc8000", + "0x3", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x482b7ffc80007ffd", + "0x40780017fff7fff", + "0x3", + "0x20780017fff8000", + "0x6", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x4845800180008000", + "0x3", + "0xa0780017fff8002", + "0x7", + "0x400380007ffb8001", + "0x402680017ffb7fff", + "0x1", + "0x10780017fff7fff", + "0x3", + "0x400a7ffb7fff7fff", + "0x480a7ffc7fff8000", + "0x4825800180007ffd", + "0x1", + "0x480a80017fff8000", + "0x48127ffb7fff8000", + "0x480a80037fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x4", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x480280007ff78002", + "0x4844800180018002", + "0x3", + "0x483280017ff88004", + "0x4800800280038004", + "0x482680017ff78004", + "0x1", + "0x4801800080017ffa", + "0x480380007ffc7ffa", + "0x480080017fff7ffd", + "0x480280017ffc7ffc", + "0x400680017fff7ffb", + "0x0", + "0x20680017fff7ffc", + "0xf", + "0x480080007fff8000", + "0x482480017fff8000", + "0x1", + "0x484480017fff8000", + "0x3", + "0x48307fff7ffa8001", + "0x4800800180007ffa", + "0x480080027fff8000", + "0x480180007ffe7ffa", + "0x402480017ff87fff", + "0x1", + "0x20680017fff7ffc", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x48317ffd80007ff9", + "0x400080007ffe7fff", + "0x48287ff780007ffe", + "0x400280027ffc7ffc", + "0x40337fff80017ffb", + "0x20780017fff8001", + "0x7", + "0x482480017ffd8000", + "0x1", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0xe", + "0x482680017ffa8000", + "0x1", + "0x48317fff80008000", + "0x400080017ffb7fff", + "0x482480017ffb8000", + "0x2", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x10780017fff7fff", + "0x32", + "0x4829800080007ffa", + "0x20680017fff7fff", + "0x4", + "0x402780017fff7fff", + "0x1", + "0x480080017ffc8000", + "0x480080027ffb8000", + "0x484480017fff8000", + "0x2aaaaaaaaaaaab05555555555555556", + "0x48307fff7ffd8000", + "0x480080037ff88000", + "0x480080047ff78000", + "0x484480017fff8000", + "0x4000000000000088000000000000001", + "0x48307fff7ffd8000", + "0x48307fff7ffb8000", + "0x48507ffe7ffa8000", + "0xa0680017fff8000", + "0xc", + "0x484680017ffa8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x402480017fff7ffc", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x4829800080007ffa", + "0x4826800180008000", + "0x1", + "0x40507fff7ffe7ffb", + "0x10780017fff7fff", + "0xf", + "0xa0680017fff8000", + "0xa", + "0x4846800180008000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x40327fff7ffa7ffa", + "0x40527fff7ffa7ffb", + "0x10780017fff7fff", + "0x5", + "0x480a80007fff7ffc", + "0x48297ffa80008000", + "0x40527fff7ffa7ffb", + "0x482480017fee8000", + "0x5", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x482680017ffc8000", + "0x3", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff98", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x48127ffa7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffa", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x464", + "0x20680017fff7ffb", + "0x45", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x4cf", + "0x20680017fff7ffd", + "0x31", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x4b656363616b", + "0x400280007ffb7fff", + "0x400280017ffb7ff9", + "0x400280027ffb7ffd", + "0x400280037ffb7ffe", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0xb", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x1104800180018000", + "0x5f6", + "0x20680017fff7ffd", + "0xa", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x5da", + "0x20680017fff7ffd", + "0x9", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080007ffc8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ff9", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x5cb", + "0x20680017fff7fff", + "0x8", + "0x40780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x5bf", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0xbb448978bd42b984d7de5970bcaf5c43", + "0x480680017fff8000", + "0x767410c1", + "0x1104800180018000", + "0x5c3", + "0x20680017fff7ffd", + "0x1d", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x788f195a6f509ca3e934f78d7a71dd85", + "0x480680017fff8000", + "0xe888fbb4cf9ae6254f19ba12e6d9af54", + "0x480680017fff8000", + "0x7a5f81cf3ee10044320a0d03b62d3e9a", + "0x480680017fff8000", + "0x4c8e4fbc1fbb1dece52185e532812c4f", + "0x480680017fff8000", + "0xc2b7f60e6a8b84965830658f08f7410c", + "0x480680017fff8000", + "0x4ac5e5c0c0e8a4871583cc131f35fb49", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0xfeb20876964d432846d9b9100b91eefd", + "0x480680017fff8000", + "0xa9a02d48081294b9bb0d8740d70d3607", + "0x480680017fff8000", + "0xd062744c75e49efb9925bf8025a7c09e", + "0x480680017fff8000", + "0x18b410b5523a1431024a6ab766c89fa5", + "0x48127ff27fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff27fff8000", + "0x480a7ff37fff8000", + "0x480a7ff47fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x597", + "0x20680017fff7ffd", + "0x1c", + "0x20680017fff7ffe", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400080007fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x6e1cda979008bfaf874ff796eb3bb1c0", + "0x480680017fff8000", + "0x49288242", + "0x1104800180018000", + "0x546", + "0x20680017fff7ffd", + "0x1d", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x27ae41e4649b934ca495991b7852b855", + "0x480680017fff8000", + "0xe3b0c44298fc1c149afbf4c8996fb924", + "0x480680017fff8000", + "0x42d16e47f219f9e98e76e09d8770b34a", + "0x480680017fff8000", + "0xb292a619339f6e567a305c951c0dcbcc", + "0x480680017fff8000", + "0xe59ec2a17ce5bd2dab2abebdf89a62e2", + "0x480680017fff8000", + "0x177e60492c5a8242f76f07bfe3661bd", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x32e41495a944d0045b522eba7240fad5", + "0x480680017fff8000", + "0x4aaec73635726f213fb8a9e64da3b86", + "0x480680017fff8000", + "0xaaf7b4e09fc81d6d1aa546e8365d525d", + "0x480680017fff8000", + "0x87d9315798aaa3a5ba01775787ced05e", + "0x48127ff27fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5365637032353672314e6577", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400380047ff97ffc", + "0x400380057ff97ffd", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xb", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ff98000", + "0x480280097ff98000", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ff47fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x57f", + "0x20680017fff7fff", + "0x5", + "0x48127ffe7fff8000", + "0x10780017fff7fff", + "0xe5", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x575", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0xda", + "0x1104800180018000", + "0x589", + "0x1104800180018000", + "0x58c", + "0x20680017fff7ffc", + "0xcc", + "0x20680017fff7ffd", + "0xbc", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x584", + "0x40137fe67fff8000", + "0x40137fe77fff8001", + "0x20680017fff7ffc", + "0xac", + "0x20680017fff7ffd", + "0x9c", + "0x48127fca7fff8000", + "0x480a7ff57fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x58a", + "0x20680017fff7ffc", + "0x8a", + "0x20680017fff7ffd", + "0x7a", + "0x48127ffa7fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x5e4", + "0x48127ffd7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127e8a7fff8000", + "0x48127e8a7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x5db", + "0x48127d197fff8000", + "0x480a7ff67fff8000", + "0x1104800180018000", + "0x64b", + "0x20680017fff7ffd", + "0x5a", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffd7fff8000", + "0x48127e6f7fff8000", + "0x48127e6f7fff8000", + "0x1104800180018000", + "0x68b", + "0x1104800180018000", + "0x6a5", + "0x20680017fff7ffd", + "0x47", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a7ffd7fff8000", + "0x48127fcd7fff8000", + "0x48127fcd7fff8000", + "0x1104800180018000", + "0x680", + "0x1104800180018000", + "0x69a", + "0x20680017fff7ffd", + "0x34", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x48127fea7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x69f", + "0x1104800180018000", + "0x690", + "0x20680017fff7ffd", + "0x22", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x6b1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe96", + "0x20680017fff7ffb", + "0x11", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffea0", + "0x48127f837fff8000", + "0x48127fdf7fff8000", + "0x48127fdf7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127f957fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127faa7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fbc7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fcf7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fe27fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fc87fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fca7fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fe07fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fe27fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1275130f95dda36bcbb6e9d28796c1d7e10b6e9fd5ed083e0ede4b12f613528", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffa99", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x113a", + "0x482480017fff8000", + "0x1139", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff8", + "0x30ca", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff77fff", + "0x10780017fff7fff", + "0x4f", + "0x4825800180007ff8", + "0x30ca", + "0x400280007ff77fff", + "0x482680017ff78000", + "0x1", + "0x20780017fff7ffd", + "0xd", + "0x48127fff7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x5f0", + "0x20680017fff7ffc", + "0x29", + "0x400280007ffc7ffd", + "0x400280017ffc7ffe", + "0x400280027ffc7fff", + "0x48127ff97fff8000", + "0x48127fb97fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x3", + "0x4825800180007ffd", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffce", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127fb97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff78000", + "0x1", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x10be", + "0x482480017fff8000", + "0x10bd", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff9", + "0x168a", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x86", + "0x4825800180007ff9", + "0x168a", + "0x400280007ff87fff", + "0x482680017ff88000", + "0x1", + "0x48297ffa80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffa8000", + "0x1", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x5f", + "0x480080007ffd8000", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x36", + "0x48127ffa7fff8000", + "0x480080007ffe8000", + "0x1104800180018000", + "0x5d0", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x20680017fff7ffd", + "0x23", + "0x48127fe87fff8000", + "0x48127fe67fff8000", + "0x48127fec7fff8000", + "0x48127fec7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb3", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127fe87fff8000", + "0x48127fe67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x48127fee7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1018", + "0x482480017fff8000", + "0x1017", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff9", + "0x1b3a", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x8c", + "0x4825800180007ff9", + "0x1b3a", + "0x400280007ff87fff", + "0x482680017ff88000", + "0x1", + "0x48297ffa80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffa8000", + "0x3", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x65", + "0x480080007ffd8000", + "0x480080017ffc8000", + "0x480080027ffb8000", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x3", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x3a", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480080007ffc8000", + "0x480080017ffb8000", + "0x480080027ffa8000", + "0x1104800180018000", + "0x531", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x20680017fff7ffd", + "0x23", + "0x48127fe07fff8000", + "0x48127fde7fff8000", + "0x48127fe47fff8000", + "0x48127fe47fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x20680017fff7ffa", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127fe07fff8000", + "0x48127fde7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fe37fff8000", + "0x48127fe37fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fee7fff8000", + "0x48127fec7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xf6c", + "0x482480017fff8000", + "0xf6b", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff9", + "0x614e", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0x59", + "0x4825800180007ff9", + "0x614e", + "0x400280007ff87fff", + "0x482680017ff88000", + "0x1", + "0x48297ffa80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffa8000", + "0x2", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x34", + "0x48127ff87fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480080007ffa8000", + "0x480080017ff98000", + "0x1104800180018000", + "0x4bf", + "0x20680017fff7ffd", + "0x20", + "0x48127ffc7fff8000", + "0x48127f597fff8000", + "0x48127f5f7fff8000", + "0x48127f5f7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc8", + "0x20680017fff7ffb", + "0xb", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x48127f597fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x11", + "0x1104800180018000", + "0x49d", + "0x20680017fff7ffd", + "0x13b", + "0x20680017fff7ffe", + "0x12c", + "0x48297ffa80007ffb", + "0x480280007ff88004", + "0x4824800180037fff", + "0x1", + "0x48307ffe7fff7ffc", + "0x480280017ff87ffe", + "0x480280027ff87fff", + "0x40507ffe7ff97ffd", + "0x40307fff7ffd7ffa", + "0x482680017ff88000", + "0x3", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x8", + "0x1104800180018000", + "0x499", + "0x20680017fff7ffd", + "0x113", + "0x48127ffc7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x4ad", + "0x20680017fff7ffd", + "0x105", + "0x4825800180007ffd", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x94", + "0x4825800180007ffd", + "0x1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x55", + "0x4825800180007ffd", + "0x2", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x49", + "0x4825800180007ffd", + "0x3", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x3d", + "0x4825800180007ffd", + "0x4", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x31", + "0x4825800180007ffd", + "0x5", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x25", + "0x4825800180007ffd", + "0x6", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x19", + "0x4825800180007ffd", + "0x7", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xf", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4b656363616b206c61737420696e70757420776f7264203e3762", + "0x400080007ffe7fff", + "0x48127ff27fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x100000000000000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x1000000000000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x10000000000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x3", + "0x480680017fff8000", + "0x100000000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1000000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x10000", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x100", + "0x1104800180018000", + "0x471", + "0x20680017fff7ffd", + "0x2c", + "0x20680017fff7ffe", + "0x1d", + "0x480080007fe18004", + "0x4824800180037fff", + "0x1", + "0x48307ffe7fff7ffd", + "0x480080017fde7ffe", + "0x480080027fdd7fff", + "0x40507ffe7ffa7ffd", + "0x40317fff7ffd7ffc", + "0x482480017fdc8000", + "0x3", + "0x48127fe77fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x46f", + "0x20680017fff7ffd", + "0x6", + "0x48127ffc7fff8000", + "0x48127ffe7fff8000", + "0x10780017fff7fff", + "0x22", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fdf7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fe17fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x35", + "0x48127fc67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x11", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x46d", + "0x20680017fff7ffd", + "0x58", + "0x48307fff80007f87", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x3b", + "0x400280007ffb7fe8", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x11", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x45e", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x1", + "0x20680017fff7ffb", + "0x27", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x48127f6c7fff8000", + "0x1104800180018000", + "0x454", + "0x20680017fff7ffd", + "0x19", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x48127fe67fff8000", + "0x48127fe67fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x476", + "0x20680017fff7ffd", + "0x9", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x8000000000000000", + "0x48127fe67fff8000", + "0x1104800180018000", + "0x3fc", + "0x20680017fff7ffd", + "0xb", + "0x400280007ffb7fff", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffb80007ffc", + "0xa0680017fff8000", + "0x6", + "0x48317ffe80007ffd", + "0x400280007ffa7fff", + "0x10780017fff7fff", + "0x10", + "0x482680017ffd8000", + "0x1", + "0x48307fff80007ffd", + "0x400280007ffa7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffa8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x482a7ffd7ffb8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e646578206f7574206f6620626f756e6473", + "0x400080007ffe7fff", + "0x482680017ffa8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48297ffd80007ffc", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x100000000", + "0x1104800180018000", + "0x435", + "0x20680017fff7ffd", + "0xb", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48287ffc7ffc8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff27fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x453", + "0x20680017fff7fff", + "0xd", + "0x48127ffe7fff8000", + "0x480a7ff37fff8000", + "0x480a7ff47fff8000", + "0x480a7ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x5369676e6174757265206f7574206f662072616e6765", + "0x208b7fff7fff7ffe", + "0x48127ffe7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x441", + "0x20680017fff7fff", + "0xd", + "0x48127ffe7fff8000", + "0x480a7ff37fff8000", + "0x480a7ff47fff8000", + "0x480a7ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x5369676e6174757265206f7574206f662072616e6765", + "0x208b7fff7fff7ffe", + "0x48127ffe7fff8000", + "0x480a7ff37fff8000", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x443", + "0x20680017fff7ffd", + "0x41", + "0x20680017fff7ffe", + "0x30", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ff47fff8000", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x529", + "0x20680017fff7ffd", + "0x1e", + "0x480a7ffd7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x5ad", + "0x20680017fff7fff", + "0xd", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x496e76616c6964207369676e6174757265", + "0x208b7fff7fff7ffe", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x48127feb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a7ff47fff8000", + "0x48127ff77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ff47fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x571", + "0x20680017fff7fff", + "0xd", + "0x1104800180018000", + "0x11", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x56d", + "0x10780017fff7fff", + "0x7", + "0x40780017fff7fff", + "0x12", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xbce6faada7179e84f3b9cac2fc632551", + "0x480680017fff8000", + "0xffffffff00000000ffffffffffffffff", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x591", + "0x20680017fff7ffd", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x597", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff95b", + "0x20680017fff7fff", + "0x54", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x58c", + "0x20680017fff7ff8", + "0x41", + "0x1104800180018000", + "0x583", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff947", + "0x20680017fff7fff", + "0xd", + "0x40780017fff7fff", + "0x33", + "0x48127fad7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x24", + "0x20680017fff7fe9", + "0x1b", + "0x48127fe07fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x1104800180018000", + "0x67b", + "0x20680017fff7ffd", + "0x9", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x12", + "0x48127ffc7fff8000", + "0x48127fad7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x33", + "0x48127fad7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fb07fff8000", + "0x48127fb07fff8000", + "0x48127ffc7fff8000", + "0x48127fa97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x66c", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x661", + "0x480080007ffb8000", + "0x480080017ffa8000", + "0x480080027ff98000", + "0x480080037ff88000", + "0x480080047ff78000", + "0x480080057ff68000", + "0x48317fff80007ffd", + "0x40780017fff7fff", + "0xc", + "0x20680017fff7ff3", + "0x8", + "0x40317ff17ff47ffc", + "0x402480017ff57ff4", + "0x1", + "0x400080067fe87ff5", + "0x10780017fff7fff", + "0x3", + "0x400080067fe87ff3", + "0x48307ff17ff68000", + "0x48307fe880007fff", + "0x4844800180007fff", + "0x100000000000000000000000000000000", + "0x40507fff7fff7fff", + "0x48307ff47fff8000", + "0x48307ff47fff8000", + "0x48307ff57fff8000", + "0x48307fec7fff8000", + "0x48307fe380007fff", + "0x4844800180007fff", + "0x100000000000000000000000000000000", + "0x400080077fdf7fff", + "0x482480017fff8000", + "0xfffffffffffffffffffffffffffffffc", + "0x400080087fde7fff", + "0x48307fef7ffe8000", + "0x48307ff07fff8000", + "0x48307ff07fff8000", + "0x48307ff17fff8000", + "0x48307fdd80007fff", + "0x4844800180007fff", + "0x100000000000000000000000000000000", + "0x400080097fd87fff", + "0x482480017fff8000", + "0xfffffffffffffffffffffffffffffffc", + "0x4000800a7fd77fff", + "0xa0680017fff7fdf", + "0xc", + "0xa0680017fff8001", + "0x6", + "0x480a7ffd7fff7ffe", + "0x40127fdb7fff7ffe", + "0x10780017fff7fff", + "0x10", + "0x48127fdc7fff7ffe", + "0x400a7ffd7fff7ffe", + "0x10780017fff7fff", + "0xc", + "0x480780017fff7ffd", + "0x0", + "0xa0680017fff8000", + "0x6", + "0x400a7ffc7fff7ffd", + "0x40127fdc7fff7ffe", + "0x10780017fff7fff", + "0x4", + "0x40127fdc7fff7ffd", + "0x400a7ffc7fff7ffe", + "0x482480017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x4000800b7fd37fff", + "0x48507ffd7ffc8000", + "0x48307fe97ff98000", + "0x48307fe67fff8000", + "0x40307ffd7fff7fd4", + "0x482480017fd08000", + "0xc", + "0x48127fd67fff8000", + "0x480a7ffc7fff8000", + "0x48127fe47fff8000", + "0x48127fe27fff8000", + "0x1104800180018000", + "0x663", + "0x48127fbf7fff8000", + "0x480a7ffd7fff8000", + "0x48127fcc7fff8000", + "0x48127fca7fff8000", + "0x1104800180018000", + "0x65d", + "0x48127fa97fff8000", + "0x480a7ffc7fff8000", + "0x48127fb27fff8000", + "0x48127fb07fff8000", + "0x1104800180018000", + "0x657", + "0x48127f927fff8000", + "0x480a7ffd7fff8000", + "0x48127f9e7fff8000", + "0x48127f9c7fff8000", + "0x1104800180018000", + "0x651", + "0x48127f7c7fff8000", + "0x480a7ffc7fff8000", + "0x48127f847fff8000", + "0x48127f827fff8000", + "0x1104800180018000", + "0x64b", + "0x48127f6a7fff8000", + "0x48127f6a7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x77037d812deb33a0f4a13945d898c296", + "0x480680017fff8000", + "0x6b17d1f2e12c4247f8bce6e563a440f2", + "0x480680017fff8000", + "0x2bce33576b315ececbb6406837bf51f5", + "0x480680017fff8000", + "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e16", + "0x480680017fff8000", + "0x5365637032353672314e6577", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffb", + "0x400280037ffd7ffc", + "0x400280047ffd7ffd", + "0x400280057ffd7ffe", + "0x480280077ffd8000", + "0x20680017fff7fff", + "0xb", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff8e5", + "0x20680017fff7ffd", + "0x1b", + "0x20680017fff7ffe", + "0xc", + "0x40780017fff7fff", + "0x2", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5365637032353672314d756c", + "0x400280007ffa7fff", + "0x400380017ffa7ff9", + "0x400380027ffa7ffb", + "0x400380037ffa7ffc", + "0x400380047ffa7ffd", + "0x480280067ffa8000", + "0x20680017fff7fff", + "0xc", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280077ffa8000", + "0x10780017fff7fff", + "0x9", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x536563703235367231416464", + "0x400280007ffb7fff", + "0x400380017ffb7ffa", + "0x400380027ffb7ffc", + "0x400380037ffb7ffd", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0xc", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280067ffb8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5365637032353672314765745879", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x10780017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffe81c", + "0x20680017fff7ffe", + "0x69", + "0x48307ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffb8000", + "0x1", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x44", + "0x480a7ffb7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffe967", + "0x20680017fff7ffe", + "0x39", + "0x48307ff080007ff1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017fef8000", + "0x1", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fec7fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x14", + "0x48127ff67fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff4c9", + "0x20680017fff7ffe", + "0xb", + "0x48127ffd7fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fd27fff8000", + "0x48127fe67fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xd", + "0x48127fe97fff8000", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x14", + "0x48127fe97fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x22", + "0x480a7ffb7fff8000", + "0x48127fdb7fff8000", + "0x48127fdb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x29", + "0x480a7ffb7fff8000", + "0x48127fd27fff8000", + "0x48127fd27fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48297ffd80007ffc", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x208b7fff7fff7ffe", + "0x48297ffb80007ff8", + "0x20680017fff7fff", + "0x18", + "0x48297ffc80007ff9", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x1", + "0x10780017fff7fff", + "0x11", + "0x48297ffd80007ffa", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x510", + "0x20680017fff7ffd", + "0x1c", + "0x400280007ffb7fff", + "0x400280017ffb7ffe", + "0x48127ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x508", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x2", + "0x20680017fff7ffb", + "0xb", + "0x400080007fff7ffd", + "0x400080017fff7ffc", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x482480017ffc8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4a", + "0x48127fb27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fb27fff8000", + "0x48127fb27fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x539", + "0x20680017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x484a7ffd7ffc8000", + "0x1104800180018000", + "0x540", + "0x20680017fff7ffe", + "0xb", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x7533325f6d756c204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x8", + "0x482a7ffd7ffc8000", + "0x4824800180007fff", + "0x100000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xd", + "0x482a7ffd7ffc8001", + "0x4824800180007fff", + "0xffffffffffffffffffffffff00000000", + "0x400280007ffb7ffe", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x7", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x7533325f616464204f766572666c6f77", + "0x1104800180018000", + "0x525", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x526", + "0x20680017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x8", + "0x482a7ffd7ffc8000", + "0x4824800180007fff", + "0x10000000000000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xd", + "0x482a7ffd7ffc8001", + "0x4824800180007fff", + "0xffffffffffffffff0000000000000000", + "0x400280007ffb7ffe", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x7", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x7536345f616464204f766572666c6f77", + "0x1104800180018000", + "0x515", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffd80017ffc", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ffb7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x482480017ffc8000", + "0x100000000", + "0x480680017fff8000", + "0x7533325f737562204f766572666c6f77", + "0x1104800180018000", + "0x4bf", + "0x20680017fff7ffd", + "0x9", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x99a", + "0x482480017fff8000", + "0x999", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ffa", + "0x1612", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x44", + "0x4825800180007ffa", + "0x1612", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x4825800180007ffd", + "0x1", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x2e", + "0x480680017fff8000", + "0x0", + "0x400280007ffc7fff", + "0x48127ffd7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb6", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x20680017fff7ffb", + "0x19", + "0x48127ffa7fff8000", + "0x48127fe37fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd5", + "0x20680017fff7ffd", + "0x9", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127fe37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x8000000000000000", + "0x400280007ffc7fff", + "0x48127ffd7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x482680017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x48d", + "0x20680017fff7ffd", + "0x2b", + "0x20680017fff7ffe", + "0x1b", + "0x480280007ffb8005", + "0x480280017ffb8005", + "0x4824800180047ffe", + "0x1", + "0x48307ffd7ffe7ffc", + "0x480280027ffb7ffd", + "0xa0680017fff7ffd", + "0x6", + "0x482480017ff97ffd", + "0xffffffffffffffff0000000000000000", + "0x10780017fff7fff", + "0x4", + "0x482480017fff7ffd", + "0xffffffffffffffff0000000000000000", + "0x400280037ffb7ffc", + "0x40507ffe7ff87ffd", + "0x40317fff7ffd7ffc", + "0x482680017ffb8000", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4469766973696f6e2062792030", + "0x400080007ffe7fff", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x7", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x195", + "0x20680017fff7fff", + "0xd", + "0x1104800180018000", + "0x45e", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x191", + "0x10780017fff7fff", + "0x7", + "0x40780017fff7fff", + "0x12", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x480a7ff57fff8000", + "0x480a7ff67fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x44b", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff577", + "0x20680017fff7ffd", + "0xde", + "0x20680017fff7ffe", + "0xd2", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x1104800180018000", + "0x45c", + "0x40137fe47fff8001", + "0x40137ffc7fff8002", + "0x20680017fff7ffd", + "0xc2", + "0x1104800180018000", + "0x436", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc11", + "0x40137fe57fff8000", + "0x20680017fff7ffc", + "0xb3", + "0x20680017fff7ffd", + "0xa3", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc08", + "0x40137fe67fff8003", + "0x40137fe77fff8004", + "0x20680017fff7ffc", + "0x93", + "0x20680017fff7ffd", + "0x83", + "0x480a7ff47fff8000", + "0x48127fc87fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc0e", + "0x20680017fff7ffc", + "0x71", + "0x20680017fff7ffd", + "0x61", + "0x48127ffa7fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc68", + "0x1104800180018000", + "0x477", + "0x20680017fff7ffd", + "0x4c", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x48127e4d7fff8000", + "0x48127e4d7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc5b", + "0x48127cdc7fff8000", + "0x480a80027fff8000", + "0x480a80007fff8000", + "0x48127e8a7fff8000", + "0x48127e8a7fff8000", + "0x1104800180018000", + "0x47c", + "0x1104800180018000", + "0x496", + "0x20680017fff7ffd", + "0x30", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480a80017fff8000", + "0x48127fe87fff8000", + "0x48127fe87fff8000", + "0x1104800180018000", + "0x471", + "0x1104800180018000", + "0x48b", + "0x20680017fff7ffd", + "0x1d", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x48127fea7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x490", + "0x1104800180018000", + "0x481", + "0x20680017fff7ffd", + "0xb", + "0x48127fc57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fc57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fd77fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fea7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x48127e4c7fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ff47fff8000", + "0x48127fc67fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff47fff8000", + "0x48127fc87fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ff47fff8000", + "0x48127fde7fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff47fff8000", + "0x48127fe07fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff47fff8000", + "0x48127ffa7fff8000", + "0x480a80027fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff47fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff47fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x41d", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff496", + "0x20680017fff7ffb", + "0x7a", + "0x40780017fff7fff", + "0x1", + "0x400080007fff7ffb", + "0x400080017fff7ffc", + "0x400080027fff7ffd", + "0x400080037fff7ffe", + "0x480a7ff97fff8000", + "0x48127ff07fff8000", + "0x480a7ffb7fff8000", + "0x48127fef7fff8000", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x4", + "0x1104800180018000", + "0x429", + "0x20680017fff7ffd", + "0x60", + "0x400080007ffb7fff", + "0x480680017fff8000", + "0xff00ff00ff00ff00ff00ff00ff00ff", + "0x400080017ffa7fff", + "0x480080027ffa8000", + "0x484480017fff8000", + "0xffff", + "0x48307fff7ffc8000", + "0x400080057ff77fff", + "0x480680017fff8000", + "0xffff0000ffff0000ffff0000ffff00", + "0x400080067ff67fff", + "0x480080077ff68000", + "0x484480017fff8000", + "0xffffffff", + "0x48307fff7ffc8000", + "0x4000800a7ff37fff", + "0x480680017fff8000", + "0xffffffff00000000ffffffff000000", + "0x4000800b7ff27fff", + "0x4800800c7ff28000", + "0x484480017fff8000", + "0xffffffffffffffff", + "0x48307fff7ffc8000", + "0x4000800f7fef7fff", + "0x480680017fff8000", + "0xffffffffffffffff00000000000000", + "0x400080107fee7fff", + "0x480080117fee8000", + "0x484480017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x48307fff7ffc8000", + "0x400080147feb7fee", + "0x480680017fff8000", + "0xff00ff00ff00ff00ff00ff00ff00ff", + "0x400080157fea7fff", + "0x480080167fea8000", + "0x484480017fff8000", + "0xffff", + "0x48307fff7feb8000", + "0x400080197fe77fff", + "0x480680017fff8000", + "0xffff0000ffff0000ffff0000ffff00", + "0x4000801a7fe67fff", + "0x4800801b7fe68000", + "0x484480017fff8000", + "0xffffffff", + "0x48307fff7ffc8000", + "0x4000801e7fe37fff", + "0x480680017fff8000", + "0xffffffff00000000ffffffff000000", + "0x4000801f7fe27fff", + "0x480080207fe28000", + "0x484480017fff8000", + "0xffffffffffffffff", + "0x48307fff7ffc8000", + "0x400080237fdf7fff", + "0x480680017fff8000", + "0xffffffffffffffff00000000000000", + "0x400080247fde7fff", + "0x480080257fde8000", + "0x484480017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x48307fff7ffc8000", + "0x48127fd97fff8000", + "0x484480017fee8000", + "0x800000000000010fffffffffffffff7ffffffffffffef000000000000000001", + "0x484480017ffd8000", + "0x800000000000010fffffffffffffff7ffffffffffffef000000000000000001", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffa27", + "0x482480017fae8000", + "0x28", + "0x20680017fff7ffc", + "0xc", + "0x48127ffb7fff8000", + "0x48127fab7fff8000", + "0x48127ffd7fff8000", + "0x48127fab7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127fab7fff8000", + "0x48127ffd7fff8000", + "0x48127fab7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x48127ff17fff8000", + "0x480a7ffb7fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x412", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff41a", + "0x208b7fff7fff7ffe", + "0x48297ffd80017ffb", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x28", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48297ffd80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x9", + "0x40780017fff7fff", + "0x3", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x17", + "0x48297ffc80017ffa", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ffb7fff", + "0x10780017fff7fff", + "0xb", + "0x400080007ffc7fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ffb8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x6", + "0x482480017ffb8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0x4", + "0x482680017ff98000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3d6", + "0x20680017fff7ffd", + "0x9", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235362069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x710", + "0x482480017fff8000", + "0x70f", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4825800180007ff9", + "0xa820", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff87fff", + "0x10780017fff7fff", + "0xe9", + "0x4825800180007ff9", + "0xa820", + "0x400280007ff87fff", + "0x480280017ff88000", + "0x480280027ff88000", + "0x480280037ff88000", + "0x480280047ff88000", + "0x48317fff80007ffd", + "0xa0680017fff7fff", + "0x8", + "0x48317ffc7fff7ffc", + "0x402480017fff7ffe", + "0x1", + "0x400280057ff87fff", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x1", + "0x400280057ff87ffd", + "0x48307ffb80008002", + "0x48287ffa80028001", + "0x4844800180028001", + "0x100000000000000000000000000000000", + "0x4850800180018001", + "0xa0680017fff7ff6", + "0xc", + "0xa0680017fff8002", + "0x6", + "0x480a7ffd7fff7fff", + "0x48127ff27fff7fff", + "0x10780017fff7fff", + "0x10", + "0x48127ff37fff7fff", + "0x480a7ffd7fff7fff", + "0x10780017fff7fff", + "0xc", + "0x480780017fff7ffd", + "0x0", + "0xa0680017fff8001", + "0x6", + "0x480a7ffc7fff7ffe", + "0x40127ff27fff7ffe", + "0x10780017fff7fff", + "0x4", + "0x48127ff37fff7ffe", + "0x400a7ffc7fff7ffe", + "0x482480017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x400280067ff87fff", + "0x48507ffd7ffc8000", + "0x48307ff77ffa8000", + "0x48307ff17fff8000", + "0x40317ffd7fff7ffb", + "0x482680017ff88000", + "0x7", + "0x48127fec7fff8000", + "0x480a7ffc7fff8000", + "0x48127ff27fff8000", + "0x48127ff07fff8000", + "0x1104800180018000", + "0x13a", + "0x1104800180018000", + "0xdf", + "0x48127fd47fff8000", + "0x48127fd47fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff372", + "0x40137fc07fff8000", + "0x40137fc17fff8001", + "0x20680017fff7fff", + "0x8f", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff9f6", + "0x20680017fff7ffc", + "0x78", + "0x20680017fff7ffd", + "0x5f", + "0x48127fd17fff8000", + "0x48127fa67fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff9a", + "0x20680017fff7ff8", + "0x44", + "0x48127ff67fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x35c", + "0x20680017fff7ffd", + "0x2a", + "0x48127ffc7fff8000", + "0x48127f687fff8000", + "0x48127f687fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x370", + "0x20680017fff7ffd", + "0x10", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127f307fff8000", + "0x480680017fff8000", + "0x0", + "0x48127f307fff8000", + "0x48127f307fff8000", + "0x48127f327fff8000", + "0x48127f327fff8000", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x48307f3080007ff6", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x48127f317fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x48127f647fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127fcf7fff8000", + "0x48127fa47fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x482480017ff58000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127fd17fff8000", + "0x48127fa67fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x46", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff14", + "0x48127fe17fff8000", + "0x48127fb67fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff88000", + "0x1", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff67fff8000", + "0x482480017ff58000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x2f2", + "0x20680017fff7ffd", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235365f737562204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x4d", + "0x40780017fff7fff", + "0x2", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x44", + "0x48127fce7fff8000", + "0x48127fe77fff8000", + "0x1104800180018000", + "0x2db", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x37", + "0x48127fe57fff8000", + "0x48127fe77fff8000", + "0x1104800180018000", + "0x2ce", + "0x48127ffd7fff8000", + "0x48127fb97fff8000", + "0x48127fdb7fff8000", + "0x1104800180018000", + "0x2c9", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x25", + "0x48127fe77fff8000", + "0x48127fe57fff8000", + "0x1104800180018000", + "0x2d4", + "0x48127ffe7fff8000", + "0x48127fdb7fff8000", + "0x48127fdd7fff8000", + "0x1104800180018000", + "0x2b7", + "0x48127ffd7fff8000", + "0x48127ff37fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x2ca", + "0x48127ffe7fff8000", + "0x48127f997fff8000", + "0x48127fbb7fff8000", + "0x1104800180018000", + "0x2c5", + "0x48127ffe7fff8000", + "0x48127fe97fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x2a8", + "0x48127ffd7fff8000", + "0x48127fe97fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x2bb", + "0x48127ffe7fff8000", + "0x48127f407fff8000", + "0x48127f9b7fff8000", + "0x48127ff17fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x4824800180008002", + "0xffffffffffffffff0000000000000000", + "0x480280007ff98001", + "0x480280017ff97ffe", + "0x400280027ff97ffe", + "0x484480017ffe8000", + "0x10000000000000000", + "0x40317ffc7fff7ffa", + "0x48487ffb7ffc8000", + "0x48487ffb7ffc8000", + "0x4824800180018002", + "0xffffffffffffffff0000000000000000", + "0x480280037ff98001", + "0x480280047ff97fff", + "0x400280057ff97ffd", + "0x484480017ffd8000", + "0x10000000000000000", + "0x40307ffd7fff7ffb", + "0x484480017ffd8000", + "0x10000000000000000", + "0x48307fff7ff98003", + "0x482480017fff8000", + "0xfffffffffffffffe0000000000000000", + "0x480280067ff97fff", + "0x480280077ff97ffd", + "0x400380087ff97ffd", + "0x404480017ffc7ffe", + "0x100000000000000000000000000000000", + "0x40287ffd7ffe7fff", + "0x40317ffc7ff77ffc", + "0x482680017ff98000", + "0x9", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x10000000000000000", + "0x1104800180018000", + "0xbc", + "0x20680017fff7ffd", + "0x44", + "0x20680017fff7ffe", + "0x34", + "0x480280007ffc8005", + "0x480280017ffc8005", + "0x4824800180047ffe", + "0x1", + "0x48307ffd7ffe7ffc", + "0x480280027ffc7ffd", + "0xa0680017fff7ffd", + "0x6", + "0x482480017ff97ffd", + "0xffffffffffffffff0000000000000000", + "0x10780017fff7fff", + "0x4", + "0x482480017fff7ffd", + "0xffffffffffffffff0000000000000000", + "0x400280037ffc7ffc", + "0x40507ffe7ff87ffd", + "0x40317fff7ffd7ffd", + "0x482680017ffc8000", + "0x4", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x28a", + "0x20680017fff7ffd", + "0x14", + "0x48127ffc7fff8000", + "0x48127feb7fff8000", + "0x1104800180018000", + "0x284", + "0x20680017fff7ffd", + "0x8", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fea7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x13", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2b", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2d", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fcf7fff8000", + "0x48127fcf7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x270", + "0x20680017fff7ffe", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x7533322069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x4825800180007ffd", + "0x100000000", + "0x400280007ffc7fff", + "0x10780017fff7fff", + "0xc", + "0x482680017ffd8000", + "0xffffffffffffffffffffffff00000000", + "0x400280007ffc7fff", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0xa", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ffd", + "0x480680017fff8000", + "0x1", + "0x48127ffe7fff8000", + "0x482480017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x239", + "0x20680017fff7ffe", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x7536342069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0xa", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400180007fff7ffd", + "0x480680017fff8000", + "0x1", + "0x48127ffe7fff8000", + "0x482480017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x21a", + "0x20680017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xbaaedce6af48a03bbfd25e8cd0364141", + "0x480680017fff8000", + "0xfffffffffffffffffffffffffffffffe", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x536563703235366b31476574506f696e7446726f6d58", + "0x400280007ffa7fff", + "0x400380017ffa7ff9", + "0x400380027ffa7ffb", + "0x400380037ffa7ffc", + "0x400380047ffa7ffd", + "0x480280067ffa8000", + "0x20680017fff7fff", + "0xb", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x10780017fff7fff", + "0x9", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x29bfcdb2dce28d959f2815b16f81798", + "0x480680017fff8000", + "0x79be667ef9dcbbac55a06295ce870b07", + "0x480680017fff8000", + "0xfd17b448a68554199c47d08ffb10d4b8", + "0x480680017fff8000", + "0x483ada7726a3c4655da4fbfc0e1108a8", + "0x480680017fff8000", + "0x536563703235366b314e6577", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffb", + "0x400280037ffd7ffc", + "0x400280047ffd7ffd", + "0x400280057ffd7ffe", + "0x480280077ffd8000", + "0x20680017fff7fff", + "0xb", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x0", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280067ffd8000", + "0x482680017ffd8000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ffd8000", + "0x480280097ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff0f0", + "0x20680017fff7ffd", + "0x1b", + "0x20680017fff7ffe", + "0xc", + "0x40780017fff7fff", + "0x2", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff98", + "0x480a7ffb7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe2c", + "0x20680017fff7ffd", + "0x8", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x536563703235366b314d756c", + "0x400280007ffa7fff", + "0x400380017ffa7ff9", + "0x400380027ffa7ffb", + "0x400380037ffa7ffc", + "0x400380047ffa7ffd", + "0x480280067ffa8000", + "0x20680017fff7fff", + "0xc", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280077ffa8000", + "0x10780017fff7fff", + "0x9", + "0x480280057ffa8000", + "0x482680017ffa8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffa8000", + "0x480280087ffa8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x536563703235366b31416464", + "0x400280007ffb7fff", + "0x400380017ffb7ffa", + "0x400380027ffb7ffc", + "0x400380037ffb7ffd", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0xc", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280067ffb8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x536563703235366b314765745879", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400380027ffc7ffd", + "0x480280047ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x10780017fff7fff", + "0xd", + "0x480280037ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280057ffc8000", + "0x480280067ffc8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x40780017fff7fff", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x135", + "0x40137ffa7fff8000", + "0x20680017fff7ffb", + "0x48", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff4af", + "0x20680017fff7ffd", + "0x33", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x4b656363616b", + "0x400280007ffb7fff", + "0x400280017ffb7ff9", + "0x400280027ffb7ffd", + "0x400280037ffb7ffe", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0xb", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff5d6", + "0x20680017fff7ffd", + "0xb", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x480a80007fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127fed7fff8000", + "0x48127ff57fff8000", + "0x480a80007fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x160", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffc", + "0xc", + "0x20780017fff7ffd", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x151", + "0x20680017fff7ffd", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235365f6d756c204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x14e", + "0x20680017fff7ffd", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235365f616464204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x14b", + "0x20680017fff7fff", + "0x8", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x482a7ffd7ffc8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ffb7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x7", + "0x482680017ffb8000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x482a7ffd7ffc8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400280007ffb7fff", + "0x10780017fff7fff", + "0xa", + "0x400280007ffb7fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x1", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x482680017ffb8000", + "0x1", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x14c", + "0x20680017fff7ffe", + "0xb", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7074696f6e3a3a756e77726170206661696c65642e", + "0x400080007ffe7fff", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x132", + "0x20680017fff7ffe", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753132382069732030", + "0x400080007ffe7fff", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x482480017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x27b", + "0x482480017fff8000", + "0x27a", + "0x480080007fff8000", + "0x480080017fff8000", + "0x484480017fff8000", + "0x8", + "0x482480017fff8000", + "0x7792", + "0xa0680017fff8000", + "0x8", + "0x48317ffe80007ff8", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff77fff", + "0x10780017fff7fff", + "0x5e", + "0x48317ffe80007ff8", + "0x400280007ff77fff", + "0x482680017ff78000", + "0x1", + "0x48297ffa80007ffb", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffa8000", + "0x2", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x39", + "0x48127ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480080007ff98000", + "0x480080017ff88000", + "0x1104800180018000", + "0xf4", + "0x20680017fff7ffd", + "0x23", + "0x48127ffb7fff8000", + "0x48127f357fff8000", + "0x48127ffa7fff8000", + "0x48127f3a7fff8000", + "0x48127f3a7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc3", + "0x20680017fff7ffb", + "0xc", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127f357fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff87fff8000", + "0x48127ff67fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff78000", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x482480017ff78000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48297ffd80007ffc", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x108", + "0x20680017fff7fff", + "0x8", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x18d", + "0x20680017fff7fff", + "0x8", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffd80017ffb", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ff97fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ff98000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x7", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x48297ffc80017ffa", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ffa7fff", + "0x10780017fff7fff", + "0xc", + "0x400080007ffb7fff", + "0x40780017fff7fff", + "0x5", + "0x482480017ff68000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x1c", + "0x480680017fff8000", + "0x1", + "0x48307fff80017ffa", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080017ff67fff", + "0x10780017fff7fff", + "0xc", + "0x400080017ff77fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x8", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x4825800180007ffd", + "0x10000000000000000", + "0x400280007ffc7fff", + "0x10780017fff7fff", + "0xc", + "0x482680017ffd8000", + "0xffffffffffffffff0000000000000000", + "0x400280007ffc7fff", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ff97ffd", + "0x480680017fff8000", + "0xff00ff00ff00ff00ff00ff00ff00ff", + "0x400280017ff97fff", + "0x480280027ff98000", + "0x484480017fff8000", + "0xffff", + "0x48327fff7ffd8000", + "0x400280057ff97fff", + "0x480680017fff8000", + "0xffff0000ffff0000ffff0000ffff00", + "0x400280067ff97fff", + "0x480280077ff98000", + "0x484480017fff8000", + "0xffffffff", + "0x48307fff7ffc8000", + "0x4002800a7ff97fff", + "0x480680017fff8000", + "0xffffffff00000000ffffffff000000", + "0x4002800b7ff97fff", + "0x4802800c7ff98000", + "0x484480017fff8000", + "0xffffffffffffffff", + "0x48307fff7ffc8000", + "0x4002800f7ff97fff", + "0x480680017fff8000", + "0xffffffffffffffff00000000000000", + "0x400280107ff97fff", + "0x480280117ff98000", + "0x484480017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x48307fff7ffc8000", + "0x480a7ff87fff8000", + "0x484480017ffe8000", + "0x800000000000010fffffffffffffff7ffffffffffffef000000000000000001", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbc6", + "0x482680017ff98000", + "0x14", + "0x20680017fff7ffc", + "0x41", + "0x400280007ffb7ffe", + "0x400280017ffb7ffd", + "0x400180007fff7ffc", + "0x480680017fff8000", + "0xff00ff00ff00ff00ff00ff00ff00ff", + "0x400080017ffe7fff", + "0x480080027ffe8000", + "0x484480017fff8000", + "0xffff", + "0x48327fff7ffc8000", + "0x400080057ffb7fff", + "0x480680017fff8000", + "0xffff0000ffff0000ffff0000ffff00", + "0x400080067ffa7fff", + "0x480080077ffa8000", + "0x484480017fff8000", + "0xffffffff", + "0x48307fff7ffc8000", + "0x4000800a7ff77fff", + "0x480680017fff8000", + "0xffffffff00000000ffffffff000000", + "0x4000800b7ff67fff", + "0x4800800c7ff68000", + "0x484480017fff8000", + "0xffffffffffffffff", + "0x48307fff7ffc8000", + "0x4000800f7ff37fff", + "0x480680017fff8000", + "0xffffffffffffffff00000000000000", + "0x400080107ff27fff", + "0x480080117ff28000", + "0x484480017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x48307fff7ffc8000", + "0x48127feb7fff8000", + "0x484480017ffe8000", + "0x800000000000010fffffffffffffff7ffffffffffffef000000000000000001", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb9b", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x2", + "0x482480017fa58000", + "0x14", + "0x20680017fff7ffa", + "0xc", + "0x400080007ffe7ffc", + "0x400080017ffe7ffb", + "0x48127ff97fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x482480017ffa8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5b", + "0x48127fa07fff8000", + "0x48127fa37fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f9f7fff8000", + "0x48127f9f7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb50", + "0x40780017fff7fff", + "0x2", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb47", + "0x40780017fff7fff", + "0x2", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb3e", + "0x48127fb57fff8000", + "0x48127fce7fff8000", + "0x48127fcc7fff8000", + "0x48127fe47fff8000", + "0x48127fe47fff8000", + "0x48127fb17fff8000", + "0x48307ffb7ffa8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080007ff67fff", + "0x10780017fff7fff", + "0x56", + "0x400080007ff77fff", + "0x482480017ff78000", + "0x1", + "0x4824800180007ff9", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x40780017fff7fff", + "0xc", + "0x10780017fff7fff", + "0x41", + "0x4824800180007ff9", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x2e", + "0x480680017fff8000", + "0x0", + "0x48287ffb80017fff", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff67fff", + "0x10780017fff7fff", + "0xb", + "0x400080007ff77fff", + "0x40780017fff7fff", + "0x5", + "0x482480017ff28000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x19", + "0x480680017fff8000", + "0x0", + "0x48287ffd80017fff", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080017ff27fff", + "0x10780017fff7fff", + "0xb", + "0x400080017ff37fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ff28000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x6", + "0x482480017ff28000", + "0x2", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x7", + "0x40780017fff7fff", + "0x8", + "0x48127ff27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x9", + "0x40780017fff7fff", + "0xf", + "0x482480017fe78000", + "0x1", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x48307fe97ffe8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080007ffa7fff", + "0x10780017fff7fff", + "0xb", + "0x400080007ffb7fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ffa8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffa7fff8000", + "0x10780017fff7fff", + "0x7", + "0x482480017ffa8000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48127fe37fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x482a7ffd7ffb8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ff97fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ff98000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x7", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x482a7ffc7ffa8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080007ffa7fff", + "0x10780017fff7fff", + "0xc", + "0x400080007ffb7fff", + "0x40780017fff7fff", + "0x5", + "0x482480017ff68000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x1c", + "0x480680017fff8000", + "0x1", + "0x48307fff7ffa8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080017ff67fff", + "0x10780017fff7fff", + "0xc", + "0x400080017ff77fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x8", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe" + ], + "hints": [ + [ + 0, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 31, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 50, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x604a" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -53 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 72, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 95, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 110, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 124, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 138, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 155, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1270" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 198, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 217, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x3458" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -13 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 257, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 272, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 294, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 308, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 322, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 339, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1180" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 379, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 398, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x3584" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -13 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 422, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 440, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 455, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 477, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 499, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 514, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 562, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 581, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x2422" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -29 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 602, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 625, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 646, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 660, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 677, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xf35c" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 733, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 752, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xa654" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -73 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 795, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 813, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 828, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 842, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 856, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 870, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 892, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 906, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 923, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1270" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 966, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 985, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x3458" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -13 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1025, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1040, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1062, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1076, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1090, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1105, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x10fe" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1154, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1173, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x69dc" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -98 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1214, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1229, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1243, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1257, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1271, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1285, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1299, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1314, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1339, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1358, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x24ea" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -38 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1379, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1397, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1412, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1426, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1443, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x262" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1479, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1498, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x33f4" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -13 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1521, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1539, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1554, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1576, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1590, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1605, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1624, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1644, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x79e" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1662, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1673, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1689, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1707, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1c34" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1756, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1775, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x364c" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -32 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1800, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1818, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1833, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1847, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1869, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1883, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1897, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1912, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1931, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1950, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xdfe8" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1970, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1988, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2003, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2018, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2037, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2062, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -11 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2081, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2101, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2117, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2133, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2152, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2171, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x4586c" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2191, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2209, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2224, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2239, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2270, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2289, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -38 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2305, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2321, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2336, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2350, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2364, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2379, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2410, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2429, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x2d78" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -38 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2451, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2474, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2489, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2503, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2517, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2538, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 2542, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 2552, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2634, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 2667, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -11 + } + } + } + } + ] + ], + [ + 2726, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 2730, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 2740, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2800, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2859, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 2908, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 2949, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2953, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "scalar": { + "Immediate": "0x8000000000000110000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": 0 + }, + "y": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 2992, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 4323, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4337, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4351, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4417, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4431, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4459, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 4463, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4473, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4520, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 4557, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4581, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -8 + } + } + } + } + ] + ], + [ + 4604, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4619, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -13 + } + } + } + } + ] + ], + [ + 4670, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 4720, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -6 + } + } + } + } + ] + ], + [ + 4761, + [ + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 4845, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -8 + } + } + } + } + ] + ], + [ + 4887, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4911, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4931, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4945, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4959, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -11 + } + } + } + } + ] + ], + [ + 4962, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5003, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5049, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 5074, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5105, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -14 + } + } + } + } + ] + ], + [ + 5108, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5156, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -7 + } + } + } + } + ] + ], + [ + 5186, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -10 + } + } + } + } + ] + ], + [ + 5235, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5309, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5333, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5382, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 5407, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5437, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -14 + } + } + } + } + ] + ], + [ + 5440, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5487, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -7 + } + } + } + } + ] + ], + [ + 5517, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -10 + } + } + } + } + ] + ], + [ + 5566, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5631, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5669, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5691, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5777, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x12a2" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5860, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5892, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 5894, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "quotient": { + "register": "AP", + "offset": 3 + }, + "remainder": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 5954, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6042, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6107, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6111, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "scalar": { + "Immediate": "0x8000000000000110000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": 0 + }, + "y": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 6149, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 6282, + [ + { + "GetSegmentArenaIndex": { + "dict_end_ptr": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "dict_index": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 6323, + [ + { + "AllocSegment": { + "dst": { + "register": "FP", + "offset": 3 + } + } + } + ] + ], + [ + 6331, + [ + { + "InitSquashData": { + "dict_accesses": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "ptr_diff": { + "Deref": { + "register": "FP", + "offset": 0 + } + }, + "n_accesses": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "big_keys": { + "register": "FP", + "offset": 2 + }, + "first_key": { + "register": "FP", + "offset": 1 + } + } + } + ] + ], + [ + 6350, + [ + { + "GetCurrentAccessIndex": { + "range_check_ptr": { + "Deref": { + "register": "FP", + "offset": -9 + } + } + } + } + ] + ], + [ + 6363, + [ + { + "ShouldSkipSquashLoop": { + "should_skip_loop": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 6365, + [ + { + "GetCurrentAccessDelta": { + "index_delta_minus1": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6376, + [ + { + "ShouldContinueSquashLoop": { + "should_continue": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 6390, + [ + { + "GetNextDictKey": { + "next_key": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 6409, + [ + { + "AssertLeFindSmallArcs": { + "range_check_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "AP", + "offset": -4 + }, + "b": { + "Immediate": "0x1" + } + } + }, + "a": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "b": { + "Deref": { + "register": "FP", + "offset": 0 + } + } + } + } + ] + ], + [ + 6421, + [ + { + "AssertLeIsFirstArcExcluded": { + "skip_exclude_a_flag": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6433, + [ + { + "AssertLeIsSecondArcExcluded": { + "skip_exclude_b_minus_a": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6479, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6511, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 6725, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 6829, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 7021, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7043, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7065, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7108, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 7154, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x30ca" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7240, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7278, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x168a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -7 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7389, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7419, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7444, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1b3a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -7 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7561, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7591, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7616, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x614e" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -7 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7712, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7739, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "quotient": { + "register": "AP", + "offset": 3 + }, + "remainder": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 7811, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 7868, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "quotient": { + "register": "AP", + "offset": 3 + }, + "remainder": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 7895, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8036, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8069, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8089, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8237, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8423, + [ + { + "Uint512DivModByUint256": { + "dividend0": { + "Deref": { + "register": "AP", + "offset": -4 + } + }, + "dividend1": { + "Deref": { + "register": "AP", + "offset": -3 + } + }, + "dividend2": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "dividend3": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "divisor0": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "divisor1": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "quotient0": { + "register": "AP", + "offset": 0 + }, + "quotient1": { + "register": "AP", + "offset": 1 + }, + "quotient2": { + "register": "AP", + "offset": 2 + }, + "quotient3": { + "register": "AP", + "offset": 3 + }, + "remainder0": { + "register": "AP", + "offset": 4 + }, + "remainder1": { + "register": "AP", + "offset": 5 + } + } + } + ] + ], + [ + 8441, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -19 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": -9 + }, + "low": { + "register": "AP", + "offset": -10 + } + } + }, + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -18 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": -7 + }, + "low": { + "register": "AP", + "offset": -8 + } + } + }, + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -19 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "high": { + "register": "AP", + "offset": -5 + }, + "low": { + "register": "AP", + "offset": -6 + } + } + }, + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -18 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "high": { + "register": "AP", + "offset": -3 + }, + "low": { + "register": "AP", + "offset": -4 + } + } + }, + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -17 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": -1 + }, + "low": { + "register": "AP", + "offset": -2 + } + } + } + ] + ], + [ + 8470, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -35 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "dst": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 8482, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -35 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8548, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 8583, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8612, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -6 + } + } + } + } + ] + ], + [ + 8652, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 8678, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 8944, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 8956, + [ + { + "TestLessThan": { + "lhs": { + "BinOp": { + "op": "Add", + "a": { + "register": "FP", + "offset": -4 + }, + "b": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + }, + "rhs": { + "Immediate": "0x100000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9015, + [ + { + "TestLessThan": { + "lhs": { + "BinOp": { + "op": "Add", + "a": { + "register": "FP", + "offset": -4 + }, + "b": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9059, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 9106, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1612" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9181, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9202, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "quotient": { + "register": "AP", + "offset": 5 + }, + "remainder": { + "register": "AP", + "offset": 6 + } + } + } + ] + ], + [ + 9208, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": -3 + } + } + } + ] + ], + [ + 9229, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9425, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9447, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9469, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9526, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9668, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 9691, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 9733, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9756, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0xa820" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -7 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9768, + [ + { + "Uint256DivMod": { + "dividend0": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dividend1": { + "Deref": { + "register": "FP", + "offset": -5 + } + }, + "divisor0": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "divisor1": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "quotient0": { + "register": "AP", + "offset": 0 + }, + "quotient1": { + "register": "AP", + "offset": 1 + }, + "remainder0": { + "register": "AP", + "offset": 2 + }, + "remainder1": { + "register": "AP", + "offset": 3 + } + } + } + ] + ], + [ + 9784, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -7 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": 1 + }, + "low": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9791, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -12 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "dst": { + "register": "AP", + "offset": 2 + } + } + } + ] + ], + [ + 9803, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -12 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "dst": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 9939, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 9996, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10037, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10054, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 10063, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 10076, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -5 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 10094, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -5 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 10138, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "quotient": { + "register": "AP", + "offset": 1 + }, + "remainder": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10148, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "quotient": { + "register": "AP", + "offset": 0 + }, + "remainder": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 10159, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 2 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "quotient": { + "register": "AP", + "offset": -1 + }, + "remainder": { + "register": "FP", + "offset": -3 + } + } + } + ] + ], + [ + 10179, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "quotient": { + "register": "AP", + "offset": 5 + }, + "remainder": { + "register": "AP", + "offset": 6 + } + } + } + ] + ], + [ + 10185, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": -3 + } + } + } + ] + ], + [ + 10231, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10264, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10275, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10309, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10331, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10352, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10389, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -6 + } + } + } + } + ] + ], + [ + 10425, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 10460, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10512, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -6 + } + } + } + } + ] + ], + [ + 10552, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 10578, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 10606, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10640, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 10738, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10767, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10806, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 10830, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 10864, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10913, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 10934, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 11034, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 11116, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11139, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11159, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11183, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x10000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 11332, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 11341, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 11350, + [ + { + "WideMul128": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -5 + } + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "high": { + "register": "AP", + "offset": 0 + }, + "low": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 11366, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11406, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11425, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11465, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11492, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11515, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 11535, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ] + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x3c118a68e16e12e97ed25cb4901c12f4d3162818669cc44c391d8049924c14", + "offset": 675, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b", + "offset": 1314, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0xf818e4530ec36b83dfe702489b4df537308c3b798b0cc120e32c2056d68b7d", + "offset": 1912, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x10d2fede95e3ec06a875a67219425c27c5bd734d57f1b221d729a2337b6b556", + "offset": 1605, + "builtins": [ + "range_check", + "segment_arena" + ] + }, + { + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "offset": 1705, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x23039bef544cff56442d9f61ae9b13cf9e36fcce009102c5b678aac93f37b36", + "offset": 514, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "offset": 153, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "offset": 337, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x2d7cf5d5a324a320f9f37804b1615a533fde487400b41af80f13f7ac5581325", + "offset": 1441, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50", + "offset": 921, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x38be5d5f7bf135b52888ba3e440a457d11107aca3f6542e574b016bf3f074d8", + "offset": 2018, + "builtins": [ + "range_check", + "bitwise" + ] + }, + { + "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331", + "offset": 1105, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97", + "offset": 0, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x3d95049b565ec2d4197a55108ef03996381d31c84acf392a0a42b28163d69d1", + "offset": 2133, + "builtins": [ + "range_check" + ] + } + ], + "L1_HANDLER": [ + { + "selector": "0x39edbbb129ad752107a94d40c3873cae369a46fd2fc578d075679aa67e85d12", + "offset": 2239, + "builtins": [ + "range_check" + ] + } + ], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "offset": 2379, + "builtins": [ + "range_check" + ] + } + ] + } +} diff --git a/crates/papyrus_rpc/resources/deprecated_class.json b/crates/papyrus_rpc/resources/deprecated_class.json new file mode 100644 index 00000000000..365d76b1f56 --- /dev/null +++ b/crates/papyrus_rpc/resources/deprecated_class.json @@ -0,0 +1,5404 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + }, + { + "inputs": [], + "name": "without_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "with_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "return_result", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "x", + "type": "felt" + }, + { + "name": "y", + "type": "felt" + } + ], + "name": "bitwise_and", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "value", + "type": "felt" + } + ], + "name": "sqrt", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_storage_read_write", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_long_retdata", + "outputs": [ + { + "name": "a", + "type": "felt" + }, + { + "name": "b", + "type": "felt" + }, + { + "name": "c", + "type": "felt" + }, + { + "name": "d", + "type": "felt" + }, + { + "name": "e", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_library_call", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "lib_selector", + "type": "felt" + }, + { + "name": "nested_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_nested_library_call", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "function_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_call_contract", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "test_replace_class", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deploy_from_zero", + "type": "felt" + } + ], + "name": "test_deploy", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_storage_var", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "salt", + "type": "felt" + }, + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deployer_address", + "type": "felt" + } + ], + "name": "test_contract_address", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "foo", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "offset": 297, + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ], + "EXTERNAL": [ + { + "offset": 383, + "selector": "0xad451bd0dba3d8d97104e1bfc474f88605ccc7acbe1c846839a120fdf30d95" + }, + { + "offset": 645, + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b" + }, + { + "offset": 332, + "selector": "0xe7def693d16806ca2a2f398d8de5951344663ba77f340ed7a958da731872fc" + }, + { + "offset": 484, + "selector": "0x120c24672855cfe872cb35256ea85172417f2aada7a22c15908906dc5f3c69d" + }, + { + "offset": 407, + "selector": "0x137a07fa9c479e27114b8ae1fbf252f2065cf91a0d8615272e060a7ccf37309" + }, + { + "offset": 680, + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f" + }, + { + "offset": 799, + "selector": "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d" + }, + { + "offset": 615, + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c" + }, + { + "offset": 505, + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50" + }, + { + "offset": 731, + "selector": "0x36fa6de2810d05c3e1a0ebe23f60b9c2f4629bbead09e5a9704e1c5632630d5" + }, + { + "offset": 766, + "selector": "0x38215592552d97419658d30db8f189b242ec2056641de3dff8a7217745ec205" + }, + { + "offset": 316, + "selector": "0x382a967a31be13f23e23a5345f7a89b0362cc157d6fbe7564e6396a83cf4b4f" + }, + { + "offset": 359, + "selector": "0x39a1491f76903a16feed0a6433bec78de4c73194944e1118e226820ad479701" + }, + { + "offset": 577, + "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331" + }, + { + "offset": 442, + "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check", + "bitwise" + ], + "compiler_version": "0.11.1.1", + "data": [ + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x480280027ffb8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017ffe8000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff9", + "0x400380027ff87ffa", + "0x400380037ff87ffb", + "0x400380047ff87ffc", + "0x400380057ff87ffd", + "0x482680017ff88000", + "0x9", + "0x480280067ff88000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5265706c616365436c617373", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x3ffffffffffffffffffffffffffffff", + "0x480280017ffc8000", + "0x48307fff80007ffe", + "0x400280027ffc7fff", + "0x480280017ffc8000", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x480280007ffc8000", + "0x40317fff7ffe7ffd", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0x10", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48127ffe7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0xc", + "0x40780017fff7fff", + "0xa", + "0x480680017fff8000", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff", + "0x480a7ffc7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd8", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0xb", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff89", + "0x400780017fff8000", + "0x0", + "0x400780017fff8001", + "0x0", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480280007ffb8000", + "0x1104800180018000", + "0x2b", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff79", + "0x40137ffd7fff8000", + "0x480280017ffb8000", + "0x40297ffd7fff8001", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffb7fff8000", + "0x480280007ffc8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff66", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6a", + "0x40137ffd7fff8000", + "0x480280017ffc8000", + "0x402580017fff8001", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x27", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff4d", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffc", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffc8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x40337fff7ffb8000", + "0x480a7ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x48317ffd80008000", + "0x400080007ffd7ffe", + "0x480080007ffc8000", + "0x400080017ffc7fff", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x3", + "0x480080027ffa8000", + "0x20680017fff7ffb", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff8", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffa2", + "0x480a7ff77fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x535441524b4e45545f434f4e54524143545f41444452455353", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb6", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb3", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb0", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffc7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb9", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc2", + "0x480a7ff87fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff61", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x391a88f3badec8650b4d8356e18655269ee975e58e0060aa076396ce0b1dccb", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff03", + "0x480a7ffc7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff53", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff22", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1b", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff13", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400780017fff7ffd", + "0x19", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff2", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x480680017fff8000", + "0xf", + "0x400280027ffb7fff", + "0x482680017ffb8000", + "0x5", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280037ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff8000", + "0x9", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8e", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe83", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x48127ff67fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x2", + "0x480680017fff8000", + "0x3", + "0x480680017fff8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ff8", + "0x4003800180007ff9", + "0x4003800280007ffa", + "0x4003800380007ffb", + "0x4003800480007ffc", + "0x4826800180008000", + "0x5", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe8", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe23", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff7ffc", + "0x2", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x2", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde8", + "0x482480017fff8000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", + "0x40137fff7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x5", + "0x480a80007fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdee", + "0x48127ffd7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde7", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280037ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x4", + "0x480280037ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x480280037ffd8000", + "0x482680017ffd8000", + "0x4", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc3", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe3", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda9", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdbf", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd89", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff98000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x27", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe48", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe36", + "0x400680017fff7fff", + "0x27", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffea", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdea", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280017ffb8000", + "0x482480017ffe8000", + "0x1", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff78000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x480280007ffb8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "19": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.call_contract" + ], + "code": "syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": 0 + } + } + } + ], + "31": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.library_call" + ], + "code": "syscall_handler.library_call(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.library_call.syscall_ptr": 1 + } + } + } + ], + "44": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.deploy" + ], + "code": "syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.deploy.syscall_ptr": 2 + } + } + } + ], + "52": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 3 + } + } + } + ], + "61": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 4 + } + } + } + ], + "68": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.replace_class" + ], + "code": "syscall_handler.replace_class(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": 5 + } + } + } + ], + "71": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_250_bit" + ], + "code": "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_250_bit.high": 8, + "starkware.cairo.common.math.assert_250_bit.low": 7, + "starkware.cairo.common.math.assert_250_bit.value": 6 + } + } + } + ], + "86": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_small": 10 + } + } + } + ], + "104": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "ids.is_250 = 1 if ids.addr < 2**250 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_250": 11 + } + } + } + ], + "305": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.constructor" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 27, + "offset": 13 + }, + "reference_ids": {} + } + } + ], + "319": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.without_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 29, + "offset": 2 + }, + "reference_ids": {} + } + } + ], + "338": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.with_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 31, + "offset": 4 + }, + "reference_ids": {} + } + } + ], + "350": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.return_result_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 33, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "391": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.bitwise_and" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 36, + "offset": 8 + }, + "reference_ids": {} + } + } + ], + "403": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.sqrt" + ], + "code": "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)", + "flow_tracking_data": { + "ap_tracking": { + "group": 37, + "offset": 1 + }, + "reference_ids": { + "__main__.sqrt.root": 13, + "__main__.sqrt.value": 12 + } + } + } + ], + "414": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.sqrt" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 38, + "offset": 7 + }, + "reference_ids": {} + } + } + ], + "433": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_read_write_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 40, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "471": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_long_retdata_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 43, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "568": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_nested_library_call_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 48, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "652": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_replace_class" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 53, + "offset": 11 + }, + "reference_ids": {} + } + } + ], + "671": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_deploy_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 55, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "737": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_var" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 58, + "offset": 126 + }, + "reference_ids": {} + } + } + ], + "757": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_contract_address_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 61, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "802": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.foo" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 65, + "offset": 2 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "__main__.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 375, + "type": "function" + }, + "__main__.bitwise_and.Args": { + "full_name": "__main__.bitwise_and.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.bitwise_and.ImplicitArgs": { + "full_name": "__main__.bitwise_and.ImplicitArgs", + "members": { + "bitwise_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.bitwise_and.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.call_contract": { + "destination": "starkware.starknet.common.syscalls.call_contract", + "type": "alias" + }, + "__main__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 291, + "type": "function" + }, + "__main__.constructor.Args": { + "full_name": "__main__.constructor.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.constructor.ImplicitArgs": { + "full_name": "__main__.constructor.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.constructor.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.deploy": { + "destination": "starkware.starknet.common.syscalls.deploy", + "type": "alias" + }, + "__main__.foo": { + "decorators": [ + "external" + ], + "pc": 798, + "type": "function" + }, + "__main__.foo.Args": { + "full_name": "__main__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.ImplicitArgs": { + "full_name": "__main__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_contract_address": { + "destination": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address", + "type": "alias" + }, + "__main__.library_call": { + "destination": "starkware.starknet.common.syscalls.library_call", + "type": "alias" + }, + "__main__.number_map": { + "type": "namespace" + }, + "__main__.number_map.Args": { + "full_name": "__main__.number_map.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.number_map.ImplicitArgs": { + "full_name": "__main__.number_map.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.addr": { + "decorators": [], + "pc": 250, + "type": "function" + }, + "__main__.number_map.addr.Args": { + "full_name": "__main__.number_map.addr.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.addr.ImplicitArgs": { + "full_name": "__main__.number_map.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.number_map.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "__main__.number_map.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "__main__.number_map.read": { + "decorators": [], + "pc": 264, + "type": "function" + }, + "__main__.number_map.read.Args": { + "full_name": "__main__.number_map.read.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.read.ImplicitArgs": { + "full_name": "__main__.number_map.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "__main__.number_map.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.number_map.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.number_map.write": { + "decorators": [], + "pc": 278, + "type": "function" + }, + "__main__.number_map.write.Args": { + "full_name": "__main__.number_map.write.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.write.ImplicitArgs": { + "full_name": "__main__.number_map.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.replace_class": { + "destination": "starkware.starknet.common.syscalls.replace_class", + "type": "alias" + }, + "__main__.return_result": { + "decorators": [ + "external" + ], + "pc": 348, + "type": "function" + }, + "__main__.return_result.Args": { + "full_name": "__main__.return_result.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.return_result.ImplicitArgs": { + "full_name": "__main__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.return_result.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.sqrt": { + "decorators": [ + "external" + ], + "pc": 401, + "type": "function" + }, + "__main__.sqrt.Args": { + "full_name": "__main__.sqrt.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.ImplicitArgs": { + "full_name": "__main__.sqrt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.sqrt.root": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.root", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ], + "type": "reference" + }, + "__main__.sqrt.value": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.value", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 607, + "type": "function" + }, + "__main__.test_call_contract.Args": { + "full_name": "__main__.test_call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_call_contract.ImplicitArgs": { + "full_name": "__main__.test_call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 747, + "type": "function" + }, + "__main__.test_contract_address.Args": { + "full_name": "__main__.test_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_contract_address.ImplicitArgs": { + "full_name": "__main__.test_contract_address.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 662, + "type": "function" + }, + "__main__.test_deploy.Args": { + "full_name": "__main__.test_deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_deploy.ImplicitArgs": { + "full_name": "__main__.test_deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 497, + "type": "function" + }, + "__main__.test_library_call.Args": { + "full_name": "__main__.test_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_library_call.ImplicitArgs": { + "full_name": "__main__.test_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 460, + "type": "function" + }, + "__main__.test_long_retdata.Args": { + "full_name": "__main__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.ImplicitArgs": { + "full_name": "__main__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.Return": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "type": "type_definition" + }, + "__main__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 530, + "type": "function" + }, + "__main__.test_nested_library_call.Args": { + "full_name": "__main__.test_nested_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "lib_selector": { + "cairo_type": "felt", + "offset": 1 + }, + "nested_selector": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_nested_library_call.ImplicitArgs": { + "full_name": "__main__.test_nested_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_nested_library_call.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 640, + "type": "function" + }, + "__main__.test_replace_class.Args": { + "full_name": "__main__.test_replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.ImplicitArgs": { + "full_name": "__main__.test_replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 424, + "type": "function" + }, + "__main__.test_storage_read_write.Args": { + "full_name": "__main__.test_storage_read_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_storage_read_write.ImplicitArgs": { + "full_name": "__main__.test_storage_read_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_storage_read_write.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 712, + "type": "function" + }, + "__main__.test_storage_var.Args": { + "full_name": "__main__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_storage_var.ImplicitArgs": { + "full_name": "__main__.test_storage_var.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.test_storage_var.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.with_arg": { + "decorators": [ + "external" + ], + "pc": 329, + "type": "function" + }, + "__main__.with_arg.Args": { + "full_name": "__main__.with_arg.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.with_arg.ImplicitArgs": { + "full_name": "__main__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.with_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.without_arg": { + "decorators": [ + "external" + ], + "pc": 315, + "type": "function" + }, + "__main__.without_arg.Args": { + "full_name": "__main__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.ImplicitArgs": { + "full_name": "__main__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 383, + "type": "function" + }, + "__wrappers__.bitwise_and.Args": { + "full_name": "__wrappers__.bitwise_and.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.ImplicitArgs": { + "full_name": "__wrappers__.bitwise_and.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: starkware.cairo.common.cairo_builtins.BitwiseBuiltin*, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and.__wrapped_func": { + "destination": "__main__.bitwise_and", + "type": "alias" + }, + "__wrappers__.bitwise_and_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 297, + "type": "function" + }, + "__wrappers__.constructor.Args": { + "full_name": "__wrappers__.constructor.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.ImplicitArgs": { + "full_name": "__wrappers__.constructor.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.constructor.__wrapped_func": { + "destination": "__main__.constructor", + "type": "alias" + }, + "__wrappers__.constructor_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.foo": { + "decorators": [ + "external" + ], + "pc": 799, + "type": "function" + }, + "__wrappers__.foo.Args": { + "full_name": "__wrappers__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.ImplicitArgs": { + "full_name": "__wrappers__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.foo.__wrapped_func": { + "destination": "__main__.foo", + "type": "alias" + }, + "__wrappers__.foo_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.return_result": { + "decorators": [ + "external" + ], + "pc": 359, + "type": "function" + }, + "__wrappers__.return_result.Args": { + "full_name": "__wrappers__.return_result.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.ImplicitArgs": { + "full_name": "__wrappers__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.return_result.__wrapped_func": { + "destination": "__main__.return_result", + "type": "alias" + }, + "__wrappers__.return_result_encode_return": { + "decorators": [], + "pc": 350, + "type": "function" + }, + "__wrappers__.return_result_encode_return.Args": { + "full_name": "__wrappers__.return_result_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.return_result_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.return_result_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.sqrt": { + "decorators": [ + "external" + ], + "pc": 407, + "type": "function" + }, + "__wrappers__.sqrt.Args": { + "full_name": "__wrappers__.sqrt.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.ImplicitArgs": { + "full_name": "__wrappers__.sqrt.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.sqrt.__wrapped_func": { + "destination": "__main__.sqrt", + "type": "alias" + }, + "__wrappers__.sqrt_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 615, + "type": "function" + }, + "__wrappers__.test_call_contract.Args": { + "full_name": "__wrappers__.test_call_contract.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.ImplicitArgs": { + "full_name": "__wrappers__.test_call_contract.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_call_contract.__wrapped_func": { + "destination": "__main__.test_call_contract", + "type": "alias" + }, + "__wrappers__.test_call_contract_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 766, + "type": "function" + }, + "__wrappers__.test_contract_address.Args": { + "full_name": "__wrappers__.test_contract_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_contract_address.__wrapped_func": { + "destination": "__main__.test_contract_address", + "type": "alias" + }, + "__wrappers__.test_contract_address_encode_return": { + "decorators": [], + "pc": 757, + "type": "function" + }, + "__wrappers__.test_contract_address_encode_return.Args": { + "full_name": "__wrappers__.test_contract_address_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_contract_address_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 680, + "type": "function" + }, + "__wrappers__.test_deploy.Args": { + "full_name": "__wrappers__.test_deploy.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_deploy.__wrapped_func": { + "destination": "__main__.test_deploy", + "type": "alias" + }, + "__wrappers__.test_deploy_encode_return": { + "decorators": [], + "pc": 671, + "type": "function" + }, + "__wrappers__.test_deploy_encode_return.Args": { + "full_name": "__wrappers__.test_deploy_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_deploy_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 505, + "type": "function" + }, + "__wrappers__.test_library_call.Args": { + "full_name": "__wrappers__.test_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_library_call.__wrapped_func": { + "destination": "__main__.test_library_call", + "type": "alias" + }, + "__wrappers__.test_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 484, + "type": "function" + }, + "__wrappers__.test_long_retdata.Args": { + "full_name": "__wrappers__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_long_retdata.__wrapped_func": { + "destination": "__main__.test_long_retdata", + "type": "alias" + }, + "__wrappers__.test_long_retdata_encode_return": { + "decorators": [], + "pc": 471, + "type": "function" + }, + "__wrappers__.test_long_retdata_encode_return.Args": { + "full_name": "__wrappers__.test_long_retdata_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 5 + }, + "ret_value": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_long_retdata_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 577, + "type": "function" + }, + "__wrappers__.test_nested_library_call.Args": { + "full_name": "__wrappers__.test_nested_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_nested_library_call.__wrapped_func": { + "destination": "__main__.test_nested_library_call", + "type": "alias" + }, + "__wrappers__.test_nested_library_call_encode_return": { + "decorators": [], + "pc": 568, + "type": "function" + }, + "__wrappers__.test_nested_library_call_encode_return.Args": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_nested_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 645, + "type": "function" + }, + "__wrappers__.test_replace_class.Args": { + "full_name": "__wrappers__.test_replace_class.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.ImplicitArgs": { + "full_name": "__wrappers__.test_replace_class.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_replace_class.__wrapped_func": { + "destination": "__main__.test_replace_class", + "type": "alias" + }, + "__wrappers__.test_replace_class_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 442, + "type": "function" + }, + "__wrappers__.test_storage_read_write.Args": { + "full_name": "__wrappers__.test_storage_read_write.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_read_write.__wrapped_func": { + "destination": "__main__.test_storage_read_write", + "type": "alias" + }, + "__wrappers__.test_storage_read_write_encode_return": { + "decorators": [], + "pc": 433, + "type": "function" + }, + "__wrappers__.test_storage_read_write_encode_return.Args": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_storage_read_write_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 731, + "type": "function" + }, + "__wrappers__.test_storage_var.Args": { + "full_name": "__wrappers__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_var.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_var.__wrapped_func": { + "destination": "__main__.test_storage_var", + "type": "alias" + }, + "__wrappers__.test_storage_var_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.with_arg": { + "decorators": [ + "external" + ], + "pc": 332, + "type": "function" + }, + "__wrappers__.with_arg.Args": { + "full_name": "__wrappers__.with_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.ImplicitArgs": { + "full_name": "__wrappers__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.with_arg.__wrapped_func": { + "destination": "__main__.with_arg", + "type": "alias" + }, + "__wrappers__.with_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.without_arg": { + "decorators": [ + "external" + ], + "pc": 316, + "type": "function" + }, + "__wrappers__.without_arg.Args": { + "full_name": "__wrappers__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.ImplicitArgs": { + "full_name": "__wrappers__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.without_arg.__wrapped_func": { + "destination": "__main__.without_arg", + "type": "alias" + }, + "__wrappers__.without_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash.hash2": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.hash.hash2.Args": { + "full_name": "starkware.cairo.common.hash.hash2.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash.hash2.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash.hash2.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash_state.HashState": { + "full_name": "starkware.cairo.common.hash_state.HashState", + "members": { + "current_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "n_words": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash_felts": { + "decorators": [], + "pc": 208, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.Args", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 0 + }, + "length": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding": { + "decorators": [], + "pc": 183, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 1 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "initial_hash": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals", + "members": { + "cur_hash": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.hash_loop": { + "pc": 196, + "type": "label" + }, + "starkware.cairo.common.hash_state.hash_finalize": { + "decorators": [], + "pc": 177, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_finalize.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_finalize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_init": { + "decorators": [], + "pc": 124, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_init.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_init.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_init.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.Return": { + "cairo_type": "(hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_init.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update": { + "decorators": [], + "pc": 134, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_single": { + "decorators": [], + "pc": 150, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_single.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + }, + "item": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_single.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain": { + "decorators": [], + "pc": 166, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.math.assert_250_bit": { + "decorators": [ + "known_ap_change" + ], + "pc": 71, + "type": "function" + }, + "starkware.cairo.common.math.assert_250_bit.Args": { + "full_name": "starkware.cairo.common.math.assert_250_bit.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.HIGH_BOUND": { + "type": "const", + "value": 5316911983139663491615228241121378304 + }, + "starkware.cairo.common.math.assert_250_bit.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_250_bit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_250_bit.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND": { + "type": "const", + "value": 1809251394333065553493296640760748560207343510400633813116524750123642650624 + }, + "starkware.cairo.common.math.assert_250_bit.high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.high", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.low", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.value", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.registers.get_ap": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.registers.get_fp_and_pc": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap": { + "decorators": [ + "known_ap_change" + ], + "pc": 7, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Return": { + "cairo_type": "(ap_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc": { + "decorators": [], + "pc": 6, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Return": { + "cairo_type": "(fp_val: felt*, pc_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.storage.normalize_address": { + "decorators": [ + "known_ap_change" + ], + "pc": 84, + "type": "function" + }, + "starkware.starknet.common.storage.normalize_address.Args": { + "full_name": "starkware.starknet.common.storage.normalize_address.Args", + "members": { + "addr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.storage.normalize_address.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.normalize_address.addr": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.addr", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_250": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_250", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_small": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_small", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract": { + "decorators": [], + "pc": 12, + "type": "function" + }, + "starkware.starknet.common.syscalls.call_contract.Args": { + "full_name": "starkware.starknet.common.syscalls.call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.call_contract.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 1 + }, + "pc": 19, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.deploy": { + "decorators": [], + "pc": 36, + "type": "function" + }, + "starkware.starknet.common.syscalls.deploy.Args": { + "full_name": "starkware.starknet.common.syscalls.deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.deploy.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.deploy.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 1 + }, + "pc": 44, + "value": "cast([fp + (-8)] + 9, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.library_call": { + "decorators": [], + "pc": 24, + "type": "function" + }, + "starkware.starknet.common.syscalls.library_call.Args": { + "full_name": "starkware.starknet.common.syscalls.library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.library_call.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.library_call.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 1 + }, + "pc": 31, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.replace_class": { + "decorators": [], + "pc": 64, + "type": "function" + }, + "starkware.starknet.common.syscalls.replace_class.Args": { + "full_name": "starkware.starknet.common.syscalls.replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.replace_class.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 68, + "value": "cast([fp + (-4)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 48, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 1 + }, + "pc": 52, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 56, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 1 + }, + "pc": 61, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.core.os.contract_address.contract_address.CONTRACT_ADDRESS_PREFIX": { + "type": "const", + "value": 523065374597054866729014270389667305596563390979550329787219 + }, + "starkware.starknet.core.os.contract_address.contract_address.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address": { + "decorators": [], + "pc": 219, + "type": "function" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_finalize": { + "destination": "starkware.cairo.common.hash_state.hash_finalize", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_init": { + "destination": "starkware.cairo.common.hash_state.hash_init", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update": { + "destination": "starkware.cairo.common.hash_state.hash_update", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_single": { + "destination": "starkware.cairo.common.hash_state.hash_update_single", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_with_hashchain": { + "destination": "starkware.cairo.common.hash_state.hash_update_with_hashchain", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ] + } + } +} diff --git a/crates/papyrus_rpc/resources/erc20_fee_contract_class.json b/crates/papyrus_rpc/resources/erc20_fee_contract_class.json new file mode 100644 index 00000000000..72ac9b768ca --- /dev/null +++ b/crates/papyrus_rpc/resources/erc20_fee_contract_class.json @@ -0,0 +1,9101 @@ +{ + "abi": [ + { + "members": [ + { + "name": "low", + "offset": 0, + "type": "felt" + }, + { + "name": "high", + "offset": 1, + "type": "felt" + } + ], + "name": "Uint256", + "size": 2, + "type": "struct" + }, + { + "data": [ + { + "name": "from_", + "type": "felt" + }, + { + "name": "to", + "type": "felt" + }, + { + "name": "value", + "type": "Uint256" + } + ], + "keys": [], + "name": "Transfer", + "type": "event" + }, + { + "data": [ + { + "name": "owner", + "type": "felt" + }, + { + "name": "spender", + "type": "felt" + }, + { + "name": "value", + "type": "Uint256" + } + ], + "keys": [], + "name": "Approval", + "type": "event" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "name", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "symbol", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "totalSupply", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "decimals", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "account", + "type": "felt" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "owner", + "type": "felt" + }, + { + "name": "spender", + "type": "felt" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "Uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permittedMinter", + "outputs": [ + { + "name": "minter", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "get_version", + "outputs": [ + { + "name": "version", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "get_identity", + "outputs": [ + { + "name": "identity", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "init_vector_len", + "type": "felt" + }, + { + "name": "init_vector", + "type": "felt*" + } + ], + "name": "initialize", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "sender", + "type": "felt" + }, + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "added_value", + "type": "Uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "spender", + "type": "felt" + }, + { + "name": "subtracted_value", + "type": "Uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "name": "success", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "recipient", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "permissionedMint", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "account", + "type": "felt" + }, + { + "name": "amount", + "type": "Uint256" + } + ], + "name": "permissionedBurn", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": "0x65d", + "selector": "0x151e58b29179122a728eab07c8847e5baf5802379c5db3a7d57a8263a7bd1d" + }, + { + "offset": "0x574", + "selector": "0x41b033f4a31df8067c24d1e9b550a2ce75fd4a29e1147af9752174f0e6cb20" + }, + { + "offset": "0x2cb", + "selector": "0x4c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9" + }, + { + "offset": "0x4f1", + "selector": "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463" + }, + { + "offset": "0x2ad", + "selector": "0x80aa9fdbfaf9615e4afc7f5f722e265daca5ccc655360fa5ccacf9c267936d" + }, + { + "offset": "0x524", + "selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e" + }, + { + "offset": "0x682", + "selector": "0xd63a78e4cd7fb4c41bc18d089154af78d400a5e837f270baea6cf8db18c8dd" + }, + { + "offset": "0x5e9", + "selector": "0x16cc063b8338363cf388ce7fe1df408bf10f16cd51635d392e21d852fafb683" + }, + { + "offset": "0x638", + "selector": "0x1aaf3e6107dd1349c81543ff4221a326814f77dadcc5810807b74f1a49ded4e" + }, + { + "offset": "0x30f", + "selector": "0x1e888a1026b19c8c0b57c72d63ed1737106aa10034105b980ba117bd0c29fe1" + }, + { + "offset": "0x28e", + "selector": "0x216b05c387bab9ac31918a3e61672f4618601f3c598a2f3f2710f37053e1ea4" + }, + { + "offset": "0x5a1", + "selector": "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c" + }, + { + "offset": "0x4bd", + "selector": "0x2a4bb4205277617b698a9a2950b938d0a236dd4619f82f05bec02bdbd245fab" + }, + { + "offset": "0x4d5", + "selector": "0x2c4943a27e820803a6ef49bb04b629950e2de615ab9ac0fb8baef037b168782" + }, + { + "offset": "0x2eb", + "selector": "0x2e4263afad30923c891518314c3c95dbe830a16874e8abc5777a9a20b54c76e" + }, + { + "offset": "0x442", + "selector": "0x358a2fe57368393087d3e6d24f1e04741c5bdc85e3e23790253e377f55c391e" + }, + { + "offset": "0x270", + "selector": "0x361458367e696363fbcc70777d07ebbd2394e89fd0adcaf147faccd1d294d60" + }, + { + "offset": "0x48d", + "selector": "0x3c0ba99f1a18bcdc81fcbcb6b4f15a9a6725f937075aed6fac107ffcb147068" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized" + ], + "end_pc": 1187, + "flow_tracking_data": { + "ap_tracking": { + "group": 79, + "offset": 28 + }, + "reference_ids": {} + }, + "name": "error_message", + "start_pc": 1185, + "value": "ALREADY_INITIALIZED" + }, + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.initialize" + ], + "end_pc": 1256, + "flow_tracking_data": { + "ap_tracking": { + "group": 87, + "offset": 60 + }, + "reference_ids": {} + }, + "name": "error_message", + "start_pc": 1254, + "value": "ILLEGAL_INIT_SIZE" + } + ], + "builtins": [ + "pedersen", + "range_check" + ], + "compiler_version": "0.10.3", + "data": [ + "0x40780017fff7fff", + "0x1", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x480280027ffb8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffd", + "0x4", + "0x400780017fff7ffd", + "0x1", + "0x208b7fff7fff7ffe", + "0x400380007ffc7ffd", + "0x482680017ffc8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x48297ffc80007ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x3ffffffffffffffffffffffffffffff", + "0x480280017ffc8000", + "0x48307fff80007ffe", + "0x400280027ffc7fff", + "0x480280017ffc8000", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x480280007ffc8000", + "0x40317fff7ffe7ffd", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x484480017fff8000", + "0x2aaaaaaaaaaaab05555555555555556", + "0x48307fff7ffd8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x484480017fff8000", + "0x4000000000000088000000000000001", + "0x48307fff7ffd8000", + "0xa0680017fff8000", + "0xe", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48287ffc80007fff", + "0x40307ffc7ff87fff", + "0x48297ffd80007ffc", + "0x482680017ffd8000", + "0x1", + "0x48507fff7ffe8000", + "0x40507ff97ff57fff", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xc", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48287ffd80007fff", + "0x48327fff7ffc8000", + "0x40307ffa7ff67fff", + "0x48527ffe7ffc8000", + "0x40507ff97ff57fff", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40317ffd7ff97ffd", + "0x48297ffc80007ffd", + "0x48527fff7ffc8000", + "0x40507ffb7ff77fff", + "0x40780017fff7fff", + "0x2", + "0x482680017ffb8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0x10", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc0", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48127ffe7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffba", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0xc", + "0x40780017fff7fff", + "0xa", + "0x480680017fff8000", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff", + "0x480a7ffc7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffab", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0xb", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffa3", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x47657443616c6c657241646472657373", + "0x400280007ffd7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x5", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xa", + "0x400380007ffc7ffd", + "0x40780017fff7fff", + "0x14", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0xe", + "0x484680017ffd8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x400280007ffc7fff", + "0x40780017fff7fff", + "0x11", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x100000000000000000000000000000000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6f", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x48297ffc80007ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x404b800280028002", + "0x404b800380038003", + "0x482a7ffc7ffa8000", + "0x4846800180028000", + "0x100000000000000000000000000000000", + "0x40327fff80007ffe", + "0x482a7ffd7ffb8000", + "0x482880027fff8000", + "0x4846800180038000", + "0x100000000000000000000000000000000", + "0x40327fff80017ffe", + "0x480a7ff97fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a80037fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffd80007ffb", + "0x20680017fff7fff", + "0x9", + "0x480a7ff97fff8000", + "0x482680017ffa8000", + "0x1", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x482680017ffb8000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd3", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480680017fff8000", + "0x1", + "0x48127ffd7fff8000", + "0x48307ffd80007ffe", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x480680017fff8000", + "0xffffffffffffffffffffffffffffffff", + "0x480a7ffb7fff8000", + "0x48287ffc80007ffd", + "0x48287ffd80007ffd", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbd", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffed7", + "0x40137fff7fff8000", + "0x480680017fff8000", + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x4002800080007fff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffed1", + "0x40137fff7fff8001", + "0x4003800080017ffa", + "0x4003800180017ffb", + "0x4003800280017ffc", + "0x4003800380017ffd", + "0x4826800180018000", + "0x4", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480a80007fff8000", + "0x4828800180007ffc", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff5b", + "0x480a7ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffebc", + "0x40137fff7fff8000", + "0x480680017fff8000", + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff", + "0x4002800080007fff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeb6", + "0x40137fff7fff8001", + "0x4003800080017ffa", + "0x4003800180017ffb", + "0x4003800280017ffc", + "0x4003800380017ffd", + "0x4826800180018000", + "0x4", + "0x480a7ff87fff8000", + "0x480680017fff8000", + "0x1", + "0x480a80007fff8000", + "0x4828800180007ffc", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff40", + "0x480a7ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x341c1bdfd89f69748aa00b5742b03adbffd79b8e80cab5c50d91cd8c2a79be1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff21", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1b", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0xb6ce5410fca59d078ee9b2a4371a9d684c530d697c64fbef0ae6d5e8f0ac72", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff03", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffefd", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1f0d4aa99431d246bac9b8e48c33e888245b15e9678f64f9bdfc8823dc8f979", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffee5", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffedf", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x110e2f729c9c2b988559994a3daccd838cf52faf88e18101373e67dd061455a", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec7", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec2", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffebb", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeb6", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x3a4e8ec16e258a799fe707996fd5d21d42b29adc1499a370edf7f809d8c458a", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe1f", + "0x480a7ffc7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe72", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe94", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8f", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdc", + "0x480a7ff87fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe87", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe82", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x3c87bf42ed4f01f11883bf54f43d91d2cbbd5fec26d1df9c74c57ae138800a4", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdeb", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde8", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe3b", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe5c", + "0x48127ffe7fff8000", + "0x482480017ff78000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe57", + "0x48127ffe7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48127ff57fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd7", + "0x480a7ff77fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe4e", + "0x482480017ff88000", + "0x1", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe49", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0xff", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc6", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff19", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff34", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff4f", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff00", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff00", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1e", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffee1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff12", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff25", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffb", + "0x4003800180007ffc", + "0x4826800180008000", + "0x2", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff37fff8000", + "0x48127ff37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffce5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda0", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd9b", + "0x48127fe57fff8000", + "0x48127fe57fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffec8", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe80", + "0x40137ffe7fff8000", + "0x40137fff7fff8001", + "0x48127ffd7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd88", + "0x40137ffd7fff8002", + "0x40137ffe7fff8003", + "0x400680017fff7fff", + "0x0", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x48127ffa7fff8000", + "0x480a80027fff8000", + "0x480a80037fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe7f", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdce", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffca6", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffca3", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd5e", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe7e", + "0x40137ffe7fff8000", + "0x40137fff7fff8001", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd7b", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc8d", + "0x48127ffc7fff8000", + "0x480a80007fff8000", + "0x480a80017fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd95", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe78", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe61", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd3c", + "0x48127fe57fff8000", + "0x48127fe57fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe69", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd86", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc60", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc5d", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd18", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe81", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd81", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x0", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc3e", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcf9", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe19", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd18", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc2a", + "0x48127ffc7fff8000", + "0x48127fc97fff8000", + "0x48127fc97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd32", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe15", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdcd", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd24", + "0x48127fb37fff8000", + "0x48127fb37fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdd5", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd24", + "0x48127ffe7fff8000", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1390569bb0a3a722eb4228e8700301347da081211d5c2ded2db22ef389551ab", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc74", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc6e", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbe0", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdb", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc31", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbb1", + "0x40127ffd7fff7fe1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x2cd2687c06d341ffd0b635e3229e2ca36108201a2112da0d058d03b77eb5092", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc1f", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc19", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe5", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x400680017fff7fff", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc5", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4552433230", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc4", + "0x400780017fff7ffc", + "0x4", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd64", + "0x480280037ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff3c", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280007ffd8000", + "0x482680017ffd8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb76", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe4c", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x3", + "0x480a7ff77fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb48", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a80007fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffce4", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbaa", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffabc", + "0x48127fc77fff8000", + "0x48127fc77fff8000", + "0x48127ffa7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe0b", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbbc", + "0x48127fb37fff8000", + "0x48127fb37fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a80007fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcd6", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x4", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x480280037ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbb", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffaf9", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127ffc7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe17", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb10", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffac6", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x48127ff77fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc62", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb01", + "0x40137ffd7fff8003", + "0x40137ffe7fff8004", + "0x400680017fff7fff", + "0x0", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x48127ffa7fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdcf", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc4", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffac8", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffa7e", + "0x40137fff7fff8000", + "0x48127ffe7fff8000", + "0x480a7ff97fff8000", + "0x48127ff77fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc1a", + "0x40137ffe7fff8001", + "0x40137fff7fff8002", + "0x48127ffd7fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb03", + "0x40137ffe7fff8003", + "0x40137fff7fff8004", + "0x48127ffd7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x480a80017fff8000", + "0x480a80027fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffad7", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff9e9", + "0x48127f7c7fff8000", + "0x48127f7c7fff8000", + "0x48127ffa7fff8000", + "0x480a80007fff8000", + "0x480a7ffb7fff8000", + "0x480a80037fff8000", + "0x480a80047fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd80", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbd", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe01", + "0x40137ffd7fff8000", + "0x480a80007fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcc9", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddc", + "0x40137ffd7fff8000", + "0x480a80007fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd4b", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x3", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "0": [ + { + "accessible_scopes": [ + "starkware.cairo.common.alloc", + "starkware.cairo.common.alloc.alloc" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "9": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_not_zero" + ], + "code": "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'", + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_not_zero.value": 0 + } + } + } + ], + "14": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_nn" + ], + "code": "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_nn.a": 1 + } + } + } + ], + "32": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_250_bit" + ], + "code": "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_250_bit.high": 4, + "starkware.cairo.common.math.assert_250_bit.low": 3, + "starkware.cairo.common.math.assert_250_bit.value": 2 + } + } + } + ], + "45": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "import itertools\n\nfrom starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\na = ids.a % PRIME\nb = ids.b % PRIME\nassert a <= b, f'a = {a} is not less than or equal to b = {b}.'\n\n# Find an arc less than PRIME / 3, and another less than PRIME / 2.\nlengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)]\nlengths_and_indices.sort()\nassert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2\nexcluded = lengths_and_indices[2][1]\n\nmemory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (\n divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH))\nmemory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (\n divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_le_felt.a": 5, + "starkware.cairo.common.math.assert_le_felt.b": 6, + "starkware.cairo.common.math.assert_le_felt.range_check_ptr": 7 + } + } + } + ], + "55": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "memory[ap] = 1 if excluded != 0 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 8 + }, + "reference_ids": {} + } + } + ], + "69": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "memory[ap] = 1 if excluded != 1 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 9 + }, + "reference_ids": {} + } + } + ], + "81": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_le_felt" + ], + "code": "assert excluded == 2", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 10 + }, + "reference_ids": {} + } + } + ], + "92": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 8, + "starkware.starknet.common.storage.normalize_address.is_small": 9 + } + } + } + ], + "110": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "ids.is_250 = 1 if ids.addr < 2**250 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 8, + "starkware.starknet.common.storage.normalize_address.is_250": 10 + } + } + } + ], + "133": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.get_caller_address" + ], + "code": "syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": 11 + } + } + } + ], + "141": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 12 + } + } + } + ], + "150": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 11, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 13 + } + } + } + ], + "160": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.emit_event" + ], + "code": "syscall_handler.emit_event(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 12, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.emit_event.syscall_ptr": 14 + } + } + } + ], + "163": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math_cmp", + "starkware.cairo.common.math_cmp.is_nn" + ], + "code": "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1", + "flow_tracking_data": { + "ap_tracking": { + "group": 13, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math_cmp.is_nn.a": 15 + } + } + } + ], + "173": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math_cmp", + "starkware.cairo.common.math_cmp.is_nn" + ], + "code": "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1", + "flow_tracking_data": { + "ap_tracking": { + "group": 13, + "offset": 1 + }, + "reference_ids": { + "starkware.cairo.common.math_cmp.is_nn.a": 15 + } + } + } + ], + "208": [ + { + "accessible_scopes": [ + "starkware.cairo.common.uint256", + "starkware.cairo.common.uint256.uint256_add" + ], + "code": "sum_low = ids.a.low + ids.b.low\nids.carry_low = 1 if sum_low >= ids.SHIFT else 0\nsum_high = ids.a.high + ids.b.high + ids.carry_low\nids.carry_high = 1 if sum_high >= ids.SHIFT else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 16, + "offset": 4 + }, + "reference_ids": { + "starkware.cairo.common.uint256.uint256_add.a": 16, + "starkware.cairo.common.uint256.uint256_add.b": 17, + "starkware.cairo.common.uint256.uint256_add.carry_high": 19, + "starkware.cairo.common.uint256.uint256_add.carry_low": 18 + } + } + } + ], + "615": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.name_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 44, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "645": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.symbol_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 47, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "675": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.totalSupply_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 50, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "706": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.decimals_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 53, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "737": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.balanceOf_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 56, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "773": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base", + "__wrappers__", + "__wrappers__.allowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 59, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1081": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.ERC20.permitted", + "blockifier.ERC20_without_some_syscalls.ERC20.permitted", + "__wrappers__", + "__wrappers__.permittedMinter_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 70, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1156": [ + { + "accessible_scopes": [ + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable", + "__wrappers__", + "__wrappers__.initialized_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 77, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1204": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_version_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 82, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1228": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_identity_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 85, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1283": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.initialize" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 88, + "offset": 185 + }, + "reference_ids": {} + } + } + ], + "1307": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.transfer_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 90, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1387": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.transferFrom_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 93, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1432": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.approve_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 96, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1504": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increaseAllowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 99, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1583": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.decreaseAllowance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 102, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "1640": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.permissionedMint" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 105, + "offset": 346 + }, + "reference_ids": {} + } + } + ], + "1677": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.permissionedBurn" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 107, + "offset": 494 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.CONTRACT_IDENTITY": { + "type": "const", + "value": 297732878896 + }, + "__main__.CONTRACT_VERSION": { + "type": "const", + "value": 1 + }, + "__main__.ERC20_allowances": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances", + "type": "alias" + }, + "__main__.ERC20_approve": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve", + "type": "alias" + }, + "__main__.ERC20_burn": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn", + "type": "alias" + }, + "__main__.ERC20_initializer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer", + "type": "alias" + }, + "__main__.ERC20_mint": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint", + "type": "alias" + }, + "__main__.ERC20_transfer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "__main__.Uint256": { + "destination": "starkware.cairo.common.uint256.Uint256", + "type": "alias" + }, + "__main__.allowance": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance", + "type": "alias" + }, + "__main__.approve": { + "decorators": [ + "external" + ], + "pc": 1417, + "type": "function" + }, + "__main__.approve.Args": { + "full_name": "__main__.approve.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "spender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.approve.ImplicitArgs": { + "full_name": "__main__.approve.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.approve.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "__main__.balanceOf": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf", + "type": "alias" + }, + "__main__.decimals": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals", + "type": "alias" + }, + "__main__.decreaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1533, + "type": "function" + }, + "__main__.decreaseAllowance.Args": { + "full_name": "__main__.decreaseAllowance.Args", + "members": { + "spender": { + "cairo_type": "felt", + "offset": 0 + }, + "subtracted_value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.decreaseAllowance.ImplicitArgs": { + "full_name": "__main__.decreaseAllowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.decreaseAllowance.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.decreaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 5 + }, + "__main__.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "__main__.get_identity": { + "decorators": [ + "view" + ], + "pc": 1225, + "type": "function" + }, + "__main__.get_identity.Args": { + "full_name": "__main__.get_identity.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_identity.ImplicitArgs": { + "full_name": "__main__.get_identity.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_identity.Return": { + "cairo_type": "(identity: felt)", + "type": "type_definition" + }, + "__main__.get_identity.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_version": { + "decorators": [ + "view" + ], + "pc": 1201, + "type": "function" + }, + "__main__.get_version.Args": { + "full_name": "__main__.get_version.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_version.ImplicitArgs": { + "full_name": "__main__.get_version.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_version.Return": { + "cairo_type": "(version: felt)", + "type": "type_definition" + }, + "__main__.get_version.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.increaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1461, + "type": "function" + }, + "__main__.increaseAllowance.Args": { + "full_name": "__main__.increaseAllowance.Args", + "members": { + "added_value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "spender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increaseAllowance.ImplicitArgs": { + "full_name": "__main__.increaseAllowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increaseAllowance.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.increaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 5 + }, + "__main__.initialize": { + "decorators": [ + "external" + ], + "pc": 1249, + "type": "function" + }, + "__main__.initialize.Args": { + "full_name": "__main__.initialize.Args", + "members": { + "init_vector": { + "cairo_type": "felt*", + "offset": 1 + }, + "init_vector_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.initialize.ImplicitArgs": { + "full_name": "__main__.initialize.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.initialize.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.initialize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.initialized": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized", + "type": "alias" + }, + "__main__.name": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name", + "type": "alias" + }, + "__main__.permissionedBurn": { + "decorators": [ + "external" + ], + "pc": 1649, + "type": "function" + }, + "__main__.permissionedBurn.Args": { + "full_name": "__main__.permissionedBurn.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedBurn.ImplicitArgs": { + "full_name": "__main__.permissionedBurn.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedBurn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.permissionedBurn.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.permissionedMint": { + "decorators": [ + "external" + ], + "pc": 1612, + "type": "function" + }, + "__main__.permissionedMint.Args": { + "full_name": "__main__.permissionedMint.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedMint.ImplicitArgs": { + "full_name": "__main__.permissionedMint.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.permissionedMint.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.permissionedMint.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.permittedMinter": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter", + "type": "alias" + }, + "__main__.permitted_initializer": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer", + "type": "alias" + }, + "__main__.permitted_minter": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter", + "type": "alias" + }, + "__main__.permitted_minter_only": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only", + "type": "alias" + }, + "__main__.set_initialized": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized", + "type": "alias" + }, + "__main__.symbol": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol", + "type": "alias" + }, + "__main__.totalSupply": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply", + "type": "alias" + }, + "__main__.transfer": { + "decorators": [ + "external" + ], + "pc": 1292, + "type": "function" + }, + "__main__.transfer.Args": { + "full_name": "__main__.transfer.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transfer.ImplicitArgs": { + "full_name": "__main__.transfer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transfer.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.transferFrom": { + "decorators": [ + "external" + ], + "pc": 1336, + "type": "function" + }, + "__main__.transferFrom.Args": { + "full_name": "__main__.transferFrom.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "recipient": { + "cairo_type": "felt", + "offset": 1 + }, + "sender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.transferFrom.ImplicitArgs": { + "full_name": "__main__.transferFrom.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.transferFrom.Return": { + "cairo_type": "(success: felt)", + "type": "type_definition" + }, + "__main__.transferFrom.SIZEOF_LOCALS": { + "type": "const", + "value": 3 + }, + "__main__.uint256_add": { + "destination": "starkware.cairo.common.uint256.uint256_add", + "type": "alias" + }, + "__main__.uint256_check": { + "destination": "starkware.cairo.common.uint256.uint256_check", + "type": "alias" + }, + "__main__.uint256_le": { + "destination": "starkware.cairo.common.uint256.uint256_le", + "type": "alias" + }, + "__main__.uint256_sub": { + "destination": "starkware.cairo.common.uint256.uint256_sub", + "type": "alias" + }, + "__wrappers__.allowance": { + "decorators": [ + "view" + ], + "pc": 783, + "type": "function" + }, + "__wrappers__.allowance.Args": { + "full_name": "__wrappers__.allowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance.ImplicitArgs": { + "full_name": "__wrappers__.allowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.allowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.allowance.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance", + "type": "alias" + }, + "__wrappers__.allowance_encode_return": { + "decorators": [], + "pc": 773, + "type": "function" + }, + "__wrappers__.allowance_encode_return.Args": { + "full_name": "__wrappers__.allowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(remaining: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.allowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.allowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.allowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.allowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.allowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.approve": { + "decorators": [ + "external" + ], + "pc": 1441, + "type": "function" + }, + "__wrappers__.approve.Args": { + "full_name": "__wrappers__.approve.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve.ImplicitArgs": { + "full_name": "__wrappers__.approve.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.approve.__wrapped_func": { + "destination": "__main__.approve", + "type": "alias" + }, + "__wrappers__.approve_encode_return": { + "decorators": [], + "pc": 1432, + "type": "function" + }, + "__wrappers__.approve_encode_return.Args": { + "full_name": "__wrappers__.approve_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.approve_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.approve_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.approve_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.approve_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.approve_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.balanceOf": { + "decorators": [ + "view" + ], + "pc": 747, + "type": "function" + }, + "__wrappers__.balanceOf.Args": { + "full_name": "__wrappers__.balanceOf.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf.ImplicitArgs": { + "full_name": "__wrappers__.balanceOf.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.balanceOf.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.balanceOf.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf", + "type": "alias" + }, + "__wrappers__.balanceOf_encode_return": { + "decorators": [], + "pc": 737, + "type": "function" + }, + "__wrappers__.balanceOf_encode_return.Args": { + "full_name": "__wrappers__.balanceOf_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.balanceOf_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.balanceOf_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.balanceOf_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.balanceOf_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.balanceOf_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.decimals": { + "decorators": [ + "view" + ], + "pc": 715, + "type": "function" + }, + "__wrappers__.decimals.Args": { + "full_name": "__wrappers__.decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals.ImplicitArgs": { + "full_name": "__wrappers__.decimals.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.decimals.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals", + "type": "alias" + }, + "__wrappers__.decimals_encode_return": { + "decorators": [], + "pc": 706, + "type": "function" + }, + "__wrappers__.decimals_encode_return.Args": { + "full_name": "__wrappers__.decimals_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(decimals: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.decimals_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.decimals_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decimals_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.decimals_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.decimals_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.decreaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1592, + "type": "function" + }, + "__wrappers__.decreaseAllowance.Args": { + "full_name": "__wrappers__.decreaseAllowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance.ImplicitArgs": { + "full_name": "__wrappers__.decreaseAllowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.decreaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.decreaseAllowance.__wrapped_func": { + "destination": "__main__.decreaseAllowance", + "type": "alias" + }, + "__wrappers__.decreaseAllowance_encode_return": { + "decorators": [], + "pc": 1583, + "type": "function" + }, + "__wrappers__.decreaseAllowance_encode_return.Args": { + "full_name": "__wrappers__.decreaseAllowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.decreaseAllowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.decreaseAllowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.decreaseAllowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.decreaseAllowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.decreaseAllowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.get_identity": { + "decorators": [ + "view" + ], + "pc": 1237, + "type": "function" + }, + "__wrappers__.get_identity.Args": { + "full_name": "__wrappers__.get_identity.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity.ImplicitArgs": { + "full_name": "__wrappers__.get_identity.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_identity.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_identity.__wrapped_func": { + "destination": "__main__.get_identity", + "type": "alias" + }, + "__wrappers__.get_identity_encode_return": { + "decorators": [], + "pc": 1228, + "type": "function" + }, + "__wrappers__.get_identity_encode_return.Args": { + "full_name": "__wrappers__.get_identity_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(identity: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_identity_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_identity_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_identity_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_identity_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_identity_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.get_version": { + "decorators": [ + "view" + ], + "pc": 1213, + "type": "function" + }, + "__wrappers__.get_version.Args": { + "full_name": "__wrappers__.get_version.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version.ImplicitArgs": { + "full_name": "__wrappers__.get_version.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_version.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_version.__wrapped_func": { + "destination": "__main__.get_version", + "type": "alias" + }, + "__wrappers__.get_version_encode_return": { + "decorators": [], + "pc": 1204, + "type": "function" + }, + "__wrappers__.get_version_encode_return.Args": { + "full_name": "__wrappers__.get_version_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(version: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_version_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_version_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_version_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_version_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_version_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.increaseAllowance": { + "decorators": [ + "external" + ], + "pc": 1513, + "type": "function" + }, + "__wrappers__.increaseAllowance.Args": { + "full_name": "__wrappers__.increaseAllowance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance.ImplicitArgs": { + "full_name": "__wrappers__.increaseAllowance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.increaseAllowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.increaseAllowance.__wrapped_func": { + "destination": "__main__.increaseAllowance", + "type": "alias" + }, + "__wrappers__.increaseAllowance_encode_return": { + "decorators": [], + "pc": 1504, + "type": "function" + }, + "__wrappers__.increaseAllowance_encode_return.Args": { + "full_name": "__wrappers__.increaseAllowance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.increaseAllowance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.increaseAllowance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increaseAllowance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.increaseAllowance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.increaseAllowance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.initialize": { + "decorators": [ + "external" + ], + "pc": 1265, + "type": "function" + }, + "__wrappers__.initialize.Args": { + "full_name": "__wrappers__.initialize.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialize.ImplicitArgs": { + "full_name": "__wrappers__.initialize.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialize.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.initialize.__wrapped_func": { + "destination": "__main__.initialize", + "type": "alias" + }, + "__wrappers__.initialize_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.initialized": { + "decorators": [ + "view" + ], + "pc": 1165, + "type": "function" + }, + "__wrappers__.initialized.Args": { + "full_name": "__wrappers__.initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized.ImplicitArgs": { + "full_name": "__wrappers__.initialized.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.initialized.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized", + "type": "alias" + }, + "__wrappers__.initialized_encode_return": { + "decorators": [], + "pc": 1156, + "type": "function" + }, + "__wrappers__.initialized_encode_return.Args": { + "full_name": "__wrappers__.initialized_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(res: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.initialized_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.initialized_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.initialized_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.initialized_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.initialized_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.name": { + "decorators": [ + "view" + ], + "pc": 624, + "type": "function" + }, + "__wrappers__.name.Args": { + "full_name": "__wrappers__.name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name.ImplicitArgs": { + "full_name": "__wrappers__.name.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.name.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name", + "type": "alias" + }, + "__wrappers__.name_encode_return": { + "decorators": [], + "pc": 615, + "type": "function" + }, + "__wrappers__.name_encode_return.Args": { + "full_name": "__wrappers__.name_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(name: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.name_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.name_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.name_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.name_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.name_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permissionedBurn": { + "decorators": [ + "external" + ], + "pc": 1666, + "type": "function" + }, + "__wrappers__.permissionedBurn.Args": { + "full_name": "__wrappers__.permissionedBurn.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedBurn.ImplicitArgs": { + "full_name": "__wrappers__.permissionedBurn.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedBurn.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permissionedBurn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permissionedBurn.__wrapped_func": { + "destination": "__main__.permissionedBurn", + "type": "alias" + }, + "__wrappers__.permissionedBurn_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permissionedMint": { + "decorators": [ + "external" + ], + "pc": 1629, + "type": "function" + }, + "__wrappers__.permissionedMint.Args": { + "full_name": "__wrappers__.permissionedMint.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedMint.ImplicitArgs": { + "full_name": "__wrappers__.permissionedMint.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permissionedMint.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permissionedMint.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permissionedMint.__wrapped_func": { + "destination": "__main__.permissionedMint", + "type": "alias" + }, + "__wrappers__.permissionedMint_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.permittedMinter": { + "decorators": [ + "view" + ], + "pc": 1090, + "type": "function" + }, + "__wrappers__.permittedMinter.Args": { + "full_name": "__wrappers__.permittedMinter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter.ImplicitArgs": { + "full_name": "__wrappers__.permittedMinter.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.permittedMinter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.permittedMinter.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter", + "type": "alias" + }, + "__wrappers__.permittedMinter_encode_return": { + "decorators": [], + "pc": 1081, + "type": "function" + }, + "__wrappers__.permittedMinter_encode_return.Args": { + "full_name": "__wrappers__.permittedMinter_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(minter: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.permittedMinter_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.permittedMinter_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.permittedMinter_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.permittedMinter_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.permittedMinter_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.symbol": { + "decorators": [ + "view" + ], + "pc": 654, + "type": "function" + }, + "__wrappers__.symbol.Args": { + "full_name": "__wrappers__.symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol.ImplicitArgs": { + "full_name": "__wrappers__.symbol.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.symbol.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol", + "type": "alias" + }, + "__wrappers__.symbol_encode_return": { + "decorators": [], + "pc": 645, + "type": "function" + }, + "__wrappers__.symbol_encode_return.Args": { + "full_name": "__wrappers__.symbol_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(symbol: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.symbol_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.symbol_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.symbol_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.symbol_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.symbol_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.totalSupply": { + "decorators": [ + "view" + ], + "pc": 685, + "type": "function" + }, + "__wrappers__.totalSupply.Args": { + "full_name": "__wrappers__.totalSupply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply.ImplicitArgs": { + "full_name": "__wrappers__.totalSupply.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.totalSupply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.totalSupply.__wrapped_func": { + "destination": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply", + "type": "alias" + }, + "__wrappers__.totalSupply_encode_return": { + "decorators": [], + "pc": 675, + "type": "function" + }, + "__wrappers__.totalSupply_encode_return.Args": { + "full_name": "__wrappers__.totalSupply_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "ret_value": { + "cairo_type": "(totalSupply: starkware.cairo.common.uint256.Uint256)", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.totalSupply_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.totalSupply_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.totalSupply_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.totalSupply_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.totalSupply_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.transfer": { + "decorators": [ + "external" + ], + "pc": 1316, + "type": "function" + }, + "__wrappers__.transfer.Args": { + "full_name": "__wrappers__.transfer.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer.ImplicitArgs": { + "full_name": "__wrappers__.transfer.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.transfer.__wrapped_func": { + "destination": "__main__.transfer", + "type": "alias" + }, + "__wrappers__.transferFrom": { + "decorators": [ + "external" + ], + "pc": 1396, + "type": "function" + }, + "__wrappers__.transferFrom.Args": { + "full_name": "__wrappers__.transferFrom.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom.ImplicitArgs": { + "full_name": "__wrappers__.transferFrom.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.transferFrom.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.transferFrom.__wrapped_func": { + "destination": "__main__.transferFrom", + "type": "alias" + }, + "__wrappers__.transferFrom_encode_return": { + "decorators": [], + "pc": 1387, + "type": "function" + }, + "__wrappers__.transferFrom_encode_return.Args": { + "full_name": "__wrappers__.transferFrom_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.transferFrom_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.transferFrom_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transferFrom_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.transferFrom_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.transferFrom_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.transfer_encode_return": { + "decorators": [], + "pc": 1307, + "type": "function" + }, + "__wrappers__.transfer_encode_return.Args": { + "full_name": "__wrappers__.transfer_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(success: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.transfer_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.transfer_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.transfer_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.transfer_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.transfer_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.SELECTOR": { + "type": "const", + "value": 544914742286571513055574265148471203182105283038408585630116262969508767999 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.alloc": { + "destination": "starkware.cairo.common.alloc.alloc", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit": { + "decorators": [], + "pc": 323, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.emit_event": { + "destination": "starkware.starknet.common.syscalls.emit_event", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Approval.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr": { + "decorators": [], + "pc": 533, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read": { + "decorators": [], + "pc": 550, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.Return": { + "cairo_type": "(allowance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write": { + "decorators": [], + "pc": 571, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_allowances.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve": { + "decorators": [], + "pc": 937, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "caller": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_approve.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr": { + "decorators": [], + "pc": 481, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read": { + "decorators": [], + "pc": 495, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.Return": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write": { + "decorators": [], + "pc": 515, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_balances.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn": { + "decorators": [], + "pc": 969, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + }, + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_burn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr": { + "decorators": [], + "pc": 410, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read": { + "decorators": [], + "pc": 415, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.Return": { + "cairo_type": "(decimals: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write": { + "decorators": [], + "pc": 428, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_decimals.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer": { + "decorators": [], + "pc": 590, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Args", + "members": { + "decimals": { + "cairo_type": "felt", + "offset": 2 + }, + "name": { + "cairo_type": "felt", + "offset": 0 + }, + "symbol": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_initializer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint": { + "decorators": [], + "pc": 802, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 1 + }, + "recipient": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_mint.SIZEOF_LOCALS": { + "type": "const", + "value": 4 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr": { + "decorators": [], + "pc": 350, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read": { + "decorators": [], + "pc": 355, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.Return": { + "cairo_type": "(name: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write": { + "decorators": [], + "pc": 368, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_name.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr": { + "decorators": [], + "pc": 380, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read": { + "decorators": [], + "pc": 385, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.Return": { + "cairo_type": "(symbol: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write": { + "decorators": [], + "pc": 398, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_symbol.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr": { + "decorators": [], + "pc": 440, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read": { + "decorators": [], + "pc": 445, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.Return": { + "cairo_type": "(total_supply: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write": { + "decorators": [], + "pc": 464, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Args", + "members": { + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_total_supply.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer": { + "decorators": [], + "pc": 865, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Args", + "members": { + "amount": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + }, + "recipient": { + "cairo_type": "felt", + "offset": 1 + }, + "sender": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.ERC20_transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.MAX_DECIMALS": { + "type": "const", + "value": 255 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.SignatureBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.SELECTOR": { + "type": "const", + "value": 271746229759260285552388728919865295615886751538523744128730118297934206697 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.alloc": { + "destination": "starkware.cairo.common.alloc.alloc", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit": { + "decorators": [], + "pc": 296, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Args", + "members": { + "from_": { + "cairo_type": "felt", + "offset": 0 + }, + "to": { + "cairo_type": "felt", + "offset": 1 + }, + "value": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.emit_event": { + "destination": "starkware.starknet.common.syscalls.emit_event", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Transfer.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.Uint256": { + "destination": "starkware.cairo.common.uint256.Uint256", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance": { + "decorators": [ + "view" + ], + "pc": 765, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Args", + "members": { + "owner": { + "cairo_type": "felt", + "offset": 0 + }, + "spender": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.Return": { + "cairo_type": "(remaining: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.allowance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.assert_nn_le": { + "destination": "starkware.cairo.common.math.assert_nn_le", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf": { + "decorators": [ + "view" + ], + "pc": 730, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Args", + "members": { + "account": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.Return": { + "cairo_type": "(balance: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.balanceOf.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals": { + "decorators": [ + "view" + ], + "pc": 700, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.Return": { + "cairo_type": "(decimals: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.decimals.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name": { + "decorators": [ + "view" + ], + "pc": 609, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.Return": { + "cairo_type": "(name: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.name.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol": { + "decorators": [ + "view" + ], + "pc": 639, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.Return": { + "cairo_type": "(symbol: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.symbol.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply": { + "decorators": [ + "view" + ], + "pc": 669, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.Return": { + "cairo_type": "(totalSupply: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.totalSupply.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_add": { + "destination": "starkware.cairo.common.uint256.uint256_add", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_check": { + "destination": "starkware.cairo.common.uint256.uint256_check", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_le": { + "destination": "starkware.cairo.common.uint256.uint256_le", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.ERC20_base.uint256_sub": { + "destination": "starkware.cairo.common.uint256.uint256_sub", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.get_caller_address": { + "destination": "starkware.starknet.common.syscalls.get_caller_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter": { + "decorators": [ + "view" + ], + "pc": 1075, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.Return": { + "cairo_type": "(minter: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permittedMinter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer": { + "decorators": [], + "pc": 1065, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Args", + "members": { + "minter_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_initializer.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr": { + "decorators": [], + "pc": 1035, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read": { + "decorators": [], + "pc": 1040, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write": { + "decorators": [], + "pc": 1053, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only": { + "decorators": [], + "pc": 1105, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.ERC20.permitted.permitted_minter_only.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized": { + "type": "namespace" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr": { + "decorators": [], + "pc": 1120, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read": { + "decorators": [], + "pc": 1125, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write": { + "decorators": [], + "pc": 1138, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable._initialized.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized": { + "decorators": [ + "view" + ], + "pc": 1150, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized": { + "decorators": [], + "pc": 1180, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.only_uninitialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized": { + "decorators": [], + "pc": 1191, + "type": "function" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Args": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.ImplicitArgs": { + "full_name": "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "blockifier.ERC20_without_some_syscalls.upgradability_proxy.initializable.set_initialized.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.alloc.alloc": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.alloc.alloc.Args": { + "full_name": "starkware.cairo.common.alloc.alloc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.ImplicitArgs": { + "full_name": "starkware.cairo.common.alloc.alloc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.Return": { + "cairo_type": "(ptr: felt*)", + "type": "type_definition" + }, + "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bitwise.ALL_ONES": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719234 + }, + "starkware.cairo.common.bitwise.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash.hash2": { + "decorators": [], + "pc": 3, + "type": "function" + }, + "starkware.cairo.common.hash.hash2.Args": { + "full_name": "starkware.cairo.common.hash.hash2.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash.hash2.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash.hash2.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.math.assert_250_bit": { + "decorators": [ + "known_ap_change" + ], + "pc": 32, + "type": "function" + }, + "starkware.cairo.common.math.assert_250_bit.Args": { + "full_name": "starkware.cairo.common.math.assert_250_bit.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.HIGH_BOUND": { + "type": "const", + "value": 5316911983139663491615228241121378304 + }, + "starkware.cairo.common.math.assert_250_bit.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_250_bit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_250_bit.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND": { + "type": "const", + "value": 1809251394333065553493296640760748560207343510400633813116524750123642650624 + }, + "starkware.cairo.common.math.assert_250_bit.high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.high", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)] + 1, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.low", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)], felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.value", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le": { + "decorators": [], + "pc": 18, + "type": "function" + }, + "starkware.cairo.common.math.assert_le.Args": { + "full_name": "starkware.cairo.common.math.assert_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_le_felt": { + "decorators": [ + "known_ap_change" + ], + "pc": 45, + "type": "function" + }, + "starkware.cairo.common.math.assert_le_felt.Args": { + "full_name": "starkware.cairo.common.math.assert_le_felt.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le_felt.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_le_felt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH": { + "type": "const", + "value": 5316911983139663648412552867652567041 + }, + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH": { + "type": "const", + "value": 3544607988759775765608368578435044694 + }, + "starkware.cairo.common.math.assert_le_felt.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_le_felt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_le_felt.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.a", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-4), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.b": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.b", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.range_check_ptr": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_le_felt.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-5), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 8 + }, + "pc": 55, + "value": "cast([fp + (-5)] + 4, felt)" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_le_felt.skip_exclude_a": { + "pc": 69, + "type": "label" + }, + "starkware.cairo.common.math.assert_le_felt.skip_exclude_b_minus_a": { + "pc": 81, + "type": "label" + }, + "starkware.cairo.common.math.assert_nn": { + "decorators": [], + "pc": 14, + "type": "function" + }, + "starkware.cairo.common.math.assert_nn.Args": { + "full_name": "starkware.cairo.common.math.assert_nn.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_nn.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_nn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_nn.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_nn.a", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 14, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_nn_le": { + "decorators": [], + "pc": 23, + "type": "function" + }, + "starkware.cairo.common.math.assert_nn_le.Args": { + "full_name": "starkware.cairo.common.math.assert_nn_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_nn_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_nn_le.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_nn_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_not_zero": { + "decorators": [], + "pc": 9, + "type": "function" + }, + "starkware.cairo.common.math.assert_not_zero.Args": { + "full_name": "starkware.cairo.common.math.assert_not_zero.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_not_zero.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_not_zero.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.math.assert_not_zero.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_not_zero.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_not_zero.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_not_zero.value", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 9, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math_cmp.RC_BOUND": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math_cmp.assert_le_felt": { + "destination": "starkware.cairo.common.math.assert_le_felt", + "type": "alias" + }, + "starkware.cairo.common.math_cmp.assert_lt_felt": { + "destination": "starkware.cairo.common.math.assert_lt_felt", + "type": "alias" + }, + "starkware.cairo.common.math_cmp.is_le": { + "decorators": [ + "known_ap_change" + ], + "pc": 196, + "type": "function" + }, + "starkware.cairo.common.math_cmp.is_le.Args": { + "full_name": "starkware.cairo.common.math_cmp.is_le.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + }, + "b": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.math_cmp.is_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_le.Return": { + "cairo_type": "felt", + "type": "type_definition" + }, + "starkware.cairo.common.math_cmp.is_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math_cmp.is_nn": { + "decorators": [ + "known_ap_change" + ], + "pc": 163, + "type": "function" + }, + "starkware.cairo.common.math_cmp.is_nn.Args": { + "full_name": "starkware.cairo.common.math_cmp.is_nn.Args", + "members": { + "a": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_nn.ImplicitArgs": { + "full_name": "starkware.cairo.common.math_cmp.is_nn.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math_cmp.is_nn.Return": { + "cairo_type": "felt", + "type": "type_definition" + }, + "starkware.cairo.common.math_cmp.is_nn.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math_cmp.is_nn.a": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math_cmp.is_nn.a", + "references": [ + { + "ap_tracking_data": { + "group": 13, + "offset": 0 + }, + "pc": 163, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math_cmp.is_nn.need_felt_comparison": { + "pc": 187, + "type": "label" + }, + "starkware.cairo.common.math_cmp.is_nn.out_of_range": { + "pc": 173, + "type": "label" + }, + "starkware.cairo.common.pow.assert_le": { + "destination": "starkware.cairo.common.math.assert_le", + "type": "alias" + }, + "starkware.cairo.common.pow.get_ap": { + "destination": "starkware.cairo.common.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.pow.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.registers.get_ap": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.registers.get_fp_and_pc": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.uint256.ALL_ONES": { + "type": "const", + "value": 340282366920938463463374607431768211455 + }, + "starkware.cairo.common.uint256.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "starkware.cairo.common.uint256.HALF_SHIFT": { + "type": "const", + "value": 18446744073709551616 + }, + "starkware.cairo.common.uint256.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.uint256.Uint256": { + "full_name": "starkware.cairo.common.uint256.Uint256", + "members": { + "high": { + "cairo_type": "felt", + "offset": 1 + }, + "low": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.assert_in_range": { + "destination": "starkware.cairo.common.math.assert_in_range", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_le": { + "destination": "starkware.cairo.common.math.assert_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_nn_le": { + "destination": "starkware.cairo.common.math.assert_nn_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.assert_not_zero": { + "destination": "starkware.cairo.common.math.assert_not_zero", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_and": { + "destination": "starkware.cairo.common.bitwise.bitwise_and", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_or": { + "destination": "starkware.cairo.common.bitwise.bitwise_or", + "type": "alias" + }, + "starkware.cairo.common.uint256.bitwise_xor": { + "destination": "starkware.cairo.common.bitwise.bitwise_xor", + "type": "alias" + }, + "starkware.cairo.common.uint256.get_ap": { + "destination": "starkware.cairo.common.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.uint256.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.uint256.is_le": { + "destination": "starkware.cairo.common.math_cmp.is_le", + "type": "alias" + }, + "starkware.cairo.common.uint256.pow": { + "destination": "starkware.cairo.common.pow.pow", + "type": "alias" + }, + "starkware.cairo.common.uint256.uint256_add": { + "decorators": [], + "pc": 206, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_add.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_add.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_add.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_add.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_add.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256, carry: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_add.SIZEOF_LOCALS": { + "type": "const", + "value": 4 + }, + "starkware.cairo.common.uint256.uint256_add.a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "full_name": "starkware.cairo.common.uint256.uint256_add.a", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-6), starkware.cairo.common.uint256.Uint256*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "full_name": "starkware.cairo.common.uint256.uint256_add.b", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-4), starkware.cairo.common.uint256.Uint256*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.carry_high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.uint256.uint256_add.carry_high", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 3, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_add.carry_low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.uint256.uint256_add.carry_low", + "references": [ + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 2, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.uint256.uint256_check": { + "decorators": [], + "pc": 201, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_check.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_check.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_check.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_check.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_check.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_check.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_le": { + "decorators": [], + "pc": 245, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_le.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_le.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_le.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_le.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_le.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_le.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_lt": { + "decorators": [], + "pc": 228, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_lt.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_lt.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_lt.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_lt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_lt.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_lt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_neg": { + "decorators": [], + "pc": 265, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_neg.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_neg.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_neg.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_neg.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_neg.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_neg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_not": { + "decorators": [], + "pc": 257, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_not.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_not.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_not.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_not.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_not.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_not.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.uint256.uint256_sub": { + "decorators": [], + "pc": 280, + "type": "function" + }, + "starkware.cairo.common.uint256.uint256_sub.Args": { + "full_name": "starkware.cairo.common.uint256.uint256_sub.Args", + "members": { + "a": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 0 + }, + "b": { + "cairo_type": "starkware.cairo.common.uint256.Uint256", + "offset": 2 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_sub.ImplicitArgs": { + "full_name": "starkware.cairo.common.uint256.uint256_sub.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.uint256.uint256_sub.Return": { + "cairo_type": "(res: starkware.cairo.common.uint256.Uint256)", + "type": "type_definition" + }, + "starkware.cairo.common.uint256.uint256_sub.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.storage.normalize_address": { + "decorators": [ + "known_ap_change" + ], + "pc": 90, + "type": "function" + }, + "starkware.starknet.common.storage.normalize_address.Args": { + "full_name": "starkware.starknet.common.storage.normalize_address.Args", + "members": { + "addr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.storage.normalize_address.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.normalize_address.addr": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.addr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 90, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_250": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_250", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 110, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_small": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_small", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 92, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event": { + "decorators": [], + "pc": 153, + "type": "function" + }, + "starkware.starknet.common.syscalls.emit_event.Args": { + "full_name": "starkware.starknet.common.syscalls.emit_event.Args", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 3 + }, + "data_len": { + "cairo_type": "felt", + "offset": 2 + }, + "keys": { + "cairo_type": "felt*", + "offset": 1 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.emit_event.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.emit_event.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.emit_event.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.emit_event.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.emit_event.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 12, + "offset": 0 + }, + "pc": 153, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 12, + "offset": 1 + }, + "pc": 160, + "value": "cast([fp + (-7)] + 5, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.get_caller_address": { + "decorators": [], + "pc": 130, + "type": "function" + }, + "starkware.starknet.common.syscalls.get_caller_address.Args": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.get_caller_address.Return": { + "cairo_type": "(caller_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.get_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.get_caller_address.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 130, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 1 + }, + "pc": 133, + "value": "cast([fp + (-3)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 137, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 137, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 141, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 145, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 11, + "offset": 0 + }, + "pc": 145, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 11, + "offset": 1 + }, + "pc": 150, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 9, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 14, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 32, + "value": "[cast([fp + (-4)] + 1, felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 45, + "value": "[cast(fp + (-5), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 90, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 92, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 110, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 130, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 137, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 11, + "offset": 0 + }, + "pc": 145, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 12, + "offset": 0 + }, + "pc": 153, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 13, + "offset": 0 + }, + "pc": 163, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-6), starkware.cairo.common.uint256.Uint256*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 0 + }, + "pc": 206, + "value": "[cast(fp + (-4), starkware.cairo.common.uint256.Uint256*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 16, + "offset": 4 + }, + "pc": 208, + "value": "[cast(fp + 3, felt*)]" + } + ] + } + } +} diff --git a/crates/papyrus_rpc/resources/sierra_program.json b/crates/papyrus_rpc/resources/sierra_program.json new file mode 100644 index 00000000000..ade6229a0af --- /dev/null +++ b/crates/papyrus_rpc/resources/sierra_program.json @@ -0,0 +1,26 @@ +[ + "0x1", + "0x3", + "0x0", + "0x2", + "0x1", + "0x0", + "0x2ce", + "0x132", + "0x54", + "0x52616e6765436865636b", + "0x0", + "0x4761734275696c74696e", + "0x66656c74323532", + "0x4172726179", + "0x1", + "0x2", + "0x536e617073686f74", + "0x3", + "0x537472756374", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0x4", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x456e756d", + "0x11c6d8087e00642489f92d2821ad6ebd6532ad1a3b6d12833da6d6810391511" +] diff --git a/crates/papyrus_rpc/resources/sierra_program_base64.json b/crates/papyrus_rpc/resources/sierra_program_base64.json new file mode 100644 index 00000000000..0b9a96b7f24 --- /dev/null +++ b/crates/papyrus_rpc/resources/sierra_program_base64.json @@ -0,0 +1 @@ +"H4sIAAAAAAAA/01QuZEEQQjLZewz+KFjuTqjHzqGC3/Z6THGEZQAScXvBf94/RTyjXAj3YhvZubh+MxUTiFDS3NTYQtTYxuvK3FDZyFXazZdCo+MWe0WwcT6KAo6ecl5e5k/Zlwe6OBfj+3yyqvs4l99fmgcPUd3Sm/Z1iANn1tkZ/WbHWAQuHbNSG5drRYkjKYMx21PlOOdiUkDR7QdU5puAsiqRh5dljgXl2S0yYdSaj1gNiWZEPPEE7WscOtEw2krIDwBTEhKt9GiIOzLciyrV/SFnYctpGBe3ZYFAjdUxOvvA1o7YaKtAQAA" diff --git a/crates/papyrus_rpc/resources/test_config.json b/crates/papyrus_rpc/resources/test_config.json new file mode 100644 index 00000000000..d31870323a9 --- /dev/null +++ b/crates/papyrus_rpc/resources/test_config.json @@ -0,0 +1,5 @@ +{ + "strk_fee_contract_address": "0x1001", + "eth_fee_contract_address": "0x1001", + "initial_gas_cost": 10000000000 +} \ No newline at end of file diff --git a/crates/papyrus_rpc/src/api.rs b/crates/papyrus_rpc/src/api.rs new file mode 100644 index 00000000000..d26e9edb368 --- /dev/null +++ b/crates/papyrus_rpc/src/api.rs @@ -0,0 +1,203 @@ +use std::sync::Arc; + +use jsonrpsee::{Methods, RpcModule}; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_common::BlockHashAndNumber; +use papyrus_execution::ExecutionConfig; +use papyrus_storage::StorageReader; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::{ChainId, ContractAddress, EntryPointSelector}; +use starknet_api::transaction::Calldata; +use starknet_client::reader::PendingData; +use starknet_client::writer::StarknetWriter; +use tokio::sync::RwLock; + +use crate::v0_6::api::api_impl::JsonRpcServerImpl as JsonRpcServerV0_6Impl; +use crate::v0_7::api::api_impl::JsonRpcServerImpl as JsonRpcServerV0_7Impl; +use crate::version_config; + +#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub enum Tag { + /// The most recent fully constructed block + #[serde(rename = "latest")] + Latest, + /// Currently constructed block + #[serde(rename = "pending")] + Pending, +} + +#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub enum BlockHashOrNumber { + #[serde(rename = "block_hash")] + Hash(BlockHash), + #[serde(rename = "block_number")] + Number(BlockNumber), +} + +#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(untagged)] +pub enum BlockId { + HashOrNumber(BlockHashOrNumber), + Tag(Tag), +} + +/// The parameters of a call. +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct CallRequest { + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +/// Returns a `Methods` object with all the methods from the supported APIs. +/// Whenever adding a new API version we need to add the new version mapping here. +#[allow(clippy::too_many_arguments)] +pub fn get_methods_from_supported_apis( + chain_id: &ChainId, + execution_config: ExecutionConfig, + storage_reader: StorageReader, + max_events_chunk_size: usize, + max_events_keys: usize, + starting_block: BlockHashAndNumber, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + starknet_writer: Arc, +) -> Methods { + let mut methods: Methods = Methods::new(); + let server_gen = JsonRpcServerImplGenerator { + chain_id: chain_id.clone(), + execution_config, + storage_reader, + max_events_chunk_size, + max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + starknet_writer, + }; + version_config::VERSION_CONFIG + .iter() + .filter_map(|version_config| { + let (version, version_state) = version_config; + match version_state { + version_config::VersionState::Deprecated => None, + version_config::VersionState::Supported => { + let methods = match *version { + version_config::VERSION_0_6 => { + server_gen.clone().generator::() + } + version_config::VERSION_0_7 => { + server_gen.clone().generator::() + } + // TODO(yair): remove this once the version is an enum instead of a string. + _ => unreachable!("Unrecognized RPC spec version: {}", version), + }; + Some(methods) + } + } + }) + .fold(&mut methods, |methods, new_methods| { + let _res = methods.merge(new_methods); + methods + }); + methods +} + +pub trait JsonRpcServerTrait: Sized { + #[allow(clippy::too_many_arguments)] + fn new( + chain_id: ChainId, + execution_config: ExecutionConfig, + storage_reader: StorageReader, + max_events_chunk_size: usize, + max_events_keys: usize, + starting_block: BlockHashAndNumber, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + starknet_writer: Arc, + ) -> Self; + + fn into_rpc_module(self) -> RpcModule; +} + +#[derive(Clone)] +struct JsonRpcServerImplGenerator { + chain_id: ChainId, + execution_config: ExecutionConfig, + storage_reader: StorageReader, + max_events_chunk_size: usize, + max_events_keys: usize, + starting_block: BlockHashAndNumber, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + // TODO(shahak): Change this struct to be with a generic type of StarknetWriter. + starknet_writer: Arc, +} + +type JsonRpcServerImplParams = ( + ChainId, + ExecutionConfig, + StorageReader, + usize, + usize, + BlockHashAndNumber, + Arc>>, + Arc>, + Arc>, + Arc, +); + +impl JsonRpcServerImplGenerator { + fn get_params(self) -> JsonRpcServerImplParams { + ( + self.chain_id, + self.execution_config, + self.storage_reader, + self.max_events_chunk_size, + self.max_events_keys, + self.starting_block, + self.shared_highest_block, + self.pending_data, + self.pending_classes, + self.starknet_writer, + ) + } + + fn generator(self) -> Methods + where + T: JsonRpcServerTrait, + { + let ( + chain_id, + fee_contract_address, + storage_reader, + max_events_chunk_size, + max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + starknet_writer, + ) = self.get_params(); + Into::::into( + T::new( + chain_id, + fee_contract_address, + storage_reader, + max_events_chunk_size, + max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + starknet_writer, + ) + .into_rpc_module(), + ) + } +} diff --git a/crates/papyrus_rpc/src/compression_utils.rs b/crates/papyrus_rpc/src/compression_utils.rs new file mode 100644 index 00000000000..961cfa6b9fc --- /dev/null +++ b/crates/papyrus_rpc/src/compression_utils.rs @@ -0,0 +1,11 @@ +#[cfg(test)] +#[path = "compression_utils_test.rs"] +mod compression_utils_test; + +// Compress the value using gzip with the default compression level and encode it in base64. +pub fn compress_and_encode(value: serde_json::Value) -> Result { + let mut compressor = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default()); + serde_json::to_writer(&mut compressor, &value)?; + let compressed_data = compressor.finish()?; + Ok(base64::encode(compressed_data)) +} diff --git a/crates/papyrus_rpc/src/compression_utils_test.rs b/crates/papyrus_rpc/src/compression_utils_test.rs new file mode 100644 index 00000000000..881b4a36e3a --- /dev/null +++ b/crates/papyrus_rpc/src/compression_utils_test.rs @@ -0,0 +1,12 @@ +use pretty_assertions::assert_eq; +use test_utils::read_json_file; + +use super::compress_and_encode; + +#[test] +fn compress_and_encode_hardcoded_value() { + let sierra_program = read_json_file("sierra_program.json"); + let expected_value = read_json_file("sierra_program_base64.json").as_str().unwrap().to_owned(); + let value = compress_and_encode(sierra_program).unwrap(); + assert_eq!(value, expected_value); +} diff --git a/crates/papyrus_rpc/src/lib.rs b/crates/papyrus_rpc/src/lib.rs new file mode 100644 index 00000000000..e7c2b5183bc --- /dev/null +++ b/crates/papyrus_rpc/src/lib.rs @@ -0,0 +1,254 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +mod api; +mod compression_utils; +mod middleware; +mod pending; +mod rpc_metrics; +#[cfg(test)] +mod rpc_test; +mod syncing_state; +#[cfg(test)] +mod test_utils; +mod v0_6; +mod v0_7; +mod version_config; + +use std::collections::BTreeMap; +use std::fmt::Display; +use std::net::SocketAddr; +use std::sync::Arc; + +use jsonrpsee::core::RpcResult; +use jsonrpsee::server::{ServerBuilder, ServerHandle}; +use jsonrpsee::types::error::ErrorCode::InternalError; +use jsonrpsee::types::error::INTERNAL_ERROR_MSG; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_common::BlockHashAndNumber; +use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; +use papyrus_config::validators::validate_ascii; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_execution::ExecutionConfig; +use papyrus_storage::base_layer::BaseLayerStorageReader; +use papyrus_storage::body::events::EventIndex; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageReader, StorageScope, StorageTxn}; +use rpc_metrics::MetricLogger; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockNumber, BlockStatus}; +use starknet_api::core::ChainId; +use starknet_client::reader::PendingData; +use starknet_client::writer::StarknetGatewayClient; +use starknet_client::RetryConfig; +use tokio::sync::RwLock; +use tracing::{debug, error, info, instrument}; +pub use v0_7::api::CompiledContractClass; +use validator::Validate; + +use crate::api::get_methods_from_supported_apis; +use crate::middleware::{deny_requests_with_unsupported_path, proxy_rpc_request}; +use crate::syncing_state::get_last_synced_block; +pub use crate::v0_6::transaction::{ + InvokeTransaction as InvokeTransactionRPC0_6, + InvokeTransactionV1 as InvokeTransactionV1RPC0_6, + TransactionVersion1 as TransactionVersion1RPC0_6, +}; +pub use crate::v0_6::write_api_result::AddInvokeOkResult as AddInvokeOkResultRPC0_6; + +// TODO(shahak): Consider adding genesis hash to the config to support chains that have +// different genesis hash. +// TODO: Consider moving to a more general place. +const GENESIS_HASH: &str = "0x0"; + +/// Maximum size of a supported transaction body - 10MB. +pub const SERVER_MAX_BODY_SIZE: u32 = 10 * 1024 * 1024; + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Validate)] +pub struct RpcConfig { + #[validate(custom = "validate_ascii")] + pub chain_id: ChainId, + pub server_address: String, + pub max_events_chunk_size: usize, + pub max_events_keys: usize, + pub collect_metrics: bool, + pub starknet_url: String, + pub starknet_gateway_retry_config: RetryConfig, + pub execution_config: ExecutionConfig, +} + +impl Default for RpcConfig { + fn default() -> Self { + RpcConfig { + chain_id: ChainId::Mainnet, + server_address: String::from("0.0.0.0:8080"), + max_events_chunk_size: 1000, + max_events_keys: 100, + collect_metrics: false, + starknet_url: String::from("https://alpha-mainnet.starknet.io/"), + starknet_gateway_retry_config: RetryConfig { + retry_base_millis: 50, + retry_max_delay_millis: 1000, + max_retries: 5, + }, + execution_config: ExecutionConfig::default(), + } + } +} + +impl SerializeConfig for RpcConfig { + fn dump(&self) -> BTreeMap { + let mut self_params_dump = BTreeMap::from_iter([ + ser_param( + "chain_id", + &self.chain_id, + "The chain to follow. For more details see https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#chain-id.", + ParamPrivacyInput::Public, + ), + ser_param( + "server_address", + &self.server_address, + "IP:PORT of the node`s JSON-RPC server.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_events_chunk_size", + &self.max_events_chunk_size, + "Maximum chunk size supported by the node in get_events requests.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_events_keys", + &self.max_events_keys, + "Maximum number of keys supported by the node in get_events requests.", + ParamPrivacyInput::Public, + ), + ser_param( + "collect_metrics", + &self.collect_metrics, + "If true, collect metrics for the rpc.", + ParamPrivacyInput::Public, + ), + ser_param( + "starknet_url", + &self.starknet_url, + "URL for communicating with Starknet in write_api methods.", + ParamPrivacyInput::Public, + ), + ]); + + self_params_dump + .append(&mut append_sub_config_name(self.execution_config.dump(), "execution_config")); + let mut retry_config_dump = append_sub_config_name( + self.starknet_gateway_retry_config.dump(), + "starknet_gateway_retry_config", + ); + for param in retry_config_dump.values_mut() { + param.description = format!( + "For communicating with Starknet gateway, {}{}", + param.description[0..1].to_lowercase(), + ¶m.description[1..] + ); + } + self_params_dump.append(&mut retry_config_dump); + self_params_dump + } +} + +fn internal_server_error(err: impl Display) -> ErrorObjectOwned { + error!("{}: {}", INTERNAL_ERROR_MSG, err); + ErrorObjectOwned::owned(InternalError.code(), INTERNAL_ERROR_MSG, None::<()>) +} + +fn internal_server_error_with_msg(err: impl Display) -> ErrorObjectOwned { + error!("{}: {}", INTERNAL_ERROR_MSG, err); + ErrorObjectOwned::owned(InternalError.code(), err.to_string(), None::<()>) +} + +fn verify_storage_scope(storage_reader: &StorageReader) -> RpcResult<()> { + match storage_reader.get_scope() { + StorageScope::StateOnly => { + Err(internal_server_error_with_msg("Unsupported method in state-only scope.")) + } + StorageScope::FullArchive => Ok(()), + } +} + +/// Get the latest block that we've downloaded and that we've downloaded its state diff. +fn get_latest_block_number( + txn: &StorageTxn<'_, Mode>, +) -> Result, ErrorObjectOwned> { + Ok(txn.get_state_marker().map_err(internal_server_error)?.prev()) +} + +fn get_block_status( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result { + let base_layer_tip = txn.get_base_layer_block_marker().map_err(internal_server_error)?; + let status = if block_number < base_layer_tip { + BlockStatus::AcceptedOnL1 + } else { + BlockStatus::AcceptedOnL2 + }; + + Ok(status) +} + +#[derive(Clone, Debug, PartialEq)] +struct ContinuationTokenAsStruct(EventIndex); + +#[instrument(skip(storage_reader), level = "debug", err)] +pub async fn run_server( + config: &RpcConfig, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + storage_reader: StorageReader, + node_version: &'static str, +) -> anyhow::Result<(SocketAddr, ServerHandle)> { + let starting_block = get_last_synced_block(storage_reader.clone())?; + debug!("Starting JSON-RPC."); + let methods = get_methods_from_supported_apis( + &config.chain_id, + config.execution_config, + storage_reader, + config.max_events_chunk_size, + config.max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + Arc::new(StarknetGatewayClient::new( + &config.starknet_url, + node_version, + config.starknet_gateway_retry_config, + )?), + ); + let addr; + let handle; + let server_builder = + ServerBuilder::default().max_request_body_size(SERVER_MAX_BODY_SIZE).set_middleware( + tower::ServiceBuilder::new() + .filter_async(deny_requests_with_unsupported_path) + .filter_async(proxy_rpc_request), + ); + + if config.collect_metrics { + let server = server_builder + .set_logger(MetricLogger::new(&methods)) + .build(&config.server_address) + .await?; + addr = server.local_addr()?; + handle = server.start(methods); + } else { + let server = server_builder.build(&config.server_address).await?; + addr = server.local_addr()?; + handle = server.start(methods); + } + info!(local_address = %addr, "JSON-RPC is running."); + Ok((addr, handle)) +} diff --git a/crates/papyrus_rpc/src/middleware.rs b/crates/papyrus_rpc/src/middleware.rs new file mode 100644 index 00000000000..9489fffc567 --- /dev/null +++ b/crates/papyrus_rpc/src/middleware.rs @@ -0,0 +1,123 @@ +use hyper::{Body, Request}; +use jsonrpsee::core::http_helpers::read_body; +use regex::Regex; +use tower::BoxError; +use tracing::{debug, instrument}; + +use crate::version_config::{VersionState, VERSION_CONFIG, VERSION_PATTERN}; +use crate::SERVER_MAX_BODY_SIZE; + +/// [`Tower`] middleware intended to proxy method requests to the right version of the API. +/// The middleware reads the JsonRPC request body and request path +/// then prefixes the method name with the appropriate version identifier. +/// It returns a new [`hyper::Request`] object with the new method name. +/// +/// # Arguments +/// * req - [`hyper::Request`] object passed by the server. +/// +/// [`Tower`]: https://crates.io/crates/tower +pub(crate) async fn proxy_rpc_request(req: Request) -> Result, BoxError> { + debug!("proxy_rpc_request -> Request received: {:?}", req); + let uri = &req.uri().clone(); + let prefix = get_version_as_prefix(uri.path())?; + let (parts, body) = req.into_parts(); + let (body_bytes, is_single) = + read_body(&parts.headers, body, SERVER_MAX_BODY_SIZE).await.map_err(BoxError::from)?; + let new_body = match is_single { + true => { + let body = serde_json::from_slice::>(&body_bytes)?; + add_version_to_method_name_in_body(vec![body], prefix, is_single) + } + false => { + let vec_body = + serde_json::from_slice::>>(&body_bytes)?; + add_version_to_method_name_in_body(vec_body, prefix, is_single) + } + }?; + Ok(Request::from_parts(parts, new_body.into())) +} + +/// ['Tower`] middleware intended to deny requests with unsupported paths. +/// supported paths are paths that starts with '/rpc/' followed by a supported version id. +/// +/// # Arguments +/// * req - [`hyper::Request`] object passed by the server. +/// +/// [`Tower`]: https://crates.io/crates/tower +pub(crate) async fn deny_requests_with_unsupported_path( + req: Request, +) -> Result, BoxError> { + debug!("deny_requests_with_unsupported_path -> Request received: {:?}", req); + let uri = req.uri(); + match is_supported_path(uri.path()) { + true => Ok(req), + false => Err(BoxError::from("Unsupported path for request")), + } +} + +fn add_version_to_method_name_in_body( + mut vec_body: Vec>, + prefix: &str, + is_single: bool, +) -> Result, BoxError> { + let Ok(vec_body) = vec_body + .iter_mut() + .map(|body| { + let Some(stripped_method) = strip_starknet_from_method(body.method.as_ref()) else { + return Err(BoxError::from("Method name has unexpected format")); + }; + body.method = format!("starknet_{prefix}_{stripped_method}").into(); + Ok(body) + }) + .collect::, _>>() + else { + return Err(BoxError::from("Method name has unexpected format")); + }; + let serialized = match is_single { + true => serde_json::to_vec(&vec_body[0]), + false => serde_json::to_vec(&vec_body), + }; + serialized.map_err(BoxError::from) +} + +/// this assumes that all methods are of the form: +/// starknet_OnlyOneUnderScoreAndMethodNameIsCamleCased +fn strip_starknet_from_method(method: &str) -> Option<&str> { + let split_method_name = method.split('_').collect::>(); + split_method_name.get(1).copied() +} + +#[instrument(level = "debug", err)] +fn get_version_as_prefix(path: &str) -> Result<&str, BoxError> { + // get the version name from the path (should be something like "http://host:port/rpc/version_id") + let uri_components = &mut path.split('/').collect::>(); + let Some(temp_version) = uri_components.get(2) else { + // as long as 'deny_requests_with_unsupported_path' middleware is used, this should never + // happen but for safety we return an error and not unreachable!() + let msg = format!("Invalid path format: {path}"); + debug!(msg); + return Err(BoxError::from(msg)); + }; + let version_comps = temp_version.split('_').collect::>(); + let mut patch_num = 0; + if version_comps.len() == 3 { + // if the version is of the form "V0_0_1" we store the path num to check that our latest + // supported patch version is at least the requested version. + patch_num = version_comps[2].parse::().map_err(BoxError::from)?; + } + let version = format!("{}_{}", version_comps[0], version_comps[1]); + let Some((version_id, _)) = + // find a matching version in the version config + VERSION_CONFIG.iter().find(|(version_id, version_state)| { + (version_id.name == version || version_id.name.to_lowercase() == version) && *version_state != VersionState::Deprecated && patch_num <= version_id.patch + }) else { + return Err(BoxError::from(format!("Invalid path, couldn't find matching version for version_id: {version}"))); + }; + Ok(version_id.name) +} + +fn is_supported_path(path: &str) -> bool { + let re = Regex::new((r"^\/rpc\/".to_string() + VERSION_PATTERN + "$").as_str()) + .expect("should be a valid regex"); + re.is_match(path) +} diff --git a/crates/papyrus_rpc/src/pending.rs b/crates/papyrus_rpc/src/pending.rs new file mode 100644 index 00000000000..38118b84533 --- /dev/null +++ b/crates/papyrus_rpc/src/pending.rs @@ -0,0 +1,23 @@ +use papyrus_common::pending_classes::PendingClasses; +use papyrus_execution::objects::PendingData as ExecutionPendingData; +use starknet_client::reader::objects::pending_data::PendingData as ClientPendingData; + +pub(crate) fn client_pending_data_to_execution_pending_data( + client_pending_data: ClientPendingData, + pending_classes: PendingClasses, +) -> ExecutionPendingData { + ExecutionPendingData { + storage_diffs: client_pending_data.state_update.state_diff.storage_diffs, + deployed_contracts: client_pending_data.state_update.state_diff.deployed_contracts, + declared_classes: client_pending_data.state_update.state_diff.declared_classes, + old_declared_contracts: client_pending_data.state_update.state_diff.old_declared_contracts, + nonces: client_pending_data.state_update.state_diff.nonces, + replaced_classes: client_pending_data.state_update.state_diff.replaced_classes, + classes: pending_classes, + timestamp: client_pending_data.block.timestamp(), + l1_gas_price: client_pending_data.block.l1_gas_price(), + l1_data_gas_price: client_pending_data.block.l1_data_gas_price(), + l1_da_mode: client_pending_data.block.l1_da_mode(), + sequencer: client_pending_data.block.sequencer_address(), + } +} diff --git a/crates/papyrus_rpc/src/rpc_metrics/mod.rs b/crates/papyrus_rpc/src/rpc_metrics/mod.rs new file mode 100644 index 00000000000..a5098f80e91 --- /dev/null +++ b/crates/papyrus_rpc/src/rpc_metrics/mod.rs @@ -0,0 +1,120 @@ +#[cfg(test)] +mod rpc_metrics_test; + +use std::collections::HashSet; +use std::net::SocketAddr; +use std::time::Instant; + +use jsonrpsee::server::logger::{HttpRequest, Logger, MethodKind, TransportProtocol}; +use jsonrpsee::types::Params; +use jsonrpsee::Methods; +use metrics::{histogram, increment_counter, register_counter, register_histogram}; + +// Name of the metrics. +const INCOMING_REQUEST: &str = "rpc_incoming_requests"; +const FAILED_REQUESTS: &str = "rpc_failed_requests"; +const REQUEST_LATENCY: &str = "rpc_request_latency_seconds"; + +// Labels for the metrics. +const METHOD_LABEL: &str = "method"; +const VERSION_LABEL: &str = "version"; +const ILLEGAL_METHOD: &str = "illegal_method"; + +// Register the metrics and returns a set of the method names. +fn init_metrics(methods: &Methods) -> HashSet { + let mut methods_set: HashSet = HashSet::new(); + register_counter!(INCOMING_REQUEST, METHOD_LABEL => ILLEGAL_METHOD); + register_counter!(FAILED_REQUESTS, METHOD_LABEL => ILLEGAL_METHOD); + for method in methods.method_names() { + methods_set.insert(method.to_string()); + let (method_name, version) = get_method_and_version(method); + register_counter!(FAILED_REQUESTS, METHOD_LABEL => method_name.clone(), VERSION_LABEL => version.clone()); + register_counter!(INCOMING_REQUEST, METHOD_LABEL => method_name.clone(), VERSION_LABEL => version.clone()); + register_histogram!(REQUEST_LATENCY, METHOD_LABEL => method_name, VERSION_LABEL => version); + } + methods_set +} +#[derive(Clone)] +pub(crate) struct MetricLogger { + // A set of all the method names the node support. + methods_set: HashSet, +} + +impl MetricLogger { + pub(crate) fn new(methods: &Methods) -> Self { + let methods_set = init_metrics(methods); + Self { methods_set } + } +} + +impl Logger for MetricLogger { + type Instant = Instant; + + fn on_result( + &self, + method_name: &str, + success_or_error: jsonrpsee::helpers::MethodResponseResult, + started_at: Self::Instant, + _transport: TransportProtocol, + ) { + // To prevent creating metrics for illegal methods. + if self.methods_set.contains(method_name) { + let (method, version) = get_method_and_version(method_name); + if let jsonrpsee::helpers::MethodResponseResult::Failed(_) = success_or_error { + increment_counter!(FAILED_REQUESTS, METHOD_LABEL=> method.clone(), VERSION_LABEL=> version.clone()); + } + increment_counter!(INCOMING_REQUEST, METHOD_LABEL=> method.clone(), VERSION_LABEL=> version.clone()); + let latency = started_at.elapsed().as_secs_f64(); + histogram!(REQUEST_LATENCY, latency,METHOD_LABEL=> method, VERSION_LABEL=> version); + } else { + increment_counter!(INCOMING_REQUEST, METHOD_LABEL => ILLEGAL_METHOD); + increment_counter!(FAILED_REQUESTS, METHOD_LABEL => ILLEGAL_METHOD); + } + } + + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn on_request(&self, _transport: TransportProtocol) -> Self::Instant { + Instant::now() + } + + // Required methods. + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn on_connect(&self, _remote_addr: SocketAddr, _request: &HttpRequest, _t: TransportProtocol) {} + + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn on_call( + &self, + _method_name: &str, + _params: Params<'_>, + _kind: MethodKind, + _transport: TransportProtocol, + ) { + } + + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn on_response( + &self, + _result: &str, + _started_at: Self::Instant, + _transport: TransportProtocol, + ) { + } + + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn on_disconnect(&self, _remote_addr: SocketAddr, _transport: TransportProtocol) {} +} + +// Given method_name returns (method, version). +// Example: method_name: starknet_V0_6_0_blockNumber; output: (blockNumber, V0_6_0). +fn get_method_and_version(method_name: &str) -> (String, String) { + // The structure of method_name is in the following format: "starknet_V0_6_0_blockNumber". + // Only method in this format will arrive to this point in the code. + let last_underscore_index = method_name + .rfind('_') + .expect("method_name should be in the following format: starknet_V0_6_0_blockNumber"); + + ( + method_name[last_underscore_index + 1..].to_string(), + method_name[9..last_underscore_index].to_string(), + ) +} diff --git a/crates/papyrus_rpc/src/rpc_metrics/rpc_metrics_test.rs b/crates/papyrus_rpc/src/rpc_metrics/rpc_metrics_test.rs new file mode 100644 index 00000000000..a14fb8b44e8 --- /dev/null +++ b/crates/papyrus_rpc/src/rpc_metrics/rpc_metrics_test.rs @@ -0,0 +1,233 @@ +use std::sync::Arc; +use std::time::Instant; + +use jsonrpsee::server::logger::{Logger, TransportProtocol}; +use jsonrpsee::Methods; +use metrics_exporter_prometheus::PrometheusBuilder; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use pretty_assertions::assert_eq; +use prometheus_parse::Value::Counter; +use starknet_api::block::{BlockBody, BlockHeader, BlockNumber}; +use starknet_api::state::ThinStateDiff; +use test_utils::{prometheus_is_contained, send_request}; + +use crate::rpc_metrics::{ + get_method_and_version, + MetricLogger, + FAILED_REQUESTS, + ILLEGAL_METHOD, + INCOMING_REQUEST, + METHOD_LABEL, + VERSION_LABEL, +}; +use crate::run_server; +use crate::test_utils::{ + get_test_highest_block, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, +}; + +#[test] +fn get_method_and_version_test() { + let method_name = "starknet_V0_6_0_blockNumber"; + let (method, version) = get_method_and_version(method_name); + assert_eq!(method, "blockNumber"); + assert_eq!(version, "V0_6_0"); +} + +// Ignored because server_metrics test is running in parallel and we are unable to install multiple +// recorders. +#[ignore] +#[test] +fn logger_test() { + let full_method_name = "starknet_V0_6_0_blockNumber"; + let (method, version) = get_method_and_version(full_method_name); + let labels = vec![(METHOD_LABEL, method.as_str()), (VERSION_LABEL, version.as_str())]; + let illegal_method_label = vec![(METHOD_LABEL, ILLEGAL_METHOD)]; + let handle = PrometheusBuilder::new().install_recorder().unwrap(); + let callback = jsonrpsee::MethodCallback::Unsubscription(Arc::new(|_, _, _, _| { + jsonrpsee::MethodResponse { + result: String::new(), + success_or_error: jsonrpsee::helpers::MethodResponseResult::Success, + } + })); + let mut methods = Methods::new(); + methods.verify_and_insert(full_method_name, callback).unwrap(); + let logger = MetricLogger::new(&methods); + + // The counters are initialized with zero. + assert_eq!( + prometheus_is_contained(handle.render(), INCOMING_REQUEST, &labels), + Some(Counter(0f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), INCOMING_REQUEST, &illegal_method_label), + Some(Counter(0f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &labels), + Some(Counter(0f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &illegal_method_label), + Some(Counter(0f64)) + ); + + // Successful call. + logger.on_result( + full_method_name, + jsonrpsee::helpers::MethodResponseResult::Success, + Instant::now(), + TransportProtocol::Http, + ); + assert_eq!( + prometheus_is_contained(handle.render(), INCOMING_REQUEST, &labels), + Some(Counter(1f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &labels), + Some(Counter(0f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &illegal_method_label), + Some(Counter(0f64)) + ); + + // Failed call. + logger.on_result( + full_method_name, + jsonrpsee::helpers::MethodResponseResult::Failed(0), + Instant::now(), + TransportProtocol::Http, + ); + assert_eq!( + prometheus_is_contained(handle.render(), INCOMING_REQUEST, &labels), + Some(Counter(2f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &labels), + Some(Counter(1f64)) + ); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &illegal_method_label), + Some(Counter(0f64)) + ); + + // Illegal method. + let bad_method_name = "starknet_V0_6_0_illegal_method"; + let (method, version) = get_method_and_version(bad_method_name); + let bad_labels = vec![(METHOD_LABEL, method.as_str()), (VERSION_LABEL, version.as_str())]; + logger.on_result( + bad_method_name, + jsonrpsee::helpers::MethodResponseResult::Failed(0), + Instant::now(), + TransportProtocol::Http, + ); + assert_eq!(prometheus_is_contained(handle.render(), INCOMING_REQUEST, &bad_labels), None); + assert_eq!( + prometheus_is_contained(handle.render(), INCOMING_REQUEST, &illegal_method_label), + Some(Counter(1f64)) + ); + assert_eq!(prometheus_is_contained(handle.render(), FAILED_REQUESTS, &bad_labels), None); + assert_eq!( + prometheus_is_contained(handle.render(), FAILED_REQUESTS, &illegal_method_label), + Some(Counter(1f64)) + ); +} + +#[tokio::test] +async fn server_metrics() { + let prometheus_handle = PrometheusBuilder::new().install_recorder().unwrap(); + + // Run the server. + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(0), &[], &[]) + .unwrap() + .commit() + .unwrap(); + let mut gateway_config = get_test_rpc_config(); + gateway_config.collect_metrics = true; + let (server_address, _handle) = run_server( + &gateway_config, + get_test_highest_block(), + get_test_pending_data(), + get_test_pending_classes(), + storage_reader, + "NODE VERSION", + ) + .await + .unwrap(); + + let get_counters = || { + let mut incoming_block_number = String::new(); + let mut failing_block_number = String::new(); + let mut incoming_get_state_update = String::new(); + let mut failing_get_state_update = String::new(); + let metrics = prometheus_handle.render(); + for line in metrics.split('\n').filter(|line| line.contains("V0_6")) { + if line.contains("rpc_incoming_requests{method=\"blockNumber\"") { + println!("{}", line); + line.split(' ').last().unwrap().clone_into(&mut incoming_block_number); + } + if line.contains("rpc_failed_requests{method=\"blockNumber\"") { + println!("{}", line); + line.split(' ').last().unwrap().clone_into(&mut failing_block_number); + } + if line.contains("rpc_incoming_requests{method=\"getStateUpdate\"") { + println!("{}", line); + line.split(' ').last().unwrap().clone_into(&mut incoming_get_state_update); + } + if line.contains("rpc_failed_requests{method=\"getStateUpdate\"") { + println!("{}", line); + line.split(' ').last().unwrap().clone_into(&mut failing_get_state_update); + } + } + ( + incoming_block_number, + failing_block_number, + incoming_get_state_update, + failing_get_state_update, + ) + }; + + let ( + incoming_block_number, + failing_block_number, + incoming_get_state_update, + failing_get_state_update, + ) = get_counters(); + + assert_eq!(incoming_block_number, "0"); + assert_eq!(failing_block_number, "0"); + assert_eq!(incoming_get_state_update, "0"); + assert_eq!(failing_get_state_update, "0"); + + send_request(server_address, "starknet_blockNumber", "", "V0_6").await; + send_request(server_address, "starknet_getStateUpdate", r#"{"block_number": 7}"#, "V0_6").await; + + let ( + incoming_block_number, + failing_block_number, + incoming_get_state_update, + failing_get_state_update, + ) = get_counters(); + + assert_eq!(incoming_block_number, "1"); + assert_eq!(failing_block_number, "0"); + assert_eq!(incoming_get_state_update, "1"); + assert_eq!(failing_get_state_update, "1"); +} diff --git a/crates/papyrus_rpc/src/rpc_test.rs b/crates/papyrus_rpc/src/rpc_test.rs new file mode 100644 index 00000000000..0ad52556571 --- /dev/null +++ b/crates/papyrus_rpc/src/rpc_test.rs @@ -0,0 +1,234 @@ +use std::error::Error as StdError; +use std::{panic, vec}; + +use assert_matches::assert_matches; +use futures_util::future::join_all; +use hyper::{header, Body, Request}; +use jsonrpsee::core::client::ClientT; +use jsonrpsee::core::http_helpers::read_body; +use jsonrpsee::core::{Error, RpcResult}; +use jsonrpsee::http_client::HttpClientBuilder; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_storage::base_layer::BaseLayerStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use pretty_assertions::assert_eq; +use rand::seq::SliceRandom; +use starknet_api::block::{BlockHash, BlockHeader, BlockNumber, BlockStatus}; +use test_utils::get_rng; +use tower::BoxError; + +use crate::middleware::proxy_rpc_request; +use crate::test_utils::{ + get_test_highest_block, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, +}; +use crate::version_config::VERSION_CONFIG; +use crate::{get_block_status, run_server, SERVER_MAX_BODY_SIZE}; + +#[tokio::test] +async fn run_server_no_blocks() { + let ((storage_reader, _), _temp_dir) = get_test_storage(); + let gateway_config = get_test_rpc_config(); + let shared_highest_block = get_test_highest_block(); + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + let (addr, _handle) = run_server( + &gateway_config, + shared_highest_block, + pending_data, + pending_classes, + storage_reader, + "NODE VERSION", + ) + .await + .unwrap(); + let client = HttpClientBuilder::default().build(format!("http://{addr:?}")).unwrap(); + let res: Result, Error> = + client.request("starknet_blockNumber", [""]).await; + let _expected_error = ErrorObjectOwned::owned(123, "", None::); + // TODO(yair): fix this test: + // 1. assert_matches doesn't compare the values, just the types + // 2. the error is not the expected one + // 3. the expected error should be "Invalid path format: {path}" + match res { + Err(err) => assert_matches!(err, _expected_error), + Ok(_) => panic!("should error with no blocks"), + }; +} + +/// Given an HTTP request, using the "read_body" function from jsonrpsee library, +/// parse the body, make sure it's a formatted JSON and within the MAX_BODY_SIZE length. +async fn get_json_rpc_body(request: Request) -> Vec { + let (res_parts, res_body) = request.into_parts(); + let (body_bytes, _is_single) = + read_body(&res_parts.headers, res_body, SERVER_MAX_BODY_SIZE).await.unwrap(); + body_bytes +} + +async fn call_proxy_request_get_method_in_out( + uri: String, + is_batch_request: bool, +) -> Result<(String, String), BoxError> { + let method_name = "myMethod"; + let params = serde_json::from_str(r#"[{"myParam": "myValue"}]"#).unwrap(); + let request_body = get_request_body(is_batch_request, params, method_name); + let req_no_version = Request::post(uri.clone()) + .header(header::CONTENT_TYPE, "application/json") + .body(Body::from(request_body.unwrap())) + .unwrap(); + let res = proxy_rpc_request(req_no_version).await?; + let body_bytes = get_json_rpc_body(res).await; + digest_body_and_assert(is_batch_request, body_bytes, params, method_name) +} + +fn digest_body_and_assert( + is_batch_request: bool, + body_bytes: Vec, + params: &serde_json::value::RawValue, + method_name: &str, +) -> Result<(String, String), Box> { + match is_batch_request { + false => { + let body = + serde_json::from_slice::>(&body_bytes).unwrap(); + // assert params not altered by proxy middleware + assert_eq!(params.to_string(), body.params.unwrap().to_string()); + Ok((method_name.to_string(), body.method.to_string())) + } + true => { + let body_batch = + serde_json::from_slice::>>(&body_bytes).unwrap(); + // assert params not altered by proxy middleware for all requests in batch + body_batch.iter().for_each(|body| { + assert_eq!(params.to_string(), body.params.unwrap().to_string()); + }); + Ok((method_name.to_string(), body_batch[0].method.to_string())) + } + } +} + +fn get_request_body( + is_batch_request: bool, + params: &serde_json::value::RawValue, + method_name: &str, +) -> Result { + match is_batch_request { + false => serde_json::to_string(&jsonrpsee::types::Request::new( + format!("starknet_{method_name}").into(), + Some(params), + jsonrpsee::types::Id::Number(0), + )), + true => serde_json::to_string(&vec![ + jsonrpsee::types::Request::new( + format!("starknet_{method_name}_1").into(), + Some(params), + jsonrpsee::types::Id::Number(0), + ), + jsonrpsee::types::Request::new( + format!("starknet_{method_name}_2").into(), + Some(params), + jsonrpsee::types::Id::Number(0), + ), + ]), + } +} + +// TODO: nevo - add middleware negative cases tests + +#[tokio::test] +async fn test_version_middleware() { + let base_uri = "http://localhost:8080/rpc/"; + let mut path_options = vec![]; + VERSION_CONFIG.iter().for_each(|(version_id, _)| { + // add version name with capital V + path_options.push((version_id.name.to_string(), version_id.name.to_string())); + // add version name with lower case v + path_options.push((version_id.name.to_lowercase(), version_id.name.to_string())); + // add version name with patch version + path_options.push((version_id.to_string(), version_id.name.to_string())); + }); + + // test all versions with single and batch requests + let mut handles = Vec::new(); + for (path, expected_version) in path_options { + let future = async move { + let uri = format!("{base_uri}{path}"); + let (in_method, out_method) = + call_proxy_request_get_method_in_out(uri.clone(), false).await.unwrap(); + { + assert_eq!(format!("starknet_{expected_version}_{in_method}"), out_method); + }; + let (in_method, out_method) = + call_proxy_request_get_method_in_out(uri, true).await.unwrap(); + { + assert_eq!(format!("starknet_{expected_version}_{in_method}"), out_method); + }; + }; + let handle = tokio::spawn(future); + handles.push(handle); + } + let join_res = join_all(handles).await; + join_res.into_iter().for_each(|res| { + if let Err(err) = res { + panic!("expected success got: {err}"); + } + }); + let unknown_version = "not_a_valid_version"; + let bad_uri = format!("{base_uri}{unknown_version}"); + if let Ok(res) = call_proxy_request_get_method_in_out(bad_uri, false).await { + panic!("expected failure got: {res:?}"); + }; + let mut rng = get_rng(); + let version_id = VERSION_CONFIG.choose(&mut rng).unwrap().0; + let newer_version_then_we_have = format!("{}_{}", version_id.name, version_id.patch + 1); + let bad_uri = format!("{base_uri}{newer_version_then_we_have}"); + if let Ok(res) = call_proxy_request_get_method_in_out(bad_uri, false).await { + panic!("expected failure got: {res:?}"); + }; +} + +#[test] +fn get_block_status_test() { + let (reader, mut writer) = get_test_storage().0; + + for block_number in 0..2 { + let header = BlockHeader { + block_number: BlockNumber(block_number), + block_hash: BlockHash(block_number.into()), + ..Default::default() + }; + writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .commit() + .unwrap(); + } + + // update the base_layer_tip_marker to BlockNumber(1). + writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&BlockNumber(1)) + .unwrap() + .commit() + .unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + assert_eq!(get_block_status(&txn, BlockNumber(0)).unwrap(), BlockStatus::AcceptedOnL1); + assert_eq!(get_block_status(&txn, BlockNumber(1)).unwrap(), BlockStatus::AcceptedOnL2); + assert_eq!(get_block_status(&txn, BlockNumber(2)).unwrap(), BlockStatus::AcceptedOnL2); +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_rpc/src/syncing_state.rs b/crates/papyrus_rpc/src/syncing_state.rs new file mode 100644 index 00000000000..bb86ce05b2e --- /dev/null +++ b/crates/papyrus_rpc/src/syncing_state.rs @@ -0,0 +1,59 @@ +use papyrus_common::BlockHashAndNumber; +use papyrus_storage::compiled_class::CasmStorageReader; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageReader, StorageResult}; +use serde::ser::Serializer; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber}; + +/// Represents the syncing status of the node. +#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)] +pub enum SyncingState { + Synced, + SyncStatus(SyncStatus), +} + +impl serde::Serialize for SyncingState { + // Serializes Synced variant into false (not syncing), and SyncStatus into its content. + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::Synced => serializer.serialize_bool(false), + Self::SyncStatus(sync_status) => sync_status.serialize(serializer), + } + } +} + +impl Default for SyncingState { + fn default() -> Self { + Self::SyncStatus(SyncStatus::default()) + } +} + +/// The status of the synchronization progress. The hash and the number of: +/// * the block from which the synchronization started, +/// * the currently syncing block, +/// * the highest known block. +#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct SyncStatus { + pub starting_block_hash: BlockHash, + pub starting_block_num: BlockNumber, + pub current_block_hash: BlockHash, + pub current_block_num: BlockNumber, + pub highest_block_hash: BlockHash, + pub highest_block_num: BlockNumber, +} + +pub(crate) fn get_last_synced_block( + storage_reader: StorageReader, +) -> StorageResult { + let txn = storage_reader.begin_ro_txn()?; + let Some(block_number) = txn.get_compiled_class_marker()?.prev() else { + return Ok(BlockHashAndNumber::default()); + }; + let block_hash = + txn.get_block_header(block_number)?.expect("No header for last compiled class").block_hash; + Ok(BlockHashAndNumber { block_hash, block_number }) +} diff --git a/crates/papyrus_rpc/src/test_utils.rs b/crates/papyrus_rpc/src/test_utils.rs new file mode 100644 index 00000000000..cba4502ac4c --- /dev/null +++ b/crates/papyrus_rpc/src/test_utils.rs @@ -0,0 +1,539 @@ +use std::path::Path; +use std::sync::Arc; + +use derive_more::Display; +use jsonrpsee::core::RpcResult; +use jsonrpsee::server::RpcModule; +use jsonrpsee::types::ErrorObjectOwned; +use jsonschema::JSONSchema; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_common::BlockHashAndNumber; +use papyrus_execution::ExecutionConfig; +use papyrus_storage::test_utils::get_test_storage_by_scope; +use papyrus_storage::{StorageScope, StorageWriter}; +use pretty_assertions::assert_eq; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; +use starknet_api::core::{ChainId, ContractAddress, PatriciaKey}; +use starknet_api::{contract_address, felt, patricia_key}; +use starknet_client::reader::PendingData; +use starknet_client::writer::MockStarknetWriter; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; +use tokio::sync::RwLock; + +use crate::api::JsonRpcServerTrait; +use crate::version_config::{VersionId, VERSION_PATTERN}; +use crate::RpcConfig; + +pub fn get_test_rpc_config() -> RpcConfig { + RpcConfig { + chain_id: ChainId::Sepolia, + execution_config: ExecutionConfig { + eth_fee_contract_address: contract_address!("0x1001"), + strk_fee_contract_address: contract_address!("0x1001"), + initial_gas_cost: 10000000000, + }, + server_address: String::from("127.0.0.1:0"), + max_events_chunk_size: 10, + max_events_keys: 10, + collect_metrics: false, + ..Default::default() + } +} + +pub(crate) fn get_test_highest_block() -> Arc>> { + Arc::new(RwLock::new(None)) +} + +pub(crate) fn get_test_pending_data() -> Arc> { + Arc::new(RwLock::new(PendingData::default())) +} + +pub(crate) fn get_test_pending_classes() -> Arc> { + Arc::new(RwLock::new(PendingClasses::default())) +} + +pub(crate) fn get_test_rpc_server_and_storage_writer() +-> (RpcModule, StorageWriter) { + get_test_rpc_server_and_storage_writer_from_params(None, None, None, None, None) +} + +pub(crate) fn get_test_rpc_server_and_storage_writer_from_params( + mock_client: Option, + shared_highest_block: Option>>>, + pending_data: Option>>, + pending_classes: Option>>, + storage_scope: Option, +) -> (RpcModule, StorageWriter) { + let mock_client = mock_client.unwrap_or_default(); + let shared_highest_block = shared_highest_block.unwrap_or(get_test_highest_block()); + let pending_data = pending_data.unwrap_or(get_test_pending_data()); + let pending_classes = pending_classes.unwrap_or(get_test_pending_classes()); + let storage_scope = storage_scope.unwrap_or_default(); + + let ((storage_reader, storage_writer), _temp_dir) = get_test_storage_by_scope(storage_scope); + let config = get_test_rpc_config(); + let mock_client_arc = Arc::new(mock_client); + ( + T::new( + config.chain_id, + config.execution_config, + storage_reader, + config.max_events_chunk_size, + config.max_events_keys, + BlockHashAndNumber::default(), + shared_highest_block, + pending_data, + pending_classes, + mock_client_arc, + ) + .into_rpc_module(), + storage_writer, + ) +} + +// Call a method on the `RPC module` without having to spin up a server. +// Returns the raw `result field` in JSON-RPC response and the deserialized result if successful. +// `params_obj` should be serialized to the format that JSON-RPC expects, which is either an array +// of parameters or a map from parameter name to parameter. +// +// For example (the parameteres of getTransactionByBlockIdAndIndex"): +// ["latest", 5] or {"block_id": "latest", "index": 5}. +pub(crate) async fn raw_call Deserialize<'a>>( + module: &RpcModule, + method: &str, + params_obj: &S, +) -> (Value, RpcResult) { + let params = serde_json::to_value(params_obj).unwrap(); + let params_str = match params { + Value::Array(vec) if vec.is_empty() => "".to_string(), + Value::Object(map) if map.is_empty() => "".to_string(), + _ => format!(r#", "params":{}"#, params), + }; + let req = format!(r#"{{"jsonrpc":"2.0","id":"1","method":"{method}"{params_str}}}"#); + let (resp_wrapper, _) = module + .raw_json_request(req.as_str(), 1) + .await + .unwrap_or_else(|_| panic!("request format, got: {req}")); + let json_resp: Value = serde_json::from_str(&resp_wrapper.result).unwrap(); + let result: Result> = + match json_resp.get("result") { + Some(resp) => Ok(serde_json::from_value::(resp.clone()) + .expect("result should match the target type")), + None => match json_resp.get("error") { + Some(err) => Err(serde_json::from_value::(err.clone()) + .expect("result should match the rpc error type")), + None => panic!("response should have result or error field, got {json_resp}"), + }, + }; + (json_resp, result) +} + +// TODO(nevo): Schmea validates null as valid for an unknown reason. +// Investigate in the future and remove this function (use is_valid directly) +pub fn validate_schema(schema: &JSONSchema, result: &Value) -> bool { + result != &Value::Null && schema.is_valid(result) +} + +#[derive(Clone, Copy, Display, EnumIter)] +pub enum SpecFile { + #[display(fmt = "starknet_api_openrpc.json")] + StarknetApiOpenrpc, + #[display(fmt = "starknet_write_api.json")] + WriteApi, + #[display(fmt = "starknet_trace_api_openrpc.json")] + TraceApi, +} + +pub fn get_starknet_spec_api_schema_for_components( + file_to_component_names: &[(SpecFile, &[&str])], + version_id: &VersionId, +) -> JSONSchema { + get_starknet_spec_api_schema( + file_to_component_names.iter().flat_map(|(file, component_names)| { + component_names + .iter() + .map(move |component| format!("file:///api/{file}#/components/schemas/{component}")) + }), + version_id, + ) +} + +pub fn get_starknet_spec_api_schema_for_method_param( + file_to_methods_and_param_indices: &[(SpecFile, &[(&str, usize)])], + version_id: &VersionId, +) -> JSONSchema { + get_starknet_spec_api_schema( + file_to_methods_and_param_indices.iter().flat_map(|(file, methods_and_param_indices)| { + let spec: serde_json::Value = + read_spec(format!("./resources/{}/{file}", version_id.name)); + + methods_and_param_indices.iter().map(move |(method, param_index)| { + let method_index = get_method_index(&spec, method); + format!("file:///api/{file}#/methods/{method_index}/params/{param_index}/schema") + }) + }), + version_id, + ) +} + +pub fn get_starknet_spec_api_schema_for_method_results( + file_to_methods: &[(SpecFile, &[&str])], + version_id: &VersionId, +) -> JSONSchema { + get_starknet_spec_api_schema( + file_to_methods.iter().flat_map(|(file, methods)| { + let spec: serde_json::Value = + read_spec(format!("./resources/{}/{file}", version_id.name)); + + methods.iter().map(move |method| { + let index = get_method_index(&spec, method); + format!("file:///api/{file}#/methods/{index}/result/schema") + }) + }), + version_id, + ) +} + +pub fn get_starknet_spec_api_schema_for_method_errors( + file_to_methods: &[(SpecFile, &[&str])], + version_id: &VersionId, +) -> JSONSchema { + get_starknet_spec_api_schema( + file_to_methods.iter().flat_map(|(file, methods)| { + let spec: serde_json::Value = + read_spec(format!("./resources/{}/{file}", version_id.name)); + + methods.iter().flat_map(move |method| { + let index = get_method_index(&spec, method); + let method_json_obj = + spec.as_object().unwrap().get("methods").unwrap().as_array().unwrap()[index] + .as_object() + .unwrap(); + let errors_len = method_json_obj.get("errors").unwrap().as_array().unwrap().len(); + + (0..errors_len).map(move |error_index| { + format!("file:///api/{file}#/methods/{index}/errors/{error_index}") + }) + }) + }), + version_id, + ) +} + +fn get_starknet_spec_api_schema>( + refs: Refs, + version_id: &VersionId, +) -> JSONSchema { + let mut options = JSONSchema::options(); + for entry in std::fs::read_dir(format!("./resources/{}", version_id.name)).unwrap() { + let path = entry.unwrap().path(); + let spec_str = std::fs::read_to_string(path.clone()).unwrap(); + let mut spec: serde_json::Value = serde_json::from_str(&spec_str).unwrap(); + fix_errors(&mut spec); + let file_name = path.file_name().unwrap().to_str().unwrap(); + options.with_document(format!("file:///api/{file_name}"), spec); + } + + let mut refs_schema_str = String::from(r#"{"anyOf": ["#); + const SEPARATOR: &str = ", "; + for ref_str in refs { + refs_schema_str += &format!(r##"{{"$ref": "{ref_str}"}}"##,); + refs_schema_str += SEPARATOR; + } + // Remove the last separator. + refs_schema_str.truncate(refs_schema_str.len() - SEPARATOR.len()); + refs_schema_str += r#"], "unevaluatedProperties": false}"#; + let refs_schema = serde_json::from_str(&refs_schema_str).unwrap(); + + options.compile(&refs_schema).unwrap() +} + +fn read_spec>(path: P) -> serde_json::Value { + let spec_str = std::fs::read_to_string(path).unwrap(); + serde_json::from_str(&spec_str).unwrap() +} + +fn get_method_index(spec: &serde_json::Value, method: &str) -> usize { + let methods_json_arr = spec.as_object().unwrap().get("methods").unwrap().as_array().unwrap(); + for (i, method_object) in methods_json_arr.iter().enumerate() { + if method_object.as_object().unwrap().get("name").unwrap() == method { + return i; + } + } + panic!("Method {method} doesn't exist"); +} + +// This function will change the errors in components/errors into schemas that accept the error. +// It will change an error from the following json object: +// { "code": 1, "message": "an error occurred" } into { +// "properties": { +// "code: { +// "type": "integer", +// "enum": [1] +// }, +// "message": { +// "type": "string", +// "enum": ["an error occurred"] +// } +// }, +// required: ["code", "message"] +// } +// And it will change an error from the following json object: +// { "code": 1, "message": "an error occurred", "data": "string" } into { +// "properties": { +// "code: { +// "type": "integer", +// "enum": [1] +// }, +// "message": { +// "type": "string", +// "enum": ["an error occurred"] +// } +// "data": {} +// }, +// required: ["code", "message", "data"] +// } +fn fix_errors(spec: &mut serde_json::Value) { + let Some(errors) = spec + .as_object_mut() + .and_then(|obj| obj.get_mut("components")) + .and_then(|components| components.as_object_mut()) + .and_then(|components| components.get_mut("errors")) + .and_then(|errors| errors.as_object_mut()) + else { + return; + }; + for value in errors.values_mut() { + let obj = value.as_object_mut().unwrap(); + let Some(code) = obj.get("code").map(|code_obj| (*code_obj).clone()) else { + continue; + }; + let Some(message) = obj.get("message").map(|message_obj| (*message_obj).clone()) else { + continue; + }; + let has_data = obj.contains_key("data"); + obj.clear(); + let mut properties = serde_json::Map::from_iter([ + ( + "code".to_string(), + serde_json::Map::from_iter([ + ("type".to_string(), "integer".into()), + ("enum".to_string(), vec![code].into()), + ]) + .into(), + ), + ( + "message".to_string(), + serde_json::Map::from_iter([ + ("type".to_string(), "string".into()), + ("enum".to_string(), vec![message].into()), + ]) + .into(), + ), + ]); + let mut required: Vec = vec!["code".into(), "message".into()]; + if has_data { + properties.insert("data".to_string(), serde_json::Map::from_iter([]).into()); + required.push("data".into()); + } + obj.insert("properties".to_string(), properties.into()); + obj.insert("required".to_string(), required.into()); + } +} + +pub fn method_name_to_spec_method_name(method_name: &str) -> String { + let re = Regex::new((VERSION_PATTERN.to_string() + "_").as_str()).unwrap(); + re.replace_all(method_name, "").to_string() +} + +pub async fn call_api_then_assert_and_validate_schema_for_err< + R: JsonRpcServerTrait, + T: for<'a> Deserialize<'a> + std::fmt::Debug, +>( + module: &RpcModule, + method: &str, + params: Vec>, + version_id: &VersionId, + spec_file: SpecFile, + expected_err: &ErrorObjectOwned, +) { + validate_schema_for_method_params(method, ¶ms, version_id, spec_file); + let params = params_vec_to_named_params(method, params, version_id, spec_file); + let (json_response, err) = raw_call::<_, _, T>(module, method, ¶ms).await; + assert_eq!(err.unwrap_err(), *expected_err); + assert!( + validate_schema( + &get_starknet_spec_api_schema_for_method_errors( + &[(spec_file, &[method_name_to_spec_method_name(method).as_str()])], + version_id, + ), + &json_response["error"], + ), + "Error of method {} does not correspond to the specs.\nError serialization:\n{}\nError \ + specs:\n{}", + method, + serde_json::to_string_pretty(&json_response).unwrap(), + // The arguments here are evaluated only when the assertion fails. + serde_json::to_string_pretty( + &get_method_spec_object(method, version_id, spec_file)["errors"] + ) + .unwrap(), + ); +} + +pub async fn call_api_then_assert_and_validate_schema_for_result< + R: JsonRpcServerTrait, + T: for<'a> Deserialize<'a> + std::fmt::Debug + std::cmp::PartialEq, +>( + module: &RpcModule, + method: &str, + params: Vec>, + version_id: &VersionId, + spec_file: SpecFile, + expected_res: &T, +) { + assert_eq!( + call_and_validate_schema_for_result::<_, T>(module, method, params, version_id, spec_file) + .await, + *expected_res + ); +} + +pub async fn call_and_validate_schema_for_result< + R: JsonRpcServerTrait, + T: for<'a> Deserialize<'a> + std::fmt::Debug, +>( + module: &RpcModule, + method: &str, + params: Vec>, + version_id: &VersionId, + spec_file: SpecFile, +) -> T { + validate_schema_for_method_params(method, ¶ms, version_id, spec_file); + let params = params_vec_to_named_params(method, params, version_id, spec_file); + let (json_response, res) = raw_call::<_, _, T>(module, method, ¶ms).await; + assert!( + validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[(spec_file, &[method_name_to_spec_method_name(method).as_str()])], + version_id, + ), + &json_response["result"], + ), + "Result of method {} does not correspond to the specs.\nResult serialization:\n{}\nResult \ + specs:\n{}", + method, + serde_json::to_string_pretty(&json_response).unwrap(), + // The arguments here are evaluated only when the assertion fails. + serde_json::to_string_pretty( + &get_method_spec_object(method, version_id, spec_file)["result"] + ) + .unwrap(), + ); + res.unwrap() +} + +pub fn get_method_names_from_spec(version_id: &VersionId) -> Vec { + SpecFile::iter() + .flat_map(|file| { + let spec: serde_json::Value = + read_spec(format!("./resources/{}/{file}", version_id.name)); + let methods_json_arr = + spec.as_object().unwrap().get("methods").unwrap().as_array().unwrap(); + methods_json_arr + .iter() + .map(|method_object| { + method_object.as_object().unwrap().get("name").unwrap().to_string() + }) + .collect::>() + }) + .collect::>() +} + +// We implement this trait because `Serialize` and `Clone` are not object safe. For more info see +// https://doc.rust-lang.org/reference/items/traits.html#object-safety +pub trait SerializeJsonValue: Send { + fn to_json_value(&self) -> Result; +} + +impl SerializeJsonValue for T { + fn to_json_value(&self) -> Result { + serde_json::to_value(self.clone()) + } +} + +fn validate_schema_for_method_params( + method: &str, + params: &[Box], + version_id: &VersionId, + spec_file: SpecFile, +) { + let method_spec_object = get_method_spec_object(method, version_id, spec_file); + if params.is_empty() { + assert!( + method_spec_object["params"].as_array().unwrap().is_empty(), + "Got no params for method {} which expects the following params according to the \ + specs:\n{}", + method, + serde_json::to_string_pretty(&method_spec_object["params"]).unwrap(), + ); + + return; + }; + for (i, param) in params.iter().enumerate() { + assert!( + validate_schema( + &get_starknet_spec_api_schema_for_method_param( + &[(spec_file, &[(method_name_to_spec_method_name(method).as_str(), i)])], + version_id, + ), + ¶m.to_json_value().unwrap(), + ), + "Param no. {} of method {} does not correspond to the specs.\nParam \ + serialization:\n{}\nParam specs:\n{}", + i, + method, + serde_json::to_string_pretty(¶m.to_json_value().unwrap()).unwrap(), + serde_json::to_string_pretty(&method_spec_object["params"][i]).unwrap(), + ); + } +} + +// Convert a vector of parameters to a map from parameter name to parameter. +// Get the name of the parameters from the specs. +fn params_vec_to_named_params( + method: &str, + params: Vec>, + version_id: &VersionId, + spec_file: SpecFile, +) -> Value { + let method_spec_object = get_method_spec_object(method, version_id, spec_file); + let method_params_spec_array = method_spec_object["params"].as_array().unwrap(); + let method_names = method_params_spec_array.iter().map(|param_spec_object| { + param_spec_object.as_object().unwrap()["name"].as_str().unwrap().to_owned() + }); + + assert_eq!(method_params_spec_array.len(), params.len()); + + let serialized_params = params.into_iter().map(|param| param.to_json_value().unwrap()); + + Value::Object(Map::from_iter(method_names.zip(serialized_params))) +} + +// Read the spec file and return the json object specifying the given method. +fn get_method_spec_object( + method: &str, + version_id: &VersionId, + spec_file: SpecFile, +) -> Map { + let spec: serde_json::Value = read_spec(format!("./resources/{}/{spec_file}", version_id.name)); + let method_index = get_method_index(&spec, &method_name_to_spec_method_name(method)); + + spec.as_object().unwrap()["methods"].as_array().unwrap()[method_index] + .as_object() + .unwrap() + .clone() +} diff --git a/crates/papyrus_rpc/src/v0_6/api/api_impl.rs b/crates/papyrus_rpc/src/v0_6/api/api_impl.rs new file mode 100644 index 00000000000..8a91b6aad83 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/api/api_impl.rs @@ -0,0 +1,1522 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use jsonrpsee::core::RpcResult; +use jsonrpsee::types::ErrorObjectOwned; +use jsonrpsee::RpcModule; +use lazy_static::lazy_static; +use papyrus_common::pending_classes::{PendingClasses, PendingClassesTrait}; +use papyrus_execution::objects::{ + FeeEstimation as ExecutionFeeEstimate, + PendingData as ExecutionPendingData, +}; +use papyrus_execution::{ + estimate_fee as exec_estimate_fee, + execute_call, + execution_utils, + simulate_transactions as exec_simulate_transactions, + ExecutableTransactionInput, + ExecutionConfig, +}; +use papyrus_storage::body::events::{EventIndex, EventsReader}; +use papyrus_storage::body::{BodyStorageReader, TransactionIndex}; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageError, StorageReader, StorageTxn}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus}; +use starknet_api::core::{ChainId, ClassHash, ContractAddress, GlobalRoot, Nonce}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{StateNumber, StorageKey}; +use starknet_api::transaction::{ + EventContent, + EventIndexInTransactionOutput, + Fee, + Transaction as StarknetApiTransaction, + TransactionHash, + TransactionOffsetInBlock, +}; +use starknet_client::reader::objects::pending_data::{ + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate as ClientPendingStateUpdate, +}; +use starknet_client::reader::PendingData; +use starknet_client::writer::{StarknetWriter, WriterClientError}; +use starknet_client::ClientError; +use starknet_types_core::felt::Felt; +use tokio::sync::RwLock; +use tracing::{instrument, trace, warn}; + +use super::super::block::{ + get_accepted_block_number, + get_block_header_by_number, + Block, + BlockHeader, + BlockNotRevertedValidator, + GeneralBlockHeader, + PendingBlockHeader, + ResourcePrice, +}; +use super::super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedTransaction, +}; +use super::super::error::{ + ContractError, + JsonRpcError, + TransactionExecutionError, + BLOCK_NOT_FOUND, + CLASS_HASH_NOT_FOUND, + CONTRACT_NOT_FOUND, + INVALID_TRANSACTION_HASH, + INVALID_TRANSACTION_INDEX, + NO_BLOCKS, + PAGE_SIZE_TOO_BIG, + TOO_MANY_KEYS_IN_FILTER, + TRANSACTION_HASH_NOT_FOUND, +}; +use super::super::execution::TransactionTrace; +use super::super::state::{AcceptedStateUpdate, PendingStateUpdate, StateUpdate}; +use super::super::transaction::{ + get_block_tx_hashes_by_number, + get_block_txs_by_number, + Event, + GeneralTransactionReceipt, + L1HandlerMsgHash, + MessageFromL1, + PendingTransactionFinalityStatus, + PendingTransactionOutput, + PendingTransactionReceipt, + TransactionOutput, + TransactionReceipt, + TransactionStatus, + TransactionWithHash, + Transactions, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::super::write_api_error::{ + starknet_error_to_declare_error, + starknet_error_to_deploy_account_error, + starknet_error_to_invoke_error, +}; +use super::super::write_api_result::{ + AddDeclareOkResult, + AddDeployAccountOkResult, + AddInvokeOkResult, +}; +use super::{ + execution_error_to_error_object_owned, + stored_txn_to_executable_txn, + BlockHashAndNumber, + BlockId, + CallRequest, + ContinuationToken, + EventFilter, + EventsChunk, + FeeEstimate, + GatewayContractClass, + JsonRpcV0_6Server as JsonRpcServer, + SimulatedTransaction, + SimulationFlag, + TransactionTraceWithHash, +}; +use crate::api::{BlockHashOrNumber, JsonRpcServerTrait, Tag}; +use crate::pending::client_pending_data_to_execution_pending_data; +use crate::syncing_state::{get_last_synced_block, SyncStatus, SyncingState}; +use crate::version_config::VERSION_0_6 as VERSION; +use crate::{ + get_block_status, + get_latest_block_number, + internal_server_error, + verify_storage_scope, + ContinuationTokenAsStruct, + GENESIS_HASH, +}; + +const IGNORE_L1_DA_MODE: bool = true; + +// TODO(yael): implement address 0x1 as a const function in starknet_api. +lazy_static! { + pub static ref BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress::from(1_u8); +} + +/// Rpc server. +pub struct JsonRpcServerImpl { + pub chain_id: ChainId, + pub execution_config: ExecutionConfig, + pub storage_reader: StorageReader, + pub max_events_chunk_size: usize, + pub max_events_keys: usize, + pub starting_block: BlockHashAndNumber, + pub shared_highest_block: Arc>>, + pub pending_data: Arc>, + pub pending_classes: Arc>, + pub writer_client: Arc, +} + +#[async_trait] +impl JsonRpcServer for JsonRpcServerImpl { + #[instrument(skip(self), level = "debug", err, ret)] + fn spec_version(&self) -> RpcResult { + Ok(format!("{VERSION}")) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn block_number(&self) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + get_latest_block_number(&txn)?.ok_or_else(|| ErrorObjectOwned::from(NO_BLOCKS)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn block_hash_and_number(&self) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let block_number = + get_latest_block_number(&txn)?.ok_or_else(|| ErrorObjectOwned::from(NO_BLOCKS))?; + let header: BlockHeader = get_block_header_by_number(&txn, block_number)?.into(); + + Ok(BlockHashAndNumber { block_hash: header.block_hash, block_number }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_w_transaction_hashes(&self, block_id: BlockId) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + if let BlockId::Tag(Tag::Pending) = block_id { + let block = read_pending_data(&self.pending_data, &txn).await?.block; + let pending_block_header = PendingBlockHeader { + parent_hash: block.parent_block_hash(), + sequencer_address: block.sequencer_address(), + timestamp: block.timestamp(), + l1_gas_price: ResourcePrice { + price_in_wei: block.l1_gas_price().price_in_wei, + price_in_fri: block.l1_gas_price().price_in_fri, + }, + starknet_version: block.starknet_version(), + }; + let header = GeneralBlockHeader::PendingBlockHeader(pending_block_header); + let client_transactions = block.transactions(); + let transaction_hashes = client_transactions + .iter() + .map(|transaction| transaction.transaction_hash()) + .collect(); + return Ok(Block { + status: None, + header, + transactions: Transactions::Hashes(transaction_hashes), + }); + } + + let block_number = get_accepted_block_number(&txn, block_id)?; + let status = get_block_status(&txn, block_number)?; + let header = + GeneralBlockHeader::BlockHeader(get_block_header_by_number(&txn, block_number)?.into()); + let transaction_hashes = get_block_tx_hashes_by_number(&txn, block_number)?; + + Ok(Block { + status: Some(status), + header, + transactions: Transactions::Hashes(transaction_hashes), + }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_w_full_transactions(&self, block_id: BlockId) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + if let BlockId::Tag(Tag::Pending) = block_id { + let block = read_pending_data(&self.pending_data, &txn).await?.block; + let pending_block_header = PendingBlockHeader { + parent_hash: block.parent_block_hash(), + sequencer_address: block.sequencer_address(), + timestamp: block.timestamp(), + l1_gas_price: ResourcePrice { + price_in_wei: block.l1_gas_price().price_in_wei, + price_in_fri: block.l1_gas_price().price_in_fri, + }, + starknet_version: block.starknet_version(), + }; + let header = GeneralBlockHeader::PendingBlockHeader(pending_block_header); + let client_transactions = block.transactions(); + let transactions = client_transactions + .iter() + .map(|client_transaction| { + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.clone().try_into().map_err(internal_server_error)?; + Ok(TransactionWithHash { + transaction: starknet_api_transaction + .try_into() + .map_err(internal_server_error)?, + transaction_hash: client_transaction.transaction_hash(), + }) + }) + .collect::, ErrorObjectOwned>>()?; + return Ok(Block { + status: None, + header, + transactions: Transactions::Full(transactions), + }); + } + + let block_number = get_accepted_block_number(&txn, block_id)?; + let status = get_block_status(&txn, block_number)?; + let header = + GeneralBlockHeader::BlockHeader(get_block_header_by_number(&txn, block_number)?.into()); + let transactions = get_block_txs_by_number(&txn, block_number)?; + let transaction_hashes = get_block_tx_hashes_by_number(&txn, block_number)?; + let transactions_with_hash = transactions + .into_iter() + .zip(transaction_hashes) + .map(|(transaction, transaction_hash)| TransactionWithHash { + transaction, + transaction_hash, + }) + .collect(); + + Ok(Block { + status: Some(status), + header, + transactions: Transactions::Full(transactions_with_hash), + }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + block_id: BlockId, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_storage_diffs = if let BlockId::Tag(Tag::Pending) = block_id { + Some( + read_pending_data(&self.pending_data, &txn) + .await? + .state_update + .state_diff + .storage_diffs, + ) + } else { + None + }; + + // Check that the block is valid and get the state number. + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let res = execution_utils::get_storage_at( + &txn, + state_number, + maybe_pending_storage_diffs.as_ref(), + contract_address, + key, + ) + .map_err(internal_server_error)?; + + // If the contract is not deployed, res will be 0. Checking if that's the case so that + // we'll return an error instead. + // Contract address 0x1 is a special address, it stores the block + // hashes. Contracts are not deployed to this address. + if res == Felt::default() && contract_address != *BLOCK_HASH_TABLE_ADDRESS { + // check if the contract exists + txn.get_state_reader() + .map_err(internal_server_error)? + .get_class_hash_at(state_number, &contract_address) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND))?; + } + Ok(res) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_by_hash( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let Some(transaction_index) = + txn.get_transaction_idx_by_hash(&transaction_hash).map_err(internal_server_error)? + { + let transaction = txn + .get_transaction(transaction_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))?; + + Ok(TransactionWithHash { transaction: transaction.try_into()?, transaction_hash }) + } else { + // The transaction is not in any non-pending block. Search for it in the pending block + // and if it's not found, return error. + let client_transaction = read_pending_data(&self.pending_data, &txn) + .await? + .block + .transactions() + .iter() + .find(|transaction| transaction.transaction_hash() == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))? + .clone(); + + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.try_into().map_err(internal_server_error)?; + return Ok(TransactionWithHash { + transaction: starknet_api_transaction.try_into()?, + transaction_hash, + }); + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_by_block_id_and_index( + &self, + block_id: BlockId, + index: TransactionOffsetInBlock, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let (starknet_api_transaction, transaction_hash) = + if let BlockId::Tag(Tag::Pending) = block_id { + let client_transaction = read_pending_data(&self.pending_data, &txn) + .await? + .block + .transactions() + .get(index.0) + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))? + .clone(); + let transaction_hash = client_transaction.transaction_hash(); + (client_transaction.try_into().map_err(internal_server_error)?, transaction_hash) + } else { + let block_number = get_accepted_block_number(&txn, block_id)?; + + let tx_index = TransactionIndex(block_number, index); + let transaction = txn + .get_transaction(tx_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))?; + let transaction_hash = txn + .get_transaction_hash_by_idx(&tx_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))?; + (transaction, transaction_hash) + }; + + Ok(TransactionWithHash { + transaction: starknet_api_transaction.try_into()?, + transaction_hash, + }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let BlockId::Tag(Tag::Pending) = block_id { + let transactions_len = + read_pending_data(&self.pending_data, &txn).await?.block.transactions().len(); + Ok(transactions_len) + } else { + let block_number = get_accepted_block_number(&txn, block_id)?; + Ok(txn + .get_block_transactions_count(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_state_update(&self, block_id: BlockId) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + if let BlockId::Tag(Tag::Pending) = block_id { + let state_update = read_pending_data(&self.pending_data, &txn).await?.state_update; + return Ok(StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: state_update.old_root, + state_diff: state_update.state_diff.into(), + })); + } + + // Get the block header for the block hash and state root. + let block_number = get_accepted_block_number(&txn, block_id)?; + let header: BlockHeader = get_block_header_by_number(&txn, block_number)?.into(); + + // Get the old root. + let old_root = match get_accepted_block_number( + &txn, + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.parent_hash)), + ) { + Ok(parent_block_number) => { + BlockHeader::from(get_block_header_by_number(&txn, parent_block_number)?).new_root + } + Err(_) => GlobalRoot(StarkHash::from_hex_unchecked(GENESIS_HASH)), + }; + + // Get the block state diff. + let mut thin_state_diff = txn + .get_state_diff(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + // Remove empty storage diffs. Some blocks contain empty storage diffs that must be kept for + // the computation of state diff commitment. + thin_state_diff.storage_diffs.retain(|_k, v| !v.is_empty()); + + Ok(StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + block_hash: header.block_hash, + new_root: header.new_root, + old_root, + state_diff: thin_state_diff.into(), + })) + } + + async fn get_transaction_status( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + Ok(self.get_transaction_receipt(transaction_hash).await?.transaction_status()) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_receipt( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let Some(transaction_index) = + txn.get_transaction_idx_by_hash(&transaction_hash).map_err(internal_server_error)? + { + let block_number = transaction_index.0; + let status = get_block_status(&txn, block_number)?; + + // rejected blocks should not be a part of the API so we early return here. + // this assumption also holds for the conversion from block status to transaction + // finality status where we set rejected blocks to unreachable. + if status == BlockStatus::Rejected { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + } + + let block_hash = get_block_header_by_number(&txn, block_number) + .map_err(internal_server_error)? + .block_hash; + + let tx = txn + .get_transaction(transaction_index) + .map_err(internal_server_error)? + .unwrap_or_else(|| panic!("Should have tx {}", transaction_hash)); + + // TODO: Add version function to transaction in SN_API. + let tx_version = match &tx { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + + let output = txn + .get_transaction_output(transaction_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))?; + + let msg_hash = match output { + starknet_api::transaction::TransactionOutput::L1Handler(_) => { + let starknet_api::transaction::Transaction::L1Handler(tx) = tx else { + panic!("tx {} should be L1 handler", transaction_hash); + }; + Some(tx.calc_msg_hash()) + } + _ => None, + }; + + let output = TransactionOutput::from((output, tx_version, msg_hash)); + + Ok(GeneralTransactionReceipt::TransactionReceipt(TransactionReceipt { + finality_status: status.into(), + transaction_hash, + block_hash, + block_number, + output, + })) + } else { + // The transaction is not in any non-pending block. Search for it in the pending block + // and if it's not found, return error. + + // TODO(shahak): Consider cloning the transactions and the receipts in order to free + // the lock sooner (Check which is better). + let pending_block = read_pending_data(&self.pending_data, &txn).await?.block; + + let client_transaction_receipt = pending_block + .transaction_receipts() + .iter() + .find(|receipt| receipt.transaction_hash == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))? + .clone(); + let client_transaction = &pending_block + .transactions() + .iter() + .find(|transaction| transaction.transaction_hash() == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))?; + let starknet_api_output = + client_transaction_receipt.into_starknet_api_transaction_output(client_transaction); + let msg_hash = match client_transaction { + starknet_client::reader::objects::transaction::Transaction::L1Handler(tx) => { + Some(tx.calc_msg_hash()) + } + _ => None, + }; + let output = PendingTransactionOutput::try_from(TransactionOutput::from(( + starknet_api_output, + client_transaction.transaction_version(), + msg_hash, + )))?; + Ok(GeneralTransactionReceipt::PendingTransactionReceipt(PendingTransactionReceipt { + // ACCEPTED_ON_L2 is the only finality status of a pending transaction. + finality_status: PendingTransactionFinalityStatus::AcceptedOnL2, + transaction_hash, + output, + })) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult { + let block_id = if let BlockId::Tag(Tag::Pending) = block_id { + let maybe_class = &self.pending_classes.read().await.get_class(class_hash); + if let Some(class) = maybe_class { + return class.clone().try_into().map_err(internal_server_error); + } else { + BlockId::Tag(Tag::Latest) + } + } else { + block_id + }; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let state_reader = txn.get_state_reader().map_err(internal_server_error)?; + + // The class might be a deprecated class. Search it first in the declared classes and if not + // found, search in the deprecated classes. + if let Some(class) = state_reader + .get_class_definition_at(state_number, &class_hash) + .map_err(internal_server_error)? + { + Ok(GatewayContractClass::Sierra(class.into())) + } else { + let class = state_reader + .get_deprecated_class_definition_at(state_number, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; + Ok(GatewayContractClass::Cairo0(class.try_into().map_err(internal_server_error)?)) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let class_hash = self.get_class_hash_at(block_id, contract_address).await?; + self.get_class(block_id, class_hash).await + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class_hash_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_deployed_contracts_and_replaced_classes = + if let BlockId::Tag(Tag::Pending) = block_id { + let pending_state_diff = + read_pending_data(&self.pending_data, &txn).await?.state_update.state_diff; + Some((pending_state_diff.deployed_contracts, pending_state_diff.replaced_classes)) + } else { + None + }; + + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + execution_utils::get_class_hash_at( + &txn, + state_number, + // This map converts &(T, S) to (&T, &S). + maybe_pending_deployed_contracts_and_replaced_classes.as_ref().map(|t| (&t.0, &t.1)), + contract_address, + ) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_nonce( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_nonces = if let BlockId::Tag(Tag::Pending) = block_id { + Some(read_pending_data(&self.pending_data, &txn).await?.state_update.state_diff.nonces) + } else { + None + }; + + // Check that the block is valid and get the state number. + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + execution_utils::get_nonce_at( + &txn, + state_number, + maybe_pending_nonces.as_ref(), + contract_address, + ) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn chain_id(&self) -> RpcResult { + Ok(self.chain_id.as_hex()) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_events(&self, filter: EventFilter) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + // Check the chunk size. + if filter.chunk_size > self.max_events_chunk_size { + return Err(ErrorObjectOwned::from(PAGE_SIZE_TOO_BIG)); + } + // Check the number of keys. + if filter.keys.len() > self.max_events_keys { + return Err(ErrorObjectOwned::from(TOO_MANY_KEYS_IN_FILTER)); + } + + // Get the requested block numbers. + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let Some(latest_block_number) = get_latest_block_number(&txn)? else { + if matches!(filter.to_block, Some(BlockId::Tag(Tag::Pending)) | None) { + warn!( + "Received a request for pending events while there are no accepted blocks. \ + This is currently unsupported. Returning no events." + ); + } + // There are no blocks. + return Ok(EventsChunk { events: vec![], continuation_token: None }); + }; + let from_block_number = match filter.from_block { + None => BlockNumber(0), + Some(BlockId::Tag(Tag::Pending)) => latest_block_number.unchecked_next(), + Some(block_id) => get_accepted_block_number(&txn, block_id)?, + }; + let mut to_block_number = match filter.to_block { + Some(BlockId::Tag(Tag::Pending)) | None => latest_block_number.unchecked_next(), + Some(block_id) => get_accepted_block_number(&txn, block_id)?, + }; + + if from_block_number > to_block_number { + return Ok(EventsChunk { events: vec![], continuation_token: None }); + } + + // Get the event index. If there's a continuation token we take the event index from there. + // Otherwise, we take the first index in the from_block_number. + let start_event_index = match &filter.continuation_token { + Some(token) => token.parse()?.0, + None => EventIndex( + TransactionIndex(from_block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + }; + + let include_pending_block = to_block_number > latest_block_number; + if include_pending_block { + to_block_number = to_block_number.prev().expect( + "A block number that's greater than another block number should have a predecessor", + ); + } + + // Collect the requested events. + // Once we collected enough events, we continue to check if there are any more events + // corresponding to the requested filter. If there are, we return a continuation token + // pointing to the next relevant event. Otherwise, we return a continuation token None. + let mut filtered_events = vec![]; + if start_event_index.0.0 <= latest_block_number { + for ((from_address, event_index), content) in txn + .iter_events(filter.address, start_event_index, to_block_number) + .map_err(internal_server_error)? + { + let block_number = (event_index.0).0; + if block_number > to_block_number { + break; + } + if let Some(filter_address) = filter.address { + if from_address != filter_address { + // The iterator of this loop outputs only events that have the filter's + // address, unless there are no more such events and then it outputs other + // events, and we can stop the iteration. + break; + } + } + // TODO: Consider changing empty sets in the filer keys to None. + if do_event_keys_match_filter(&content, &filter) { + if filtered_events.len() == filter.chunk_size { + return Ok(EventsChunk { + events: filtered_events, + continuation_token: Some(ContinuationToken::new( + ContinuationTokenAsStruct(event_index), + )?), + }); + } + let header: BlockHeader = get_block_header_by_number(&txn, block_number) + .map_err(internal_server_error)? + .into(); + let transaction_hash = txn + .get_transaction_hash_by_idx(&event_index.0) + .map_err(internal_server_error)? + .ok_or_else(|| internal_server_error("Unknown internal error."))?; + let emitted_event = Event { + block_hash: Some(header.block_hash), + block_number: Some(block_number), + transaction_hash, + event: starknet_api::transaction::Event { from_address, content }, + }; + filtered_events.push(emitted_event); + } + } + } + + if include_pending_block { + let pending_block = read_pending_data(&self.pending_data, &txn).await?.block; + let pending_transaction_receipts = pending_block.transaction_receipts(); + // Extract the first transaction offset and event offset from the starting EventIndex. + let (transaction_start, event_start) = if start_event_index.0.0 > latest_block_number { + (start_event_index.0.1.0, start_event_index.1.0) + } else { + (0, 0) + }; + // TODO(shahak): Consider creating the iterator flattened and filtered. + for (transaction_offset, receipt) in pending_transaction_receipts.iter().enumerate() { + if transaction_offset < transaction_start { + continue; + } + for (event_offset, event) in receipt.events.iter().cloned().enumerate() { + if transaction_offset == transaction_start && event_offset < event_start { + continue; + } + if filtered_events.len() == filter.chunk_size { + return Ok(EventsChunk { + events: filtered_events, + continuation_token: Some(ContinuationToken::new( + ContinuationTokenAsStruct(EventIndex( + TransactionIndex( + latest_block_number.unchecked_next(), + TransactionOffsetInBlock(transaction_offset), + ), + EventIndexInTransactionOutput(event_offset), + )), + )?), + }); + } + if !do_event_keys_match_filter(&event.content, &filter) { + continue; + } + if let Some(filter_address) = filter.address { + if event.from_address != filter_address { + continue; + } + } + filtered_events.push(Event { + block_hash: None, + block_number: None, + transaction_hash: receipt.transaction_hash, + event, + }) + } + } + } + + Ok(EventsChunk { events: filtered_events, continuation_token: None }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn syncing(&self) -> RpcResult { + let Some(highest_block) = *self.shared_highest_block.read().await else { + return Ok(SyncingState::Synced); + }; + let current_block = + get_last_synced_block(self.storage_reader.clone()).map_err(internal_server_error)?; + if highest_block.block_number <= current_block.block_number { + return Ok(SyncingState::Synced); + } + Ok(SyncingState::SyncStatus(SyncStatus { + starting_block_hash: self.starting_block.block_hash, + starting_block_num: self.starting_block.block_number, + current_block_hash: current_block.block_hash, + current_block_num: current_block.block_number, + highest_block_hash: highest_block.block_hash, + highest_block_num: highest_block.block_number, + })) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn call(&self, request: CallRequest, block_id: BlockId) -> RpcResult> { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + let block_number = get_accepted_block_number(&txn, block_id)?; + let block_not_reverted_validator = BlockNotRevertedValidator::new(block_number, &txn)?; + drop(txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + let contract_address_copy = request.contract_address; + + let res = tokio::task::spawn_blocking(move || { + execute_call( + reader, + maybe_pending_data, + &chain_id, + state_number, + block_number, + &contract_address_copy, + request.entry_point_selector, + request.calldata, + &execution_config, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(res.retdata.0) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_invoke_transaction( + &self, + invoke_transaction: TypedInvokeTransaction, + ) -> RpcResult { + let result = self.writer_client.add_invoke_transaction(&invoke_transaction.into()).await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_invoke_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_deploy_account_transaction( + &self, + deploy_account_transaction: TypedDeployAccountTransaction, + ) -> RpcResult { + let result = self + .writer_client + .add_deploy_account_transaction(&deploy_account_transaction.into()) + .await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_deploy_account_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_declare_transaction( + &self, + declare_transaction: BroadcastedDeclareTransaction, + ) -> RpcResult { + let result = self + .writer_client + .add_declare_transaction( + &declare_transaction.try_into().map_err(internal_server_error)?, + ) + .await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_declare_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self, transactions), level = "debug", err, ret)] + async fn estimate_fee( + &self, + transactions: Vec, + simulation_flags: Vec, + block_id: BlockId, + ) -> RpcResult> { + trace!("Estimating fee of transactions: {:#?}", transactions); + let validate = !simulation_flags.contains(&SimulationFlag::SkipValidate); + + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + + let executable_txns = + transactions.into_iter().map(|tx| tx.try_into()).collect::>()?; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let estimate_fee_result = tokio::task::spawn_blocking(move || { + exec_estimate_fee( + executable_txns, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + validate, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + match estimate_fee_result { + Ok(Ok(fees)) => Ok(fees + .into_iter() + .map(|ExecutionFeeEstimate { gas_price, overall_fee, unit, .. }| { + FeeEstimate::from(gas_price, overall_fee, unit) + }) + .collect()), + Ok(Err(reverted_tx)) => { + Err(ErrorObjectOwned::from(JsonRpcError::::from( + TransactionExecutionError { + transaction_index: reverted_tx.index, + execution_error: reverted_tx.revert_reason, + }, + ))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self, transactions), level = "debug", err, ret)] + async fn simulate_transactions( + &self, + block_id: BlockId, + transactions: Vec, + simulation_flags: Vec, + ) -> RpcResult> { + trace!("Simulating transactions: {:#?}", transactions); + let executable_txns = + transactions.into_iter().map(|tx| tx.try_into()).collect::>()?; + + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let charge_fee = !simulation_flags.contains(&SimulationFlag::SkipFeeCharge); + let validate = !simulation_flags.contains(&SimulationFlag::SkipValidate); + + let simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_txns, + None, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + charge_fee, + validate, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(simulation_results + .into_iter() + .map(|simulation_output| SimulatedTransaction { + transaction_trace: simulation_output.transaction_trace.into(), + fee_estimation: FeeEstimate::from( + simulation_output.fee_estimation.gas_price, + simulation_output.fee_estimation.overall_fee, + simulation_output.fee_estimation.unit, + ), + }) + .collect()) + } + + #[instrument(skip(self), level = "debug", err)] + async fn trace_transaction( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let pending_block = read_pending_data(&self.pending_data, &storage_txn).await?.block; + // Search for the transaction inside the pending block. + let ( + maybe_pending_data, + executable_transactions, + transaction_hashes, + block_number, + state_number, + ) = if let Some((pending_transaction_offset, _)) = pending_block + .transaction_receipts() + .iter() + .enumerate() + .find(|(_, receipt)| receipt.transaction_hash == transaction_hash) + { + // If there are no blocks in the network and there is a pending block, as an edge + // case we treat this as if the pending block is empty. + let block_number = + get_latest_block_number(&storage_txn)?.ok_or(INVALID_TRANSACTION_HASH)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let executable_transactions = pending_block + .transactions() + .iter() + .take(pending_transaction_offset + 1) + .map(|client_transaction| { + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.clone().try_into().map_err(internal_server_error)?; + stored_txn_to_executable_txn( + starknet_api_transaction, + &storage_txn, + state_number, + ) + }) + .collect::>()?; + let transaction_hashes = pending_block + .transaction_receipts() + .iter() + .map(|receipt| receipt.transaction_hash) + .collect(); + let maybe_pending_data = Some(ExecutionPendingData { + timestamp: pending_block.timestamp(), + l1_gas_price: pending_block.l1_gas_price(), + l1_data_gas_price: pending_block.l1_data_gas_price(), + sequencer: pending_block.sequencer_address(), + // The pending state diff should be empty since we look at the state in the + // start of the pending block. + // Not using ..Default::default() to avoid missing fields in the future. + storage_diffs: Default::default(), + deployed_contracts: Default::default(), + declared_classes: Default::default(), + old_declared_contracts: Default::default(), + nonces: Default::default(), + replaced_classes: Default::default(), + classes: Default::default(), + l1_da_mode: Default::default(), + }); + ( + maybe_pending_data, + executable_transactions, + transaction_hashes, + block_number, + state_number, + ) + } else { + // Transaction is not inside the pending block. Search for it in the storage. + let TransactionIndex(block_number, tx_offset) = storage_txn + .get_transaction_idx_by_hash(&transaction_hash) + .map_err(internal_server_error)? + .ok_or(TRANSACTION_HASH_NOT_FOUND)?; + + let block_transactions = storage_txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?; + + let transaction_hashes = storage_txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?; + + let state_number = StateNumber::right_before_block(block_number); + let executable_transactions = block_transactions + .into_iter() + .take(tx_offset.0 + 1) + .map(|tx| stored_txn_to_executable_txn(tx, &storage_txn, state_number)) + .collect::>()?; + + (None, executable_transactions, transaction_hashes, block_number, state_number) + }; + + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + + drop(storage_txn); + + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let mut simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_transactions, + Some(transaction_hashes), + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + true, + true, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(simulation_results + .pop() + .expect("Should have transaction exeuction result") + .transaction_trace + .into()) + } + + #[instrument(skip(self), level = "debug", err)] + async fn trace_block_transactions( + &self, + block_id: BlockId, + ) -> RpcResult> { + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_client_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(read_pending_data(&self.pending_data, &storage_txn).await?) + } else { + None + }; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + + let (maybe_pending_data, block_transactions, transaction_hashes, state_number) = + match maybe_client_pending_data { + Some(client_pending_data) => ( + Some(ExecutionPendingData { + timestamp: client_pending_data.block.timestamp(), + l1_gas_price: client_pending_data.block.l1_gas_price(), + l1_data_gas_price: client_pending_data.block.l1_data_gas_price(), + sequencer: client_pending_data.block.sequencer_address(), + // The pending state diff should be empty since we look at the state in the + // start of the pending block. + // Not using ..Default::default() to avoid missing fields in the future. + storage_diffs: Default::default(), + deployed_contracts: Default::default(), + declared_classes: Default::default(), + old_declared_contracts: Default::default(), + nonces: Default::default(), + replaced_classes: Default::default(), + classes: Default::default(), + l1_da_mode: Default::default(), + }), + client_pending_data + .block + .transactions() + .iter() + .map(|client_transaction| { + client_transaction.clone().try_into().map_err(internal_server_error) + }) + .collect::, ErrorObjectOwned>>()?, + client_pending_data + .block + .transaction_receipts() + .iter() + .map(|receipt| receipt.transaction_hash) + .collect(), + StateNumber::unchecked_right_after_block(block_number), + ), + None => ( + None, + storage_txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?, + storage_txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?, + StateNumber::right_before_block(block_number), + ), + }; + + let executable_txns = block_transactions + .into_iter() + .map(|tx| stored_txn_to_executable_txn(tx, &storage_txn, state_number)) + .collect::>()?; + + drop(storage_txn); + + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + let transaction_hashes_clone = transaction_hashes.clone(); + + let simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_txns, + Some(transaction_hashes_clone), + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + true, + true, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(simulation_results + .into_iter() + .zip(transaction_hashes) + .map(|(simulation_output, transaction_hash)| TransactionTraceWithHash { + transaction_hash, + trace_root: simulation_output.transaction_trace.into(), + }) + .collect()) + } + + #[instrument(skip(self, message), level = "debug", err)] + async fn estimate_message_fee( + &self, + message: MessageFromL1, + block_id: BlockId, + ) -> RpcResult { + trace!("Estimating fee of message: {:#?}", message); + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + // Convert the message to an L1 handler transaction, and estimate the fee of the + // transaction. + // The fee input is used to bound the amount of fee used. Because we want to estimate the + // fee, we pass u128::MAX so the execution won't fail. + let executable_txns = + vec![ExecutableTransactionInput::L1Handler(message.into(), Fee(u128::MAX), false)]; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let estimate_fee_result = tokio::task::spawn_blocking(move || { + exec_estimate_fee( + executable_txns, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + false, + IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + match estimate_fee_result { + Ok(Ok(fee_as_vec)) => { + if fee_as_vec.len() != 1 { + return Err(internal_server_error(format!( + "Expected a single fee, got {}", + fee_as_vec.len() + ))); + } + let Some(ExecutionFeeEstimate { gas_price, overall_fee, unit, .. }) = + fee_as_vec.first() + else { + return Err(internal_server_error( + "Expected a single fee, got an empty vector", + )); + }; + Ok(FeeEstimate::from(*gas_price, *overall_fee, *unit)) + } + // Error in the execution of the contract. + Ok(Err(reverted_tx)) => Err(JsonRpcError::::from(ContractError { + revert_error: reverted_tx.revert_reason, + }) + .into()), + // Internal error during the execution. + Err(err) => Err(internal_server_error(err)), + } + } +} + +async fn read_pending_data( + pending_data: &Arc>, + txn: &StorageTxn<'_, Mode>, +) -> RpcResult { + let latest_header = match get_latest_block_number(txn)? { + Some(latest_block_number) => get_block_header_by_number(txn, latest_block_number)?, + None => starknet_api::block::BlockHeader { + parent_hash: BlockHash(StarkHash::from_hex_unchecked(GENESIS_HASH)), + ..Default::default() + }, + }; + let pending_data = &pending_data.read().await; + if pending_data.block.parent_block_hash() == latest_header.block_hash { + Ok((*pending_data).clone()) + } else { + Ok(PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: latest_header.block_hash, + eth_l1_gas_price: latest_header.l1_gas_price.price_in_wei, + strk_l1_gas_price: latest_header.l1_gas_price.price_in_fri, + timestamp: latest_header.timestamp, + sequencer_address: latest_header.sequencer, + starknet_version: latest_header.starknet_version.0, + ..Default::default() + }), + state_update: ClientPendingStateUpdate { + old_root: latest_header.state_root, + state_diff: Default::default(), + }, + }) + } +} + +fn do_event_keys_match_filter(event_content: &EventContent, filter: &EventFilter) -> bool { + filter.keys.iter().enumerate().all(|(i, keys)| { + event_content.keys.len() > i && (keys.is_empty() || keys.contains(&event_content.keys[i])) + }) +} + +impl JsonRpcServerTrait for JsonRpcServerImpl { + fn new( + chain_id: ChainId, + execution_config: ExecutionConfig, + storage_reader: StorageReader, + max_events_chunk_size: usize, + max_events_keys: usize, + starting_block: BlockHashAndNumber, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + writer_client: Arc, + ) -> Self { + Self { + chain_id, + execution_config, + storage_reader, + max_events_chunk_size, + max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + writer_client, + } + } + + fn into_rpc_module(self) -> RpcModule { + self.into_rpc() + } +} diff --git a/crates/papyrus_rpc/src/v0_6/api/mod.rs b/crates/papyrus_rpc/src/v0_6/api/mod.rs new file mode 100644 index 00000000000..6c20c3db505 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/api/mod.rs @@ -0,0 +1,678 @@ +use std::collections::HashSet; +use std::io::Read; + +use flate2::bufread::GzDecoder; +use jsonrpsee::core::RpcResult; +use jsonrpsee::proc_macros::rpc; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_common::deprecated_class_abi::calculate_deprecated_class_abi_length; +use papyrus_common::pending_classes::ApiContractClass; +use papyrus_common::BlockHashAndNumber; +use papyrus_execution::objects::PriceUnit; +use papyrus_execution::{AbiSize, ExecutableTransactionInput, ExecutionError, SierraSize}; +use papyrus_proc_macros::versioned_rpc; +use papyrus_storage::compiled_class::CasmStorageReader; +use papyrus_storage::db::serialization::StorageSerdeError; +use papyrus_storage::db::RO; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::StorageTxn; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockNumber, GasPrice}; +use starknet_api::core::{ClassHash, ContractAddress, Nonce}; +use starknet_api::deprecated_contract_class::Program; +use starknet_api::state::{StateNumber, StorageKey}; +use starknet_api::transaction::{EventKey, Fee, TransactionHash, TransactionOffsetInBlock}; +use starknet_types_core::felt::Felt; +use tracing::debug; + +use super::block::Block; +use super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedTransaction, +}; +use super::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use super::error::{ + ContractError, + JsonRpcError, + BLOCK_NOT_FOUND, + CONTRACT_NOT_FOUND, + INVALID_CONTINUATION_TOKEN, +}; +use super::execution::TransactionTrace; +use super::state::{ContractClass, StateUpdate}; +use super::transaction::{ + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + Event, + GeneralTransactionReceipt, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + MessageFromL1, + TransactionStatus, + TransactionWithHash, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::write_api_result::{AddDeclareOkResult, AddDeployAccountOkResult, AddInvokeOkResult}; +use crate::api::{BlockId, CallRequest}; +use crate::syncing_state::SyncingState; +use crate::{internal_server_error, ContinuationTokenAsStruct}; + +pub mod api_impl; +#[cfg(test)] +mod test; + +#[versioned_rpc("V0_6")] +#[async_trait] +pub trait JsonRpc { + /// Returns the version of the Starknet JSON-RPC specification being used + #[method(name = "specVersion")] + fn spec_version(&self) -> RpcResult; + + /// Gets the most recent accepted block number. + #[method(name = "blockNumber")] + fn block_number(&self) -> RpcResult; + + /// Gets the most recent accepted block hash and number. + #[method(name = "blockHashAndNumber")] + fn block_hash_and_number(&self) -> RpcResult; + + /// Gets block information with transaction hashes given a block identifier. + #[method(name = "getBlockWithTxHashes")] + async fn get_block_w_transaction_hashes(&self, block_id: BlockId) -> RpcResult; + + /// Gets block information with full transactions given a block identifier. + #[method(name = "getBlockWithTxs")] + async fn get_block_w_full_transactions(&self, block_id: BlockId) -> RpcResult; + + /// Gets the value of the storage at the given address, key, and block. + #[method(name = "getStorageAt")] + async fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + block_id: BlockId, + ) -> RpcResult; + + /// Gets the details of a submitted transaction. + #[method(name = "getTransactionByHash")] + async fn get_transaction_by_hash( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the details of a transaction by a given block id and index. + #[method(name = "getTransactionByBlockIdAndIndex")] + async fn get_transaction_by_block_id_and_index( + &self, + block_id: BlockId, + index: TransactionOffsetInBlock, + ) -> RpcResult; + + /// Gets the number of transactions in a block given a block id. + #[method(name = "getBlockTransactionCount")] + async fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult; + + /// Gets the information about the result of executing the requested block. + #[method(name = "getStateUpdate")] + async fn get_state_update(&self, block_id: BlockId) -> RpcResult; + + /// Gets the transaction status. + #[method(name = "getTransactionStatus")] + async fn get_transaction_status( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the transaction receipt by the transaction hash. + #[method(name = "getTransactionReceipt")] + async fn get_transaction_receipt( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the contract class definition associated with the given hash. + #[method(name = "getClass")] + async fn get_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult; + + /// Gets the contract class definition in the given block at the given address. + #[method(name = "getClassAt")] + async fn get_class_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Gets the contract class hash in the given block for the contract deployed at the given + /// address. + #[method(name = "getClassHashAt")] + async fn get_class_hash_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Gets the nonce associated with the given address in the given block. + #[method(name = "getNonce")] + async fn get_nonce( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Returns the currently configured StarkNet chain id. + #[method(name = "chainId")] + fn chain_id(&self) -> RpcResult; + + /// Returns all events matching the given filter. + #[method(name = "getEvents")] + async fn get_events(&self, filter: EventFilter) -> RpcResult; + + /// Returns the synching status of the node, or false if the node is not synching. + #[method(name = "syncing")] + async fn syncing(&self) -> RpcResult; + + /// Executes the entry point of the contract at the given address with the given calldata, + /// returns the result (Retdata). + #[method(name = "call")] + async fn call(&self, request: CallRequest, block_id: BlockId) -> RpcResult>; + + /// Submits a new invoke transaction to be added to the chain. + #[method(name = "addInvokeTransaction")] + async fn add_invoke_transaction( + &self, + invoke_transaction: TypedInvokeTransaction, + ) -> RpcResult; + + /// Submits a new deploy account transaction to be added to the chain. + #[method(name = "addDeployAccountTransaction")] + async fn add_deploy_account_transaction( + &self, + deploy_account_transaction: TypedDeployAccountTransaction, + ) -> RpcResult; + + /// Submits a new declare transaction to be added to the chain. + #[method(name = "addDeclareTransaction")] + async fn add_declare_transaction( + &self, + declare_transaction: BroadcastedDeclareTransaction, + ) -> RpcResult; + + /// Estimates the fee of a series of transactions. + #[method(name = "estimateFee")] + async fn estimate_fee( + &self, + request: Vec, + simulation_flags: Vec, + block_id: BlockId, + ) -> RpcResult>; + + /// Estimates the fee of a message from L1. + #[method(name = "estimateMessageFee")] + async fn estimate_message_fee( + &self, + message: MessageFromL1, + block_id: BlockId, + ) -> RpcResult; + + /// Simulates execution of a series of transactions. + #[method(name = "simulateTransactions")] + async fn simulate_transactions( + &self, + block_id: BlockId, + transactions: Vec, + simulation_flags: Vec, + ) -> RpcResult>; + + /// Calculates the transaction trace of a transaction that is already included in a block. + #[method(name = "traceTransaction")] + async fn trace_transaction( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Calculates the transaction trace of all of the transactions in a block. + #[method(name = "traceBlockTransactions")] + async fn trace_block_transactions( + &self, + block_id: BlockId, + ) -> RpcResult>; +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(test, derive(PartialEq))] +#[serde(untagged)] +pub enum GatewayContractClass { + Cairo0(DeprecatedContractClass), + Sierra(ContractClass), +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct EventsChunk { + pub events: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct EventFilter { + #[serde(skip_serializing_if = "Option::is_none")] + pub from_block: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub to_block: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, + pub chunk_size: usize, + #[serde(skip_serializing_if = "Option::is_none")] + pub address: Option, + #[serde(default)] + pub keys: Vec>, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct ContinuationToken(pub String); + +impl ContinuationToken { + fn parse(&self) -> Result { + let ct = serde_json::from_str(&self.0) + .map_err(|_| ErrorObjectOwned::from(INVALID_CONTINUATION_TOKEN))?; + + Ok(ContinuationTokenAsStruct(ct)) + } + + fn new(ct: ContinuationTokenAsStruct) -> Result { + Ok(Self(serde_json::to_string(&ct.0).map_err(internal_server_error)?)) + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct FeeEstimate { + pub gas_consumed: Felt, + pub gas_price: GasPrice, + pub overall_fee: Fee, + pub unit: PriceUnit, +} + +impl FeeEstimate { + pub fn from(gas_price: GasPrice, overall_fee: Fee, unit: PriceUnit) -> Self { + match gas_price { + GasPrice(0) => Self::default(), + _ => Self { + gas_consumed: (overall_fee.0 / gas_price.0).into(), + gas_price, + overall_fee, + unit, + }, + } + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct SimulatedTransaction { + pub transaction_trace: TransactionTrace, + pub fee_estimation: FeeEstimate, +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum SimulationFlag { + SkipValidate, + SkipFeeCharge, +} + +impl TryFrom for ExecutableTransactionInput { + type Error = ErrorObjectOwned; + fn try_from(value: BroadcastedTransaction) -> Result { + // TODO(yair): pass the right value for only_query field. + match value { + BroadcastedTransaction::Declare(tx) => Ok(tx.try_into()?), + BroadcastedTransaction::DeployAccount(tx) => Ok(Self::DeployAccount(tx.into(), false)), + BroadcastedTransaction::Invoke(tx) => Ok(Self::Invoke(tx.into(), false)), + } + } +} + +pub(crate) fn stored_txn_to_executable_txn( + stored_txn: starknet_api::transaction::Transaction, + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, +) -> Result { + match stored_txn { + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V0(value), + ) => { + // Copy the class hash before the value moves. + let class_hash = value.class_hash; + let deprecated_class = + get_deprecated_class_for_re_execution(storage_txn, state_number, class_hash)?; + let abi_length = calculate_deprecated_class_abi_length(&deprecated_class) + .map_err(internal_server_error)?; + Ok(ExecutableTransactionInput::DeclareV0(value, deprecated_class, abi_length, false)) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V1(value), + ) => { + // Copy the class hash before the value moves. + let class_hash = value.class_hash; + let deprecated_class = + get_deprecated_class_for_re_execution(storage_txn, state_number, class_hash)?; + let abi_length = calculate_deprecated_class_abi_length(&deprecated_class) + .map_err(internal_server_error)?; + Ok(ExecutableTransactionInput::DeclareV1(value, deprecated_class, abi_length, false)) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V2(value), + ) => { + let casm = storage_txn + .get_casm(&value.class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!( + "Missing casm of class hash {}.", + value.class_hash + )) + })?; + let (sierra_program_length, abi_length) = + get_class_lengths(storage_txn, state_number, value.class_hash)?; + Ok(ExecutableTransactionInput::DeclareV2( + value, + casm, + sierra_program_length, + abi_length, + false, + )) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V3(value), + ) => { + let casm = storage_txn + .get_casm(&value.class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!( + "Missing casm of class hash {}.", + value.class_hash + )) + })?; + let (sierra_program_length, abi_length) = + get_class_lengths(storage_txn, state_number, value.class_hash)?; + Ok(ExecutableTransactionInput::DeclareV3( + value, + casm, + sierra_program_length, + abi_length, + false, + )) + } + starknet_api::transaction::Transaction::Deploy(_) => { + Err(internal_server_error("Deploy txns not supported in execution")) + } + starknet_api::transaction::Transaction::DeployAccount(deploy_account_tx) => { + Ok(ExecutableTransactionInput::DeployAccount(deploy_account_tx, false)) + } + starknet_api::transaction::Transaction::Invoke(value) => { + Ok(ExecutableTransactionInput::Invoke(value, false)) + } + starknet_api::transaction::Transaction::L1Handler(value) => { + // todo(yair): This is a temporary solution until we have a better way to get the l1 + // fee. + let paid_fee_on_l1 = Fee(1); + Ok(ExecutableTransactionInput::L1Handler(value, paid_fee_on_l1, false)) + } + } +} + +// For re-execution (traceTransaction, traceBlockTransactions) we need to get the class definition +// of declare transactions from the storage before the execution. They are stored in the state after +// the block in which they appeared, so we need to get it from the state after given block. +fn get_deprecated_class_for_re_execution( + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, + class_hash: ClassHash, +) -> Result { + let state_number_after_block = + StateNumber::unchecked_right_after_block(state_number.block_after()); + storage_txn + .get_state_reader() + .map_err(internal_server_error)? + .get_deprecated_class_definition_at(state_number_after_block, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!("Missing deprecated class definition of {class_hash}.")) + }) +} + +fn get_class_lengths( + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, + class_hash: ClassHash, +) -> Result<(SierraSize, AbiSize), ErrorObjectOwned> { + let state_number_after_block = + StateNumber::unchecked_right_after_block(state_number.block_after()); + storage_txn + .get_state_reader() + .map_err(internal_server_error)? + .get_class_definition_at(state_number_after_block, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!("Missing deprecated class definition of {class_hash}.")) + }) + .map(|contract_class| (contract_class.sierra_program.len(), contract_class.abi.len())) +} + +impl TryFrom for ExecutableTransactionInput { + type Error = ErrorObjectOwned; + fn try_from(value: BroadcastedDeclareTransaction) -> Result { + match value { + BroadcastedDeclareTransaction::V1(BroadcastedDeclareV1Transaction { + r#type: _, + contract_class, + sender_address, + nonce, + max_fee, + signature, + }) => { + let sn_api_contract_class = + user_deprecated_contract_class_to_sn_api(contract_class)?; + let abi_length = calculate_deprecated_class_abi_length(&sn_api_contract_class) + .map_err(internal_server_error)?; + Ok(Self::DeclareV1( + starknet_api::transaction::DeclareTransactionV0V1 { + max_fee, + signature, + nonce, + // The blockifier doesn't need the class hash, but it uses the SN_API + // DeclareTransactionV0V1 which requires it. + class_hash: ClassHash::default(), + sender_address, + }, + sn_api_contract_class, + abi_length, + // TODO(yair): pass the right value for only_query field. + false, + )) + } + BroadcastedDeclareTransaction::V2(_) => { + // TODO(yair): We need a way to get the casm of a declare V2 transaction. + Err(internal_server_error("Declare V2 is not supported yet in execution.")) + } + BroadcastedDeclareTransaction::V3(_) => { + // TODO(yair): We need a way to get the casm of a declare V3 transaction. + Err(internal_server_error("Declare V3 is not supported yet in execution.")) + } + } + } +} + +fn user_deprecated_contract_class_to_sn_api( + value: starknet_client::writer::objects::transaction::DeprecatedContractClass, +) -> Result { + Ok(starknet_api::deprecated_contract_class::ContractClass { + abi: value.abi, + program: decompress_program(&value.compressed_program)?, + entry_points_by_type: value.entry_points_by_type, + }) +} + +impl From for starknet_api::transaction::DeployAccountTransaction { + fn from(tx: DeployAccountTransaction) -> Self { + match tx { + DeployAccountTransaction::Version1(DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: _, + }) => Self::V1(starknet_api::transaction::DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + }), + DeployAccountTransaction::Version3(DeployAccountTransactionV3 { + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: _, + resource_bounds, + tip, + paymaster_data, + nonce_data_availability_mode, + fee_data_availability_mode, + }) => Self::V3(starknet_api::transaction::DeployAccountTransactionV3 { + resource_bounds: resource_bounds.into(), + tip, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + }), + } + } +} + +impl From for starknet_api::transaction::InvokeTransaction { + fn from(value: InvokeTransaction) -> Self { + match value { + InvokeTransaction::Version0(InvokeTransactionV0 { + max_fee, + version: _, + signature, + contract_address, + entry_point_selector, + calldata, + }) => Self::V0(starknet_api::transaction::InvokeTransactionV0 { + max_fee, + signature, + contract_address, + entry_point_selector, + calldata, + }), + InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee, + version: _, + signature, + nonce, + sender_address, + calldata, + }) => Self::V1(starknet_api::transaction::InvokeTransactionV1 { + max_fee, + signature, + nonce, + sender_address, + calldata, + }), + InvokeTransaction::Version3(InvokeTransactionV3 { + sender_address, + calldata, + version: _, + signature, + nonce, + resource_bounds, + tip, + paymaster_data, + account_deployment_data, + nonce_data_availability_mode, + fee_data_availability_mode, + }) => Self::V3(starknet_api::transaction::InvokeTransactionV3 { + resource_bounds: resource_bounds.into(), + tip, + signature, + nonce, + sender_address, + calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }), + } + } +} + +impl TryFrom for GatewayContractClass { + type Error = StorageSerdeError; + fn try_from(class: ApiContractClass) -> Result { + match class { + ApiContractClass::DeprecatedContractClass(deprecated_class) => { + Ok(Self::Cairo0(deprecated_class.try_into()?)) + } + ApiContractClass::ContractClass(sierra_class) => Ok(Self::Sierra(sierra_class.into())), + } + } +} + +pub(crate) fn execution_error_to_error_object_owned(err: ExecutionError) -> ErrorObjectOwned { + match err { + ExecutionError::MissingCompiledClass { class_hash } => { + debug!( + "Execution failed because it required the compiled class with hash {class_hash} \ + and we didn't download it yet." + ); + BLOCK_NOT_FOUND.into() + } + ExecutionError::ContractError(blockifier_err) => { + let contract_err = ContractError { revert_error: blockifier_err.to_string() }; + let rpc_err: JsonRpcError = contract_err.into(); + rpc_err.into() + } + ExecutionError::ContractNotFound { .. } => CONTRACT_NOT_FOUND.into(), + _ => internal_server_error(err), + } +} + +pub(crate) fn decompress_program( + base64_compressed_program: &String, +) -> Result { + base64::decode(base64_compressed_program).map_err(internal_server_error)?; + let compressed_data = + base64::decode(base64_compressed_program).map_err(internal_server_error)?; + let mut decoder = GzDecoder::new(compressed_data.as_slice()); + let mut decompressed = Vec::new(); + decoder.read_to_end(&mut decompressed).map_err(internal_server_error)?; + serde_json::from_reader(decompressed.as_slice()).map_err(internal_server_error) +} + +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct TransactionTraceWithHash { + pub transaction_hash: TransactionHash, + pub trace_root: TransactionTrace, +} diff --git a/crates/papyrus_rpc/src/v0_6/api/test.rs b/crates/papyrus_rpc/src/v0_6/api/test.rs new file mode 100644 index 00000000000..ddd51778b32 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/api/test.rs @@ -0,0 +1,3716 @@ +use std::collections::{HashMap, HashSet}; +use std::fmt::Debug; +use std::iter; +use std::net::SocketAddr; +use std::ops::Index; + +use assert_matches::assert_matches; +use async_trait::async_trait; +use indexmap::{indexmap, IndexMap}; +use itertools::Itertools; +use jsonrpsee::core::Error; +use jsonrpsee::Methods; +use jsonschema::JSONSchema; +use lazy_static::lazy_static; +use mockall::predicate::eq; +use papyrus_common::pending_classes::{ApiContractClass, PendingClassesTrait}; +use papyrus_common::BlockHashAndNumber; +use papyrus_storage::base_layer::BaseLayerStorageWriter; +use papyrus_storage::body::events::EventIndex; +use papyrus_storage::body::{BodyStorageWriter, TransactionIndex}; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::StorageScope; +use pretty_assertions::assert_eq; +use rand::{random, RngCore}; +use rand_chacha::ChaCha8Rng; +use reqwest::StatusCode; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{ + Block as StarknetApiBlock, + BlockHash, + BlockHeader, + BlockNumber, + BlockStatus, + BlockTimestamp, + GasPrice, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + ClassHash, + ContractAddress, + GlobalRoot, + Nonce, + PatriciaKey, + SequencerContractAddress, +}; +use starknet_api::deprecated_contract_class::{ + ContractClassAbiEntry, + FunctionAbiEntry, + FunctionStateMutability, +}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass as StarknetApiContractClass, StateDiff, StorageKey}; +use starknet_api::transaction::{ + Event as StarknetApiEvent, + EventContent, + EventData, + EventIndexInTransactionOutput, + EventKey, + Transaction as StarknetApiTransaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput as StarknetApiTransactionOutput, +}; +use starknet_api::{felt, patricia_key}; +use starknet_client::reader::objects::pending_data::{ + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate as ClientPendingStateUpdate, +}; +use starknet_client::reader::objects::state::{ + DeclaredClassHashEntry as ClientDeclaredClassHashEntry, + DeployedContract as ClientDeployedContract, + ReplacedClass as ClientReplacedClass, + StateDiff as ClientStateDiff, + StorageEntry as ClientStorageEntry, +}; +use starknet_client::reader::objects::transaction::{ + Transaction as ClientTransaction, + TransactionReceipt as ClientTransactionReceipt, +}; +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, +}; +use starknet_client::writer::objects::transaction::{ + DeclareTransaction as ClientDeclareTransaction, + DeployAccountTransaction as ClientDeployAccountTransaction, + InvokeTransaction as ClientInvokeTransaction, +}; +use starknet_client::writer::{MockStarknetWriter, WriterClientError, WriterClientResult}; +use starknet_client::ClientError; +use starknet_types_core::felt::Felt; +use test_utils::{ + auto_impl_get_test_instance, + get_number_of_variants, + get_rng, + get_test_block, + get_test_body, + get_test_state_diff, + send_request, + GetTestInstance, +}; + +use super::super::api::EventsChunk; +use super::super::block::{Block, GeneralBlockHeader, PendingBlockHeader, ResourcePrice}; +use super::super::broadcasted_transaction::BroadcastedDeclareTransaction; +use super::super::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use super::super::error::{ + unexpected_error, + JsonRpcError, + BLOCK_NOT_FOUND, + CLASS_HASH_NOT_FOUND, + COMPILATION_FAILED, + CONTRACT_NOT_FOUND, + DUPLICATE_TX, + INVALID_CONTINUATION_TOKEN, + INVALID_TRANSACTION_INDEX, + NO_BLOCKS, + PAGE_SIZE_TOO_BIG, + TOO_MANY_KEYS_IN_FILTER, + TRANSACTION_HASH_NOT_FOUND, +}; +use super::super::state::{ + AcceptedStateUpdate, + ClassHashes, + ContractClass, + ContractNonce, + DeployedContract, + PendingStateUpdate, + ReplacedClasses, + StateUpdate, + StorageDiff, + StorageEntry, + ThinStateDiff, +}; +use super::super::transaction::{ + DeployAccountTransaction, + Event, + GeneralTransactionReceipt, + InvokeTransaction, + L1HandlerMsgHash, + L1L2MsgHash, + PendingTransactionFinalityStatus, + PendingTransactionOutput, + PendingTransactionReceipt, + TransactionFinalityStatus, + TransactionOutput, + TransactionReceipt, + TransactionStatus, + TransactionWithHash, + Transactions, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::super::write_api_result::{ + AddDeclareOkResult, + AddDeployAccountOkResult, + AddInvokeOkResult, +}; +use super::api_impl::{JsonRpcServerImpl, BLOCK_HASH_TABLE_ADDRESS}; +use super::{ContinuationToken, EventFilter, GatewayContractClass}; +use crate::api::{BlockHashOrNumber, BlockId, Tag}; +use crate::syncing_state::SyncStatus; +use crate::test_utils::{ + call_api_then_assert_and_validate_schema_for_err, + call_api_then_assert_and_validate_schema_for_result, + get_method_names_from_spec, + get_starknet_spec_api_schema_for_components, + get_starknet_spec_api_schema_for_method_results, + get_test_highest_block, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, + get_test_rpc_server_and_storage_writer, + get_test_rpc_server_and_storage_writer_from_params, + method_name_to_spec_method_name, + raw_call, + validate_schema, + SpecFile, +}; +use crate::version_config::VERSION_0_6 as VERSION; +use crate::{ + internal_server_error, + internal_server_error_with_msg, + run_server, + ContinuationTokenAsStruct, + GENESIS_HASH, +}; + +const NODE_VERSION: &str = "NODE VERSION"; + +#[tokio::test] +async fn spec_version() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_6_specVersion", + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &format!("{VERSION}"), + ) + .await; +} + +#[tokio::test] +async fn chain_id() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + // The result should be equal to the result of the following python code + // hex(int.from_bytes(b'SN_SEPOLIA', byteorder="big", signed=False)) + // taken from starknet documentation: + // https://docs.starknet.io/documentation/develop/Blocks/transactions/#chain-id. + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_6_chainId", + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &String::from("0x534e5f5345504f4c4941"), + ) + .await; +} + +#[tokio::test] +async fn block_hash_and_number() { + let method_name = "starknet_V0_6_blockHashAndNumber"; + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + + // No blocks yet. + call_api_then_assert_and_validate_schema_for_err::<_, BlockHashAndNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &NO_BLOCKS.into(), + ) + .await; + + // Add a block without state diff and check that there are still no blocks. + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockHashAndNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &NO_BLOCKS.into(), + ) + .await; + + // Add a state diff to the block and check that we get the block. + storage_writer + .begin_rw_txn() + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BlockHashAndNumber { + block_hash: block.header.block_hash, + block_number: block.header.block_number, + }, + ) + .await; +} + +#[tokio::test] +async fn block_number() { + let method_name = "starknet_V0_6_blockNumber"; + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + + // No blocks yet. + let expected_err = NO_BLOCKS.into(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_err, + ) + .await; + + // Add a block without state diff and check that there are still no blocks. + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_err, + ) + .await; + + // Add a state diff to the block and check that we get the block. + storage_writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BlockNumber(0), + ) + .await; +} + +#[tokio::test] +async fn syncing() { + const API_METHOD_NAME: &str = "starknet_V0_6_syncing"; + + let shared_highest_block = get_test_highest_block(); + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + None, + Some(shared_highest_block.clone()), + None, + None, + None, + ); + + call_api_then_assert_and_validate_schema_for_result( + &module, + API_METHOD_NAME, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &false, + ) + .await; + + *shared_highest_block.write().await = + Some(BlockHashAndNumber { block_number: BlockNumber(5), ..Default::default() }); + call_api_then_assert_and_validate_schema_for_result( + &module, + API_METHOD_NAME, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &SyncStatus { highest_block_num: BlockNumber(5), ..Default::default() }, + ) + .await; +} + +#[tokio::test] +async fn get_block_transaction_count() { + let method_name = "starknet_V0_6_getBlockTransactionCount"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let transaction_count = 5; + let block = get_test_block(transaction_count, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &transaction_count, + ) + .await; + + // Get block by number. + let res = module + .call::<_, usize>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(block.header.block_number))], + ) + .await + .unwrap(); + assert_eq!(res, transaction_count); + + // Ask for the latest block. + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(res, transaction_count); + + // Ask for pending block + let pending_transaction_count = 3; + let mut rng = get_rng(); + pending_data.write().await.block.transactions_mutable().extend( + iter::repeat(ClientTransaction::get_test_instance(&mut rng)) + .take(pending_transaction_count), + ); + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, pending_transaction_count); + + // Ask for pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, 0); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, usize>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, usize>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_block_w_full_transactions() { + // TODO(omri): Add test for pending block. + let method_name = "starknet_V0_6_getBlockWithTxs"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + + let mut block = get_test_block(1, None, None, None); + let block_hash = BlockHash(random::().into()); + let sequencer_address = SequencerContractAddress(random::().into()); + let timestamp = BlockTimestamp(random::()); + let starknet_version = StarknetVersion("test".to_owned()); + block.header.block_hash = block_hash; + block.header.sequencer = sequencer_address; + block.header.timestamp = timestamp; + block.header.starknet_version = starknet_version.clone(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + let expected_block = Block { + status: Some(BlockStatus::AcceptedOnL2), + header: GeneralBlockHeader::BlockHeader(block.header.into()), + transactions: Transactions::Full(vec![expected_transaction]), + }; + let GeneralBlockHeader::BlockHeader(expected_block_header) = expected_block.clone().header + else { + panic!("Unexpected block_header type. Expected BlockHeader."); + }; + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash( + expected_block_header.block_hash, + )))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_block, + ) + .await; + + // Get block by number. + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(expected_block_header.block_number))], + ) + .await + .unwrap(); + assert_eq!(block, expected_block); + + // Ask for the latest block. + let block = module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(block, expected_block); + + // Ask for a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&expected_block_header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(expected_block_header.block_hash))], + ) + .await + .unwrap(); + assert_eq!(block.status, Some(BlockStatus::AcceptedOnL1)); + + // Ask for an invalid block hash. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Ask for an invalid block number. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Get pending block. + let mut rng = get_rng(); + let (client_transactions, rpc_transactions): (Vec<_>, Vec<_>) = + iter::repeat_with(|| generate_client_transaction_and_rpc_transaction(&mut rng)) + .take(3) + .unzip(); + let pending_sequencer_address = SequencerContractAddress(random::().into()); + let pending_timestamp = BlockTimestamp(random::()); + let pending_l1_gas_price = GasPricePerToken { + price_in_wei: GasPrice(random::()), + price_in_fri: GasPrice(random::()), + }; + let expected_pending_block = Block { + header: GeneralBlockHeader::PendingBlockHeader(PendingBlockHeader { + parent_hash: block_hash, + sequencer_address: pending_sequencer_address, + timestamp: pending_timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: pending_l1_gas_price.price_in_wei, + price_in_fri: pending_l1_gas_price.price_in_fri, + }, + starknet_version: starknet_version.0.clone(), + }), + status: None, + transactions: Transactions::Full(rpc_transactions), + }; + { + let pending_block = &mut pending_data.write().await.block; + + pending_block.transactions_mutable().extend(client_transactions); + *pending_block.parent_block_hash_mutable() = block_hash; + *pending_block.timestamp_mutable() = pending_timestamp; + *pending_block.sequencer_address_mutable() = pending_sequencer_address; + pending_block.set_l1_gas_price(&pending_l1_gas_price); + *pending_block.starknet_version_mutable() = starknet_version.0; + } + // Using call_api_then_assert_and_validate_schema_for_result in order to validate the schema for + // pending block. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_block, + ) + .await; + + // Get pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res_block = + module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + let GeneralBlockHeader::PendingBlockHeader(pending_block_header) = res_block.header else { + panic!("Unexpected block_header type. Expected PendingBlockHeader.") + }; + assert_eq!(pending_block_header.parent_hash, block_hash); + assert_eq!(pending_block_header.sequencer_address, sequencer_address); + assert_eq!(pending_block_header.timestamp, timestamp); + match res_block.transactions { + Transactions::Hashes(transactions) => assert_eq!(transactions.len(), 0), + Transactions::Full(transactions) => assert_eq!(transactions.len(), 0), + }; +} + +#[tokio::test] +async fn get_block_w_transaction_hashes() { + let method_name = "starknet_V0_6_getBlockWithTxHashes"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + + let mut block = get_test_block(1, None, None, None); + let block_hash = BlockHash(random::().into()); + let sequencer_address = SequencerContractAddress(random::().into()); + let timestamp = BlockTimestamp(random::()); + let starknet_version = StarknetVersion("test".to_owned()); + block.header.block_hash = block_hash; + block.header.sequencer = sequencer_address; + block.header.timestamp = timestamp; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_block = Block { + status: Some(BlockStatus::AcceptedOnL2), + header: GeneralBlockHeader::BlockHeader(block.header.into()), + transactions: Transactions::Hashes(vec![block.body.transaction_hashes[0]]), + }; + let GeneralBlockHeader::BlockHeader(expected_block_header) = expected_block.clone().header + else { + panic!("Unexpected block_header type. Expected BlockHeader."); + }; + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash( + expected_block_header.block_hash, + )))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_block, + ) + .await; + + // Get block by number. + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(expected_block_header.block_number))], + ) + .await + .unwrap(); + assert_eq!(block, expected_block); + + // Ask for the latest block. + let block = module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(block, expected_block); + + // Ask for a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&expected_block_header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(expected_block_header.block_hash))], + ) + .await + .unwrap(); + assert_eq!(block.status, Some(BlockStatus::AcceptedOnL1)); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Block>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Get pending block. + let mut rng = get_rng(); + let (client_transactions, _): (Vec<_>, Vec<_>) = + iter::repeat_with(|| generate_client_transaction_and_rpc_transaction(&mut rng)) + .take(3) + .unzip(); + let pending_sequencer_address = SequencerContractAddress(random::().into()); + let pending_timestamp = BlockTimestamp(random::()); + let pending_l1_gas_price = GasPricePerToken { + price_in_wei: GasPrice(random::()), + price_in_fri: GasPrice(random::()), + }; + let expected_pending_block = Block { + header: GeneralBlockHeader::PendingBlockHeader(PendingBlockHeader { + parent_hash: block_hash, + sequencer_address: pending_sequencer_address, + timestamp: pending_timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: pending_l1_gas_price.price_in_wei, + price_in_fri: pending_l1_gas_price.price_in_fri, + }, + starknet_version: starknet_version.0.clone(), + }), + status: None, + transactions: Transactions::Hashes( + client_transactions + .iter() + .map(|client_transaction| client_transaction.transaction_hash()) + .collect(), + ), + }; + { + let pending_block = &mut pending_data.write().await.block; + + pending_block.transactions_mutable().extend(client_transactions); + *pending_block.parent_block_hash_mutable() = block_hash; + *pending_block.timestamp_mutable() = pending_timestamp; + *pending_block.sequencer_address_mutable() = pending_sequencer_address; + pending_block.set_l1_gas_price(&pending_l1_gas_price); + *pending_block.starknet_version_mutable() = starknet_version.0; + } + // Using call_api_then_assert_and_validate_schema_for_result in order to validate the schema for + // pending block. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_block, + ) + .await; + + // Get pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res_block = + module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + let GeneralBlockHeader::PendingBlockHeader(pending_block_header) = res_block.header else { + panic!("Unexpected block_header type. Expected PendingBlockHeader.") + }; + assert_eq!(pending_block_header.parent_hash, block_hash); + assert_eq!(pending_block_header.sequencer_address, sequencer_address); + assert_eq!(pending_block_header.timestamp, timestamp); + match res_block.transactions { + Transactions::Hashes(transactions) => assert_eq!(transactions.len(), 0), + Transactions::Full(transactions) => assert_eq!(transactions.len(), 0), + }; +} + +#[tokio::test] +async fn get_class() { + let method_name = "starknet_V0_6_getClass"; + let pending_classes = get_test_pending_classes(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, None, Some(pending_classes.clone()), None); + let parent_header = BlockHeader::default(); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + ..BlockHeader::default() + }; + let (diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes( + parent_header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + // Deprecated Class + let class_hash = diff.deprecated_declared_classes[0]; + let expected_contract_class = + deprecated_classes.get(&class_hash).unwrap().clone().try_into().unwrap(); + + // Get class by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*class_hash), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_contract_class, + ) + .await; + + // Get class by block number. + let res = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class of pending block + let pending_class_hash = ClassHash(random::().into()); + let pending_class = ApiContractClass::ContractClass( + StarknetApiContractClass::get_test_instance(&mut get_rng()), + ); + pending_classes.write().await.add_class(pending_class_hash, pending_class.clone()); + let res = module + .call::<_, GatewayContractClass>( + method_name, + (BlockId::Tag(Tag::Pending), pending_class_hash), + ) + .await + .unwrap(); + assert_eq!(res, pending_class.try_into().unwrap()); + + // Ask for an invalid class hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ClassHash(felt!("0x7"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CLASS_HASH_NOT_FOUND.into(), + ) + .await; + + // New Class + let (class_hash, contract_class) = classes.get_index(0).unwrap(); + let expected_contract_class = contract_class.clone().into(); + + // Get class by block hash. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class by block number. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Invalid Call + // Ask for an invalid class hash in the given block. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + ( + BlockId::HashOrNumber(BlockHashOrNumber::Number(parent_header.block_number)), + *class_hash, + ), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == CLASS_HASH_NOT_FOUND.into()); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(ClassHash(felt!("0x7"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))), *class_hash), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_transaction_status() { + let method_name = "starknet_V0_6_getTransactionStatus"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let transaction_hash = block.body.transaction_hashes[0]; + let transaction_version = match block.body.transactions.index(0) { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + let tx = block.body.transaction_outputs.index(0).clone(); + let msg_hash = match tx { + starknet_api::transaction::TransactionOutput::L1Handler(_) => Some(L1L2MsgHash::default()), + _ => None, + }; + let output = TransactionOutput::from((tx, transaction_version, msg_hash)); + let expected_status = TransactionStatus { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + execution_status: output.execution_status().clone(), + }; + let (json_response, res) = + raw_call::<_, _, TransactionStatus>(&module, method_name, &[transaction_hash]).await; + assert_eq!(res.unwrap(), expected_status); + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for a transaction in a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&block.header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let res = module.call::<_, TransactionStatus>(method_name, [transaction_hash]).await.unwrap(); + assert_eq!(res.finality_status, TransactionFinalityStatus::AcceptedOnL1); + + // Add a pending transaction and ask for its status. + let mut rng = get_rng(); + let (client_transaction, client_transaction_receipt, expected_receipt) = + generate_client_transaction_client_receipt_and_rpc_receipt(&mut rng); + let expected_status = TransactionStatus { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + execution_status: expected_receipt.output.execution_status().clone(), + }; + + { + let pending_block = &mut pending_data.write().await.block; + pending_block.transactions_mutable().push(client_transaction.clone()); + pending_block.transaction_receipts_mutable().push(client_transaction_receipt.clone()); + } + let (json_response, result) = raw_call::<_, _, TransactionStatus>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(result.unwrap(), expected_status); + // Validating schema again since pending has a different schema + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for transaction status when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let (_, res) = raw_call::<_, _, TransactionStatus>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(res.unwrap_err(), TRANSACTION_HASH_NOT_FOUND.into()); + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionStatus>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_transaction_receipt() { + let method_name = "starknet_V0_6_getTransactionReceipt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let transaction_hash = block.body.transaction_hashes[0]; + let transaction_version = match block.body.transactions.index(0) { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + let tx = block.body.transactions.index(0).clone(); + let msg_hash = match tx { + starknet_api::transaction::Transaction::L1Handler(tx) => Some(tx.calc_msg_hash()), + _ => None, + }; + let output = TransactionOutput::from(( + block.body.transaction_outputs.index(0).clone(), + transaction_version, + msg_hash, + )); + let expected_receipt = TransactionReceipt { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + transaction_hash, + block_hash: block.header.block_hash, + block_number: block.header.block_number, + output, + }; + let (json_response, res) = + raw_call::<_, _, TransactionReceipt>(&module, method_name, &[transaction_hash]).await; + // The returned jsons of some transaction outputs are the same. When deserialized, the first + // struct in the TransactionOutput enum that matches the json is chosen. To not depend here + // on the order of structs we compare the serialized data. + assert_eq!( + serde_json::to_value(res.unwrap()).unwrap(), + serde_json::to_value(&expected_receipt).unwrap(), + ); + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for a transaction in a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&block.header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let res = module.call::<_, TransactionReceipt>(method_name, [transaction_hash]).await.unwrap(); + assert_eq!(res.finality_status, TransactionFinalityStatus::AcceptedOnL1); + + // Add a pending transaction and ask for its receipt. + let mut rng = get_rng(); + let (client_transaction, client_transaction_receipt, expected_receipt) = + generate_client_transaction_client_receipt_and_rpc_receipt(&mut rng); + + { + let pending_block = &mut pending_data.write().await.block; + pending_block.transactions_mutable().push(client_transaction.clone()); + pending_block.transaction_receipts_mutable().push(client_transaction_receipt.clone()); + } + + let expected_result = GeneralTransactionReceipt::PendingTransactionReceipt(expected_receipt); + let (json_response, result) = raw_call::<_, _, PendingTransactionReceipt>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + // See above for explanation why we compare the json strings. + assert_eq!( + serde_json::to_value(result.unwrap()).unwrap(), + serde_json::to_value(&expected_result).unwrap(), + ); + // Validating schema again since pending has a different schema + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for transaction receipt when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let (_, res) = raw_call::<_, _, TransactionReceipt>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(res.unwrap_err(), TRANSACTION_HASH_NOT_FOUND.into()); + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionReceipt>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_class_at() { + let method_name = "starknet_V0_6_getClassAt"; + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer_from_params::( + None, + None, + Some(pending_data.clone()), + Some(pending_classes.clone()), + None, + ); + let parent_header = BlockHeader::default(); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + ..BlockHeader::default() + }; + let (mut diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(get_test_state_diff()); + // Add a deployed contract with Cairo 1 class. + let new_class_hash = diff.declared_classes.get_index(0).unwrap().0; + diff.deployed_contracts.insert(ContractAddress(patricia_key!("0x2")), *new_class_hash); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes( + parent_header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let pending_address: ContractAddress = random::().into(); + let pending_class_hash = ClassHash(random::().into()); + let pending_class = ApiContractClass::ContractClass( + StarknetApiContractClass::get_test_instance(&mut get_rng()), + ); + pending_data + .write() + .await + .state_update + .state_diff + .deployed_contracts + .push(ClientDeployedContract { address: pending_address, class_hash: pending_class_hash }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + pending_classes.write().await.add_class(pending_class_hash, pending_class.clone()); + + // Deprecated Class + let class_hash = diff.deprecated_declared_classes.last().unwrap(); + let expected_contract_class = + deprecated_classes.get(class_hash).unwrap().clone().try_into().unwrap(); + assert_eq!(diff.deployed_contracts.get_index(0).unwrap().1, class_hash); + let address = diff.deployed_contracts.get_index(0).unwrap().0; + + // Get class by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_contract_class, + ) + .await; + + // Get class by block number. + let res = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // New Class + let class_hash = diff.declared_classes.get_index(0).unwrap().0; + let expected_contract_class = classes.get(class_hash).unwrap().clone().into(); + assert_eq!(diff.deployed_contracts.get_index(1).unwrap().1, class_hash); + let address = diff.deployed_contracts.get_index(1).unwrap().0; + + // Get class by block hash. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class by block number. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class hash of pending block. + let res = module + .call::<_, GatewayContractClass>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, pending_class.try_into().unwrap()); + + // Get class hash of pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, ContractClass>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(pending_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Invalid Call + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x12"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid contract in the given block. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + ( + BlockId::HashOrNumber(BlockHashOrNumber::Number(parent_header.block_number)), + *address, + ), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == CONTRACT_NOT_FOUND.into()); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_class_hash_at() { + let method_name = "starknet_V0_6_getClassHashAt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + // No need to write the class definitions. + .commit() + .unwrap(); + + let (address, expected_class_hash) = diff.deployed_contracts.get_index(0).unwrap(); + + let pending_address: ContractAddress = random::().into(); + let pending_class_hash = ClassHash(random::().into()); + pending_data + .write() + .await + .state_update + .state_diff + .deployed_contracts + .push(ClientDeployedContract { address: pending_address, class_hash: pending_class_hash }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + + // Get class hash by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_class_hash, + ) + .await; + + // Get class hash by block number. + let res = module + .call::<_, ClassHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Get class hash by latest tag. + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Latest), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Get class hash of pending block. + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, pending_class_hash); + + // Get class hash of pending block when it's replaced. + let replaced_class_hash = ClassHash(random::().into()); + pending_data.write().await.state_update.state_diff.replaced_classes.append(&mut vec![ + ClientReplacedClass { address: *address, class_hash: replaced_class_hash }, + ClientReplacedClass { address: pending_address, class_hash: replaced_class_hash }, + ]); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, replaced_class_hash); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, replaced_class_hash); + + // Get class hash of pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(pending_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x12"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, ClassHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_nonce() { + let method_name = "starknet_V0_6_getNonce"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let (address, expected_nonce) = diff.nonces.get_index(0).unwrap(); + + // Get nonce by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_nonce, + ) + .await; + + // Get nonce by block number. + let res = module + .call::<_, Nonce>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block when it wasn't changed in pending block. + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block when it was changed in pending block. + let new_nonce = Nonce(Felt::from(1234_u128)); + pending_data.write().await.state_update.state_diff.nonces.insert(*address, new_nonce); + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, new_nonce); + + // Ask for nonce in pending block where the contract is deployed in the pending block. + let new_pending_contract_address = ContractAddress(patricia_key!("0x1234")); + pending_data + .write() + .await + .state_update + .state_diff + .nonces + .insert(new_pending_contract_address, new_nonce); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(new_pending_contract_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &new_nonce, + ) + .await; + + // Ask for nonce in pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block where the contract is deployed in the pending block, and the + // pending block is not up to date. + // Expected outcome: Failure due to contract not found. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(new_pending_contract_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, Nonce>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x31"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Nonce>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Nonce>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_storage_at() { + let method_name = "starknet_V0_6_getStorageAt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let (address, storage_entries) = diff.storage_diffs.get_index(0).unwrap(); + let (key, expected_value) = storage_entries.get_index(0).unwrap(); + + // Get storage by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(*address), + Box::new(*key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_value, + ) + .await; + + // Get storage by block number. + let res = module + .call::<_, Felt>( + method_name, + (*address, *key, BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + ) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when contract's storage wasn't changed in pending block. + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when it wasn't changed in pending block. + let other_key = random::().into(); + let other_value = random::().into(); + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(*address, vec![ClientStorageEntry { key: other_key, value: other_value }]); + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when it was changed in pending block. + let res = module + .call::<_, Felt>(method_name, (*address, other_key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, other_value); + + // Ask for storage that was changed both in the pending block and the non-pending block. + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(*address, vec![ClientStorageEntry { key: *key, value: other_value }]); + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, other_value); + + // Ask for storage in pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = module + .call::<_, Felt>(method_name, (*address, other_key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, Felt::default()); + + // Ask for storage updated both in pending block and non-pending block when the pending block is + // not up to date. + let res = module + .call::<_, Felt>(method_name, (*address, *key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block where the contract is deployed in the pending block, and the + // pending block is not up to date. + // Expected outcome: Failure due to contract not found. + let key = StorageKey(patricia_key!("0x1001")); + let contract_address = ContractAddress(patricia_key!("0x1234")); + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(contract_address, vec![ClientStorageEntry { key, value: Felt::default() }]); + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![Box::new(contract_address), Box::new(key), Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for storage at address 0x1 - the block hash table contract address + let res = module + .call::<_, Felt>( + "starknet_V0_6_getStorageAt", + ( + *BLOCK_HASH_TABLE_ADDRESS, + key, + BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), + ), + ) + .await + .unwrap(); + assert_eq!(res, Felt::default()); + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![ + Box::new(ContractAddress(patricia_key!("0x12"))), + Box::new(key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![ + Box::new(*address), + Box::new(key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Felt>( + method_name, + (*address, key, BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +fn generate_client_transaction_client_receipt_and_rpc_receipt( + rng: &mut ChaCha8Rng, +) -> (ClientTransaction, ClientTransactionReceipt, PendingTransactionReceipt) { + let pending_transaction_hash = TransactionHash(StarkHash::from(rng.next_u64())); + let mut client_transaction_receipt = ClientTransactionReceipt::get_test_instance(rng); + client_transaction_receipt.transaction_hash = pending_transaction_hash; + client_transaction_receipt.execution_resources.n_memory_holes = 1; + client_transaction_receipt.execution_resources.n_steps = 1; + client_transaction_receipt.execution_resources.builtin_instance_counter.retain(|_, v| *v > 0); + // Generating a transaction until we receive a transaction that can have pending output (i.e a + // non-deploy transaction). + let (mut client_transaction, output) = loop { + let (client_transaction, _) = generate_client_transaction_and_rpc_transaction(rng); + let starknet_api_output = client_transaction_receipt + .clone() + .into_starknet_api_transaction_output(&client_transaction); + let msg_hash = match &client_transaction { + starknet_client::reader::objects::transaction::Transaction::L1Handler(tx) => { + Some(tx.calc_msg_hash()) + } + _ => None, + }; + let maybe_output = PendingTransactionOutput::try_from(TransactionOutput::from(( + starknet_api_output, + client_transaction.transaction_version(), + msg_hash, + ))); + let Ok(output) = maybe_output else { + continue; + }; + break (client_transaction, output); + }; + *client_transaction.transaction_hash_mut() = pending_transaction_hash; + ( + client_transaction, + client_transaction_receipt, + PendingTransactionReceipt { + finality_status: PendingTransactionFinalityStatus::AcceptedOnL2, + transaction_hash: pending_transaction_hash, + output, + }, + ) +} + +fn generate_client_transaction_and_rpc_transaction( + rng: &mut ChaCha8Rng, +) -> (ClientTransaction, TransactionWithHash) { + // TODO(shahak): Remove retry once v3 transactions are supported and the impl of TryInto will + // become impl of Into. + loop { + let client_transaction = ClientTransaction::get_test_instance(rng); + let Ok(starknet_api_transaction): Result = + client_transaction.clone().try_into() + else { + continue; + }; + let Ok(rpc_transaction) = starknet_api_transaction.try_into() else { + continue; + }; + let transaction_hash = client_transaction.transaction_hash(); + break ( + client_transaction, + TransactionWithHash { transaction: rpc_transaction, transaction_hash }, + ); + } +} + +#[tokio::test] +async fn get_transaction_by_hash() { + let method_name = "starknet_V0_6_getTransactionByHash"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let mut block = get_test_block(1, None, None, None); + // Change the transaction hash from 0 to a random value, so that later on we can add a + // transaction with 0 hash to the pending block. + block.body.transaction_hashes[0] = TransactionHash(StarkHash::from(random::())); + storage_writer + .begin_rw_txn() + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(block.body.transaction_hashes[0])], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction, + ) + .await; + + // Ask for a transaction in the pending block. + let (client_transaction, expected_transaction_with_hash) = + generate_client_transaction_and_rpc_transaction(&mut get_rng()); + pending_data.write().await.block.transactions_mutable().push(client_transaction.clone()); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(client_transaction.transaction_hash())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction_with_hash, + ) + .await; + + // Get pending block when it's not updated. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(client_transaction.transaction_hash())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_transaction_by_hash_state_only() { + let method_name = "starknet_V0_6_getTransactionByHash"; + let params = [TransactionHash(StarkHash::from(1_u8))]; + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + None, + None, + None, + None, + Some(StorageScope::StateOnly), + ); + + let (_, err) = raw_call::<_, _, TransactionWithHash>(&module, method_name, ¶ms).await; + assert_eq!( + err.unwrap_err(), + internal_server_error_with_msg("Unsupported method in state-only scope.") + ); +} + +#[tokio::test] +async fn get_transaction_by_block_id_and_index() { + let method_name = "starknet_V0_6_getTransactionByBlockIdAndIndex"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + + // Get transaction by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash))), + Box::new(TransactionOffsetInBlock(0)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction, + ) + .await; + + // Get transaction by block number. + let res = module + .call::<_, TransactionWithHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(block.header.block_number)), 0), + ) + .await + .unwrap(); + assert_eq!(res, expected_transaction); + + // Get transaction of pending block. + let (client_transaction, expected_transaction_with_hash) = + generate_client_transaction_and_rpc_transaction(&mut get_rng()); + pending_data.write().await.block.transactions_mutable().push(client_transaction); + let res = module + .call::<_, TransactionWithHash>(method_name, (BlockId::Tag(Tag::Pending), 0)) + .await + .unwrap(); + assert_eq!(res, expected_transaction_with_hash); + + // Ask for an invalid transaction index in pending block. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(TransactionOffsetInBlock(1))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; + + // Get transaction of pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(TransactionOffsetInBlock(0))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(TransactionOffsetInBlock(0)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, TransactionWithHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), 0), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Ask for an invalid transaction index. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash))), + Box::new(TransactionOffsetInBlock(1)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; +} + +#[tokio::test] +async fn get_state_update() { + let method_name = "starknet_V0_6_getStateUpdate"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let parent_header = BlockHeader::default(); + let expected_pending_old_root = GlobalRoot(felt!("0x1234")); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + state_root: expected_pending_old_root, + ..BlockHeader::default() + }; + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + // No need to write the class definitions + .commit() + .unwrap(); + + let expected_old_root = parent_header.state_root; + let expected_state_diff = ThinStateDiff::from(diff); + let expected_update = StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + block_hash: header.block_hash, + new_root: header.state_root, + old_root: expected_old_root, + state_diff: expected_state_diff.clone(), + }); + + // Get state update by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_update, + ) + .await; + + // Get state update by block number. + let res = module + .call::<_, StateUpdate>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))], + ) + .await + .unwrap(); + assert_eq!(res, expected_update); + + // Get state update of pending block. + let expected_pending_update = StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: expected_old_root, + state_diff: expected_state_diff.clone(), + }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + pending_data.write().await.state_update = ClientPendingStateUpdate { + old_root: expected_old_root, + state_diff: ClientStateDiff { + storage_diffs: IndexMap::from_iter(expected_state_diff.storage_diffs.into_iter().map( + |StorageDiff { address, storage_entries }| { + let storage_entries = Vec::from_iter( + storage_entries + .into_iter() + .map(|StorageEntry { key, value }| ClientStorageEntry { key, value }), + ); + (address, storage_entries) + }, + )), + deployed_contracts: Vec::from_iter( + expected_state_diff.deployed_contracts.into_iter().map( + |DeployedContract { address, class_hash }| ClientDeployedContract { + address, + class_hash, + }, + ), + ), + declared_classes: expected_state_diff + .declared_classes + .into_iter() + .map(|ClassHashes { class_hash, compiled_class_hash }| { + ClientDeclaredClassHashEntry { class_hash, compiled_class_hash } + }) + .collect(), + old_declared_contracts: expected_state_diff.deprecated_declared_classes, + nonces: IndexMap::from_iter( + expected_state_diff + .nonces + .into_iter() + .map(|ContractNonce { contract_address, nonce }| (contract_address, nonce)), + ), + replaced_classes: Vec::from_iter(expected_state_diff.replaced_classes.into_iter().map( + |ReplacedClasses { contract_address, class_hash }| ClientReplacedClass { + address: contract_address, + class_hash, + }, + )), + }, + }; + // Validating schema because the state diff of pending block contains less fields. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_update, + ) + .await; + + // Get state update of pending block when the pending block is not up to date. + let expected_pending_update = StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: expected_pending_old_root, + ..PendingStateUpdate::default() + }); + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = + module.call::<_, StateUpdate>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, expected_pending_update); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, StateUpdate>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, StateUpdate>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_state_update_with_empty_storage_diff() { + let method_name = "starknet_V0_6_getStateUpdate"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let state_diff = starknet_api::state::ThinStateDiff { + storage_diffs: indexmap!(ContractAddress::default() => indexmap![]), + ..Default::default() + }; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_state_diff(BlockNumber(0), state_diff) + .unwrap() + .commit() + .unwrap(); + + // The empty storage diff should be removed in the result. + let expected_state_diff = + ThinStateDiff::from(starknet_api::state::ThinStateDiff::from(StateDiff::default())); + let expected_update = StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + state_diff: expected_state_diff.clone(), + ..Default::default() + }); + + // Get state update by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_update, + ) + .await; +} + +#[derive(Clone)] +struct EventMetadata { + pub address: Option, + pub keys: Option>, +} + +const DEFAULT_EVENT_METADATA: EventMetadata = EventMetadata { address: None, keys: None }; + +impl EventMetadata { + pub fn generate_event(&self, rng: &mut ChaCha8Rng) -> StarknetApiEvent { + StarknetApiEvent { + from_address: self.address.unwrap_or_else(|| ContractAddress(rng.next_u64().into())), + content: EventContent { + keys: self.keys.clone().unwrap_or_else(|| vec![EventKey(rng.next_u64().into())]), + data: EventData(vec![rng.next_u64().into()]), + }, + } + } +} + +#[derive(Clone, Default)] +struct BlockMetadata(pub Vec>); + +impl BlockMetadata { + pub fn generate_block( + &self, + rng: &mut ChaCha8Rng, + parent_hash: BlockHash, + block_number: BlockNumber, + ) -> StarknetApiBlock { + // Generate a block with no events, And then add the events manually. + let mut block = get_test_block(self.0.len(), Some(0), None, None); + block.header.parent_hash = parent_hash; + block.header.block_number = block_number; + block.header.block_hash = BlockHash(rng.next_u64().into()); + // Randomize the transaction hashes because get_test_block returns constant hashes + for transaction_hash in &mut block.body.transaction_hashes { + *transaction_hash = TransactionHash(rng.next_u64().into()); + } + + for (output, event_metadatas_of_tx) in + block.body.transaction_outputs.iter_mut().zip(self.0.iter()) + { + let events = match output { + StarknetApiTransactionOutput::Declare(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::Deploy(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::DeployAccount(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::Invoke(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::L1Handler(transaction) => &mut transaction.events, + }; + for event_metadata in event_metadatas_of_tx { + events.push(event_metadata.generate_event(rng)); + } + } + block + } + + pub fn generate_pending_block( + &self, + rng: &mut ChaCha8Rng, + parent_hash: BlockHash, + ) -> PendingBlockOrDeprecated { + let transaction_hashes = iter::repeat_with(|| TransactionHash(rng.next_u64().into())) + .take(self.0.len()) + .collect::>(); + PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: parent_hash, + transactions: transaction_hashes + .iter() + .map(|transaction_hash| { + let mut transaction = ClientTransaction::get_test_instance(rng); + *transaction.transaction_hash_mut() = *transaction_hash; + transaction + }) + .collect(), + transaction_receipts: transaction_hashes + .iter() + .zip(self.0.iter()) + .enumerate() + .map(|(i, (transaction_hash, event_metadatas_of_tx))| ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(i), + transaction_hash: *transaction_hash, + events: event_metadatas_of_tx + .iter() + .map(|event_metadata| event_metadata.generate_event(rng)) + .collect(), + ..Default::default() + }) + .collect(), + ..Default::default() + }) + } +} + +async fn test_get_events( + block_metadatas: Vec, + pending_block_metadata: Option, + is_pending_up_to_date: bool, + mut filter: EventFilter, + expected_result_by_index: Vec<(Vec, Option)>, +) { + let method_name = "starknet_V0_6_getEvents"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let mut rng = get_rng(); + + let mut event_index_to_event = HashMap::::new(); + let mut parent_hash = BlockHash(felt!(GENESIS_HASH)); + let mut rw_txn = storage_writer.begin_rw_txn().unwrap(); + for (i, block_metadata) in block_metadatas.iter().enumerate() { + let block_number = BlockNumber(i as u64); + let block = block_metadata.generate_block(&mut rng, parent_hash, block_number); + + parent_hash = block.header.block_hash; + + for (i_transaction, (output, transaction_hash)) in block + .body + .transaction_outputs + .iter() + .zip(block.body.transaction_hashes.iter().cloned()) + .enumerate() + { + for (i_event, event) in output.events().iter().cloned().enumerate() { + event_index_to_event.insert( + EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(i_transaction)), + EventIndexInTransactionOutput(i_event), + ), + Event { + block_hash: Some(block.header.block_hash), + block_number: Some(block_number), + transaction_hash, + event, + }, + ); + } + } + + rw_txn = rw_txn + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body) + .unwrap() + .append_state_diff( + block.header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap(); + } + rw_txn.commit().unwrap(); + + if let Some(pending_block_metadata) = pending_block_metadata { + if !is_pending_up_to_date { + parent_hash = BlockHash(rng.next_u64().into()); + } + let pending_block = pending_block_metadata.generate_pending_block(&mut rng, parent_hash); + + for (i_transaction, receipt) in pending_block.transaction_receipts().iter().enumerate() { + for (i_event, event) in receipt.events.iter().cloned().enumerate() { + event_index_to_event.insert( + EventIndex( + TransactionIndex( + BlockNumber(block_metadatas.len() as u64), + TransactionOffsetInBlock(i_transaction), + ), + EventIndexInTransactionOutput(i_event), + ), + Event { + block_hash: None, + block_number: None, + transaction_hash: receipt.transaction_hash, + event, + }, + ); + } + } + + pending_data.write().await.block = pending_block; + } + + for (expected_event_indices, expected_continuation_token) in expected_result_by_index { + let expected_result = EventsChunk { + events: expected_event_indices + .iter() + .map(|event_index| event_index_to_event.get(event_index).unwrap()) + .cloned() + .collect(), + continuation_token: expected_continuation_token + .map(|x| ContinuationToken::new(x).unwrap()), + }; + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(filter.clone())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_result, + ) + .await; + filter.continuation_token = expected_result.continuation_token; + } +} + +lazy_static! { + static ref BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: Vec = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA], vec![DEFAULT_EVENT_METADATA]]), + // There should be a chunk that starts at the non-first transaction of the second block, in + // order to test the continuation token for pending. + BlockMetadata(vec![ + [DEFAULT_EVENT_METADATA; 3].to_vec(), + [DEFAULT_EVENT_METADATA; 2].to_vec(), + ]), + ]; + static ref EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: EventFilter = + EventFilter { chunk_size: 3, ..Default::default() }; + static ref EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: Vec<(Vec, Option,)> = vec![ + ( + vec![ + EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(0), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + ], + Some(ContinuationTokenAsStruct(EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ))), + ), + ( + vec![ + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(2), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(0), + ), + ], + Some(ContinuationTokenAsStruct(EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(1), + ))), + ), + ( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(1), + )], + None, + ), + ]; +} + +#[tokio::test] +async fn get_events_chunk_across_2_blocks() { + let pending_block_metadata = None; + let is_pending_up_to_date = true; + test_get_events( + BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_chunk_across_block_and_pending_block() { + let mut blocks_metadata = BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(); + let pending_block_metadata = Some(blocks_metadata.pop().unwrap()); + let is_pending_up_to_date = true; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_address_filter() { + let address = ContractAddress(patricia_key!("0x22")); + let blocks_metadata = vec![BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { address: Some(address), keys: None }, + DEFAULT_EVENT_METADATA, + ]])]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, address: Some(address), ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_address_filter() { + let address = ContractAddress(patricia_key!("0x22")); + // As a special edge case, the function get_events doesn't return events if there are no + // accepted blocks, even if there is a pending block. Therefore, we need to have a block in the + // storage. + let blocks_metadata = vec![BlockMetadata(vec![])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { address: Some(address), keys: None }, + DEFAULT_EVENT_METADATA, + ]])); + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, address: Some(address), ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +lazy_static! { + static ref KEY0_0: EventKey = EventKey(felt!("0x00")); + static ref KEY0_1: EventKey = EventKey(felt!("0x01")); + static ref KEY2_0: EventKey = EventKey(felt!("0x20")); + static ref KEY2_1: EventKey = EventKey(felt!("0x21")); + static ref UNRELATED_KEY: EventKey = EventKey(felt!("0xff")); + static ref BLOCKS_METADATA_FOR_KEYS_FILTER_TEST: Vec = + // Adding an empty block at the start so that in the pending test there will be an accepted + // block. See above for explanation on the special edge case of no accepted blocks. + vec![ + BlockMetadata(vec![]), + BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { + address: None, + keys: Some(vec![KEY0_0.clone(), UNRELATED_KEY.clone(), KEY2_1.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![KEY2_0.clone(), UNRELATED_KEY.clone(), KEY2_1.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![KEY0_1.clone(), UNRELATED_KEY.clone(), KEY0_0.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![ + KEY0_1.clone(), + UNRELATED_KEY.clone(), + KEY2_0.clone(), + UNRELATED_KEY.clone(), + ]), + }, + EventMetadata { address: None, keys: Some(vec![KEY0_1.clone()]) }, + EventMetadata { address: None, keys: Some(vec![]) }, + ]] + )]; + static ref EVENT_FILTER_FOR_KEYS_FILTER_TEST: EventFilter = EventFilter { + chunk_size: 6, + keys: vec![ + HashSet::from([KEY0_0.clone(), KEY0_1.clone()]), + HashSet::from([]), + HashSet::from([KEY2_0.clone(), KEY2_1.clone()]), + ], + ..Default::default() + }; + static ref EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST: Vec<(Vec, Option,)> = + vec![( + vec![ + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(4), + ), + ], + None, + )]; +} + +#[tokio::test] +async fn get_events_keys_filter() { + let pending_block_metadata = None; + let is_pending_up_to_date = true; + test_get_events( + BLOCKS_METADATA_FOR_KEYS_FILTER_TEST.clone(), + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_KEYS_FILTER_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_keys_filter() { + let mut blocks_metadata = BLOCKS_METADATA_FOR_KEYS_FILTER_TEST.clone(); + let pending_block_metadata = Some(blocks_metadata.pop().unwrap()); + let is_pending_up_to_date = true; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_KEYS_FILTER_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_from_block() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata.clone(), + pending_block_metadata.clone(), + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + ..Default::default() + }, + expected_result_by_index.clone(), + ) + .await; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::Tag(Tag::Latest)), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_from_pending() { + let blocks_metadata = vec![BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])); + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::Tag(Tag::Pending)), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_to_block() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + to_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +// TODO(nevo): add a test that returns the block not found error for getEvents +#[tokio::test] +async fn get_events_no_blocks() { + let blocks_metadata = vec![BlockMetadata::default()]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![(vec![], None)]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_no_blocks_in_filter() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![(vec![], None)]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + to_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_not_up_to_date() { + // As a special edge case, the function get_events doesn't return events if there are no + // accepted blocks, even if there is a pending block. Therefore, we need to have a block in the + // storage. + let blocks_metadata = vec![BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])); + let is_pending_up_to_date = false; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_page_size_too_big() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: None, + chunk_size: get_test_rpc_config().max_events_chunk_size + 1, + address: None, + keys: vec![], + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_6_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &PAGE_SIZE_TOO_BIG.into(), + ) + .await; +} + +#[tokio::test] +async fn get_events_too_many_keys() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + let keys = (0..get_test_rpc_config().max_events_keys + 1) + .map(|i| HashSet::from([EventKey(Felt::from(i as u128))])) + .collect(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: None, + chunk_size: 2, + address: None, + keys, + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_6_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TOO_MANY_KEYS_IN_FILTER.into(), + ) + .await; +} + +#[tokio::test] +async fn get_events_invalid_ct() { + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + let block = starknet_api::block::Block::default(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: Some(ContinuationToken("junk".to_owned())), + chunk_size: 2, + address: None, + keys: vec![], + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_6_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_CONTINUATION_TOKEN.into(), + ) + .await; +} + +#[tokio::test] +async fn serialize_returns_valid_json() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let mut rng = get_rng(); + let parent_block = starknet_api::block::Block::default(); + let block = starknet_api::block::Block { + header: BlockHeader { + parent_hash: parent_block.header.block_hash, + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + ..BlockHeader::default() + }, + body: get_test_body(5, Some(5), None, None), + }; + let mut state_diff = StateDiff::get_test_instance(&mut rng); + // In the test instance both declared_classes and deprecated_declared_classes have an entry + // with class hash 0x0, which is illegal. + state_diff.deprecated_declared_classes = IndexMap::from([( + ClassHash(felt!("0x2")), + starknet_api::deprecated_contract_class::ContractClass::get_test_instance(&mut rng), + )]); + // For checking the schema also for deprecated contract classes. + state_diff + .deployed_contracts + .insert(ContractAddress(patricia_key!("0x2")), ClassHash(felt!("0x2"))); + // TODO(yair): handle replaced classes. + state_diff.replaced_classes.clear(); + + let (thin_state_diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(state_diff.clone()); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_block.header.block_number, &parent_block.header) + .unwrap() + .append_body(parent_block.header.block_number, parent_block.body) + .unwrap() + .append_state_diff( + parent_block.header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes(parent_block.header.block_number, &[], &[]) + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, thin_state_diff) + .unwrap() + .append_classes( + block.header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .commit() + .unwrap(); + + let gateway_config = get_test_rpc_config(); + let (server_address, _handle) = run_server( + &gateway_config, + get_test_highest_block(), + get_test_pending_data(), + get_test_pending_classes(), + storage_reader, + NODE_VERSION, + ) + .await + .unwrap(); + + let schema = get_starknet_spec_api_schema_for_components( + &[( + SpecFile::StarknetApiOpenrpc, + &[ + "BLOCK_WITH_TXS", + "BLOCK_WITH_TX_HASHES", + "STATE_UPDATE", + "CONTRACT_CLASS", + "DEPRECATED_CONTRACT_CLASS", + "TXN", + "TXN_RECEIPT", + "EVENTS_CHUNK", + ], + )], + &VERSION, + ); + validate_state(&state_diff, server_address, &schema).await; + validate_block(&block.header, server_address, &schema).await; + validate_transaction(block.body.transaction_hashes.index(0), server_address, &schema).await; +} + +async fn validate_state(state_diff: &StateDiff, server_address: SocketAddr, schema: &JSONSchema) { + let res = send_request( + server_address, + "starknet_getStateUpdate", + r#"{"block_number": 1}"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "State update is not valid."); + + let (address, _) = state_diff.deployed_contracts.get_index(0).unwrap(); + let res = send_request( + server_address, + "starknet_getClassAt", + format!(r#"{{"block_number": 1}}, "0x{}""#, hex::encode(address.0.key().to_bytes_be())) + .as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Class is not valid."); + + // TODO(dvir): Remove this after regenesis. + // This checks the deployed deprecated class. + let (address, _) = state_diff.deployed_contracts.get_index(1).unwrap(); + let res = send_request( + server_address, + "starknet_getClassAt", + format!(r#"{{"block_number": 1}}, "0x{}""#, address.0.key().to_hex_string()).as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Class is not valid."); +} + +async fn validate_block(header: &BlockHeader, server_address: SocketAddr, schema: &JSONSchema) { + let res = send_request( + server_address, + "starknet_getBlockWithTxs", + r#"{"block_number": 1}"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Block with transactions is not valid."); + + let res = send_request( + server_address, + "starknet_getBlockWithTxHashes", + format!(r#"{{"block_hash": "0x{}"}}"#, hex::encode(header.block_hash.0.to_bytes_be())) + .as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Block with transaction hashes is not valid."); +} + +async fn validate_transaction( + tx_hash: &TransactionHash, + server_address: SocketAddr, + schema: &JSONSchema, +) { + let res = send_request( + server_address, + "starknet_getTransactionByBlockIdAndIndex", + r#"{"block_number": 1}, 0"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction is not valid."); + + let res = send_request( + server_address, + "starknet_getTransactionByHash", + format!(r#""0x{}""#, hex::encode(tx_hash.0.to_bytes_be())).as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction is not valid."); + + let res = send_request( + server_address, + "starknet_getTransactionReceipt", + format!(r#""0x{}""#, hex::encode(tx_hash.0.to_bytes_be())).as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction receipt is not valid."); + + let res = + send_request(server_address, "starknet_getEvents", r#"{"chunk_size": 2}"#, VERSION.name) + .await; + assert!(validate_schema(schema, &res["result"]), "Events are not valid."); +} + +// This test checks that the deprecated contract class is returned with the correct state mutability +// field in the function abi entry. If there is no stateMutability field, the gateway should return +// an answer without this field at all, and if it is present, it should be returned as is. +#[tokio::test] +async fn get_deprecated_class_state_mutability() { + // Without state mutability. + let function_abi_without_state_mutability = + FunctionAbiEntry { state_mutability: None, ..Default::default() }; + let function_abi_without_state_mutability = + ContractClassAbiEntry::Function(function_abi_without_state_mutability); + let class_without_state_mutability = starknet_api::deprecated_contract_class::ContractClass { + abi: Some(vec![function_abi_without_state_mutability]), + ..Default::default() + }; + + // With state mutability. + let function_abi_with_state_mutability = FunctionAbiEntry { + state_mutability: Some(FunctionStateMutability::View), + ..Default::default() + }; + let function_abi_with_state_mutability = + ContractClassAbiEntry::Function(function_abi_with_state_mutability); + let class_with_state_mutability = starknet_api::deprecated_contract_class::ContractClass { + abi: Some(vec![function_abi_with_state_mutability]), + ..Default::default() + }; + + let state_diff = starknet_api::state::ThinStateDiff { + deprecated_declared_classes: vec![ClassHash(felt!("0x0")), ClassHash(felt!("0x1"))], + ..Default::default() + }; + + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + let header = BlockHeader::default(); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, state_diff) + .unwrap() + .append_classes( + header.block_number, + &[], + &[ + (ClassHash(felt!("0x0")), &class_without_state_mutability), + (ClassHash(felt!("0x1")), &class_with_state_mutability), + ], + ) + .unwrap() + .commit() + .unwrap(); + + // Get class without state mutability. + let res = module + .call::<_, DeprecatedContractClass>( + "starknet_V0_6_getClass", + ( + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), + ClassHash(felt!("0x0")), + ), + ) + .await + .unwrap(); + let res_as_value = serde_json::to_value(res).unwrap(); + let entry = res_as_value["abi"][0].as_object().unwrap(); + assert!(!entry.contains_key("stateMutability")); + + // Get class with state mutability. + let res = module + .call::<_, DeprecatedContractClass>( + "starknet_V0_6_getClass", + ( + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), + ClassHash(felt!("0x1")), + ), + ) + .await + .unwrap(); + let res_as_value = serde_json::to_value(res).unwrap(); + let entry = res_as_value["abi"][0].as_object().unwrap(); + assert_eq!(entry.get("stateMutability").unwrap().as_str().unwrap(), "view"); +} + +#[async_trait] +trait AddTransactionTest +where + // This bound is a work-around for associated type bounds. It bounds + // `Self::ClientTransaction::Error` to implement `Debug`. + // associated type bounds is described here: + // https://github.com/rust-lang/rfcs/blob/master/text/2289-associated-type-bounds.md + <::ClientTransaction as TryFrom>::Error: Debug, +{ + type Transaction: GetTestInstance + Serialize + Clone + Send + Sync + 'static + Debug; + type ClientTransaction: TryFrom + Send + Debug; + type Response: From + + for<'de> Deserialize<'de> + + Eq + + Debug + + Clone + + Send + + Sync; + type ClientResponse: GetTestInstance + Clone + Send; + + const METHOD_NAME: &'static str; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ); + + async fn test_positive_flow() { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + let client_resp = Self::ClientResponse::get_test_instance(&mut rng); + let expected_resp = Self::Response::from(client_resp.clone()); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Ok(client_resp), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + call_api_then_assert_and_validate_schema_for_result( + &module, + Self::METHOD_NAME, + vec![Box::new(tx)], + &VERSION, + SpecFile::WriteApi, + &expected_resp, + ) + .await; + } + + async fn test_internal_error() { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + let client_error = WriterClientError::ClientError(ClientError::BadResponseStatus { + code: StatusCode::from_u16(404).unwrap(), + message: "This site can’t be reached".to_owned(), + }); + let expected_error = internal_server_error(&client_error); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, expected_error); + } + + async fn test_known_starknet_error( + known_starknet_error_code: KnownStarknetErrorCode, + expected_error: JsonRpcError, + ) { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + const MESSAGE: &str = "message"; + let client_error = + WriterClientError::ClientError(ClientError::StarknetError(StarknetError { + code: StarknetErrorCode::KnownErrorCode(known_starknet_error_code), + message: MESSAGE.to_owned(), + })); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, expected_error.into()); + } + + async fn test_unexpected_error(known_starknet_error_code: KnownStarknetErrorCode) { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + const MESSAGE: &str = "message"; + let client_error = + WriterClientError::ClientError(ClientError::StarknetError(StarknetError { + code: StarknetErrorCode::KnownErrorCode(known_starknet_error_code), + message: MESSAGE.to_owned(), + })); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, unexpected_error(MESSAGE.to_owned()).into()); + } +} + +struct AddInvokeTest {} +impl AddTransactionTest for AddInvokeTest { + type Transaction = TypedInvokeTransaction; + type ClientTransaction = ClientInvokeTransaction; + type Response = AddInvokeOkResult; + type ClientResponse = InvokeResponse; + + const METHOD_NAME: &'static str = "starknet_V0_6_addInvokeTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_invoke_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +struct AddDeployAccountTest {} +impl AddTransactionTest for AddDeployAccountTest { + type Transaction = TypedDeployAccountTransaction; + type ClientTransaction = ClientDeployAccountTransaction; + type Response = AddDeployAccountOkResult; + type ClientResponse = DeployAccountResponse; + + const METHOD_NAME: &'static str = "starknet_V0_6_addDeployAccountTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_deploy_account_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +struct AddDeclareTest {} +impl AddTransactionTest for AddDeclareTest { + type Transaction = BroadcastedDeclareTransaction; + type ClientTransaction = ClientDeclareTransaction; + type Response = AddDeclareOkResult; + type ClientResponse = DeclareResponse; + + const METHOD_NAME: &'static str = "starknet_V0_6_addDeclareTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_declare_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +// TODO(shahak): Test starknet error. + +#[tokio::test] +async fn add_invoke_positive_flow() { + AddInvokeTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_invoke_internal_error() { + AddInvokeTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_invoke_known_starknet_error() { + AddInvokeTest::test_known_starknet_error( + KnownStarknetErrorCode::DuplicatedTransaction, + DUPLICATE_TX, + ) + .await; +} + +#[tokio::test] +async fn add_invoke_unexpected_error() { + // Choosing error codes that map under the other transaction types into an expected error in + // order to check that we call invoke's error conversion. + AddInvokeTest::test_unexpected_error(KnownStarknetErrorCode::CompilationFailed).await; + AddInvokeTest::test_unexpected_error(KnownStarknetErrorCode::UndeclaredClass).await; +} + +#[tokio::test] +async fn add_deploy_account_positive_flow() { + AddDeployAccountTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_deploy_account_internal_error() { + AddDeployAccountTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_deploy_account_known_starknet_error() { + // Choosing an error code that maps under the other transaction types into an unexpected error + // in order to check that we call deploy_account's error conversion. + AddDeployAccountTest::test_known_starknet_error( + KnownStarknetErrorCode::UndeclaredClass, + CLASS_HASH_NOT_FOUND, + ) + .await; +} + +#[tokio::test] +async fn add_deploy_account_unexpected_error() { + // Choosing an error code that maps under the other transaction types into an expected error in + // order to check that we call deploy_account's error conversion. + AddDeployAccountTest::test_unexpected_error(KnownStarknetErrorCode::CompilationFailed).await; +} + +#[tokio::test] +async fn add_declare_positive_flow() { + AddDeclareTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_declare_internal_error() { + AddDeclareTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_declare_known_starknet_error() { + // Choosing an error code that maps under the other transaction types into an unexpected error + // in order to check that we call declare's error conversion. + AddDeclareTest::test_known_starknet_error( + KnownStarknetErrorCode::CompilationFailed, + COMPILATION_FAILED, + ) + .await; +} + +#[tokio::test] +async fn add_declare_unexpected_error() { + // Choosing an error code that maps under the other transaction types into an expected error in + // order to check that we call declare's error conversion. + AddDeclareTest::test_unexpected_error(KnownStarknetErrorCode::UndeclaredClass).await; +} + +#[test] +fn spec_api_methods_coverage() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + let implemented_methods: Methods = module.into(); + let implemented_method_names = implemented_methods + .method_names() + .map(method_name_to_spec_method_name) + .sorted() + .collect::>(); + let non_implemented_apis = ["starknet_pendingTransactions".to_string()]; + let method_names_in_spec = get_method_names_from_spec(&VERSION) + .iter() + .filter_map(|method| { + let stripped_method_name = method.clone().replace('\"', ""); + if non_implemented_apis.contains(&stripped_method_name) { + None + } else { + Some(stripped_method_name) + } + }) + .sorted() + .collect::>(); + assert!(method_names_in_spec.eq(&implemented_method_names)); +} + +auto_impl_get_test_instance! { + pub struct PendingBlockHeader { + pub parent_hash: BlockHash, + pub sequencer_address: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub starknet_version: String, + } + pub struct ResourcePrice { + pub price_in_wei: GasPrice, + pub price_in_fri: GasPrice, + } + pub enum TypedInvokeTransaction { + Invoke(InvokeTransaction) = 0, + } + pub enum TypedDeployAccountTransaction { + DeployAccount(DeployAccountTransaction) = 0, + } +} diff --git a/crates/papyrus_rpc/src/v0_6/block.rs b/crates/papyrus_rpc/src/v0_6/block.rs new file mode 100644 index 00000000000..da3c35a662a --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/block.rs @@ -0,0 +1,162 @@ +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageError, StorageReader, StorageTxn}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus, BlockTimestamp, GasPrice}; +use starknet_api::core::{GlobalRoot, SequencerContractAddress}; + +use super::error::BLOCK_NOT_FOUND; +use super::transaction::Transactions; +use crate::api::{BlockHashOrNumber, BlockId, Tag}; +use crate::{get_latest_block_number, internal_server_error}; + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct BlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub sequencer_address: SequencerContractAddress, + pub new_root: GlobalRoot, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub starknet_version: String, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct PendingBlockHeader { + pub parent_hash: BlockHash, + pub sequencer_address: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub starknet_version: String, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum GeneralBlockHeader { + BlockHeader(BlockHeader), + PendingBlockHeader(PendingBlockHeader), +} + +impl From for BlockHeader { + fn from(header: starknet_api::block::BlockHeader) -> Self { + BlockHeader { + block_hash: header.block_hash, + parent_hash: header.parent_hash, + block_number: header.block_number, + sequencer_address: header.sequencer, + new_root: header.state_root, + timestamp: header.timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: header.l1_gas_price.price_in_wei, + price_in_fri: header.l1_gas_price.price_in_fri, + }, + starknet_version: header.starknet_version.0, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ResourcePrice { + pub price_in_wei: GasPrice, + pub price_in_fri: GasPrice, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct Block { + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(flatten)] + pub header: GeneralBlockHeader, + pub transactions: Transactions, +} + +pub fn get_block_header_by_number( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result { + let header = txn + .get_block_header(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + Ok(header) +} + +/// Return the closest block number that corresponds to the given block id and is accepted (i.e not +/// pending). Latest block means the most advanced block that we've downloaded and that we've +/// downloaded its state diff. +pub(crate) fn get_accepted_block_number( + txn: &StorageTxn<'_, Mode>, + block_id: BlockId, +) -> Result { + Ok(match block_id { + BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash)) => { + let block_number = txn + .get_block_number_by_hash(&block_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + // Check that the block has state diff. + let last_block_number = get_latest_block_number(txn)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + if block_number > last_block_number { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND)); + } + block_number + } + BlockId::HashOrNumber(BlockHashOrNumber::Number(block_number)) => { + // Check that the block exists and has state diff. + let last_block_number = get_latest_block_number(txn)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + if block_number > last_block_number { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND)); + } + block_number + } + BlockId::Tag(Tag::Latest | Tag::Pending) => { + get_latest_block_number(txn)?.ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))? + } + }) +} + +/// Validates that a given block wasn't reverted. Given an instance of this class, we can call its +/// `validate` method and it will validate that the block's hash didn't change from the validator's +/// creation. +pub(crate) struct BlockNotRevertedValidator { + block_number: BlockNumber, + old_block_hash: BlockHash, +} + +impl BlockNotRevertedValidator { + pub fn new( + block_number: BlockNumber, + txn: &StorageTxn<'_, Mode>, + ) -> Result { + let header = txn + .get_block_header(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + ErrorObjectOwned::from(internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block header {block_number}"), + })) + })?; + Ok(Self { block_number, old_block_hash: header.block_hash }) + } + + pub fn validate(self, storage_reader: &StorageReader) -> Result<(), ErrorObjectOwned> { + let error = ErrorObjectOwned::from(internal_server_error(format!( + "Block {} was reverted mid-execution.", + self.block_number + ))); + let txn = storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let new_block_hash = txn + .get_block_header(self.block_number) + .map_err(internal_server_error)? + .ok_or(error.clone())? + .block_hash; + if new_block_hash == self.old_block_hash { Ok(()) } else { Err(error) } + } +} diff --git a/crates/papyrus_rpc/src/v0_6/broadcasted_transaction.rs b/crates/papyrus_rpc/src/v0_6/broadcasted_transaction.rs new file mode 100644 index 00000000000..496eea2b8bf --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/broadcasted_transaction.rs @@ -0,0 +1,195 @@ +//! This module contains structs for representing a broadcasted transaction. +//! +//! A broadcasted transaction is a transaction that wasn't accepted yet to Starknet. +//! +//! The broadcasted transaction follows the same structure as described in the [`Starknet specs`] +//! +//! [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + +#[cfg(test)] +#[path = "broadcasted_transaction_test.rs"] +mod broadcasted_transaction_test; + +use papyrus_storage::db::serialization::StorageSerdeError; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::transaction::{ + AccountDeploymentData, + Fee, + PaymasterData, + Tip, + TransactionSignature, + TransactionVersion, +}; +use starknet_client::writer::objects::transaction as client_transaction; +use starknet_client::writer::objects::transaction::DeprecatedContractClass; + +use super::state::ContractClass; +use super::transaction::{DeployAccountTransaction, InvokeTransaction, ResourceBoundsMapping}; +use crate::compression_utils::compress_and_encode; + +/// Transactions that are ready to be broadcasted to the network and are not included in a block. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum BroadcastedTransaction { + #[serde(rename = "DECLARE")] + Declare(BroadcastedDeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), +} + +/// A broadcasted declare transaction. +/// +/// This transaction is equivalent to the component DECLARE_TXN in the +/// [`Starknet specs`] without the V0 variant and with a contract class (DECLARE_TXN allows having +/// either a contract class or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +#[serde(tag = "version")] +pub enum BroadcastedDeclareTransaction { + #[serde(rename = "0x1")] + V1(BroadcastedDeclareV1Transaction), + #[serde(rename = "0x2")] + V2(BroadcastedDeclareV2Transaction), + #[serde(rename = "0x3")] + V3(BroadcastedDeclareV3Transaction), +} + +/// A broadcasted declare transaction of a Cairo-v0 contract. +/// +/// This transaction is equivalent to the component DECLARE_TXN_V1 in the +/// [`Starknet specs`] with a contract class (DECLARE_TXN_V1 allows having either a contract class +/// or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV1Transaction { + pub r#type: DeclareType, + pub contract_class: DeprecatedContractClass, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, +} + +/// A broadcasted declare transaction of a Cairo-v1 contract. +/// +/// This transaction is equivalent to the component DECLARE_TXN_V2 in the +/// [`Starknet specs`] with a contract class (DECLARE_TXN_V2 allows having either a contract class +/// or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Default)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV2Transaction { + pub r#type: DeclareType, + pub contract_class: ContractClass, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV3Transaction { + pub r#type: DeclareType, + pub sender_address: ContractAddress, + pub compiled_class_hash: CompiledClassHash, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +/// The type field of a declare transaction. This enum serializes/deserializes into a constant +/// string. +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] +pub enum DeclareType { + #[serde(rename = "DECLARE")] + #[default] + Declare, +} + +impl TryFrom for client_transaction::DeclareTransaction { + type Error = StorageSerdeError; + + fn try_from(value: BroadcastedDeclareTransaction) -> Result { + match value { + BroadcastedDeclareTransaction::V1(declare_v1) => { + Ok(Self::DeclareV1(client_transaction::DeclareV1Transaction { + contract_class: declare_v1.contract_class, + sender_address: declare_v1.sender_address, + nonce: declare_v1.nonce, + max_fee: declare_v1.max_fee, + signature: declare_v1.signature, + version: TransactionVersion::ONE, + r#type: client_transaction::DeclareType::default(), + })) + } + BroadcastedDeclareTransaction::V2(declare_v2) => { + Ok(Self::DeclareV2(client_transaction::DeclareV2Transaction { + contract_class: client_transaction::ContractClass { + compressed_sierra_program: compress_and_encode(serde_json::to_value( + &declare_v2.contract_class.sierra_program, + )?)?, + contract_class_version: declare_v2.contract_class.contract_class_version, + entry_points_by_type: declare_v2 + .contract_class + .entry_points_by_type + .to_hash_map(), + abi: declare_v2.contract_class.abi, + }, + compiled_class_hash: declare_v2.compiled_class_hash, + sender_address: declare_v2.sender_address, + nonce: declare_v2.nonce, + max_fee: declare_v2.max_fee, + signature: declare_v2.signature, + version: TransactionVersion::TWO, + r#type: client_transaction::DeclareType::default(), + })) + } + BroadcastedDeclareTransaction::V3(declare_v3) => { + Ok(Self::DeclareV3(client_transaction::DeclareV3Transaction { + contract_class: client_transaction::ContractClass { + compressed_sierra_program: compress_and_encode(serde_json::to_value( + &declare_v3.contract_class.sierra_program, + )?)?, + contract_class_version: declare_v3.contract_class.contract_class_version, + entry_points_by_type: declare_v3 + .contract_class + .entry_points_by_type + .to_hash_map(), + abi: declare_v3.contract_class.abi, + }, + resource_bounds: declare_v3.resource_bounds.into(), + tip: declare_v3.tip, + signature: declare_v3.signature, + nonce: declare_v3.nonce, + compiled_class_hash: declare_v3.compiled_class_hash, + sender_address: declare_v3.sender_address, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: declare_v3.paymaster_data, + account_deployment_data: declare_v3.account_deployment_data, + version: TransactionVersion::THREE, + r#type: client_transaction::DeclareType::Declare, + })) + } + } + } +} diff --git a/crates/papyrus_rpc/src/v0_6/broadcasted_transaction_test.rs b/crates/papyrus_rpc/src/v0_6/broadcasted_transaction_test.rs new file mode 100644 index 00000000000..726caffbdbe --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/broadcasted_transaction_test.rs @@ -0,0 +1,175 @@ +use std::collections::HashMap; + +use jsonschema::JSONSchema; +use lazy_static::lazy_static; +use starknet_api::core::{CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::deprecated_contract_class::{ + ContractClassAbiEntry as DeprecatedContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointType as DeprecatedEntryPointType, + EventAbiEntry, + FunctionAbiEntry, + StructAbiEntry, +}; +use starknet_api::state::EntryPoint; +use starknet_api::transaction::{ + AccountDeploymentData, + Fee, + PaymasterData, + ResourceBounds, + Tip, + TransactionSignature, +}; +use starknet_client::writer::objects::transaction::DeprecatedContractClass; +use starknet_types_core::felt::Felt; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, get_rng, GetTestInstance}; + +use super::super::state::{ContractClass, EntryPointByType}; +use super::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedDeclareV2Transaction, + BroadcastedDeclareV3Transaction, + DeclareType, + ResourceBoundsMapping, +}; +use crate::test_utils::{get_starknet_spec_api_schema_for_components, SpecFile}; +use crate::version_config::VERSION_0_6 as Version; + +fn validate_tx_fits_rpc(tx: BroadcastedDeclareTransaction) { + lazy_static! { + static ref SCHEMA: JSONSchema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::StarknetApiOpenrpc, &["BROADCASTED_DECLARE_TXN"])], + &Version + ); + } + assert!(SCHEMA.is_valid(&serde_json::to_value(tx).unwrap())); +} + +auto_impl_get_test_instance! { + pub enum BroadcastedDeclareTransaction { + V1(BroadcastedDeclareV1Transaction) = 0, + V2(BroadcastedDeclareV2Transaction) = 1, + V3(BroadcastedDeclareV3Transaction) = 2, + } + pub struct BroadcastedDeclareV1Transaction { + pub r#type: DeclareType, + pub contract_class: DeprecatedContractClass, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + } + pub struct BroadcastedDeclareV2Transaction { + pub r#type: DeclareType, + pub contract_class: ContractClass, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + } + pub struct BroadcastedDeclareV3Transaction { + pub r#type: DeclareType, + pub sender_address: ContractAddress, + pub compiled_class_hash: CompiledClassHash, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + // TODO(yair): Move out the test instances of ContractClass and EntryPointByType. + pub struct ContractClass { + pub sierra_program: Vec, + pub contract_class_version: String, + pub entry_points_by_type: EntryPointByType, + pub abi: String, + } + + pub struct EntryPointByType { + pub constructor: Vec, + pub external: Vec, + pub l1handler: Vec, + } + pub enum DeclareType { + Declare = 0, + } + + pub struct ResourceBoundsMapping { + pub l1_gas: ResourceBounds, + pub l2_gas: ResourceBounds, + } +} + +#[test] +fn declare_v1_fits_rpc() { + let mut rng = get_rng(); + for has_abi in [true, false] { + let abi = if has_abi { + Some(vec![ + DeprecatedContractClassAbiEntry::Event(EventAbiEntry::get_test_instance(&mut rng)), + DeprecatedContractClassAbiEntry::Function(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::Constructor(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::L1Handler(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::Struct(StructAbiEntry::get_test_instance( + &mut rng, + )), + ]) + } else { + None + }; + let tx = BroadcastedDeclareTransaction::V1(BroadcastedDeclareV1Transaction { + contract_class: DeprecatedContractClass { + abi, + entry_points_by_type: HashMap::from([ + ( + DeprecatedEntryPointType::Constructor, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ( + DeprecatedEntryPointType::External, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ( + DeprecatedEntryPointType::L1Handler, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ]), + ..GetTestInstance::get_test_instance(&mut rng) + }, + ..GetTestInstance::get_test_instance(&mut rng) + }); + validate_tx_fits_rpc(tx); + } +} + +#[test] +fn declare_v2_fits_rpc() { + let mut rng = get_rng(); + let tx = BroadcastedDeclareTransaction::V2(BroadcastedDeclareV2Transaction::get_test_instance( + &mut rng, + )); + validate_tx_fits_rpc(tx); +} + +#[test] +fn declare_v3_fits_rpc() { + let mut rng = get_rng(); + let tx = BroadcastedDeclareTransaction::V3(BroadcastedDeclareV3Transaction::get_test_instance( + &mut rng, + )); + + validate_tx_fits_rpc(tx); +} diff --git a/crates/papyrus_rpc/src/v0_6/deprecated_contract_class.rs b/crates/papyrus_rpc/src/v0_6/deprecated_contract_class.rs new file mode 100644 index 00000000000..0625c917b42 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/deprecated_contract_class.rs @@ -0,0 +1,44 @@ +use std::collections::HashMap; + +use papyrus_storage::db::serialization::StorageSerdeError; +use serde::{Deserialize, Serialize}; +use starknet_api::deprecated_contract_class::{ContractClassAbiEntry, EntryPoint, EntryPointType}; + +use crate::compression_utils::compress_and_encode; + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub abi: Vec, + /// A base64 encoding of the gzip-compressed JSON representation of program. + pub program: String, + /// The selector of each entry point is a unique identifier in the program. + pub entry_points_by_type: HashMap>, +} + +impl TryFrom for ContractClass { + type Error = StorageSerdeError; + fn try_from( + class: starknet_api::deprecated_contract_class::ContractClass, + ) -> Result { + let mut program_value = serde_json::to_value(&class.program)?; + // Remove the 'attributes' key if it is null. + if class.program.attributes == serde_json::value::Value::Null { + program_value.as_object_mut().expect("Expecting json object").remove("attributes"); + } + // Remove the 'compiler_version' key if it is null. + if class.program.compiler_version == serde_json::value::Value::Null { + program_value + .as_object_mut() + .expect("Expecting json object") + .remove("compiler_version"); + } + + let abi = class.abi.unwrap_or_default(); + + Ok(Self { + abi, + program: compress_and_encode(program_value)?, + entry_points_by_type: class.entry_points_by_type, + }) + } +} diff --git a/crates/papyrus_rpc/src/v0_6/error.rs b/crates/papyrus_rpc/src/v0_6/error.rs new file mode 100644 index 00000000000..cbc08c77a70 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/error.rs @@ -0,0 +1,132 @@ +use jsonrpsee::types::ErrorObjectOwned; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug)] +pub struct JsonRpcError { + pub code: i32, + pub message: &'static str, + pub data: Option, +} + +// TODO(yair): Remove allow(dead_code) once all errors are used. +#[allow(dead_code)] +pub const FAILED_TO_RECEIVE_TRANSACTION: JsonRpcError = + JsonRpcError { code: 1, message: "Failed to write transaction", data: None }; + +pub const CONTRACT_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 20, message: "Contract not found", data: None }; + +pub const INVALID_TRANSACTION_HASH: JsonRpcError = + JsonRpcError { code: 25, message: "Invalid transaction hash", data: None }; + +// TODO(shahak): Remove allow(dead_code) once all errors are used. +#[allow(dead_code)] +pub const INVALID_BLOCK_HASH: JsonRpcError = + JsonRpcError { code: 26, message: "Invalid block hash", data: None }; + +pub const BLOCK_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 24, message: "Block not found", data: None }; + +pub const INVALID_TRANSACTION_INDEX: JsonRpcError = + JsonRpcError { code: 27, message: "Invalid transaction index in a block", data: None }; + +pub const CLASS_HASH_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 28, message: "Class hash not found", data: None }; + +pub const TRANSACTION_HASH_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 29, message: "Transaction hash not found", data: None }; + +pub const PAGE_SIZE_TOO_BIG: JsonRpcError = + JsonRpcError { code: 31, message: "Requested page size is too big", data: None }; + +pub const NO_BLOCKS: JsonRpcError = + JsonRpcError { code: 32, message: "There are no blocks", data: None }; + +pub const INVALID_CONTINUATION_TOKEN: JsonRpcError = JsonRpcError { + code: 33, + message: "The supplied continuation token is invalid or unknown", + data: None, +}; + +pub const TOO_MANY_KEYS_IN_FILTER: JsonRpcError = + JsonRpcError { code: 34, message: "Too many keys provided in a filter", data: None }; + +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct ContractError { + pub revert_error: String, +} + +impl From for JsonRpcError { + fn from(contract_error: ContractError) -> Self { + Self { code: 40, message: "Contract error", data: Some(contract_error) } + } +} +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct TransactionExecutionError { + pub transaction_index: usize, + pub execution_error: String, +} + +impl From for JsonRpcError { + fn from(tx_execution_error: TransactionExecutionError) -> Self { + Self { code: 41, message: "Transaction execution error", data: Some(tx_execution_error) } + } +} +pub const CLASS_ALREADY_DECLARED: JsonRpcError = + JsonRpcError { code: 51, message: "Class already declared", data: None }; + +pub const INVALID_TRANSACTION_NONCE: JsonRpcError = + JsonRpcError { code: 52, message: "Invalid transaction nonce", data: None }; + +pub const INSUFFICIENT_MAX_FEE: JsonRpcError = JsonRpcError { + code: 53, + message: "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)", + data: None, +}; + +pub const INSUFFICIENT_ACCOUNT_BALANCE: JsonRpcError = JsonRpcError { + code: 54, + message: "Account balance is smaller than the transaction's max_fee", + data: None, +}; + +pub fn validation_failure(data: String) -> JsonRpcError { + JsonRpcError { code: 55, message: "Account validation failed", data: Some(data) } +} + +pub const COMPILATION_FAILED: JsonRpcError = + JsonRpcError { code: 56, message: "Compilation failed", data: None }; + +pub const CONTRACT_CLASS_SIZE_IS_TOO_LARGE: JsonRpcError = + JsonRpcError { code: 57, message: "Contract class size it too large", data: None }; + +pub const NON_ACCOUNT: JsonRpcError = + JsonRpcError { code: 58, message: "Sender address in not an account contract", data: None }; + +pub const DUPLICATE_TX: JsonRpcError = JsonRpcError { + code: 59, + message: "A transaction with the same hash already exists in the mempool", + data: None, +}; + +pub const COMPILED_CLASS_HASH_MISMATCH: JsonRpcError = JsonRpcError { + code: 60, + message: "the compiled class hash did not match the one supplied in the transaction", + data: None, +}; + +pub const UNSUPPORTED_TX_VERSION: JsonRpcError = + JsonRpcError { code: 61, message: "the transaction version is not supported", data: None }; + +pub const UNSUPPORTED_CONTRACT_CLASS_VERSION: JsonRpcError = + JsonRpcError { code: 62, message: "the contract class version is not supported", data: None }; + +pub fn unexpected_error(data: String) -> JsonRpcError { + JsonRpcError { code: 63, message: "An unexpected error occurred", data: Some(data) } +} + +impl From> for ErrorObjectOwned { + fn from(err: JsonRpcError) -> Self { + ErrorObjectOwned::owned(err.code, err.message, err.data) + } +} diff --git a/crates/papyrus_rpc/src/v0_6/execution.rs b/crates/papyrus_rpc/src/v0_6/execution.rs new file mode 100644 index 00000000000..b935855d891 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/execution.rs @@ -0,0 +1,169 @@ +use papyrus_execution::objects::{ + CallType, + FunctionCall, + FunctionInvocation as ExecutionFunctionInvocation, + FunctionInvocationResult as ExecutionFunctionInvocationResult, + OrderedEvent, + OrderedL2ToL1Message, + Retdata, + RevertReason, + TransactionTrace as ExecutionTransactionTrace, +}; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::deprecated_contract_class::EntryPointType; + +use super::transaction::ExecutionResources; + +// The only difference between this and TransactionTrace in the execution crate is the +// ExecutionResources inside FunctionInvocation. +/// The execution trace of a transaction. +#[allow(missing_docs)] +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum TransactionTrace { + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionTrace), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionTrace), + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionTrace), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionTrace), +} + +/// The execution trace of an L1Handler transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct L1HandlerTransactionTrace { + /// The trace of the funcion call. + pub function_invocation: FunctionInvocation, +} + +/// The execution trace of an Invoke transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct InvokeTransactionTrace { + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __validate__ call. + pub validate_invocation: Option, + /// The trace of the __execute__ call or the reason in case of reverted transaction. + pub execute_invocation: FunctionInvocationResult, + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __fee_transfer__ call. + pub fee_transfer_invocation: Option, +} + +/// The execution trace of a Declare transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeclareTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, +} + +/// The execution trace of a DeployAccount transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeployAccountTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __constructor__ call. + pub constructor_invocation: FunctionInvocation, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, +} + +/// Wether the function invocation succeeded or reverted. +// Not using `Result` because it is not being serialized according to the spec. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[allow(missing_docs)] +#[serde(untagged)] +pub enum FunctionInvocationResult { + Ok(FunctionInvocation), + Err(RevertReason), +} + +/// The execution trace of a function call. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct FunctionInvocation { + #[serde(flatten)] + /// The details of the function call. + pub function_call: FunctionCall, + /// The address of the invoking contract. 0 for the root invocation. + pub caller_address: ContractAddress, + /// The hash of the class being called. + pub class_hash: ClassHash, + /// The type of the entry point being called. + pub entry_point_type: EntryPointType, + /// library call or regular call. + pub call_type: CallType, + /// The value returned from the function invocation. + pub result: Retdata, + /// The calls made by this invocation. + pub calls: Vec, + /// The events emitted in this invocation. + pub events: Vec, + /// The messages sent by this invocation to L1. + pub messages: Vec, + /// The VM execution resources used by this invocation. + pub execution_resources: ExecutionResources, +} + +impl From for TransactionTrace { + fn from(value: ExecutionTransactionTrace) -> Self { + match value { + ExecutionTransactionTrace::L1Handler(trace) => { + Self::L1Handler(L1HandlerTransactionTrace { + function_invocation: trace.function_invocation.into(), + }) + } + ExecutionTransactionTrace::Invoke(trace) => { + let execute_invocation = match trace.execute_invocation { + ExecutionFunctionInvocationResult::Ok(function_invocation) => { + FunctionInvocationResult::Ok(function_invocation.into()) + } + ExecutionFunctionInvocationResult::Err(revert_reason) => { + FunctionInvocationResult::Err(revert_reason) + } + }; + + Self::Invoke(InvokeTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + execute_invocation, + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + }) + } + ExecutionTransactionTrace::Declare(trace) => Self::Declare(DeclareTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + }), + ExecutionTransactionTrace::DeployAccount(trace) => { + Self::DeployAccount(DeployAccountTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + constructor_invocation: trace.constructor_invocation.into(), + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + }) + } + } + } +} + +impl From for FunctionInvocation { + fn from(invocation: ExecutionFunctionInvocation) -> Self { + Self { + function_call: invocation.function_call, + caller_address: invocation.caller_address, + class_hash: invocation.class_hash, + entry_point_type: invocation.entry_point_type, + call_type: invocation.call_type, + result: invocation.result, + calls: invocation.calls.into_iter().map(Into::into).collect(), + events: invocation.events, + messages: invocation.messages, + execution_resources: invocation.execution_resources.into(), + } + } +} diff --git a/crates/papyrus_rpc/src/v0_6/execution_test.rs b/crates/papyrus_rpc/src/v0_6/execution_test.rs new file mode 100644 index 00000000000..cfb37c55a85 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/execution_test.rs @@ -0,0 +1,1679 @@ +use std::collections::HashMap; +use std::env; +use std::fs::read_to_string; +use std::path::Path; +use std::sync::Arc; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::indexmap; +use jsonrpsee::core::Error; +use jsonrpsee::RpcModule; +use lazy_static::lazy_static; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses, PendingClassesTrait}; +use papyrus_common::state::{DeclaredClassHashEntry, DeployedContract, StorageEntry}; +use papyrus_execution::execution_utils::selector_from_name; +use papyrus_execution::objects::{ + CallType, + FunctionCall, + OrderedEvent, + OrderedL2ToL1Message, + PriceUnit, + Retdata, + RevertReason, +}; +use papyrus_execution::testing_instances::get_storage_var_address; +use papyrus_execution::ExecutableTransactionInput; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::StorageWriter; +use pretty_assertions::assert_eq; +use starknet_api::block::{ + BlockBody, + BlockHash, + BlockHeader, + BlockNumber, + BlockTimestamp, + GasPrice, + GasPricePerToken, +}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, + PatriciaKey, + SequencerContractAddress, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::deprecated_contract_class::{ + ContractClass as SN_API_DeprecatedContractClass, + EntryPointType, +}; +use starknet_api::hash::StarkHash; +use starknet_api::state::ThinStateDiff; +use starknet_api::transaction::{ + Calldata, + Fee, + L1HandlerTransaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionVersion, +}; +use starknet_api::{calldata, class_hash, contract_address, felt, patricia_key}; +use starknet_client::reader::objects::pending_data::{ + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate, +}; +use starknet_client::reader::objects::state::StateDiff as ClientStateDiff; +use starknet_client::reader::objects::transaction::{ + IntermediateInvokeTransaction as ClientInvokeTransaction, + Transaction as ClientTransaction, + TransactionReceipt as ClientTransactionReceipt, +}; +use starknet_client::reader::PendingData; +use starknet_types_core::felt::Felt; +use test_utils::{ + auto_impl_get_test_instance, + get_number_of_variants, + get_rng, + read_json_file, + GetTestInstance, +}; +use tokio::sync::RwLock; + +use super::api::api_impl::JsonRpcServerImpl; +use super::api::{ + decompress_program, + FeeEstimate, + SimulatedTransaction, + SimulationFlag, + TransactionTraceWithHash, +}; +use super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedTransaction, +}; +use super::error::{TransactionExecutionError, BLOCK_NOT_FOUND, CONTRACT_NOT_FOUND}; +use super::execution::{ + DeclareTransactionTrace, + DeployAccountTransactionTrace, + FunctionInvocation, + FunctionInvocationResult, + InvokeTransactionTrace, + L1HandlerTransactionTrace, + TransactionTrace, +}; +use super::transaction::{ + Builtin, + DeployAccountTransaction, + ExecutionResources, + InvokeTransaction, + InvokeTransactionV1, + MessageFromL1, + TransactionVersion1, +}; +use crate::api::{BlockHashOrNumber, BlockId, CallRequest, Tag}; +use crate::test_utils::{ + call_and_validate_schema_for_result, + call_api_then_assert_and_validate_schema_for_result, + get_starknet_spec_api_schema_for_components, + get_starknet_spec_api_schema_for_method_results, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, + get_test_rpc_server_and_storage_writer, + get_test_rpc_server_and_storage_writer_from_params, + validate_schema, + SpecFile, +}; +use crate::version_config::VERSION_0_6 as VERSION; + +lazy_static! { + pub static ref GAS_PRICE: GasPricePerToken = GasPricePerToken{ + price_in_wei: GasPrice(100 * u128::pow(10, 9)), + price_in_fri: GasPrice(0), + }; + pub static ref MAX_FEE: Fee = Fee(1000000 * GAS_PRICE.price_in_wei.0); + pub static ref BLOCK_TIMESTAMP: BlockTimestamp = BlockTimestamp(1234); + pub static ref SEQUENCER_ADDRESS: SequencerContractAddress = + SequencerContractAddress(contract_address!("0xa")); + pub static ref DEPRECATED_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1"); + pub static ref CONTRACT_ADDRESS: ContractAddress = contract_address!("0x2"); + pub static ref ACCOUNT_CLASS_HASH: ClassHash = class_hash!("0x333"); + pub static ref ACCOUNT_ADDRESS: ContractAddress = contract_address!("0x444"); + pub static ref TEST_ERC20_CONTRACT_CLASS_HASH: ClassHash = class_hash!("0x1010"); + pub static ref TEST_ERC20_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1001"); + pub static ref ACCOUNT_INITIAL_BALANCE: Felt = felt!(2 * MAX_FEE.0); + // TODO(yair): verify this is the correct fee, got this value by printing the result of the + // call. + pub static ref EXPECTED_FEE_ESTIMATE: FeeEstimate = FeeEstimate { + gas_consumed: felt!("0x680"), + gas_price: GAS_PRICE.price_in_wei, + overall_fee: Fee(166400000000000,), + unit: PriceUnit::Wei, + }; + + pub static ref EXPECTED_FEE_ESTIMATE_SKIP_VALIDATE: FeeEstimate = FeeEstimate { + gas_consumed: felt!("0x680"), + gas_price: GAS_PRICE.price_in_wei, + overall_fee: Fee(166400000000000,), + unit: PriceUnit::Wei, + }; + + // A message from L1 contract at address 0x987 to the contract at CONTRACT_ADDRESS that calls + // the entry point "l1_handle" with the value 0x123, the retdata should be 0x123. + pub static ref MESSAGE_FROM_L1: MessageFromL1 = MessageFromL1 { + from_address: EthAddress::try_from(felt!( + "0x987" + )) + .unwrap(), + to_address: *CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("l1_handle"), + payload: calldata![ + felt!("0x123") + ], + }; +} + +#[tokio::test] +async fn execution_call() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let key = felt!(1234_u16); + let value = felt!(18_u8); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_6_call", + vec![ + Box::new(CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("test_storage_read_write"), + calldata: calldata![key, value], + }), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &vec![value], + ) + .await; + + // Calling a non-existent contract. + let err = module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { + contract_address: ContractAddress(patricia_key!("0x1234")), + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap_err(); + + assert_matches!(err, Error::Call(err) if err == CONTRACT_NOT_FOUND.into()); + + // Calling a non-existent block. + let err = module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { + contract_address: ContractAddress(patricia_key!("0x1234")), + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(7))), + ), + ) + .await + .unwrap_err(); + + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Calling a non-existent function (contract error). + let err = module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap_err(); + + const CONTRACT_ERROR_CODE: i32 = 40; + assert_matches!(err, Error::Call(err) if err.code() == CONTRACT_ERROR_CODE); + + // Test that the block context is passed correctly to blockifier. + let mut calldata = get_calldata_for_test_execution_info( + BlockNumber(0), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &InvokeTransactionV1::default(), + TransactionHash(StarkHash::ZERO), + Some(Felt::ZERO), + ); + // Calling the contract directly and not through the account contract. + let contract_address = ContractAddress( + PatriciaKey::try_from(Arc::get_mut(&mut calldata.0).unwrap().remove(0)).unwrap(), + ); + let entry_point_selector = EntryPointSelector(Arc::get_mut(&mut calldata.0).unwrap().remove(0)); + let _calldata_length = Arc::get_mut(&mut calldata.0).unwrap().remove(0); + + module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { contract_address, entry_point_selector, calldata }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap(); +} + +#[tokio::test] +async fn pending_execution_call() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + let key = felt!(1234_u16); + let value = felt!(18_u8); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("test_storage_read_write"), + calldata: calldata![key, value], + }, + BlockId::Tag(Tag::Pending), + ), + ) + .await + .unwrap(); + + assert_eq!(res, vec![value]); + + // Test that the block context is passed correctly to blockifier with a block number that is + // after the latest block in the storage. + let mut calldata = get_calldata_for_test_execution_info( + BlockNumber(1), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &InvokeTransactionV1::default(), + TransactionHash(StarkHash::ZERO), + Some(Felt::ZERO), + ); + // Calling the contract directly and not through the account contract. + let contract_address = ContractAddress( + PatriciaKey::try_from(Arc::get_mut(&mut calldata.0).unwrap().remove(0)).unwrap(), + ); + let entry_point_selector = EntryPointSelector(Arc::get_mut(&mut calldata.0).unwrap().remove(0)); + let _calldata_length = Arc::get_mut(&mut calldata.0).unwrap().remove(0); + + module + .call::<_, Vec>( + "starknet_V0_6_call", + ( + CallRequest { contract_address, entry_point_selector, calldata }, + BlockId::Tag(Tag::Pending), + ), + ) + .await + .unwrap(); +} + +#[tokio::test] +async fn call_estimate_fee() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let account_address = ContractAddress(patricia_key!("0x444")); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_6_estimateFee", + vec![ + Box::new(vec![invoke.clone()]), + Box::>::default(), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &vec![EXPECTED_FEE_ESTIMATE.clone()], + ) + .await; + + // Test that calling the same transaction with a different block context with a different gas + // price produces a different fee. + let res = module + .call::<_, Vec>( + "starknet_V0_6_estimateFee", + ( + vec![invoke.clone()], + Vec::::new(), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), + ), + ) + .await + .unwrap(); + assert_ne!(res, vec![EXPECTED_FEE_ESTIMATE.clone()]); + + // Test that calling the same transaction with skip_validate produces a lower gas consumed. + // TODO(yair): test with an account contract which has a lengthy validate function. + let res = module + .call::<_, Vec>( + "starknet_V0_6_estimateFee", + ( + vec![invoke], + Vec::::from([SimulationFlag::SkipValidate]), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap(); + assert!(res.first().unwrap().gas_consumed <= EXPECTED_FEE_ESTIMATE.gas_consumed); + + // Test that reverted transaction fails the fee estimation. + let non_existent_entry_point = + BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("non_existent_ep").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + let res = module + .call::<_, Vec>( + "starknet_V0_6_estimateFee", + ( + vec![non_existent_entry_point], + Vec::::new(), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .expect_err("Expecting error"); + let Error::Call(err) = res else { + panic!("Expecting error"); + }; + assert_eq!(err.code(), 41); + let Some(data) = err.data() else { + panic!("Expecting error data"); + }; + let tx_execution_error: TransactionExecutionError = serde_json::from_str(data.get()).unwrap(); + assert_eq!(tx_execution_error.transaction_index, 0); + + // TODO(shahak): Write a new contract and test execution info. The reason we can't do this with + // the current contract is that the transaction hash appears in the calldata and thus it is + // calculated inside the hash. +} + +#[tokio::test] +async fn pending_call_estimate_fee() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + let account_address = ContractAddress(patricia_key!("0x444")); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_estimateFee", + (vec![invoke.clone()], Vec::::new(), BlockId::Tag(Tag::Pending)), + ) + .await + .unwrap(); + assert_eq!(res, vec![EXPECTED_FEE_ESTIMATE.clone()]); + + // TODO(shahak): Write a new contract and test execution info. The reason we can't do this with + // the current contract is that the transaction hash appears in the calldata and thus it is + // calculated inside the hash. +} + +#[tokio::test] +async fn call_simulate() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + test_call_simulate( + &module, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + BlockNumber(0), + ) + .await; +} + +#[tokio::test] +async fn pending_call_simulate() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + test_call_simulate(&module, BlockId::Tag(Tag::Pending), BlockNumber(1)).await; +} + +// Test call_simulate. Assumes that the given block is equal to block number 0 that is returned +// from the function `prepare_storage_for_execution`. +async fn test_call_simulate( + module: &RpcModule, + block_id: BlockId, + block_context_number: BlockNumber, +) { + let mut invoke_v1 = InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + }; + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(invoke_v1.clone())); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + module, + "starknet_V0_6_simulateTransactions", + vec![Box::new(block_id), Box::new(vec![invoke]), Box::>::default()], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, Some(_)); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, Some(_)); + + // Test that the block context is passed correctly to blockifier. + let calldata = get_calldata_for_test_execution_info( + block_context_number, + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &invoke_v1, + // Because the transaction hash depends on the calldata and the calldata needs to contain + // the transaction hash, there's no way to put the correct hash here. Instead, we'll check + // that the function `test_get_execution_info` fails on the transaction hash validation. + TransactionHash(StarkHash::ZERO), + None, + ); + invoke_v1.calldata = calldata; + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(invoke_v1)); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_simulateTransactions", + (block_id, vec![invoke], Vec::::new()), + ) + .await + .unwrap(); + + let TransactionTrace::Invoke(invoke_trace) = &res[0].transaction_trace else { + panic!("Got a non-invoke transaction trace from an invoke transaction."); + }; + // As described above, we want to check that `test_get_execution_info` fails on the transaction + // hash validation (which is done after the block context validation). + let FunctionInvocationResult::Err(RevertReason::RevertReason(error_str)) = + &invoke_trace.execute_invocation + else { + panic!("Expected call to test_get_execution_info to fail."); + }; + assert!(error_str.contains("TX_INFO_MISMATCH")); +} + +#[tokio::test] +async fn call_simulate_skip_validate() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_6_simulateTransactions", + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + Box::new(vec![invoke]), + Box::new(vec![SimulationFlag::SkipValidate]), + ], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE_SKIP_VALIDATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, None); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, Some(_)); +} + +#[tokio::test] +async fn call_simulate_skip_fee_charge() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_6_simulateTransactions", + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + Box::new(vec![invoke]), + Box::new(vec![SimulationFlag::SkipFeeCharge]), + ], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, Some(_)); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, None); +} + +// TODO(shahak): Add test for trace_transaction that doesn't depend on trace_block_transactions +#[tokio::test] +async fn trace_block_transactions_regular_and_pending() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + let mut writer = prepare_storage_for_execution(storage_writer); + + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let client_tx1 = ClientTransaction::Invoke(ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + nonce: Some(Nonce(felt!(0_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }); + let tx1: starknet_api::transaction::Transaction = client_tx1.clone().try_into().unwrap(); + let client_tx2 = ClientTransaction::Invoke(ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + nonce: Some(Nonce(felt!(1_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }); + let tx2: starknet_api::transaction::Transaction = client_tx2.clone().try_into().unwrap(); + + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(2), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x2")), + parent_hash: BlockHash(felt!("0x1")), + ..Default::default() + }, + ) + .unwrap() + .append_body( + BlockNumber(2), + BlockBody { + transactions: vec![tx1, tx2], + transaction_outputs: vec![ + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + ], + transaction_hashes: vec![tx_hash1, tx_hash2], + }, + ) + .unwrap() + .append_state_diff( + BlockNumber(2), + ThinStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + ) + .unwrap() + .append_classes(BlockNumber(2), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + let tx_1_trace = call_and_validate_schema_for_result::<_, TransactionTrace>( + &module, + "starknet_V0_6_traceTransaction", + vec![Box::new(tx_hash1)], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_matches!(tx_1_trace, TransactionTrace::Invoke(_)); + + let tx_2_trace = module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash2]) + .await + .unwrap(); + + assert_matches!(tx_2_trace, TransactionTrace::Invoke(_)); + + let res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_6_traceBlockTransactions", + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))))], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 2); + assert_eq!(res[0].trace_root, tx_1_trace); + assert_eq!(res[0].transaction_hash, tx_hash1); + assert_eq!(res[1].trace_root, tx_2_trace); + assert_eq!(res[1].transaction_hash, tx_hash2); + + // Ask for trace of pending block. + // Create a new storage without the last block and put the last block as pending + + let pending_data = get_test_pending_data(); + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + eth_l1_gas_price: GAS_PRICE.price_in_wei, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + parent_block_hash: BlockHash(felt!("0x1")), + transactions: vec![client_tx1, client_tx2], + transaction_receipts: vec![ + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash1, + ..Default::default() + }, + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash2, + ..Default::default() + }, + ], + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + }, + }; + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data), None, None); + + prepare_storage_for_execution(storage_writer); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_traceBlockTransactions", + [BlockId::Tag(Tag::Pending)], + ) + .await + .unwrap(); + + assert_eq!(res.len(), 2); + assert_eq!(res[0].trace_root, tx_1_trace); + assert_eq!(res[0].transaction_hash, tx_hash1); + assert_eq!(res[1].trace_root, tx_2_trace); + assert_eq!(res[1].transaction_hash, tx_hash2); + + // Ask for trace of transactions in the pending block. + let pending_tx_1_trace = module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash1]) + .await + .unwrap(); + assert_eq!(pending_tx_1_trace, tx_1_trace); + let pending_tx_2_trace = module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash2]) + .await + .unwrap(); + assert_eq!(pending_tx_2_trace, tx_2_trace); +} + +#[tokio::test] +async fn trace_block_transactions_and_trace_transaction_execution_context() { + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let mut invoke_tx1 = starknet_api::transaction::InvokeTransactionV1 { + max_fee: *MAX_FEE, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Nonce(felt!(0_u128)), + ..Default::default() + }; + let mut invoke_tx2 = starknet_api::transaction::InvokeTransactionV1 { + max_fee: *MAX_FEE, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Nonce(felt!(1_u128)), + ..Default::default() + }; + + let fix_calldata_of_invoke_tx = + |invoke_tx: &mut starknet_api::transaction::InvokeTransactionV1, tx_hash| { + let tx: super::transaction::Transaction = + starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx.clone()), + ) + .try_into() + .unwrap(); + let super::transaction::Transaction::Invoke(InvokeTransaction::Version1(rpc_invoke_v1)) = + tx + else { + panic!( + "Converting an InvokeV1 client transaction to a starknet api transaction did \ + not yield an InvokeV1 transaction" + ); + }; + invoke_tx.calldata = get_calldata_for_test_execution_info( + BlockNumber(2), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &rpc_invoke_v1, + tx_hash, + None, + ); + }; + fix_calldata_of_invoke_tx(&mut invoke_tx1, tx_hash1); + fix_calldata_of_invoke_tx(&mut invoke_tx2, tx_hash2); + let tx1 = starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx1), + ); + let tx2 = starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx2), + ); + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + let mut writer = prepare_storage_for_execution(storage_writer); + + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(2), + &BlockHeader { + block_number: BlockNumber(2), + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x2")), + parent_hash: BlockHash(felt!("0x1")), + ..Default::default() + }, + ) + .unwrap() + .append_body( + BlockNumber(2), + BlockBody { + transactions: vec![tx1, tx2], + transaction_outputs: vec![ + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + ], + transaction_hashes: vec![tx_hash1, tx_hash2], + }, + ) + .unwrap() + .append_state_diff( + BlockNumber(2), + ThinStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + ) + .unwrap() + .append_classes(BlockNumber(2), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + let validate_result = |res| { + assert_matches!( + &res, + TransactionTrace::Invoke(invoke_trace) + if matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)) + ); + }; + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash1]) + .await + .unwrap(), + ); + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash2]) + .await + .unwrap(), + ); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_traceBlockTransactions", + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2)))], + ) + .await + .unwrap(); + validate_result(res[0].trace_root.clone()); + validate_result(res[1].trace_root.clone()); +} + +#[tokio::test] +async fn pending_trace_block_transactions_and_trace_transaction_execution_context() { + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let mut client_invoke_tx1 = ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Some(Nonce(felt!(0_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }; + let mut client_invoke_tx2 = ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Some(Nonce(felt!(1_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }; + + let fix_calldata_of_client_invoke_tx = |client_invoke_tx: &mut ClientInvokeTransaction, + tx_hash| { + let starknet_api_tx: starknet_api::transaction::Transaction = + ClientTransaction::Invoke(client_invoke_tx.clone()).try_into().unwrap(); + let tx: super::transaction::Transaction = starknet_api_tx.try_into().unwrap(); + let super::transaction::Transaction::Invoke(InvokeTransaction::Version1(invoke_v1)) = tx + else { + panic!( + "Converting an InvokeV1 client transaction to a starknet api transaction did not \ + yield an InvokeV1 transaction" + ); + }; + client_invoke_tx.calldata = get_calldata_for_test_execution_info( + BlockNumber(2), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &invoke_v1, + tx_hash, + None, + ); + }; + fix_calldata_of_client_invoke_tx(&mut client_invoke_tx1, tx_hash1); + fix_calldata_of_client_invoke_tx(&mut client_invoke_tx2, tx_hash2); + let client_tx1 = ClientTransaction::Invoke(client_invoke_tx1); + let client_tx2 = ClientTransaction::Invoke(client_invoke_tx2); + + let pending_data = get_test_pending_data(); + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + eth_l1_gas_price: GAS_PRICE.price_in_wei, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + parent_block_hash: BlockHash(felt!("0x1")), + transactions: vec![client_tx1, client_tx2], + transaction_receipts: vec![ + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash1, + ..Default::default() + }, + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash2, + ..Default::default() + }, + ], + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + }, + }; + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data), None, None); + + prepare_storage_for_execution(storage_writer); + + let validate_result = |res| { + assert_matches!( + &res, + TransactionTrace::Invoke(invoke_trace) + if matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)) + ); + }; + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash1]) + .await + .unwrap(), + ); + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_6_traceTransaction", [tx_hash2]) + .await + .unwrap(), + ); + + let res = module + .call::<_, Vec>( + "starknet_V0_6_traceBlockTransactions", + [BlockId::Tag(Tag::Pending)], + ) + .await + .unwrap(); + validate_result(res[0].trace_root.clone()); + validate_result(res[1].trace_root.clone()); +} + +#[test] +fn message_from_l1_to_l1_handler_tx() { + let l1_handler_tx = L1HandlerTransaction::from(MESSAGE_FROM_L1.clone()); + assert_eq!(l1_handler_tx.version, TransactionVersion::ONE); + assert_eq!(l1_handler_tx.contract_address, *CONTRACT_ADDRESS); + assert_eq!(l1_handler_tx.entry_point_selector, selector_from_name("l1_handle")); + // The first item of calldata is the from_address. + let from_address = EthAddress::try_from(*l1_handler_tx.calldata.0.first().unwrap()).unwrap(); + assert_eq!(from_address, MESSAGE_FROM_L1.from_address); + let rest_of_calldata = &l1_handler_tx.calldata.0[1..]; + assert_eq!(rest_of_calldata, MESSAGE_FROM_L1.payload.0.as_slice()); +} + +#[tokio::test] +async fn call_estimate_message_fee() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + prepare_storage_for_execution(storage_writer); + + // TODO(yair): get a l1_handler entry point that actually does something and check that the fee + // is correct. + let expected_fee_estimate = FeeEstimate { + gas_consumed: felt!("0x0"), + gas_price: GAS_PRICE.price_in_wei, + overall_fee: Fee(0), + unit: PriceUnit::default(), + }; + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_6_estimateMessageFee", + vec![ + Box::new(MESSAGE_FROM_L1.clone()), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_fee_estimate, + ) + .await; +} + +#[test] +fn broadcasted_to_executable_declare_v1() { + let mut rng = get_rng(); + let mut tx = BroadcastedDeclareV1Transaction::get_test_instance(&mut rng); + tx.contract_class.compressed_program = get_test_compressed_program(); + let broadcasted_declare_v1 = + BroadcastedTransaction::Declare(BroadcastedDeclareTransaction::V1(tx)); + assert_matches!( + broadcasted_declare_v1.try_into(), + Ok(ExecutableTransactionInput::DeclareV1(_tx, _class, _abi_length, _only_query)) + ); +} + +#[test] +fn validate_fee_estimation_schema() { + let mut rng = get_rng(); + let fee_estimate = FeeEstimate::get_test_instance(&mut rng); + let schema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::StarknetApiOpenrpc, &["FEE_ESTIMATE"])], + &VERSION, + ); + let serialized = serde_json::to_value(fee_estimate).unwrap(); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn validate_transaction_trace_with_hash_schema() { + let mut rng = get_rng(); + let txs_with_trace = Vec::::get_test_instance(&mut rng); + let serialized = serde_json::to_value(txs_with_trace).unwrap(); + let schema = get_starknet_spec_api_schema_for_method_results( + &[(SpecFile::TraceApi, &["starknet_traceBlockTransactions"])], + &VERSION, + ); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn validate_transaction_trace_schema() { + let mut rng = get_rng(); + let schema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::TraceApi, &["TRANSACTION_TRACE"])], + &VERSION, + ); + + let invoke_trace = + TransactionTrace::Invoke(InvokeTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(invoke_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let declare_trace = + TransactionTrace::Declare(DeclareTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(declare_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let deploy_account_trace = + TransactionTrace::DeployAccount(DeployAccountTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(deploy_account_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let l1_handler_trace = + TransactionTrace::L1Handler(L1HandlerTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(l1_handler_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn broadcasted_to_executable_deploy_account() { + let mut rng = get_rng(); + let broadcasted_deploy_account = BroadcastedTransaction::DeployAccount( + DeployAccountTransaction::get_test_instance(&mut rng), + ); + assert_matches!( + broadcasted_deploy_account.try_into(), + Ok(ExecutableTransactionInput::DeployAccount(_tx, _only_query)) + ); +} + +#[test] +fn broadcasted_to_executable_invoke() { + let mut rng = get_rng(); + let broadcasted_deploy_account = + BroadcastedTransaction::Invoke(InvokeTransaction::get_test_instance(&mut rng)); + assert_matches!( + broadcasted_deploy_account.try_into(), + Ok(ExecutableTransactionInput::Invoke(_tx, _only_query)) + ); +} + +#[test] +fn get_decompressed_program() { + let compressed = get_test_compressed_program(); + let decompressed = decompress_program(&compressed); + decompressed.expect("Couldn't decompress program"); +} + +fn get_test_compressed_program() -> String { + let path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("resources") + .join("base64_compressed_program.txt"); + read_to_string(path).expect("Couldn't read compressed program") +} + +auto_impl_get_test_instance! { + pub enum TransactionTrace { + L1Handler(L1HandlerTransactionTrace) = 0, + Invoke(InvokeTransactionTrace) = 1, + Declare(DeclareTransactionTrace) = 2, + DeployAccount(DeployAccountTransactionTrace) = 3, + } + + pub struct L1HandlerTransactionTrace { + pub function_invocation: FunctionInvocation, + } + + pub struct InvokeTransactionTrace { + pub validate_invocation: Option, + pub execute_invocation: FunctionInvocationResult, + pub fee_transfer_invocation: Option, + } + + pub struct DeclareTransactionTrace { + pub validate_invocation: Option, + pub fee_transfer_invocation: Option, + } + + pub struct DeployAccountTransactionTrace { + pub validate_invocation: Option, + pub constructor_invocation: FunctionInvocation, + pub fee_transfer_invocation: Option, + } + + pub enum FunctionInvocationResult { + Ok(FunctionInvocation) = 0, + Err(RevertReason) = 1, + } + + pub struct ExecutionResources { + pub steps: u64, + pub builtin_instance_counter: HashMap, + pub memory_holes: Option, + } + + pub enum Builtin { + RangeCheck = 0, + Pedersen = 1, + Poseidon = 2, + EcOp = 3, + Ecdsa = 4, + Bitwise = 5, + Keccak = 6, + SegmentArena = 7, + } + + pub struct FeeEstimate { + pub gas_consumed: Felt, + pub gas_price: GasPrice, + pub overall_fee: Fee, + pub unit: PriceUnit, + } + + pub struct TransactionTraceWithHash { + pub transaction_hash: TransactionHash, + pub trace_root: TransactionTrace, + } +} + +impl GetTestInstance for FunctionInvocation { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self { + function_call: FunctionCall::get_test_instance(rng), + caller_address: ContractAddress::get_test_instance(rng), + class_hash: ClassHash::get_test_instance(rng), + entry_point_type: EntryPointType::get_test_instance(rng), + call_type: CallType::get_test_instance(rng), + result: Retdata::get_test_instance(rng), + // TODO(shahak): fill with non empty value. + calls: Vec::new(), + events: Vec::::get_test_instance(rng), + messages: Vec::::get_test_instance(rng), + execution_resources: ExecutionResources::get_test_instance(rng), + } + } +} + +/// Get calldata for invoking the function `test_execution_info` in the contract located in +/// `casm.json`. The function `test_execution_info` receives the expected block context and +/// transaction context and validates first the block context and then the transaction context. The +/// returned calldata will also contain the contract address, entry point selector and calldata +/// length so that it can be used from an account contract. If you want to call the function +/// directly, remove the first 3 arguments of the calldata. +fn get_calldata_for_test_execution_info( + expected_block_number: BlockNumber, + expected_block_timestamp: BlockTimestamp, + expected_sequencer_address: SequencerContractAddress, + invoke_tx: &InvokeTransactionV1, + tx_hash: TransactionHash, + override_tx_version: Option, +) -> Calldata { + let entry_point_selector = selector_from_name("test_get_execution_info"); + let expected_block_number = felt!(expected_block_number.0); + let expected_block_timestamp = felt!(expected_block_timestamp.0); + let expected_sequencer_address = *(expected_sequencer_address.0.0.key()); + let expected_caller_address = *(invoke_tx.sender_address.0.key()); + let expected_contract_address = *CONTRACT_ADDRESS.0.key(); + let expected_transaction_version = override_tx_version.unwrap_or(Felt::ONE); + let expected_signature = invoke_tx.signature.0.clone(); + let expected_transaction_hash = tx_hash.0; + let expected_chain_id = felt!(&*(get_test_rpc_config().chain_id.as_hex())); + let expected_nonce = invoke_tx.nonce.0; + let expected_max_fee = felt!(invoke_tx.max_fee.0); + let expected_resource_bounds_length = Felt::ZERO; + let expected_tip = Felt::ZERO; + let expected_paymaster_data = Felt::ZERO; + let expected_nonce_da = Felt::ZERO; + let expected_fee_da = Felt::ZERO; + let expected_account_data = Felt::ZERO; + + let calldata = [ + vec![ + expected_block_number, + expected_block_timestamp, + expected_sequencer_address, + expected_transaction_version, + expected_caller_address, + expected_max_fee, + felt!(expected_signature.len() as u64), + ], + expected_signature, + vec![ + expected_transaction_hash, + expected_chain_id, + expected_nonce, + expected_resource_bounds_length, + expected_tip, + expected_paymaster_data, + expected_nonce_da, + expected_fee_da, + expected_account_data, + expected_caller_address, + expected_contract_address, + entry_point_selector.0, + ], + ] + .iter() + .flatten() + .cloned() + .collect::>(); + + Calldata(Arc::new( + [ + vec![*CONTRACT_ADDRESS.0.key(), entry_point_selector.0, felt!(calldata.len() as u64)], + calldata, + ] + .iter() + .flatten() + .cloned() + .collect::>(), + )) +} + +// Write into the pending block the first block that the function `prepare_storage_for_execution` +// writes to the storage. +async fn write_block_0_as_pending( + pending_data: Arc>, + pending_classes: Arc>, +) { + let class1 = serde_json::from_value::(read_json_file( + "deprecated_class.json", + )) + .unwrap(); + let class_hash1 = class_hash!("0x1"); + + let class2 = starknet_api::state::ContractClass::default(); + let casm = serde_json::from_value::(read_json_file("casm.json")).unwrap(); + let class_hash2 = class_hash!("0x2"); + let compiled_class_hash = CompiledClassHash(StarkHash::default()); + + let account_class = serde_json::from_value(read_json_file("account_class.json")).unwrap(); + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + + let fee_contract_class = serde_json::from_value::( + read_json_file("erc20_fee_contract_class.json"), + ) + .unwrap(); + let minter_var_address = get_storage_var_address("permitted_minter", &[]); + + let mut pending_classes_ref = pending_classes.write().await; + pending_classes_ref.add_class(class_hash2, ApiContractClass::ContractClass(class2)); + pending_classes_ref.add_compiled_class(class_hash2, casm); + pending_classes_ref.add_class(class_hash1, ApiContractClass::DeprecatedContractClass(class1)); + pending_classes_ref + .add_class(*ACCOUNT_CLASS_HASH, ApiContractClass::DeprecatedContractClass(account_class)); + pending_classes_ref.add_class( + *TEST_ERC20_CONTRACT_CLASS_HASH, + ApiContractClass::DeprecatedContractClass(fee_contract_class), + ); + + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + eth_l1_gas_price: GAS_PRICE.price_in_wei, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + deployed_contracts: vec![ + DeployedContract { + address: *DEPRECATED_CONTRACT_ADDRESS, + class_hash: class_hash1, + }, + DeployedContract { address: *CONTRACT_ADDRESS, class_hash: class_hash2 }, + DeployedContract { address: *ACCOUNT_ADDRESS, class_hash: *ACCOUNT_CLASS_HASH }, + DeployedContract { + address: *TEST_ERC20_CONTRACT_ADDRESS, + class_hash: *TEST_ERC20_CONTRACT_CLASS_HASH, + }, + ], + storage_diffs: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => vec![ + // Give the accounts some balance. + StorageEntry { + key: account_balance_key, value: *ACCOUNT_INITIAL_BALANCE + }, + // Give the first account mint permission (what is this?). + StorageEntry { + key: minter_var_address, value: *ACCOUNT_ADDRESS.0.key() + }, + ], + ), + declared_classes: vec![DeclaredClassHashEntry { + class_hash: class_hash2, + compiled_class_hash, + }], + old_declared_contracts: vec![ + class_hash1, + *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_CLASS_HASH, + ], + nonces: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => Nonce::default(), + *CONTRACT_ADDRESS => Nonce::default(), + *DEPRECATED_CONTRACT_ADDRESS => Nonce::default(), + *ACCOUNT_ADDRESS => Nonce::default(), + ), + replaced_classes: vec![], + }, + }, + } +} + +fn prepare_storage_for_execution(mut storage_writer: StorageWriter) -> StorageWriter { + let class1 = serde_json::from_value::(read_json_file( + "deprecated_class.json", + )) + .unwrap(); + let class_hash1 = class_hash!("0x1"); + + let class2 = starknet_api::state::ContractClass::default(); + let casm = serde_json::from_value::(read_json_file("casm.json")).unwrap(); + let class_hash2 = class_hash!("0x2"); + let compiled_class_hash = CompiledClassHash(StarkHash::default()); + + let account_class = serde_json::from_value(read_json_file("account_class.json")).unwrap(); + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + + let fee_contract_class = serde_json::from_value::( + read_json_file("erc20_fee_contract_class.json"), + ) + .unwrap(); + let minter_var_address = get_storage_var_address("permitted_minter", &[]); + + let different_gas_price = GasPricePerToken { + price_in_wei: GasPrice(GAS_PRICE.price_in_wei.0 + 100), + price_in_fri: GasPrice(0), + }; + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + // Test that l1_da_mode is ignored by changing its value + l1_da_mode: L1DataAvailabilityMode::Blob, + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff( + BlockNumber(0), + ThinStateDiff { + deployed_contracts: indexmap!( + *DEPRECATED_CONTRACT_ADDRESS => class_hash1, + *CONTRACT_ADDRESS => class_hash2, + *ACCOUNT_ADDRESS => *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_ADDRESS => *TEST_ERC20_CONTRACT_CLASS_HASH, + ), + storage_diffs: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!( + // Give the accounts some balance. + account_balance_key => *ACCOUNT_INITIAL_BALANCE, + // Give the first account mint permission (what is this?). + minter_var_address => *ACCOUNT_ADDRESS.0.key() + ), + ), + declared_classes: indexmap!(class_hash2 => compiled_class_hash), + deprecated_declared_classes: vec![ + class_hash1, + *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_CLASS_HASH, + ], + nonces: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => Nonce::default(), + *CONTRACT_ADDRESS => Nonce::default(), + *DEPRECATED_CONTRACT_ADDRESS => Nonce::default(), + *ACCOUNT_ADDRESS => Nonce::default(), + ), + replaced_classes: indexmap!(), + }, + ) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash2, &class2)], + &[ + (class_hash1, &class1), + (*ACCOUNT_CLASS_HASH, &account_class), + (*TEST_ERC20_CONTRACT_CLASS_HASH, &fee_contract_class), + ], + ) + .unwrap() + .append_casm(&class_hash2, &casm) + .unwrap() + .append_header( + BlockNumber(1), + &BlockHeader { + l1_gas_price: different_gas_price, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(1), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(1), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(1), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + storage_writer +} + +fn write_empty_block(mut storage_writer: StorageWriter) { + storage_writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(0), &[], &[]) + .unwrap() + .commit() + .unwrap(); +} diff --git a/crates/papyrus_rpc/src/v0_6/mod.rs b/crates/papyrus_rpc/src/v0_6/mod.rs new file mode 100644 index 00000000000..52fbcd50e87 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/mod.rs @@ -0,0 +1,12 @@ +pub mod api; +pub mod block; +pub mod broadcasted_transaction; +pub mod deprecated_contract_class; +pub mod error; +pub mod execution; +#[cfg(test)] +mod execution_test; +pub mod state; +pub mod transaction; +pub mod write_api_error; +pub mod write_api_result; diff --git a/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap new file mode 100644 index 00000000000..bbfa45815e1 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap @@ -0,0 +1,164 @@ +--- +source: crates/papyrus_rpc/src/v0_6/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_declare_error) +--- +{ + "51": [ + { + "code": { + "$serde_json::private::Number": "51" + }, + "message": "Class already declared" + }, + { + "code": "StarknetErrorCode.CLASS_ALREADY_DECLARED", + "message": "message" + } + ], + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "56": [ + { + "code": { + "$serde_json::private::Number": "56" + }, + "message": "Compilation failed" + }, + { + "code": "StarknetErrorCode.COMPILATION_FAILED", + "message": "message" + } + ], + "57": [ + { + "code": { + "$serde_json::private::Number": "57" + }, + "message": "Contract class size it too large" + }, + { + "code": "StarknetErrorCode.CONTRACT_CLASS_OBJECT_SIZE_TOO_LARGE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "60": [ + { + "code": { + "$serde_json::private::Number": "60" + }, + "message": "the compiled class hash did not match the one supplied in the transaction" + }, + { + "code": "StarknetErrorCode.INVALID_COMPILED_CLASS_HASH", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "62": [ + { + "code": { + "$serde_json::private::Number": "62" + }, + "message": "the contract class version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_CONTRACT_CLASS_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap new file mode 100644 index 00000000000..205403a892b --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap @@ -0,0 +1,116 @@ +--- +source: crates/papyrus_rpc/src/v0_6/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_deploy_account_error) +--- +{ + "28": [ + { + "code": { + "$serde_json::private::Number": "28" + }, + "message": "Class hash not found" + }, + { + "code": "StarknetErrorCode.UNDECLARED_CLASS", + "message": "message" + } + ], + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap new file mode 100644 index 00000000000..f6cdf5383b0 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/snapshots/papyrus_rpc__v0_6__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap @@ -0,0 +1,104 @@ +--- +source: crates/papyrus_rpc/src/v0_6/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_invoke_error) +--- +{ + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_6/state.rs b/crates/papyrus_rpc/src/v0_6/state.rs new file mode 100644 index 00000000000..8f687f803b0 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/state.rs @@ -0,0 +1,224 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockHash; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, GlobalRoot, Nonce}; +use starknet_api::state::{ + EntryPoint, + EntryPointType, + StorageKey, + ThinStateDiff as starknet_api_ThinStateDiff, +}; +use starknet_client::reader::objects::state::{ + DeclaredClassHashEntry as ClientDeclaredClassHashEntry, + DeployedContract as ClientDeployedContract, + ReplacedClass as ClientReplacedClass, + StateDiff as ClientStateDiff, + StorageEntry as ClientStorageEntry, +}; +use starknet_types_core::felt::Felt; + +const CONTRACT_CLASS_VERSION: &str = "0.1.0"; + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(untagged)] +pub enum StateUpdate { + AcceptedStateUpdate(AcceptedStateUpdate), + PendingStateUpdate(PendingStateUpdate), +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct AcceptedStateUpdate { + pub block_hash: BlockHash, + pub new_root: GlobalRoot, + pub old_root: GlobalRoot, + pub state_diff: ThinStateDiff, +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct PendingStateUpdate { + pub old_root: GlobalRoot, + pub state_diff: ThinStateDiff, +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct ThinStateDiff { + pub deployed_contracts: Vec, + pub storage_diffs: Vec, + pub declared_classes: Vec, + pub deprecated_declared_classes: Vec, + pub nonces: Vec, + pub replaced_classes: Vec, +} + +impl From for ThinStateDiff { + fn from(diff: starknet_api_ThinStateDiff) -> Self { + Self { + deployed_contracts: Vec::from_iter( + diff.deployed_contracts + .into_iter() + .map(|(address, class_hash)| DeployedContract { address, class_hash }), + ), + storage_diffs: Vec::from_iter(diff.storage_diffs.into_iter().map( + |(address, entries)| { + let storage_entries = Vec::from_iter( + entries.into_iter().map(|(key, value)| StorageEntry { key, value }), + ); + StorageDiff { address, storage_entries } + }, + )), + declared_classes: diff + .declared_classes + .into_iter() + .map(|(class_hash, compiled_class_hash)| ClassHashes { + class_hash, + compiled_class_hash, + }) + .collect(), + deprecated_declared_classes: diff.deprecated_declared_classes, + nonces: Vec::from_iter( + diff.nonces + .into_iter() + .map(|(contract_address, nonce)| ContractNonce { contract_address, nonce }), + ), + replaced_classes: Vec::from_iter(diff.replaced_classes.into_iter().map( + |(contract_address, class_hash)| ReplacedClasses { contract_address, class_hash }, + )), + } + } +} + +impl From for ThinStateDiff { + fn from(diff: ClientStateDiff) -> Self { + Self { + deployed_contracts: Vec::from_iter(diff.deployed_contracts.into_iter().map( + |ClientDeployedContract { address, class_hash }| DeployedContract { + address, + class_hash, + }, + )), + storage_diffs: Vec::from_iter(diff.storage_diffs.into_iter().map( + |(address, entries)| { + let storage_entries = Vec::from_iter( + entries + .into_iter() + .map(|ClientStorageEntry { key, value }| StorageEntry { key, value }), + ); + StorageDiff { address, storage_entries } + }, + )), + declared_classes: diff + .declared_classes + .into_iter() + .map(|ClientDeclaredClassHashEntry { class_hash, compiled_class_hash }| { + ClassHashes { class_hash, compiled_class_hash } + }) + .collect(), + deprecated_declared_classes: diff.old_declared_contracts, + nonces: Vec::from_iter( + diff.nonces + .into_iter() + .map(|(contract_address, nonce)| ContractNonce { contract_address, nonce }), + ), + replaced_classes: Vec::from_iter(diff.replaced_classes.into_iter().map( + |ClientReplacedClass { address: contract_address, class_hash }| ReplacedClasses { + contract_address, + class_hash, + }, + )), + } + } +} + +/// The nonce of a StarkNet contract. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ContractNonce { + pub contract_address: ContractAddress, + pub nonce: Nonce, +} + +/// A deployed contract in StarkNet. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployedContract { + pub address: ContractAddress, + pub class_hash: ClassHash, +} + +/// Storage differences in StarkNet. +// Invariant: Storage keys are strictly increasing. In particular, no key appears twice. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StorageDiff { + pub address: ContractAddress, + pub(super) storage_entries: Vec, +} + +/// A storage entry in a contract. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StorageEntry { + pub key: StorageKey, + pub value: Felt, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct EntryPointByType { + #[serde(rename = "CONSTRUCTOR")] + pub constructor: Vec, + #[serde(rename = "EXTERNAL")] + pub external: Vec, + #[serde(rename = "L1_HANDLER")] + pub l1handler: Vec, +} + +impl EntryPointByType { + pub fn from_hash_map(entry_points_by_type: HashMap>) -> Self { + macro_rules! get_entrypoint_by_type { + ($variant:ident) => { + (*(entry_points_by_type.get(&EntryPointType::$variant).unwrap_or(&vec![]))).to_vec() + }; + } + + Self { + constructor: get_entrypoint_by_type!(Constructor), + external: get_entrypoint_by_type!(External), + l1handler: get_entrypoint_by_type!(L1Handler), + } + } + pub fn to_hash_map(&self) -> HashMap> { + HashMap::from_iter([ + (EntryPointType::Constructor, self.constructor.clone()), + (EntryPointType::External, self.external.clone()), + (EntryPointType::L1Handler, self.l1handler.clone()), + ]) + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub sierra_program: Vec, + pub contract_class_version: String, + pub entry_points_by_type: EntryPointByType, + pub abi: String, +} + +impl From for ContractClass { + fn from(class: starknet_api::state::ContractClass) -> Self { + Self { + sierra_program: class.sierra_program, + contract_class_version: CONTRACT_CLASS_VERSION.to_owned(), + entry_points_by_type: EntryPointByType::from_hash_map(class.entry_points_by_type), + abi: class.abi, + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ClassHashes { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ReplacedClasses { + pub contract_address: ContractAddress, + pub class_hash: ClassHash, +} diff --git a/crates/papyrus_rpc/src/v0_6/transaction.rs b/crates/papyrus_rpc/src/v0_6/transaction.rs new file mode 100644 index 00000000000..da557ee56ae --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/transaction.rs @@ -0,0 +1,1166 @@ +#[cfg(test)] +#[path = "transaction_test.rs"] +mod transaction_test; + +use std::collections::HashMap; +use std::fmt::Display; +use std::sync::Arc; + +use ethers::core::abi::{encode_packed, Token}; +use ethers::core::utils::keccak256; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_execution::objects::PriceUnit; +use papyrus_storage::body::BodyStorageReader; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::StorageTxn; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, +}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::serde_utils::bytes_from_hex_str; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + DeployTransaction, + Fee, + L1HandlerTransaction, + MessageToL1, + PaymasterData, + Resource, + ResourceBounds, + Tip, + TransactionExecutionStatus, + TransactionHash, + TransactionSignature, + TransactionVersion, +}; +use starknet_client::writer::objects::transaction as client_transaction; +use starknet_types_core::felt::Felt; + +use super::error::BLOCK_NOT_FOUND; +use crate::internal_server_error; + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion0 { + #[serde(rename = "0x0")] + #[default] + Version0, + #[serde(rename = "0x100000000000000000000000000000000")] + Version0OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion1 { + #[serde(rename = "0x1")] + #[default] + Version1, + #[serde(rename = "0x100000000000000000000000000000001")] + Version1OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion2 { + #[serde(rename = "0x2")] + #[default] + Version2, + #[serde(rename = "0x100000000000000000000000000000002")] + Version2OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion3 { + #[serde(rename = "0x3")] + #[default] + Version3, + #[serde(rename = "0x100000000000000000000000000000003")] + Version3OnlyQuery, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum Transactions { + Hashes(Vec), + Full(Vec), +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct DeclareTransactionV0 { + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct DeclareTransactionV1 { + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV2 { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion2, + pub signature: TransactionSignature, +} + +impl From for DeclareTransactionV2 { + fn from(tx: starknet_api::transaction::DeclareTransactionV2) -> Self { + Self { + class_hash: tx.class_hash, + compiled_class_hash: tx.compiled_class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion2::Version2, + signature: tx.signature, + } + } +} + +// The serialization of the struct in SN_API is in capital letters, not following the spec. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ResourceBoundsMapping { + pub l1_gas: ResourceBounds, + pub l2_gas: ResourceBounds, +} + +impl From for starknet_api::transaction::ResourceBoundsMapping { + fn from(value: ResourceBoundsMapping) -> Self { + Self([(Resource::L1Gas, value.l1_gas), (Resource::L2Gas, value.l2_gas)].into()) + } +} + +impl From for ResourceBoundsMapping { + fn from(value: starknet_api::transaction::ResourceBoundsMapping) -> Self { + Self { + l1_gas: value.0.get(&Resource::L1Gas).cloned().unwrap_or_default(), + l2_gas: value.0.get(&Resource::L2Gas).cloned().unwrap_or_default(), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub version: TransactionVersion3, +} + +impl From for DeclareTransactionV3 { + fn from(tx: starknet_api::transaction::DeclareTransactionV3) -> Self { + Self { + resource_bounds: tx.resource_bounds.into(), + tip: tx.tip, + signature: tx.signature, + nonce: tx.nonce, + class_hash: tx.class_hash, + compiled_class_hash: tx.compiled_class_hash, + sender_address: tx.sender_address, + nonce_data_availability_mode: tx.nonce_data_availability_mode, + fee_data_availability_mode: tx.fee_data_availability_mode, + paymaster_data: tx.paymaster_data, + account_deployment_data: tx.account_deployment_data, + version: TransactionVersion3::Version3, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum DeclareTransaction { + Version0(DeclareTransactionV0), + Version1(DeclareTransactionV1), + Version2(DeclareTransactionV2), + Version3(DeclareTransactionV3), +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion1, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV3 { + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion3, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum DeployAccountTransaction { + Version1(DeployAccountTransactionV1), + Version3(DeployAccountTransactionV3), +} + +impl TryFrom for DeployAccountTransaction { + type Error = ErrorObjectOwned; + + fn try_from( + tx: starknet_api::transaction::DeployAccountTransaction, + ) -> Result { + match tx { + starknet_api::transaction::DeployAccountTransaction::V1( + starknet_api::transaction::DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + }, + ) => Ok(Self::Version1(DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: TransactionVersion1::Version1, + })), + starknet_api::transaction::DeployAccountTransaction::V3( + starknet_api::transaction::DeployAccountTransactionV3 { + resource_bounds, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + }, + ) => Ok(Self::Version3(DeployAccountTransactionV3 { + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: TransactionVersion3::Version3, + resource_bounds: resource_bounds.into(), + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + })), + } + } +} + +impl From for client_transaction::DeployAccountTransaction { + fn from(tx: DeployAccountTransaction) -> Self { + match tx { + DeployAccountTransaction::Version1(deploy_account_tx) => { + Self::DeployAccountV1(client_transaction::DeployAccountV1Transaction { + contract_address_salt: deploy_account_tx.contract_address_salt, + class_hash: deploy_account_tx.class_hash, + constructor_calldata: deploy_account_tx.constructor_calldata, + nonce: deploy_account_tx.nonce, + max_fee: deploy_account_tx.max_fee, + signature: deploy_account_tx.signature, + version: TransactionVersion::ONE, + r#type: client_transaction::DeployAccountType::DeployAccount, + }) + } + DeployAccountTransaction::Version3(deploy_account_tx) => { + Self::DeployAccountV3(client_transaction::DeployAccountV3Transaction { + contract_address_salt: deploy_account_tx.contract_address_salt, + class_hash: deploy_account_tx.class_hash, + constructor_calldata: deploy_account_tx.constructor_calldata, + nonce: deploy_account_tx.nonce, + signature: deploy_account_tx.signature, + version: TransactionVersion::THREE, + resource_bounds: deploy_account_tx.resource_bounds.into(), + tip: deploy_account_tx.tip, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: deploy_account_tx.paymaster_data, + r#type: client_transaction::DeployAccountType::DeployAccount, + }) + } + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV0) -> Self { + Self::InvokeV0(client_transaction::InvokeV0Transaction { + max_fee: tx.max_fee, + version: TransactionVersion::ZERO, + signature: tx.signature, + contract_address: tx.contract_address, + entry_point_selector: tx.entry_point_selector, + calldata: tx.calldata, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV1) -> Self { + Self::InvokeV1(client_transaction::InvokeV1Transaction { + max_fee: tx.max_fee, + version: TransactionVersion::ONE, + signature: tx.signature, + nonce: tx.nonce, + sender_address: tx.sender_address, + calldata: tx.calldata, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV3 { + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub version: TransactionVersion3, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV3) -> Self { + Self::InvokeV3(client_transaction::InvokeV3Transaction { + sender_address: tx.sender_address, + calldata: tx.calldata, + version: TransactionVersion::THREE, + signature: tx.signature, + nonce: tx.nonce, + resource_bounds: tx.resource_bounds.into(), + tip: tx.tip, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: tx.paymaster_data, + account_deployment_data: tx.account_deployment_data, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransaction) -> Self { + match tx { + InvokeTransaction::Version0(invoke_tx) => invoke_tx.into(), + InvokeTransaction::Version1(invoke_tx) => invoke_tx.into(), + InvokeTransaction::Version3(invoke_tx) => invoke_tx.into(), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum InvokeTransaction { + Version0(InvokeTransactionV0), + Version1(InvokeTransactionV1), + Version3(InvokeTransactionV3), +} + +impl TryFrom for InvokeTransaction { + type Error = ErrorObjectOwned; + + fn try_from(tx: starknet_api::transaction::InvokeTransaction) -> Result { + match tx { + starknet_api::transaction::InvokeTransaction::V0( + starknet_api::transaction::InvokeTransactionV0 { + max_fee, + signature, + contract_address, + entry_point_selector, + calldata, + }, + ) => Ok(Self::Version0(InvokeTransactionV0 { + max_fee, + version: TransactionVersion0::Version0, + signature, + contract_address, + entry_point_selector, + calldata, + })), + starknet_api::transaction::InvokeTransaction::V1( + starknet_api::transaction::InvokeTransactionV1 { + max_fee, + signature, + nonce, + sender_address, + calldata, + }, + ) => Ok(Self::Version1(InvokeTransactionV1 { + max_fee, + version: TransactionVersion1::Version1, + signature, + nonce, + sender_address, + calldata, + })), + starknet_api::transaction::InvokeTransaction::V3( + starknet_api::transaction::InvokeTransactionV3 { + resource_bounds, + tip, + signature, + nonce, + sender_address, + calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }, + ) => Ok(Self::Version3(InvokeTransactionV3 { + sender_address, + calldata, + version: TransactionVersion3::Version3, + signature, + nonce, + resource_bounds: resource_bounds.into(), + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + })), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionWithHash { + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub transaction: Transaction, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum Transaction { + #[serde(rename = "DECLARE")] + Declare(DeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), + #[serde(rename = "DEPLOY")] + Deploy(DeployTransaction), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransaction), +} + +impl TryFrom for Transaction { + type Error = ErrorObjectOwned; + + fn try_from(tx: starknet_api::transaction::Transaction) -> Result { + match tx { + starknet_api::transaction::Transaction::Declare(declare_tx) => match declare_tx { + starknet_api::transaction::DeclareTransaction::V0(tx) => { + Ok(Self::Declare(DeclareTransaction::Version0(DeclareTransactionV0 { + class_hash: tx.class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion0::Version0, + signature: tx.signature, + }))) + } + starknet_api::transaction::DeclareTransaction::V1(tx) => { + Ok(Self::Declare(DeclareTransaction::Version1(DeclareTransactionV1 { + class_hash: tx.class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion1::Version1, + signature: tx.signature, + }))) + } + starknet_api::transaction::DeclareTransaction::V2(tx) => { + Ok(Self::Declare(DeclareTransaction::Version2(tx.into()))) + } + starknet_api::transaction::DeclareTransaction::V3(tx) => { + Ok(Self::Declare(DeclareTransaction::Version3(tx.into()))) + } + }, + starknet_api::transaction::Transaction::Deploy(deploy_tx) => { + Ok(Transaction::Deploy(deploy_tx)) + } + starknet_api::transaction::Transaction::DeployAccount(deploy_account_tx) => { + Ok(Self::DeployAccount(deploy_account_tx.try_into()?)) + } + starknet_api::transaction::Transaction::Invoke(invoke_tx) => { + Ok(Self::Invoke(invoke_tx.try_into()?)) + } + starknet_api::transaction::Transaction::L1Handler(l1_handler_tx) => { + Ok(Transaction::L1Handler(l1_handler_tx)) + } + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default)] +pub struct TransactionStatus { + pub finality_status: TransactionFinalityStatus, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, +} + +/// Transaction Finality status on starknet. +#[derive( + Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default, +)] +pub enum TransactionFinalityStatus { + /// The transaction passed the validation and entered an actual created block. + #[serde(rename = "ACCEPTED_ON_L2")] + #[default] + AcceptedOnL2, + /// The transaction was accepted on-chain. + #[serde(rename = "ACCEPTED_ON_L1")] + AcceptedOnL1, +} + +/// Transaction Finality status on starknet for transactions in the pending block. +#[derive( + Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default, +)] +pub enum PendingTransactionFinalityStatus { + #[serde(rename = "ACCEPTED_ON_L2")] + #[default] + AcceptedOnL2, +} + +impl From for TransactionFinalityStatus { + fn from(status: BlockStatus) -> Self { + match status { + BlockStatus::AcceptedOnL1 => TransactionFinalityStatus::AcceptedOnL1, + BlockStatus::AcceptedOnL2 => TransactionFinalityStatus::AcceptedOnL2, + BlockStatus::Pending => TransactionFinalityStatus::AcceptedOnL2, /* for backward compatibility pending transactions are considered accepted on L2 */ + // we convert the block status to transaction status only in the creation of + // TransactionReceiptWithStatus before that we verify that the block is not + // rejected so this conversion should never happen + BlockStatus::Rejected => unreachable!("Rejected blocks are not returned by the API"), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(untagged)] +pub enum GeneralTransactionReceipt { + TransactionReceipt(TransactionReceipt), + PendingTransactionReceipt(PendingTransactionReceipt), +} + +impl GeneralTransactionReceipt { + pub fn transaction_status(&self) -> TransactionStatus { + match self { + GeneralTransactionReceipt::TransactionReceipt(receipt) => TransactionStatus { + execution_status: receipt.output.execution_status().clone(), + finality_status: receipt.finality_status, + }, + GeneralTransactionReceipt::PendingTransactionReceipt(receipt) => TransactionStatus { + execution_status: receipt.output.execution_status().clone(), + finality_status: TransactionFinalityStatus::AcceptedOnL2, + }, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct TransactionReceipt { + pub finality_status: TransactionFinalityStatus, + pub transaction_hash: TransactionHash, + pub block_hash: BlockHash, + pub block_number: BlockNumber, + #[serde(flatten)] + pub output: TransactionOutput, +} + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct PendingTransactionReceipt { + pub finality_status: PendingTransactionFinalityStatus, + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub output: PendingTransactionOutput, +} + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(tag = "type")] +pub enum TransactionOutput { + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionOutput), + #[serde(rename = "DEPLOY")] + Deploy(DeployTransactionOutput), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionOutput), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionOutput), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionOutput), +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct FeePayment { + pub amount: Fee, + pub unit: PriceUnit, +} + +/// A declare transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeclareTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy-account transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeployAccountTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeployTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An invoke transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct InvokeTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An L1 handler transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct L1HandlerTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + pub message_hash: L1L2MsgHash, +} + +// Note: This is not the same as the Builtins in starknet_api, the serialization of SegmentArena is +// different. TODO(yair): remove this once a newer version of the API is published. +#[derive(Hash, Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub enum Builtin { + #[serde(rename = "range_check_builtin_applications")] + RangeCheck, + #[serde(rename = "pedersen_builtin_applications")] + Pedersen, + #[serde(rename = "poseidon_builtin_applications")] + Poseidon, + #[serde(rename = "ec_op_builtin_applications")] + EcOp, + #[serde(rename = "ecdsa_builtin_applications")] + Ecdsa, + #[serde(rename = "bitwise_builtin_applications")] + Bitwise, + #[serde(rename = "keccak_builtin_applications")] + Keccak, + #[serde(rename = "segment_arena_builtin")] + SegmentArena, +} + +impl TryFrom for Builtin { + type Error = (); + fn try_from(builtin: starknet_api::transaction::Builtin) -> Result { + match builtin { + starknet_api::transaction::Builtin::RangeCheck => Ok(Builtin::RangeCheck), + starknet_api::transaction::Builtin::Pedersen => Ok(Builtin::Pedersen), + starknet_api::transaction::Builtin::Poseidon => Ok(Builtin::Poseidon), + starknet_api::transaction::Builtin::EcOp => Ok(Builtin::EcOp), + starknet_api::transaction::Builtin::Ecdsa => Ok(Builtin::Ecdsa), + starknet_api::transaction::Builtin::Bitwise => Ok(Builtin::Bitwise), + starknet_api::transaction::Builtin::Keccak => Ok(Builtin::Keccak), + starknet_api::transaction::Builtin::SegmentArena => Ok(Builtin::SegmentArena), + // These builtins are not part of the specs. + starknet_api::transaction::Builtin::AddMod + | starknet_api::transaction::Builtin::MulMod + | starknet_api::transaction::Builtin::RangeCheck96 => Err(()), + } + } +} + +// Note: This is not the same as the ExecutionResources in starknet_api, it's missing DA gas +// consumption. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ExecutionResources { + pub steps: u64, + #[serde(flatten)] + pub builtin_instance_counter: HashMap, + #[serde(skip_serializing_if = "Option::is_none")] + pub memory_holes: Option, +} + +impl From for ExecutionResources { + fn from(value: starknet_api::transaction::ExecutionResources) -> Self { + Self { + steps: value.steps, + builtin_instance_counter: value + .builtin_instance_counter + .into_iter() + .filter_map(|(k, v)| match v { + 0 => None, + _ => Builtin::try_from(k).ok().map(|k| (k, v)), + }) + .collect(), + memory_holes: match value.memory_holes { + 0 => None, + _ => Some(value.memory_holes), + }, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(tag = "type")] +// Applying deny_unknown_fields on the inner type instead of on PendingTransactionReceipt because +// of a bug that makes deny_unknown_fields not work well with flatten: +// https://github.com/serde-rs/serde/issues/1358 +#[serde(deny_unknown_fields)] +pub enum PendingTransactionOutput { + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionOutput), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionOutput), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionOutput), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionOutput), +} + +impl PendingTransactionOutput { + pub fn execution_status(&self) -> &TransactionExecutionStatus { + match self { + PendingTransactionOutput::Declare(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::DeployAccount(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::Invoke(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::L1Handler(tx_output) => &tx_output.execution_status, + } + } +} + +impl TransactionOutput { + pub fn execution_status(&self) -> &TransactionExecutionStatus { + match self { + TransactionOutput::Declare(tx_output) => &tx_output.execution_status, + TransactionOutput::Deploy(tx_output) => &tx_output.execution_status, + TransactionOutput::DeployAccount(tx_output) => &tx_output.execution_status, + TransactionOutput::Invoke(tx_output) => &tx_output.execution_status, + TransactionOutput::L1Handler(tx_output) => &tx_output.execution_status, + } + } +} + +impl From<(starknet_api::transaction::TransactionOutput, TransactionVersion, Option)> + for TransactionOutput +{ + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn from( + tx_output_msg_hash: ( + starknet_api::transaction::TransactionOutput, + TransactionVersion, + Option, + ), + ) -> Self { + let (tx_output, tx_version, maybe_msg_hash) = tx_output_msg_hash; + // TODO: consider supporting match instead. + let actual_fee = if tx_version == TransactionVersion::ZERO + || tx_version == TransactionVersion::ONE + || tx_version == TransactionVersion::TWO + { + FeePayment { amount: tx_output.actual_fee(), unit: PriceUnit::Wei } + } else { + // TransactionVersion::THREE + FeePayment { amount: tx_output.actual_fee(), unit: PriceUnit::Fri } + }; + + match tx_output { + starknet_api::transaction::TransactionOutput::Declare(declare_tx_output) => { + TransactionOutput::Declare(DeclareTransactionOutput { + actual_fee, + messages_sent: declare_tx_output.messages_sent, + events: declare_tx_output.events, + execution_status: declare_tx_output.execution_status, + execution_resources: declare_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::Deploy(deploy_tx_output) => { + TransactionOutput::Deploy(DeployTransactionOutput { + actual_fee, + messages_sent: deploy_tx_output.messages_sent, + events: deploy_tx_output.events, + contract_address: deploy_tx_output.contract_address, + execution_status: deploy_tx_output.execution_status, + execution_resources: deploy_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::DeployAccount(deploy_tx_output) => { + TransactionOutput::DeployAccount(DeployAccountTransactionOutput { + actual_fee, + messages_sent: deploy_tx_output.messages_sent, + events: deploy_tx_output.events, + contract_address: deploy_tx_output.contract_address, + execution_status: deploy_tx_output.execution_status, + execution_resources: deploy_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::Invoke(invoke_tx_output) => { + TransactionOutput::Invoke(InvokeTransactionOutput { + actual_fee, + messages_sent: invoke_tx_output.messages_sent, + events: invoke_tx_output.events, + execution_status: invoke_tx_output.execution_status, + execution_resources: invoke_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::L1Handler(l1_handler_tx_output) => { + TransactionOutput::L1Handler(L1HandlerTransactionOutput { + actual_fee, + messages_sent: l1_handler_tx_output.messages_sent, + events: l1_handler_tx_output.events, + execution_status: l1_handler_tx_output.execution_status, + execution_resources: l1_handler_tx_output.execution_resources.into(), + message_hash: maybe_msg_hash + .expect("Missing message hash to construct L1Handler output."), + }) + } + } + } +} + +impl TryFrom for PendingTransactionOutput { + type Error = ErrorObjectOwned; + + fn try_from(tx_output: TransactionOutput) -> Result { + match tx_output { + TransactionOutput::Declare(declare_tx_output) => { + Ok(PendingTransactionOutput::Declare(declare_tx_output)) + } + TransactionOutput::Deploy(_) => { + Err(internal_server_error("Got a pending deploy transaction.")) + } + TransactionOutput::DeployAccount(deploy_tx_output) => { + Ok(PendingTransactionOutput::DeployAccount(deploy_tx_output)) + } + TransactionOutput::Invoke(invoke_tx_output) => { + Ok(PendingTransactionOutput::Invoke(invoke_tx_output)) + } + TransactionOutput::L1Handler(l1_handler_tx_output) => { + Ok(PendingTransactionOutput::L1Handler(l1_handler_tx_output)) + } + } + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct Event { + // Can't have a different struct for pending events because then that struct will need to have + // deny_unknown_fields. And there's a bug in serde that forbids having deny_unknown_fields with + // flatten: https://github.com/serde-rs/serde/issues/1701 + // TODO(shahak): Create a PendingEvent struct when the serde bug is solved. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub block_hash: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub block_number: Option, + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub event: starknet_api::transaction::Event, +} + +pub fn get_block_txs_by_number< + Mode: TransactionKind, + Transaction: TryFrom, +>( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result, ErrorObjectOwned> { + let transactions = txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + transactions.into_iter().map(Transaction::try_from).collect() +} + +pub fn get_block_tx_hashes_by_number( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result, ErrorObjectOwned> { + let transaction_hashes = txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + Ok(transaction_hashes) +} + +/// The hash of a L1 -> L2 message. +// The hash is Keccak256, so it doesn't necessarily fit in a Felt. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct L1L2MsgHash(pub [u8; 32]); + +impl Display for L1L2MsgHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "0x{}", hex::encode(self.0)) + } +} + +impl Serialize for L1L2MsgHash { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(format!("{}", self).as_str()) + } +} + +impl<'de> Deserialize<'de> for L1L2MsgHash { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(Self(bytes_from_hex_str::<32, true>(s.as_str()).map_err(serde::de::Error::custom)?)) + } +} + +pub trait L1HandlerMsgHash { + fn calc_msg_hash(&self) -> L1L2MsgHash; +} + +impl L1HandlerMsgHash for L1HandlerTransaction { + fn calc_msg_hash(&self) -> L1L2MsgHash { + l1_handler_message_hash( + &self.contract_address, + self.nonce, + &self.entry_point_selector, + &self.calldata, + ) + } +} + +impl L1HandlerMsgHash for starknet_client::reader::objects::transaction::L1HandlerTransaction { + fn calc_msg_hash(&self) -> L1L2MsgHash { + l1_handler_message_hash( + &self.contract_address, + self.nonce, + &self.entry_point_selector, + &self.calldata, + ) + } +} + +/// Calculating the message hash of L1 -> L2 message. +/// `` +fn l1_handler_message_hash( + contract_address: &ContractAddress, + nonce: Nonce, + entry_point_selector: &EntryPointSelector, + calldata: &Calldata, +) -> L1L2MsgHash { + let (from_address, payload) = + calldata.0.split_first().expect("Invalid calldata, expected at least from_address"); + + let from_address = Token::Bytes(from_address.to_bytes_be().to_vec()); + let to_address = Token::Bytes(contract_address.0.key().to_bytes_be().to_vec()); + let nonce = Token::Bytes(nonce.to_bytes_be().to_vec()); + let selector = Token::Bytes(entry_point_selector.0.to_bytes_be().to_vec()); + let payload_length_as_felt = Felt::from(payload.len() as u64); + let payload_length = Token::Bytes(payload_length_as_felt.to_bytes_be().to_vec()); + + let mut payload: Vec<_> = + payload.iter().map(|felt| Token::Bytes(felt.to_bytes_be().to_vec())).collect(); + + let mut to_encode = vec![from_address, to_address, nonce, selector, payload_length]; + to_encode.append(&mut payload); + let encoded = encode_packed(to_encode.as_slice()).expect("Should be able to encode"); + + L1L2MsgHash(keccak256(encoded)) +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct MessageFromL1 { + // TODO: fix serialization of EthAddress in SN_API to fit the spec. + #[serde(serialize_with = "serialize_eth_address")] + pub from_address: EthAddress, + pub to_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub payload: Calldata, +} + +// Serialize EthAddress to a 40 character hex string with a 0x prefix. +fn serialize_eth_address(eth_address: &EthAddress, serializer: S) -> Result +where + S: serde::Serializer, +{ + let hex_string = hex::encode(eth_address.0.as_bytes()); + let fixed_size_hex_string = format!("0x{:0<40}", hex_string); + serializer.serialize_str(fixed_size_hex_string.as_str()) +} + +impl From for L1HandlerTransaction { + fn from(message: MessageFromL1) -> Self { + let sender_as_felt = eth_address_to_felt(message.from_address); + let mut calldata = vec![sender_as_felt]; + calldata.extend_from_slice(&message.payload.0); + let calldata = Calldata(Arc::new(calldata)); + Self { + version: TransactionVersion::ONE, + contract_address: message.to_address, + entry_point_selector: message.entry_point_selector, + calldata, + ..Default::default() + } + } +} + +// TODO(yair): move to SN_API and implement as From. +fn eth_address_to_felt(eth_address: EthAddress) -> Felt { + let eth_address_as_bytes = eth_address.0.to_fixed_bytes(); + let mut bytes: [u8; 32] = [0; 32]; + bytes[12..32].copy_from_slice(ð_address_as_bytes); + Felt::from_bytes_be(&bytes) +} + +/// An InvokeTransactionV1 that has the type field. This enum can be used to serialize/deserialize +/// invoke v1 transactions directly while `InvokeTransactionV1` can be serialized/deserialized only +/// from the `Transaction` enum. +/// This allows RPC methods to receive an invoke v1 transaction directly. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum TypedInvokeTransaction { + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: TypedInvokeTransaction) -> Self { + let TypedInvokeTransaction::Invoke(tx) = tx; + tx.into() + } +} + +/// A DeployAccountTransaction that has the type field. This enum can be used to +/// serialize/deserialize deploy account transactions directly while `DeployAccountTransaction` can +/// be serialized/deserialized only from the `Transaction` enum. +/// This allows RPC methods to receive a deploy account transaction directly. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum TypedDeployAccountTransaction { + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), +} + +impl From for client_transaction::DeployAccountTransaction { + fn from(tx: TypedDeployAccountTransaction) -> Self { + let TypedDeployAccountTransaction::DeployAccount(tx) = tx; + tx.into() + } +} diff --git a/crates/papyrus_rpc/src/v0_6/transaction_test.rs b/crates/papyrus_rpc/src/v0_6/transaction_test.rs new file mode 100644 index 00000000000..9b60a118049 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/transaction_test.rs @@ -0,0 +1,230 @@ +use pretty_assertions::assert_eq; +use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, Nonce, PatriciaKey}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + Fee, + L1HandlerTransaction, + PaymasterData, + Tip, + Transaction, + TransactionSignature, + TransactionVersion, +}; +use starknet_api::{calldata, contract_address, felt, patricia_key}; +use starknet_client::writer::objects::transaction as client_transaction; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, get_rng, GetTestInstance}; + +use super::super::transaction::{L1HandlerMsgHash, L1L2MsgHash}; +use super::{ + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + ResourceBoundsMapping, + TransactionVersion0, + TransactionVersion1, + TransactionVersion3, +}; + +lazy_static::lazy_static! { + // A transaction from MAINNET with tx hash 0x439e12f67962c353182d72b4af12c3f11eaba4b36e552aebcdcd6db66971bdb. + static ref L1_HANDLER_TX: L1HandlerTransaction = L1HandlerTransaction { + version: TransactionVersion::ZERO, + nonce: Nonce(felt!("0x18e94d")), + contract_address: contract_address!( + "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82" + ), + entry_point_selector: EntryPointSelector(felt!( + "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19" + )), + calldata: calldata![ + felt!("0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419"), + felt!("0x455448"), + felt!("0xc27947400e26e534e677afc2e9b2ec1bab14fc89"), + felt!("0x4af4754baf89f1b8b449215a8ea7ce558824a33a5393eaa3829658549f2bfa2"), + felt!("0x9184e72a000"), + felt!("0x0") + ], + }; +} + +// The msg hash of the L1Handler transaction. +const MSG_HASH: &str = "0x99b2a7830e1c860734b308d90bb05b0e09ecda0a2b243ecddb12c50bdebaa3a9"; + +auto_impl_get_test_instance! { + pub enum DeployAccountTransaction { + Version1(DeployAccountTransactionV1) = 0, + Version3(DeployAccountTransactionV3) = 1, + } + pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion1, + } + pub struct DeployAccountTransactionV3 { + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion3, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + pub enum InvokeTransaction { + Version0(InvokeTransactionV0) = 0, + Version1(InvokeTransactionV1) = 1, + Version3(InvokeTransactionV3) = 2, + } + pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + } + pub struct InvokeTransactionV3 { + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub version: TransactionVersion3, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + pub enum TransactionVersion0 { + Version0 = 0, + } + pub enum TransactionVersion1 { + Version1 = 0, + } + pub enum TransactionVersion3 { + Version3 = 0, + } +} + +// TODO: check the conversion against the expected GW transaction. +#[test] +fn test_gateway_trascation_from_starknet_api_transaction() { + let mut rng = get_rng(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV0V1::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V0(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV0V1::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V1(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::DeclareTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V3(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV2::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V2(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::InvokeTransactionV0::default(); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V0(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::InvokeTransactionV1::default(); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V1(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::InvokeTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V3(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::L1HandlerTransaction::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::L1Handler(inner_transaction).try_into().unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployTransaction::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Deploy(inner_transaction).try_into().unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployAccountTransactionV1::get_test_instance(&mut rng); + let _transaction: super::Transaction = Transaction::DeployAccount( + starknet_api::transaction::DeployAccountTransaction::V1(inner_transaction), + ) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployAccountTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = Transaction::DeployAccount( + starknet_api::transaction::DeployAccountTransaction::V3(inner_transaction), + ) + .try_into() + .unwrap(); +} + +#[test] +fn test_invoke_transaction_to_client_transaction() { + let _invoke_transaction: client_transaction::InvokeTransaction = + InvokeTransactionV1::get_test_instance(&mut get_rng()).into(); + + let _invoke_transaction: client_transaction::InvokeTransaction = + InvokeTransactionV3::get_test_instance(&mut get_rng()).into(); +} + +#[test] +fn l1handler_msg_hash() { + let msg_hash = format!("{}", L1_HANDLER_TX.calc_msg_hash()); + assert_eq!(msg_hash, MSG_HASH); +} + +#[test] +fn l1handler_msg_hash_serde() { + let ser = serde_json::to_string(MSG_HASH).unwrap(); + assert_eq!(ser, "\"0x99b2a7830e1c860734b308d90bb05b0e09ecda0a2b243ecddb12c50bdebaa3a9\""); + let des = serde_json::from_str::(&ser).unwrap(); + let expected_hash = L1_HANDLER_TX.calc_msg_hash(); + assert_eq!(des, expected_hash); +} diff --git a/crates/papyrus_rpc/src/v0_6/write_api_error.rs b/crates/papyrus_rpc/src/v0_6/write_api_error.rs new file mode 100644 index 00000000000..ba977c04112 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/write_api_error.rs @@ -0,0 +1,85 @@ +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +use super::error::{ + unexpected_error, + validation_failure, + JsonRpcError, + CLASS_ALREADY_DECLARED, + CLASS_HASH_NOT_FOUND, + COMPILATION_FAILED, + COMPILED_CLASS_HASH_MISMATCH, + CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + DUPLICATE_TX, + INSUFFICIENT_ACCOUNT_BALANCE, + INSUFFICIENT_MAX_FEE, + INVALID_TRANSACTION_NONCE, + NON_ACCOUNT, + UNSUPPORTED_CONTRACT_CLASS_VERSION, + UNSUPPORTED_TX_VERSION, +}; + +#[cfg(test)] +#[path = "write_api_error_test.rs"] +mod write_api_error_test; + +pub(crate) fn starknet_error_to_invoke_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // EntryPointNotFoundInContract is not thrown in __execute__ since that is + // considered as a reverted transaction. It is also not thrown in __validate__ since + // every error there is considered a ValidateFailure. This means that if + // EntryPointNotFoundInContract is thrown then it failed because it couldn't find + // __validate__ or __execute__ and that means the contract is not an account contract. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} + +pub(crate) fn starknet_error_to_declare_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::ClassAlreadyDeclared => CLASS_ALREADY_DECLARED, + KnownStarknetErrorCode::CompilationFailed => COMPILATION_FAILED, + KnownStarknetErrorCode::ContractBytecodeSizeTooLarge => CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + KnownStarknetErrorCode::ContractClassObjectSizeTooLarge => CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // See explanation on this mapping in AddInvokeError. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidCompiledClassHash => COMPILED_CLASS_HASH_MISMATCH, + KnownStarknetErrorCode::InvalidContractClassVersion => UNSUPPORTED_CONTRACT_CLASS_VERSION, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} + +pub(crate) fn starknet_error_to_deploy_account_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // See explanation on this mapping in AddInvokeError. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::UndeclaredClass => CLASS_HASH_NOT_FOUND, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} diff --git a/crates/papyrus_rpc/src/v0_6/write_api_error_test.rs b/crates/papyrus_rpc/src/v0_6/write_api_error_test.rs new file mode 100644 index 00000000000..dc7b8a7d2e3 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/write_api_error_test.rs @@ -0,0 +1,92 @@ +use std::collections::BTreeMap; + +use enum_iterator::all; +use jsonrpsee::types::ErrorObjectOwned; +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +use super::super::error::JsonRpcError; +use super::{ + starknet_error_to_declare_error, + starknet_error_to_deploy_account_error, + starknet_error_to_invoke_error, +}; +use crate::test_utils::{get_starknet_spec_api_schema_for_method_errors, SpecFile}; +use crate::version_config::VERSION_0_6 as Version; + +const MESSAGE: &str = "message"; +const UNKNOWN_CODE: &str = "code"; + +fn starknet_errors() -> impl Iterator { + all::() + .map(StarknetErrorCode::KnownErrorCode) + .chain([StarknetErrorCode::UnknownErrorCode(UNKNOWN_CODE.to_owned())]) + .map(|error_code| StarknetError { code: error_code, message: MESSAGE.to_owned() }) +} + +fn test_error_from_conversion_fits_rpc JsonRpcError>( + f: F, + spec_method: &str, +) { + let schema = get_starknet_spec_api_schema_for_method_errors( + &[(SpecFile::WriteApi, &[spec_method])], + &Version, + ); + for starknet_error in starknet_errors() { + // Converting into ErrorObjectOwned since it has serialization. + let rpc_error: ErrorObjectOwned = f(starknet_error).into(); + let mut json_value = serde_json::to_value(rpc_error).unwrap(); + json_value.as_object_mut().unwrap().retain(|_, v| !v.is_null()); + assert!(schema.is_valid(&json_value)); + } +} + +#[test] +fn starknet_error_to_invoke_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_invoke_error, + "starknet_addInvokeTransaction", + ); +} + +#[test] +fn starknet_error_to_declare_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_declare_error, + "starknet_addDeclareTransaction", + ); +} + +#[test] +fn starknet_error_to_deploy_account_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_deploy_account_error, + "starknet_addDeployAccountTransaction", + ); +} + +fn get_conversion_snapshot JsonRpcError>( + f: F, +) -> serde_json::Value { + // Using BTreeMap to keep the keys sorted. + let mut rpc_error_code_to_errors = BTreeMap::new(); + for starknet_error in starknet_errors() { + let rpc_error: ErrorObjectOwned = f(starknet_error.clone()).into(); + rpc_error_code_to_errors.insert(rpc_error.code(), (rpc_error, starknet_error)); + } + serde_json::to_value(rpc_error_code_to_errors).unwrap() +} + +#[test] +fn starknet_error_to_invoke_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_invoke_error)); +} + +#[test] +fn starknet_error_to_declare_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_declare_error)); +} + +#[test] +fn starknet_error_to_deploy_account_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_deploy_account_error)); +} diff --git a/crates/papyrus_rpc/src/v0_6/write_api_result.rs b/crates/papyrus_rpc/src/v0_6/write_api_result.rs new file mode 100644 index 00000000000..ddc54e96f97 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/write_api_result.rs @@ -0,0 +1,50 @@ +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::transaction::TransactionHash; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, +}; + +#[cfg(test)] +#[path = "write_api_result_test.rs"] +mod write_api_result_test; + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddInvokeOkResult { + pub transaction_hash: TransactionHash, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddDeclareOkResult { + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddDeployAccountOkResult { + pub transaction_hash: TransactionHash, + pub contract_address: ContractAddress, +} + +impl From for AddInvokeOkResult { + fn from(response: InvokeResponse) -> Self { + Self { transaction_hash: response.transaction_hash } + } +} + +impl From for AddDeclareOkResult { + fn from(response: DeclareResponse) -> Self { + Self { transaction_hash: response.transaction_hash, class_hash: response.class_hash } + } +} + +impl From for AddDeployAccountOkResult { + fn from(response: DeployAccountResponse) -> Self { + Self { transaction_hash: response.transaction_hash, contract_address: response.address } + } +} diff --git a/crates/papyrus_rpc/src/v0_6/write_api_result_test.rs b/crates/papyrus_rpc/src/v0_6/write_api_result_test.rs new file mode 100644 index 00000000000..3f82d3d9d02 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_6/write_api_result_test.rs @@ -0,0 +1,90 @@ +use serde::Serialize; +use starknet_api::core::{ClassHash, ContractAddress, PatriciaKey}; +use starknet_api::felt; +use starknet_api::transaction::TransactionHash; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, + SuccessfulStarknetErrorCode, +}; +use test_utils::{auto_impl_get_test_instance, get_rng, GetTestInstance}; + +use super::{AddDeclareOkResult, AddDeployAccountOkResult, AddInvokeOkResult}; +use crate::test_utils::{get_starknet_spec_api_schema_for_method_results, SpecFile}; +use crate::version_config::VERSION_0_6 as VERSION; + +auto_impl_get_test_instance! { + pub struct AddInvokeOkResult { + pub transaction_hash: TransactionHash, + } + pub struct AddDeclareOkResult { + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, + } + pub struct AddDeployAccountOkResult { + pub transaction_hash: TransactionHash, + pub contract_address: ContractAddress, + } +} + +fn test_ok_result_fits_rpc(spec_method: &str) { + let schema = get_starknet_spec_api_schema_for_method_results( + &[(SpecFile::WriteApi, &[spec_method])], + &VERSION, + ); + let result = AddOkResult::get_test_instance(&mut get_rng()); + assert!(schema.is_valid(&serde_json::to_value(result).unwrap())); +} + +#[test] +fn add_invoke_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addInvokeTransaction"); +} + +#[test] +fn add_declare_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addDeclareTransaction"); +} + +#[test] +fn add_deploy_account_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addDeployAccountTransaction"); +} + +#[test] +fn add_invoke_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let ok_result = AddInvokeOkResult::from(InvokeResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + }); + let expected_ok_result = AddInvokeOkResult { transaction_hash }; + assert_eq!(expected_ok_result, ok_result); +} + +#[test] +fn add_declare_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let class_hash = ClassHash(felt!("0xabcde")); + let ok_result = AddDeclareOkResult::from(DeclareResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + class_hash, + }); + let expected_ok_result = AddDeclareOkResult { transaction_hash, class_hash }; + assert_eq!(expected_ok_result, ok_result); +} + +#[test] +fn add_deploy_account_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let contract_address = ContractAddress(PatriciaKey::try_from(felt!("0xabcde")).unwrap()); + let ok_result = AddDeployAccountOkResult::from(DeployAccountResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + address: contract_address, + }); + let expected_ok_result = AddDeployAccountOkResult { transaction_hash, contract_address }; + assert_eq!(expected_ok_result, ok_result); +} diff --git a/crates/papyrus_rpc/src/v0_7/api/api_impl.rs b/crates/papyrus_rpc/src/v0_7/api/api_impl.rs new file mode 100644 index 00000000000..fc503f168c4 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/api/api_impl.rs @@ -0,0 +1,1651 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use jsonrpsee::core::RpcResult; +use jsonrpsee::types::ErrorObjectOwned; +use jsonrpsee::RpcModule; +use lazy_static::lazy_static; +use papyrus_common::pending_classes::{PendingClasses, PendingClassesTrait}; +use papyrus_execution::objects::{FeeEstimation, PendingData as ExecutionPendingData}; +use papyrus_execution::{ + estimate_fee as exec_estimate_fee, + execute_call, + execution_utils, + simulate_transactions as exec_simulate_transactions, + ExecutableTransactionInput, + ExecutionConfig, +}; +use papyrus_storage::body::events::{EventIndex, EventsReader}; +use papyrus_storage::body::{BodyStorageReader, TransactionIndex}; +use papyrus_storage::compiled_class::CasmStorageReader; +use papyrus_storage::db::{TransactionKind, RO}; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageError, StorageReader, StorageTxn}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus}; +use starknet_api::core::{ChainId, ClassHash, ContractAddress, GlobalRoot, Nonce}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{StateNumber, StorageKey}; +use starknet_api::transaction::{ + EventContent, + EventIndexInTransactionOutput, + Fee, + Transaction as StarknetApiTransaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionVersion, +}; +use starknet_client::reader::objects::pending_data::{ + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate as ClientPendingStateUpdate, +}; +use starknet_client::reader::objects::transaction::{ + Transaction as ClientTransaction, + TransactionReceipt as ClientTransactionReceipt, +}; +use starknet_client::reader::PendingData; +use starknet_client::writer::{StarknetWriter, WriterClientError}; +use starknet_client::ClientError; +use starknet_types_core::felt::Felt; +use tokio::sync::RwLock; +use tracing::{instrument, trace, warn}; + +use super::super::block::{ + get_accepted_block_number, + get_block_header_by_number, + Block, + BlockHeader, + BlockNotRevertedValidator, + GeneralBlockHeader, + PendingBlockHeader, + ResourcePrice, +}; +use super::super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedTransaction, +}; +use super::super::error::{ + ContractError, + JsonRpcError, + TransactionExecutionError, + BLOCK_NOT_FOUND, + CLASS_HASH_NOT_FOUND, + CONTRACT_NOT_FOUND, + INVALID_TRANSACTION_HASH, + INVALID_TRANSACTION_INDEX, + NO_BLOCKS, + PAGE_SIZE_TOO_BIG, + TOO_MANY_KEYS_IN_FILTER, + TRANSACTION_HASH_NOT_FOUND, +}; +use super::super::execution::TransactionTrace; +use super::super::state::{AcceptedStateUpdate, PendingStateUpdate, StateUpdate}; +use super::super::transaction::{ + get_block_tx_hashes_by_number, + get_block_txs_by_number, + Event, + GeneralTransactionReceipt, + L1HandlerMsgHash, + L1L2MsgHash, + MessageFromL1, + PendingTransactionFinalityStatus, + PendingTransactionOutput, + PendingTransactionReceipt, + Transaction, + TransactionOutput, + TransactionReceipt, + TransactionStatus, + TransactionWithHash, + TransactionWithReceipt, + Transactions, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::super::write_api_error::{ + starknet_error_to_declare_error, + starknet_error_to_deploy_account_error, + starknet_error_to_invoke_error, +}; +use super::super::write_api_result::{ + AddDeclareOkResult, + AddDeployAccountOkResult, + AddInvokeOkResult, +}; +use super::{ + execution_error_to_error_object_owned, + stored_txn_to_executable_txn, + BlockHashAndNumber, + BlockId, + CallRequest, + CompiledContractClass, + ContinuationToken, + EventFilter, + EventsChunk, + GatewayContractClass, + JsonRpcV0_7Server as JsonRpcServer, + SimulatedTransaction, + SimulationFlag, + TransactionTraceWithHash, +}; +use crate::api::{BlockHashOrNumber, JsonRpcServerTrait, Tag}; +use crate::pending::client_pending_data_to_execution_pending_data; +use crate::syncing_state::{get_last_synced_block, SyncStatus, SyncingState}; +use crate::version_config::VERSION_0_7 as VERSION; +use crate::{ + get_block_status, + get_latest_block_number, + internal_server_error, + verify_storage_scope, + ContinuationTokenAsStruct, + GENESIS_HASH, +}; + +const DONT_IGNORE_L1_DA_MODE: bool = false; + +// TODO(yael): implement address 0x1 as a const function in starknet_api. +lazy_static! { + pub static ref BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress::from(1_u8); +} + +/// Rpc server. +pub struct JsonRpcServerImpl { + pub chain_id: ChainId, + pub execution_config: ExecutionConfig, + pub storage_reader: StorageReader, + pub max_events_chunk_size: usize, + pub max_events_keys: usize, + pub starting_block: BlockHashAndNumber, + pub shared_highest_block: Arc>>, + pub pending_data: Arc>, + pub pending_classes: Arc>, + pub writer_client: Arc, +} + +#[async_trait] +impl JsonRpcServer for JsonRpcServerImpl { + #[instrument(skip(self), level = "debug", err, ret)] + fn spec_version(&self) -> RpcResult { + Ok(format!("{VERSION}")) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn block_number(&self) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + get_latest_block_number(&txn)?.ok_or_else(|| ErrorObjectOwned::from(NO_BLOCKS)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn block_hash_and_number(&self) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let block_number = + get_latest_block_number(&txn)?.ok_or_else(|| ErrorObjectOwned::from(NO_BLOCKS))?; + let header: BlockHeader = get_block_header_by_number(&txn, block_number)?.into(); + + Ok(BlockHashAndNumber { block_hash: header.block_hash, block_number }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_w_transaction_hashes(&self, block_id: BlockId) -> RpcResult { + self.get_block( + block_id, + |pending_data| { + Ok(Transactions::Hashes( + pending_data + .block + .transactions() + .iter() + .map(|transaction| transaction.transaction_hash()) + .collect(), + )) + }, + |txn, block_number| { + Ok(Transactions::Hashes(get_block_tx_hashes_by_number(txn, block_number)?)) + }, + ) + .await + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_w_full_transactions(&self, block_id: BlockId) -> RpcResult { + self.get_block( + block_id, + |mut pending_data| { + let client_transactions = pending_data.block.transactions_mutable().drain(..); + Ok(Transactions::Full( + client_transactions + .map(|client_transaction| { + let transaction_hash = client_transaction.transaction_hash(); + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.try_into().map_err(internal_server_error)?; + Ok(TransactionWithHash { + transaction: starknet_api_transaction + .try_into() + .map_err(internal_server_error)?, + transaction_hash, + }) + }) + .collect::, ErrorObjectOwned>>()?, + )) + }, + |txn, block_number| { + let transactions = get_block_txs_by_number(txn, block_number)?; + let transaction_hashes = get_block_tx_hashes_by_number(txn, block_number)?; + Ok(Transactions::Full( + transactions + .into_iter() + .zip(transaction_hashes) + .map(|(transaction, transaction_hash)| TransactionWithHash { + transaction, + transaction_hash, + }) + .collect(), + )) + }, + ) + .await + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_w_full_transactions_and_receipts( + &self, + block_id: BlockId, + ) -> RpcResult { + self.get_block( + block_id, + |mut pending_data| { + let (client_transactions, client_receipts) = + pending_data.block.transactions_and_receipts_mutable(); + let client_transactions_and_receipts = + client_transactions.drain(..).zip(client_receipts.drain(..)); + Ok(Transactions::FullWithReceipts( + client_transactions_and_receipts + .map(|(client_transaction, client_transaction_receipt)| { + let receipt = client_receipt_to_rpc_pending_receipt( + &client_transaction, + client_transaction_receipt, + )? + .into(); + + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.try_into().map_err(internal_server_error)?; + Ok(TransactionWithReceipt { + transaction: starknet_api_transaction + .try_into() + .map_err(internal_server_error)?, + receipt, + }) + }) + .collect::, ErrorObjectOwned>>()?, + )) + }, + |txn, block_number| { + let transactions = get_block_txs_by_number(txn, block_number)?; + let transaction_hashes = get_block_tx_hashes_by_number(txn, block_number)?; + Ok(Transactions::FullWithReceipts( + transactions + .into_iter() + .zip(transaction_hashes) + .enumerate() + .map(|(transaction_offset, (transaction, transaction_hash))| { + let transaction_index = TransactionIndex( + block_number, + TransactionOffsetInBlock(transaction_offset), + ); + let msg_hash = match &transaction { + Transaction::L1Handler(l1_handler_tx) => { + Some(l1_handler_tx.calc_msg_hash()) + } + _ => None, + }; + let transaction_version = transaction.version(); + Ok(TransactionWithReceipt { + transaction, + receipt: get_non_pending_receipt( + txn, + transaction_index, + transaction_hash, + transaction_version, + msg_hash, + )? + .into(), + }) + }) + .collect::, ErrorObjectOwned>>()?, + )) + }, + ) + .await + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + block_id: BlockId, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_storage_diffs = if let BlockId::Tag(Tag::Pending) = block_id { + Some( + read_pending_data(&self.pending_data, &txn) + .await? + .state_update + .state_diff + .storage_diffs, + ) + } else { + None + }; + + // Check that the block is valid and get the state number. + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let res = execution_utils::get_storage_at( + &txn, + state_number, + maybe_pending_storage_diffs.as_ref(), + contract_address, + key, + ) + .map_err(internal_server_error)?; + + // If the contract is not deployed, res will be 0. Checking if that's the case so that + // we'll return an error instead. + // Contract address 0x1 is a special address, it stores the block + // hashes. Contracts are not deployed to this address. + if res == Felt::default() && contract_address != *BLOCK_HASH_TABLE_ADDRESS { + // check if the contract exists + txn.get_state_reader() + .map_err(internal_server_error)? + .get_class_hash_at(state_number, &contract_address) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND))?; + } + Ok(res) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_by_hash( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let Some(transaction_index) = + txn.get_transaction_idx_by_hash(&transaction_hash).map_err(internal_server_error)? + { + let transaction = txn + .get_transaction(transaction_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))?; + + Ok(TransactionWithHash { transaction: transaction.try_into()?, transaction_hash }) + } else { + // The transaction is not in any non-pending block. Search for it in the pending block + // and if it's not found, return error. + let client_transaction = read_pending_data(&self.pending_data, &txn) + .await? + .block + .transactions() + .iter() + .find(|transaction| transaction.transaction_hash() == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))? + .clone(); + + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.try_into().map_err(internal_server_error)?; + return Ok(TransactionWithHash { + transaction: starknet_api_transaction.try_into()?, + transaction_hash, + }); + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_by_block_id_and_index( + &self, + block_id: BlockId, + index: TransactionOffsetInBlock, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let (starknet_api_transaction, transaction_hash) = + if let BlockId::Tag(Tag::Pending) = block_id { + let client_transaction = read_pending_data(&self.pending_data, &txn) + .await? + .block + .transactions() + .get(index.0) + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))? + .clone(); + let transaction_hash = client_transaction.transaction_hash(); + (client_transaction.try_into().map_err(internal_server_error)?, transaction_hash) + } else { + let block_number = get_accepted_block_number(&txn, block_id)?; + + let tx_index = TransactionIndex(block_number, index); + let transaction = txn + .get_transaction(tx_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))?; + let transaction_hash = txn + .get_transaction_hash_by_idx(&tx_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(INVALID_TRANSACTION_INDEX))?; + (transaction, transaction_hash) + }; + + Ok(TransactionWithHash { + transaction: starknet_api_transaction.try_into()?, + transaction_hash, + }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let BlockId::Tag(Tag::Pending) = block_id { + let transactions_len = + read_pending_data(&self.pending_data, &txn).await?.block.transactions().len(); + Ok(transactions_len) + } else { + let block_number = get_accepted_block_number(&txn, block_id)?; + Ok(txn + .get_block_transactions_count(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_state_update(&self, block_id: BlockId) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + if let BlockId::Tag(Tag::Pending) = block_id { + let state_update = read_pending_data(&self.pending_data, &txn).await?.state_update; + return Ok(StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: state_update.old_root, + state_diff: state_update.state_diff.into(), + })); + } + + // Get the block header for the block hash and state root. + let block_number = get_accepted_block_number(&txn, block_id)?; + let header: BlockHeader = get_block_header_by_number(&txn, block_number)?.into(); + + // Get the old root. + let old_root = match get_accepted_block_number( + &txn, + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.parent_hash)), + ) { + Ok(parent_block_number) => { + BlockHeader::from(get_block_header_by_number(&txn, parent_block_number)?).new_root + } + Err(_) => GlobalRoot(StarkHash::from_hex_unchecked(GENESIS_HASH)), + }; + + // Get the block state diff. + let mut thin_state_diff = txn + .get_state_diff(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + // Remove empty storage diffs. Some blocks contain empty storage diffs that must be kept for + // the computation of state diff commitment. + thin_state_diff.storage_diffs.retain(|_k, v| !v.is_empty()); + + Ok(StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + block_hash: header.block_hash, + new_root: header.new_root, + old_root, + state_diff: thin_state_diff.into(), + })) + } + + async fn get_transaction_status( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + Ok(self.get_transaction_receipt(transaction_hash).await?.transaction_status()) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_transaction_receipt( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + if let Some(transaction_index) = + txn.get_transaction_idx_by_hash(&transaction_hash).map_err(internal_server_error)? + { + let tx = txn + .get_transaction(transaction_index) + .map_err(internal_server_error)? + .unwrap_or_else(|| panic!("Should have tx {}", transaction_hash)); + + // TODO: Add version function to transaction in SN_API. + let tx_version = match &tx { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + + let msg_hash = match tx { + StarknetApiTransaction::L1Handler(l1_handler_tx) => { + Some(l1_handler_tx.calc_msg_hash()) + } + _ => None, + }; + + get_non_pending_receipt(&txn, transaction_index, transaction_hash, tx_version, msg_hash) + } else { + // The transaction is not in any non-pending block. Search for it in the pending block + // and if it's not found, return error. + + // TODO(shahak): Consider cloning the transactions and the receipts in order to free + // the lock sooner (Check which is better). + let pending_data = read_pending_data(&self.pending_data, &txn).await?; + + let client_transaction_receipt = pending_data + .block + .transaction_receipts() + .iter() + .find(|receipt| receipt.transaction_hash == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))? + .clone(); + let client_transaction = &pending_data + .block + .transactions() + .iter() + .find(|tx| tx.transaction_hash() == transaction_hash) + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))? + .clone(); + client_receipt_to_rpc_pending_receipt(client_transaction, client_transaction_receipt) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult { + let block_id = if let BlockId::Tag(Tag::Pending) = block_id { + let maybe_class = &self.pending_classes.read().await.get_class(class_hash); + if let Some(class) = maybe_class { + return class.clone().try_into().map_err(internal_server_error); + } else { + BlockId::Tag(Tag::Latest) + } + } else { + block_id + }; + + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let state_reader = txn.get_state_reader().map_err(internal_server_error)?; + + // The class might be a deprecated class. Search it first in the declared classes and if not + // found, search in the deprecated classes. + if let Some(class) = state_reader + .get_class_definition_at(state_number, &class_hash) + .map_err(internal_server_error)? + { + Ok(GatewayContractClass::Sierra(class.into())) + } else { + let class = state_reader + .get_deprecated_class_definition_at(state_number, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; + Ok(GatewayContractClass::Cairo0(class.try_into().map_err(internal_server_error)?)) + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let class_hash = self.get_class_hash_at(block_id, contract_address).await?; + self.get_class(block_id, class_hash).await + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_class_hash_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_deployed_contracts_and_replaced_classes = + if let BlockId::Tag(Tag::Pending) = block_id { + let pending_state_diff = + read_pending_data(&self.pending_data, &txn).await?.state_update.state_diff; + Some((pending_state_diff.deployed_contracts, pending_state_diff.replaced_classes)) + } else { + None + }; + + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + execution_utils::get_class_hash_at( + &txn, + state_number, + // This map converts &(T, S) to (&T, &S). + maybe_pending_deployed_contracts_and_replaced_classes.as_ref().map(|t| (&t.0, &t.1)), + contract_address, + ) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_nonce( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_nonces = if let BlockId::Tag(Tag::Pending) = block_id { + Some(read_pending_data(&self.pending_data, &txn).await?.state_update.state_diff.nonces) + } else { + None + }; + + // Check that the block is valid and get the state number. + let block_number = get_accepted_block_number(&txn, block_id)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + execution_utils::get_nonce_at( + &txn, + state_number, + maybe_pending_nonces.as_ref(), + contract_address, + ) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CONTRACT_NOT_FOUND)) + } + + #[instrument(skip(self), level = "debug", err, ret)] + fn chain_id(&self) -> RpcResult { + Ok(self.chain_id.as_hex()) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn get_events(&self, filter: EventFilter) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + + // Check the chunk size. + if filter.chunk_size > self.max_events_chunk_size { + return Err(ErrorObjectOwned::from(PAGE_SIZE_TOO_BIG)); + } + // Check the number of keys. + if filter.keys.len() > self.max_events_keys { + return Err(ErrorObjectOwned::from(TOO_MANY_KEYS_IN_FILTER)); + } + + // Get the requested block numbers. + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let Some(latest_block_number) = get_latest_block_number(&txn)? else { + if matches!(filter.to_block, Some(BlockId::Tag(Tag::Pending)) | None) { + warn!( + "Received a request for pending events while there are no accepted blocks. \ + This is currently unsupported. Returning no events." + ); + } + // There are no blocks. + return Ok(EventsChunk { events: vec![], continuation_token: None }); + }; + let from_block_number = match filter.from_block { + None => BlockNumber(0), + Some(BlockId::Tag(Tag::Pending)) => latest_block_number.unchecked_next(), + Some(block_id) => get_accepted_block_number(&txn, block_id)?, + }; + let mut to_block_number = match filter.to_block { + Some(BlockId::Tag(Tag::Pending)) | None => latest_block_number.unchecked_next(), + Some(block_id) => get_accepted_block_number(&txn, block_id)?, + }; + + if from_block_number > to_block_number { + return Ok(EventsChunk { events: vec![], continuation_token: None }); + } + + // Get the event index. If there's a continuation token we take the event index from there. + // Otherwise, we take the first index in the from_block_number. + let start_event_index = match &filter.continuation_token { + Some(token) => token.parse()?.0, + None => EventIndex( + TransactionIndex(from_block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + }; + + let include_pending_block = to_block_number > latest_block_number; + if include_pending_block { + to_block_number = to_block_number.prev().expect( + "A block number that's greater than another block number should have a predecessor", + ); + } + + // Collect the requested events. + // Once we collected enough events, we continue to check if there are any more events + // corresponding to the requested filter. If there are, we return a continuation token + // pointing to the next relevant event. Otherwise, we return a continuation token None. + let mut filtered_events = vec![]; + if start_event_index.0.0 <= latest_block_number { + for ((from_address, event_index), content) in txn + .iter_events(filter.address, start_event_index, to_block_number) + .map_err(internal_server_error)? + { + let block_number = (event_index.0).0; + if block_number > to_block_number { + break; + } + if let Some(filter_address) = filter.address { + if from_address != filter_address { + // The iterator of this loop outputs only events that have the filter's + // address, unless there are no more such events and then it outputs other + // events, and we can stop the iteration. + break; + } + } + // TODO: Consider changing empty sets in the filer keys to None. + if do_event_keys_match_filter(&content, &filter) { + if filtered_events.len() == filter.chunk_size { + return Ok(EventsChunk { + events: filtered_events, + continuation_token: Some(ContinuationToken::new( + ContinuationTokenAsStruct(event_index), + )?), + }); + } + let header: BlockHeader = get_block_header_by_number(&txn, block_number) + .map_err(internal_server_error)? + .into(); + let transaction_hash = txn + .get_transaction_hash_by_idx(&event_index.0) + .map_err(internal_server_error)? + .ok_or_else(|| internal_server_error("Unknown internal error."))?; + let emitted_event = Event { + block_hash: Some(header.block_hash), + block_number: Some(block_number), + transaction_hash, + event: starknet_api::transaction::Event { from_address, content }, + }; + filtered_events.push(emitted_event); + } + } + } + + if include_pending_block { + let pending_block = read_pending_data(&self.pending_data, &txn).await?.block; + let pending_transaction_receipts = pending_block.transaction_receipts(); + // Extract the first transaction offset and event offset from the starting EventIndex. + let (transaction_start, event_start) = if start_event_index.0.0 > latest_block_number { + (start_event_index.0.1.0, start_event_index.1.0) + } else { + (0, 0) + }; + // TODO(shahak): Consider creating the iterator flattened and filtered. + for (transaction_offset, receipt) in pending_transaction_receipts.iter().enumerate() { + if transaction_offset < transaction_start { + continue; + } + for (event_offset, event) in receipt.events.iter().cloned().enumerate() { + if transaction_offset == transaction_start && event_offset < event_start { + continue; + } + if filtered_events.len() == filter.chunk_size { + return Ok(EventsChunk { + events: filtered_events, + continuation_token: Some(ContinuationToken::new( + ContinuationTokenAsStruct(EventIndex( + TransactionIndex( + latest_block_number.unchecked_next(), + TransactionOffsetInBlock(transaction_offset), + ), + EventIndexInTransactionOutput(event_offset), + )), + )?), + }); + } + if !do_event_keys_match_filter(&event.content, &filter) { + continue; + } + if let Some(filter_address) = filter.address { + if event.from_address != filter_address { + continue; + } + } + filtered_events.push(Event { + block_hash: None, + block_number: None, + transaction_hash: receipt.transaction_hash, + event, + }) + } + } + } + + Ok(EventsChunk { events: filtered_events, continuation_token: None }) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn syncing(&self) -> RpcResult { + let Some(highest_block) = *self.shared_highest_block.read().await else { + return Ok(SyncingState::Synced); + }; + let current_block = + get_last_synced_block(self.storage_reader.clone()).map_err(internal_server_error)?; + if highest_block.block_number <= current_block.block_number { + return Ok(SyncingState::Synced); + } + Ok(SyncingState::SyncStatus(SyncStatus { + starting_block_hash: self.starting_block.block_hash, + starting_block_num: self.starting_block.block_number, + current_block_hash: current_block.block_hash, + current_block_num: current_block.block_number, + highest_block_hash: highest_block.block_hash, + highest_block_num: highest_block.block_number, + })) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn call(&self, request: CallRequest, block_id: BlockId) -> RpcResult> { + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + let block_number = get_accepted_block_number(&txn, block_id)?; + let block_not_reverted_validator = BlockNotRevertedValidator::new(block_number, &txn)?; + drop(txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + let contract_address_copy = request.contract_address; + + let res = tokio::task::spawn_blocking(move || { + execute_call( + reader, + maybe_pending_data, + &chain_id, + state_number, + block_number, + &contract_address_copy, + request.entry_point_selector, + request.calldata, + &execution_config, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(res.retdata.0) + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_invoke_transaction( + &self, + invoke_transaction: TypedInvokeTransaction, + ) -> RpcResult { + let result = self.writer_client.add_invoke_transaction(&invoke_transaction.into()).await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_invoke_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_deploy_account_transaction( + &self, + deploy_account_transaction: TypedDeployAccountTransaction, + ) -> RpcResult { + let result = self + .writer_client + .add_deploy_account_transaction(&deploy_account_transaction.into()) + .await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_deploy_account_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self), level = "debug", err, ret)] + async fn add_declare_transaction( + &self, + declare_transaction: BroadcastedDeclareTransaction, + ) -> RpcResult { + let result = self + .writer_client + .add_declare_transaction( + &declare_transaction.try_into().map_err(internal_server_error)?, + ) + .await; + match result { + Ok(res) => Ok(res.into()), + Err(WriterClientError::ClientError(ClientError::StarknetError(starknet_error))) => { + Err(ErrorObjectOwned::from(starknet_error_to_declare_error(starknet_error))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self, transactions), level = "debug", err, ret)] + async fn estimate_fee( + &self, + transactions: Vec, + simulation_flags: Vec, + block_id: BlockId, + ) -> RpcResult> { + trace!("Estimating fee of transactions: {:#?}", transactions); + let validate = !simulation_flags.contains(&SimulationFlag::SkipValidate); + + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + + let executable_txns = + transactions.into_iter().map(|tx| tx.try_into()).collect::>()?; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let estimate_fee_result = tokio::task::spawn_blocking(move || { + exec_estimate_fee( + executable_txns, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + validate, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + match estimate_fee_result { + Ok(Ok(fees)) => Ok(fees), + Ok(Err(reverted_tx)) => { + Err(ErrorObjectOwned::from(JsonRpcError::::from( + TransactionExecutionError { + transaction_index: reverted_tx.index, + execution_error: reverted_tx.revert_reason, + }, + ))) + } + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self, transactions), level = "debug", err, ret)] + async fn simulate_transactions( + &self, + block_id: BlockId, + transactions: Vec, + simulation_flags: Vec, + ) -> RpcResult> { + trace!("Simulating transactions: {:#?}", transactions); + let executable_txns = + transactions.into_iter().map(|tx| tx.try_into()).collect::>()?; + + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let charge_fee = !simulation_flags.contains(&SimulationFlag::SkipFeeCharge); + let validate = !simulation_flags.contains(&SimulationFlag::SkipValidate); + + let simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_txns, + None, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + charge_fee, + validate, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(simulation_results + .into_iter() + .map(|simulation_output| SimulatedTransaction { + transaction_trace: ( + simulation_output.transaction_trace, + simulation_output.induced_state_diff, + ) + .into(), + fee_estimation: simulation_output.fee_estimation, + }) + .collect()) + } + + #[instrument(skip(self), level = "debug", err)] + async fn trace_transaction( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult { + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let pending_block = read_pending_data(&self.pending_data, &storage_txn).await?.block; + // Search for the transaction inside the pending block. + let ( + maybe_pending_data, + executable_transactions, + transaction_hashes, + block_number, + state_number, + ) = if let Some((pending_transaction_offset, _)) = pending_block + .transaction_receipts() + .iter() + .enumerate() + .find(|(_, receipt)| receipt.transaction_hash == transaction_hash) + { + // If there are no blocks in the network and there is a pending block, as an edge + // case we treat this as if the pending block is empty. + let block_number = + get_latest_block_number(&storage_txn)?.ok_or(INVALID_TRANSACTION_HASH)?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + let executable_transactions = pending_block + .transactions() + .iter() + .take(pending_transaction_offset + 1) + .map(|client_transaction| { + let starknet_api_transaction: StarknetApiTransaction = + client_transaction.clone().try_into().map_err(internal_server_error)?; + stored_txn_to_executable_txn( + starknet_api_transaction, + &storage_txn, + state_number, + ) + }) + .collect::>()?; + let transaction_hashes = pending_block + .transaction_receipts() + .iter() + .map(|receipt| receipt.transaction_hash) + .collect(); + let maybe_pending_data = Some(ExecutionPendingData { + timestamp: pending_block.timestamp(), + l1_gas_price: pending_block.l1_gas_price(), + l1_data_gas_price: pending_block.l1_data_gas_price(), + l1_da_mode: pending_block.l1_da_mode(), + sequencer: pending_block.sequencer_address(), + // The pending state diff should be empty since we look at the state in the + // start of the pending block. + // Not using ..Default::default() to avoid missing fields in the future. + storage_diffs: Default::default(), + deployed_contracts: Default::default(), + declared_classes: Default::default(), + old_declared_contracts: Default::default(), + nonces: Default::default(), + replaced_classes: Default::default(), + classes: Default::default(), + }); + ( + maybe_pending_data, + executable_transactions, + transaction_hashes, + block_number, + state_number, + ) + } else { + // Transaction is not inside the pending block. Search for it in the storage. + let TransactionIndex(block_number, tx_offset) = storage_txn + .get_transaction_idx_by_hash(&transaction_hash) + .map_err(internal_server_error)? + .ok_or(TRANSACTION_HASH_NOT_FOUND)?; + + let block_transactions = storage_txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?; + + let transaction_hashes = storage_txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?; + + let state_number = StateNumber::right_before_block(block_number); + let executable_transactions = block_transactions + .into_iter() + .take(tx_offset.0 + 1) + .map(|tx| stored_txn_to_executable_txn(tx, &storage_txn, state_number)) + .collect::>()?; + + (None, executable_transactions, transaction_hashes, block_number, state_number) + }; + + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + + drop(storage_txn); + + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let mut simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_transactions, + Some(transaction_hashes), + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + true, + true, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + let simulation_result = + simulation_results.pop().expect("Should have transaction exeuction result"); + Ok((simulation_result.transaction_trace, simulation_result.induced_state_diff).into()) + } + + #[instrument(skip(self), level = "debug", err)] + async fn trace_block_transactions( + &self, + block_id: BlockId, + ) -> RpcResult> { + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + + let maybe_client_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(read_pending_data(&self.pending_data, &storage_txn).await?) + } else { + None + }; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + + let (maybe_pending_data, block_transactions, transaction_hashes, state_number) = + match maybe_client_pending_data { + Some(client_pending_data) => ( + Some(ExecutionPendingData { + timestamp: client_pending_data.block.timestamp(), + l1_gas_price: client_pending_data.block.l1_gas_price(), + l1_data_gas_price: client_pending_data.block.l1_data_gas_price(), + l1_da_mode: client_pending_data.block.l1_da_mode(), + sequencer: client_pending_data.block.sequencer_address(), + // The pending state diff should be empty since we look at the state in the + // start of the pending block. + // Not using ..Default::default() to avoid missing fields in the future. + storage_diffs: Default::default(), + deployed_contracts: Default::default(), + declared_classes: Default::default(), + old_declared_contracts: Default::default(), + nonces: Default::default(), + replaced_classes: Default::default(), + classes: Default::default(), + }), + client_pending_data + .block + .transactions() + .iter() + .map(|client_transaction| { + client_transaction.clone().try_into().map_err(internal_server_error) + }) + .collect::, ErrorObjectOwned>>()?, + client_pending_data + .block + .transaction_receipts() + .iter() + .map(|receipt| receipt.transaction_hash) + .collect(), + StateNumber::unchecked_right_after_block(block_number), + ), + None => ( + None, + storage_txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?, + storage_txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block {block_number} transactions"), + }) + })?, + StateNumber::right_before_block(block_number), + ), + }; + + let executable_txns = block_transactions + .into_iter() + .map(|tx| stored_txn_to_executable_txn(tx, &storage_txn, state_number)) + .collect::>()?; + + drop(storage_txn); + + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + let transaction_hashes_clone = transaction_hashes.clone(); + + let simulation_results = tokio::task::spawn_blocking(move || { + exec_simulate_transactions( + executable_txns, + Some(transaction_hashes_clone), + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + true, + true, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)? + .map_err(execution_error_to_error_object_owned)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + Ok(simulation_results + .into_iter() + .zip(transaction_hashes) + .map(|(simulation_output, transaction_hash)| TransactionTraceWithHash { + transaction_hash, + trace_root: ( + simulation_output.transaction_trace, + simulation_output.induced_state_diff, + ) + .into(), + }) + .collect()) + } + + #[instrument(skip(self, message), level = "debug", err)] + async fn estimate_message_fee( + &self, + message: MessageFromL1, + block_id: BlockId, + ) -> RpcResult { + trace!("Estimating fee of message: {:#?}", message); + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let maybe_pending_data = if let BlockId::Tag(Tag::Pending) = block_id { + Some(client_pending_data_to_execution_pending_data( + read_pending_data(&self.pending_data, &storage_txn).await?, + self.pending_classes.read().await.clone(), + )) + } else { + None + }; + // Convert the message to an L1 handler transaction, and estimate the fee of the + // transaction. + // The fee input is used to bound the amount of fee used. Because we want to estimate the + // fee, we pass u128::MAX so the execution won't fail. + let executable_txns = + vec![ExecutableTransactionInput::L1Handler(message.into(), Fee(u128::MAX), false)]; + + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + let block_not_reverted_validator = + BlockNotRevertedValidator::new(block_number, &storage_txn)?; + drop(storage_txn); + let state_number = StateNumber::unchecked_right_after_block(block_number); + let execution_config = self.execution_config; + + let chain_id = self.chain_id.clone(); + let reader = self.storage_reader.clone(); + + let estimate_fee_result = tokio::task::spawn_blocking(move || { + exec_estimate_fee( + executable_txns, + &chain_id, + reader, + maybe_pending_data, + state_number, + block_number, + &execution_config, + false, + DONT_IGNORE_L1_DA_MODE, + ) + }) + .await + .map_err(internal_server_error)?; + + block_not_reverted_validator.validate(&self.storage_reader)?; + + match estimate_fee_result { + Ok(Ok(mut fee_as_vec)) => { + if fee_as_vec.len() != 1 { + return Err(internal_server_error(format!( + "Expected a single fee, got {}", + fee_as_vec.len() + ))); + } + let Some(fee_estimation) = fee_as_vec.pop() else { + return Err(internal_server_error( + "Expected a single fee, got an empty vector", + )); + }; + Ok(fee_estimation) + } + // Error in the execution of the contract. + Ok(Err(reverted_tx)) => Err(JsonRpcError::::from(ContractError { + revert_error: reverted_tx.revert_reason, + }) + .into()), + // Internal error during the execution. + Err(err) => Err(internal_server_error(err)), + } + } + + #[instrument(skip(self), level = "debug", err)] + fn get_compiled_contract_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult { + let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let state_reader = storage_txn.get_state_reader().map_err(internal_server_error)?; + let block_number = get_accepted_block_number(&storage_txn, block_id)?; + + // Check if this class exists in the Cairo1 classes table. + if let Some(class_definition_block_number) = state_reader + .get_class_definition_block_number(&class_hash) + .map_err(internal_server_error)? + { + if class_definition_block_number > block_number { + return Err(ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND)); + } + let casm = storage_txn + .get_casm(&class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; + return Ok(CompiledContractClass::V1(casm)); + } + + // Check if this class exists in the Cairo0 classes table. + let state_number = StateNumber::right_after_block(block_number) + .ok_or_else(|| internal_server_error("Could not compute state number"))?; + let deprecated_compiled_contract_class = state_reader + .get_deprecated_class_definition_at(state_number, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; + Ok(CompiledContractClass::V0(deprecated_compiled_contract_class)) + } +} + +async fn read_pending_data( + pending_data: &Arc>, + txn: &StorageTxn<'_, Mode>, +) -> RpcResult { + let latest_header = match get_latest_block_number(txn)? { + Some(latest_block_number) => get_block_header_by_number(txn, latest_block_number)?, + None => starknet_api::block::BlockHeader { + parent_hash: BlockHash(StarkHash::from_hex_unchecked(GENESIS_HASH)), + ..Default::default() + }, + }; + let pending_data = &pending_data.read().await; + if pending_data.block.parent_block_hash() == latest_header.block_hash { + Ok((*pending_data).clone()) + } else { + Ok(PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: latest_header.block_hash, + eth_l1_gas_price: latest_header.l1_gas_price.price_in_wei, + strk_l1_gas_price: latest_header.l1_gas_price.price_in_fri, + timestamp: latest_header.timestamp, + sequencer_address: latest_header.sequencer, + starknet_version: latest_header.starknet_version.0, + ..Default::default() + }), + state_update: ClientPendingStateUpdate { + old_root: latest_header.state_root, + state_diff: Default::default(), + }, + }) + } +} + +impl JsonRpcServerImpl { + // Get the block with the given ID and the given custom logic for getting the transactions. + async fn get_block( + &self, + block_id: BlockId, + get_pending_transactions: impl FnOnce(PendingData) -> RpcResult, + get_transactions: impl FnOnce(&StorageTxn<'_, RO>, BlockNumber) -> RpcResult, + ) -> RpcResult { + verify_storage_scope(&self.storage_reader)?; + let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; + if let BlockId::Tag(Tag::Pending) = block_id { + let pending_data = read_pending_data(&self.pending_data, &txn).await?; + let block = &pending_data.block; + let pending_block_header = PendingBlockHeader { + parent_hash: block.parent_block_hash(), + sequencer_address: block.sequencer_address(), + timestamp: block.timestamp(), + l1_gas_price: ResourcePrice { + price_in_wei: block.l1_gas_price().price_in_wei, + price_in_fri: block.l1_gas_price().price_in_fri, + }, + l1_data_gas_price: ResourcePrice { + price_in_wei: block.l1_data_gas_price().price_in_wei, + price_in_fri: block.l1_data_gas_price().price_in_fri, + }, + l1_da_mode: block.l1_da_mode(), + starknet_version: block.starknet_version(), + }; + let header = GeneralBlockHeader::PendingBlockHeader(pending_block_header); + + return Ok(Block { + status: None, + header, + transactions: get_pending_transactions(pending_data)?, + }); + } + + let block_number = get_accepted_block_number(&txn, block_id)?; + let status = get_block_status(&txn, block_number)?; + let header = + GeneralBlockHeader::BlockHeader(get_block_header_by_number(&txn, block_number)?.into()); + Ok(Block { + status: Some(status), + header, + transactions: get_transactions(&txn, block_number)?, + }) + } +} + +fn get_non_pending_receipt( + txn: &StorageTxn<'_, Mode>, + transaction_index: TransactionIndex, + transaction_hash: TransactionHash, + tx_version: TransactionVersion, + msg_hash: Option, +) -> RpcResult { + let block_number = transaction_index.0; + let status = get_block_status(txn, block_number)?; + + // rejected blocks should not be a part of the API so we early return here. + // this assumption also holds for the conversion from block status to transaction + // finality status where we set rejected blocks to unreachable. + if status == BlockStatus::Rejected { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND)); + } + + let block_hash = + get_block_header_by_number(txn, block_number).map_err(internal_server_error)?.block_hash; + + let output = txn + .get_transaction_output(transaction_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(TRANSACTION_HASH_NOT_FOUND))?; + + let output = TransactionOutput::from((output, tx_version, msg_hash)); + + Ok(GeneralTransactionReceipt::TransactionReceipt(TransactionReceipt { + finality_status: status.into(), + transaction_hash, + block_hash, + block_number, + output, + })) +} + +fn client_receipt_to_rpc_pending_receipt( + client_transaction: &ClientTransaction, + client_transaction_receipt: ClientTransactionReceipt, +) -> RpcResult { + let transaction_hash = client_transaction.transaction_hash(); + let starknet_api_output = + client_transaction_receipt.into_starknet_api_transaction_output(client_transaction); + let msg_hash = match client_transaction { + ClientTransaction::L1Handler(tx) => Some(tx.calc_msg_hash()), + _ => None, + }; + let output = PendingTransactionOutput::try_from(TransactionOutput::from(( + starknet_api_output, + client_transaction.transaction_version(), + msg_hash, + )))?; + Ok(GeneralTransactionReceipt::PendingTransactionReceipt(PendingTransactionReceipt { + // ACCEPTED_ON_L2 is the only finality status of a pending transaction. + finality_status: PendingTransactionFinalityStatus::AcceptedOnL2, + transaction_hash, + output, + })) +} + +fn do_event_keys_match_filter(event_content: &EventContent, filter: &EventFilter) -> bool { + filter.keys.iter().enumerate().all(|(i, keys)| { + event_content.keys.len() > i && (keys.is_empty() || keys.contains(&event_content.keys[i])) + }) +} + +impl JsonRpcServerTrait for JsonRpcServerImpl { + fn new( + chain_id: ChainId, + execution_config: ExecutionConfig, + storage_reader: StorageReader, + max_events_chunk_size: usize, + max_events_keys: usize, + starting_block: BlockHashAndNumber, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + writer_client: Arc, + ) -> Self { + Self { + chain_id, + execution_config, + storage_reader, + max_events_chunk_size, + max_events_keys, + starting_block, + shared_highest_block, + pending_data, + pending_classes, + writer_client, + } + } + + fn into_rpc_module(self) -> RpcModule { + self.into_rpc() + } +} diff --git a/crates/papyrus_rpc/src/v0_7/api/mod.rs b/crates/papyrus_rpc/src/v0_7/api/mod.rs new file mode 100644 index 00000000000..a19000eaf09 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/api/mod.rs @@ -0,0 +1,681 @@ +use std::collections::HashSet; +use std::io::Read; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use flate2::bufread::GzDecoder; +use jsonrpsee::core::RpcResult; +use jsonrpsee::proc_macros::rpc; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_common::deprecated_class_abi::calculate_deprecated_class_abi_length; +use papyrus_common::pending_classes::ApiContractClass; +use papyrus_common::BlockHashAndNumber; +use papyrus_execution::objects::FeeEstimation; +use papyrus_execution::{AbiSize, ExecutableTransactionInput, ExecutionError, SierraSize}; +use papyrus_proc_macros::versioned_rpc; +use papyrus_storage::compiled_class::CasmStorageReader; +use papyrus_storage::db::serialization::StorageSerdeError; +use papyrus_storage::db::RO; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::StorageTxn; +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, ContractAddress, Nonce}; +use starknet_api::deprecated_contract_class::{ + ContractClass as StarknetApiDeprecatedContractClass, + Program, +}; +use starknet_api::state::{StateNumber, StorageKey}; +use starknet_api::transaction::{EventKey, Fee, TransactionHash, TransactionOffsetInBlock}; +use starknet_types_core::felt::Felt; +use tracing::debug; + +use super::block::Block; +use super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedTransaction, +}; +use super::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use super::error::{ + ContractError, + JsonRpcError, + BLOCK_NOT_FOUND, + CONTRACT_NOT_FOUND, + INVALID_CONTINUATION_TOKEN, +}; +use super::execution::TransactionTrace; +use super::state::{ContractClass, StateUpdate}; +use super::transaction::{ + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + Event, + GeneralTransactionReceipt, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + MessageFromL1, + TransactionStatus, + TransactionWithHash, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::write_api_result::{AddDeclareOkResult, AddDeployAccountOkResult, AddInvokeOkResult}; +use crate::api::{BlockId, CallRequest}; +use crate::syncing_state::SyncingState; +use crate::{internal_server_error, ContinuationTokenAsStruct}; + +pub mod api_impl; +#[cfg(test)] +mod test; + +#[versioned_rpc("V0_7")] +#[async_trait] +pub trait JsonRpc { + /// Returns the version of the Starknet JSON-RPC specification being used + #[method(name = "specVersion")] + fn spec_version(&self) -> RpcResult; + + /// Gets the most recent accepted block number. + #[method(name = "blockNumber")] + fn block_number(&self) -> RpcResult; + + /// Gets the most recent accepted block hash and number. + #[method(name = "blockHashAndNumber")] + fn block_hash_and_number(&self) -> RpcResult; + + /// Gets block information with transaction hashes given a block identifier. + #[method(name = "getBlockWithTxHashes")] + async fn get_block_w_transaction_hashes(&self, block_id: BlockId) -> RpcResult; + + /// Gets block information with full transactions given a block identifier. + #[method(name = "getBlockWithTxs")] + async fn get_block_w_full_transactions(&self, block_id: BlockId) -> RpcResult; + + /// Gets block information with full transactions given a block identifier. + #[method(name = "getBlockWithReceipts")] + async fn get_block_w_full_transactions_and_receipts( + &self, + block_id: BlockId, + ) -> RpcResult; + + /// Gets the value of the storage at the given address, key, and block. + #[method(name = "getStorageAt")] + async fn get_storage_at( + &self, + contract_address: ContractAddress, + key: StorageKey, + block_id: BlockId, + ) -> RpcResult; + + /// Gets the details of a submitted transaction. + #[method(name = "getTransactionByHash")] + async fn get_transaction_by_hash( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the details of a transaction by a given block id and index. + #[method(name = "getTransactionByBlockIdAndIndex")] + async fn get_transaction_by_block_id_and_index( + &self, + block_id: BlockId, + index: TransactionOffsetInBlock, + ) -> RpcResult; + + /// Gets the number of transactions in a block given a block id. + #[method(name = "getBlockTransactionCount")] + async fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult; + + /// Gets the information about the result of executing the requested block. + #[method(name = "getStateUpdate")] + async fn get_state_update(&self, block_id: BlockId) -> RpcResult; + + /// Gets the transaction status. + #[method(name = "getTransactionStatus")] + async fn get_transaction_status( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the transaction receipt by the transaction hash. + #[method(name = "getTransactionReceipt")] + async fn get_transaction_receipt( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Gets the contract class definition associated with the given hash. + #[method(name = "getClass")] + async fn get_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult; + + /// Gets the contract class definition in the given block at the given address. + #[method(name = "getClassAt")] + async fn get_class_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Gets the contract class hash in the given block for the contract deployed at the given + /// address. + #[method(name = "getClassHashAt")] + async fn get_class_hash_at( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Gets the nonce associated with the given address in the given block. + #[method(name = "getNonce")] + async fn get_nonce( + &self, + block_id: BlockId, + contract_address: ContractAddress, + ) -> RpcResult; + + /// Returns the currently configured StarkNet chain id. + #[method(name = "chainId")] + fn chain_id(&self) -> RpcResult; + + /// Returns all events matching the given filter. + #[method(name = "getEvents")] + async fn get_events(&self, filter: EventFilter) -> RpcResult; + + /// Returns the synching status of the node, or false if the node is not synching. + #[method(name = "syncing")] + async fn syncing(&self) -> RpcResult; + + /// Executes the entry point of the contract at the given address with the given calldata, + /// returns the result (Retdata). + #[method(name = "call")] + async fn call(&self, request: CallRequest, block_id: BlockId) -> RpcResult>; + + /// Submits a new invoke transaction to be added to the chain. + #[method(name = "addInvokeTransaction")] + async fn add_invoke_transaction( + &self, + invoke_transaction: TypedInvokeTransaction, + ) -> RpcResult; + + /// Submits a new deploy account transaction to be added to the chain. + #[method(name = "addDeployAccountTransaction")] + async fn add_deploy_account_transaction( + &self, + deploy_account_transaction: TypedDeployAccountTransaction, + ) -> RpcResult; + + /// Submits a new declare transaction to be added to the chain. + #[method(name = "addDeclareTransaction")] + async fn add_declare_transaction( + &self, + declare_transaction: BroadcastedDeclareTransaction, + ) -> RpcResult; + + /// Estimates the fee of a series of transactions. + #[method(name = "estimateFee")] + async fn estimate_fee( + &self, + request: Vec, + simulation_flags: Vec, + block_id: BlockId, + ) -> RpcResult>; + + /// Estimates the fee of a message from L1. + #[method(name = "estimateMessageFee")] + async fn estimate_message_fee( + &self, + message: MessageFromL1, + block_id: BlockId, + ) -> RpcResult; + + /// Simulates execution of a series of transactions. + #[method(name = "simulateTransactions")] + async fn simulate_transactions( + &self, + block_id: BlockId, + transactions: Vec, + simulation_flags: Vec, + ) -> RpcResult>; + + /// Calculates the transaction trace of a transaction that is already included in a block. + #[method(name = "traceTransaction")] + async fn trace_transaction( + &self, + transaction_hash: TransactionHash, + ) -> RpcResult; + + /// Calculates the transaction trace of all of the transactions in a block. + #[method(name = "traceBlockTransactions")] + async fn trace_block_transactions( + &self, + block_id: BlockId, + ) -> RpcResult>; + + /// Returns the compiled contract class associated with the given class hash. + #[method(name = "getCompiledContractClass")] + fn get_compiled_contract_class( + &self, + block_id: BlockId, + class_hash: ClassHash, + ) -> RpcResult; +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(test, derive(PartialEq))] +#[serde(untagged)] +pub enum GatewayContractClass { + Cairo0(DeprecatedContractClass), + Sierra(ContractClass), +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct EventsChunk { + pub events: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct EventFilter { + #[serde(skip_serializing_if = "Option::is_none")] + pub from_block: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub to_block: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, + pub chunk_size: usize, + #[serde(skip_serializing_if = "Option::is_none")] + pub address: Option, + #[serde(default)] + pub keys: Vec>, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct ContinuationToken(pub String); + +impl ContinuationToken { + fn parse(&self) -> Result { + let ct = serde_json::from_str(&self.0) + .map_err(|_| ErrorObjectOwned::from(INVALID_CONTINUATION_TOKEN))?; + + Ok(ContinuationTokenAsStruct(ct)) + } + + fn new(ct: ContinuationTokenAsStruct) -> Result { + Ok(Self(serde_json::to_string(&ct.0).map_err(internal_server_error)?)) + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct SimulatedTransaction { + pub transaction_trace: TransactionTrace, + pub fee_estimation: FeeEstimation, +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum SimulationFlag { + SkipValidate, + SkipFeeCharge, +} + +impl TryFrom for ExecutableTransactionInput { + type Error = ErrorObjectOwned; + fn try_from(value: BroadcastedTransaction) -> Result { + // TODO(yair): pass the right value for only_query field. + match value { + BroadcastedTransaction::Declare(tx) => Ok(tx.try_into()?), + BroadcastedTransaction::DeployAccount(tx) => Ok(Self::DeployAccount(tx.into(), false)), + BroadcastedTransaction::Invoke(tx) => Ok(Self::Invoke(tx.into(), false)), + } + } +} + +pub(crate) fn stored_txn_to_executable_txn( + stored_txn: starknet_api::transaction::Transaction, + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, +) -> Result { + match stored_txn { + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V0(value), + ) => { + // Copy the class hash before the value moves. + let class_hash = value.class_hash; + let deprecated_class = + get_deprecated_class_for_re_execution(storage_txn, state_number, class_hash)?; + let abi_length = calculate_deprecated_class_abi_length(&deprecated_class) + .map_err(internal_server_error)?; + Ok(ExecutableTransactionInput::DeclareV0(value, deprecated_class, abi_length, false)) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V1(value), + ) => { + // Copy the class hash before the value moves. + let class_hash = value.class_hash; + let deprecated_class = + get_deprecated_class_for_re_execution(storage_txn, state_number, class_hash)?; + let abi_length = calculate_deprecated_class_abi_length(&deprecated_class) + .map_err(internal_server_error)?; + Ok(ExecutableTransactionInput::DeclareV1(value, deprecated_class, abi_length, false)) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V2(value), + ) => { + let casm = storage_txn + .get_casm(&value.class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!( + "Missing casm of class hash {}.", + value.class_hash + )) + })?; + let (sierra_program_length, abi_length) = + get_class_lengths(storage_txn, state_number, value.class_hash)?; + Ok(ExecutableTransactionInput::DeclareV2( + value, + casm, + sierra_program_length, + abi_length, + false, + )) + } + starknet_api::transaction::Transaction::Declare( + starknet_api::transaction::DeclareTransaction::V3(value), + ) => { + let casm = storage_txn + .get_casm(&value.class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!( + "Missing casm of class hash {}.", + value.class_hash + )) + })?; + let (sierra_program_length, abi_length) = + get_class_lengths(storage_txn, state_number, value.class_hash)?; + Ok(ExecutableTransactionInput::DeclareV3( + value, + casm, + sierra_program_length, + abi_length, + false, + )) + } + starknet_api::transaction::Transaction::Deploy(_) => { + Err(internal_server_error("Deploy txns not supported in execution")) + } + starknet_api::transaction::Transaction::DeployAccount(deploy_account_tx) => { + Ok(ExecutableTransactionInput::DeployAccount(deploy_account_tx, false)) + } + starknet_api::transaction::Transaction::Invoke(value) => { + Ok(ExecutableTransactionInput::Invoke(value, false)) + } + starknet_api::transaction::Transaction::L1Handler(value) => { + // todo(yair): This is a temporary solution until we have a better way to get the l1 + // fee. + let paid_fee_on_l1 = Fee(1); + Ok(ExecutableTransactionInput::L1Handler(value, paid_fee_on_l1, false)) + } + } +} + +// For re-execution (traceTransaction, traceBlockTransactions) we need to get the class definition +// of declare transactions from the storage before the execution. They are stored in the state after +// the block in which they appeared, so we need to get it from the state after given block. +fn get_deprecated_class_for_re_execution( + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, + class_hash: ClassHash, +) -> Result { + let state_number_after_block = + StateNumber::unchecked_right_after_block(state_number.block_after()); + storage_txn + .get_state_reader() + .map_err(internal_server_error)? + .get_deprecated_class_definition_at(state_number_after_block, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!("Missing deprecated class definition of {class_hash}.")) + }) +} + +fn get_class_lengths( + storage_txn: &StorageTxn<'_, RO>, + state_number: StateNumber, + class_hash: ClassHash, +) -> Result<(SierraSize, AbiSize), ErrorObjectOwned> { + let state_number_after_block = + StateNumber::unchecked_right_after_block(state_number.block_after()); + storage_txn + .get_state_reader() + .map_err(internal_server_error)? + .get_class_definition_at(state_number_after_block, &class_hash) + .map_err(internal_server_error)? + .ok_or_else(|| { + internal_server_error(format!("Missing deprecated class definition of {class_hash}.")) + }) + .map(|contract_class| (contract_class.sierra_program.len(), contract_class.abi.len())) +} + +impl TryFrom for ExecutableTransactionInput { + type Error = ErrorObjectOwned; + fn try_from(value: BroadcastedDeclareTransaction) -> Result { + match value { + BroadcastedDeclareTransaction::V1(BroadcastedDeclareV1Transaction { + r#type: _, + contract_class, + sender_address, + nonce, + max_fee, + signature, + }) => { + let sn_api_contract_class = + user_deprecated_contract_class_to_sn_api(contract_class)?; + let abi_length = calculate_deprecated_class_abi_length(&sn_api_contract_class) + .map_err(internal_server_error)?; + Ok(Self::DeclareV1( + starknet_api::transaction::DeclareTransactionV0V1 { + max_fee, + signature, + nonce, + // The blockifier doesn't need the class hash, but it uses the SN_API + // DeclareTransactionV0V1 which requires it. + class_hash: ClassHash::default(), + sender_address, + }, + sn_api_contract_class, + abi_length, + // TODO(yair): pass the right value for only_query field. + false, + )) + } + BroadcastedDeclareTransaction::V2(_) => { + // TODO(yair): We need a way to get the casm of a declare V2 transaction. + Err(internal_server_error("Declare V2 is not supported yet in execution.")) + } + BroadcastedDeclareTransaction::V3(_) => { + // TODO(yair): We need a way to get the casm of a declare V3 transaction. + Err(internal_server_error("Declare V3 is not supported yet in execution.")) + } + } + } +} + +fn user_deprecated_contract_class_to_sn_api( + value: starknet_client::writer::objects::transaction::DeprecatedContractClass, +) -> Result { + Ok(starknet_api::deprecated_contract_class::ContractClass { + abi: value.abi, + program: decompress_program(&value.compressed_program)?, + entry_points_by_type: value.entry_points_by_type, + }) +} + +impl From for starknet_api::transaction::DeployAccountTransaction { + fn from(tx: DeployAccountTransaction) -> Self { + match tx { + DeployAccountTransaction::Version1(DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: _, + }) => Self::V1(starknet_api::transaction::DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + }), + DeployAccountTransaction::Version3(DeployAccountTransactionV3 { + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: _, + resource_bounds, + tip, + paymaster_data, + nonce_data_availability_mode, + fee_data_availability_mode, + }) => Self::V3(starknet_api::transaction::DeployAccountTransactionV3 { + resource_bounds: resource_bounds.into(), + tip, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + }), + } + } +} + +impl From for starknet_api::transaction::InvokeTransaction { + fn from(value: InvokeTransaction) -> Self { + match value { + InvokeTransaction::Version0(InvokeTransactionV0 { + max_fee, + version: _, + signature, + contract_address, + entry_point_selector, + calldata, + }) => Self::V0(starknet_api::transaction::InvokeTransactionV0 { + max_fee, + signature, + contract_address, + entry_point_selector, + calldata, + }), + InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee, + version: _, + signature, + nonce, + sender_address, + calldata, + }) => Self::V1(starknet_api::transaction::InvokeTransactionV1 { + max_fee, + signature, + nonce, + sender_address, + calldata, + }), + InvokeTransaction::Version3(InvokeTransactionV3 { + sender_address, + calldata, + version: _, + signature, + nonce, + resource_bounds, + tip, + paymaster_data, + account_deployment_data, + nonce_data_availability_mode, + fee_data_availability_mode, + }) => Self::V3(starknet_api::transaction::InvokeTransactionV3 { + resource_bounds: resource_bounds.into(), + tip, + signature, + nonce, + sender_address, + calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }), + } + } +} + +impl TryFrom for GatewayContractClass { + type Error = StorageSerdeError; + fn try_from(class: ApiContractClass) -> Result { + match class { + ApiContractClass::DeprecatedContractClass(deprecated_class) => { + Ok(Self::Cairo0(deprecated_class.try_into()?)) + } + ApiContractClass::ContractClass(sierra_class) => Ok(Self::Sierra(sierra_class.into())), + } + } +} + +pub(crate) fn execution_error_to_error_object_owned(err: ExecutionError) -> ErrorObjectOwned { + match err { + ExecutionError::MissingCompiledClass { class_hash } => { + debug!( + "Execution failed because it required the compiled class with hash {class_hash} \ + and we didn't download it yet." + ); + BLOCK_NOT_FOUND.into() + } + ExecutionError::ContractError(blockifier_err) => { + let contract_err = ContractError { revert_error: blockifier_err.to_string() }; + let rpc_err: JsonRpcError = contract_err.into(); + rpc_err.into() + } + ExecutionError::ContractNotFound { .. } => CONTRACT_NOT_FOUND.into(), + _ => internal_server_error(err), + } +} + +pub(crate) fn decompress_program( + base64_compressed_program: &String, +) -> Result { + base64::decode(base64_compressed_program).map_err(internal_server_error)?; + let compressed_data = + base64::decode(base64_compressed_program).map_err(internal_server_error)?; + let mut decoder = GzDecoder::new(compressed_data.as_slice()); + let mut decompressed = Vec::new(); + decoder.read_to_end(&mut decompressed).map_err(internal_server_error)?; + serde_json::from_reader(decompressed.as_slice()).map_err(internal_server_error) +} + +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct TransactionTraceWithHash { + pub transaction_hash: TransactionHash, + pub trace_root: TransactionTrace, +} + +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub enum CompiledContractClass { + V0(StarknetApiDeprecatedContractClass), + V1(CasmContractClass), +} diff --git a/crates/papyrus_rpc/src/v0_7/api/test.rs b/crates/papyrus_rpc/src/v0_7/api/test.rs new file mode 100644 index 00000000000..73a41cc064f --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/api/test.rs @@ -0,0 +1,3993 @@ +use std::collections::{HashMap, HashSet}; +use std::fmt::Debug; +use std::iter; +use std::net::SocketAddr; +use std::ops::Index; + +use assert_matches::assert_matches; +use async_trait::async_trait; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::{indexmap, IndexMap}; +use itertools::Itertools; +use jsonrpsee::core::Error; +use jsonrpsee::Methods; +use jsonschema::JSONSchema; +use lazy_static::lazy_static; +use mockall::predicate::eq; +use papyrus_common::pending_classes::{ApiContractClass, PendingClassesTrait}; +use papyrus_common::BlockHashAndNumber; +use papyrus_storage::base_layer::BaseLayerStorageWriter; +use papyrus_storage::body::events::EventIndex; +use papyrus_storage::body::{BodyStorageWriter, TransactionIndex}; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::StorageScope; +use pretty_assertions::assert_eq; +use rand::{random, RngCore}; +use rand_chacha::ChaCha8Rng; +use reqwest::StatusCode; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{ + Block as StarknetApiBlock, + BlockHash, + BlockHeader, + BlockNumber, + BlockStatus, + BlockTimestamp, + GasPrice, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + GlobalRoot, + Nonce, + PatriciaKey, + SequencerContractAddress, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::deprecated_contract_class::{ + ContractClass as StarknetApiDeprecatedContractClass, + ContractClassAbiEntry, + FunctionAbiEntry, + FunctionStateMutability, +}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass as StarknetApiContractClass, StateDiff, StorageKey}; +use starknet_api::transaction::{ + Event as StarknetApiEvent, + EventContent, + EventData, + EventIndexInTransactionOutput, + EventKey, + Transaction as StarknetApiTransaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput as StarknetApiTransactionOutput, +}; +use starknet_api::{felt, patricia_key}; +use starknet_client::reader::objects::pending_data::{ + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate as ClientPendingStateUpdate, +}; +use starknet_client::reader::objects::state::{ + DeclaredClassHashEntry as ClientDeclaredClassHashEntry, + DeployedContract as ClientDeployedContract, + ReplacedClass as ClientReplacedClass, + StateDiff as ClientStateDiff, + StorageEntry as ClientStorageEntry, +}; +use starknet_client::reader::objects::transaction::{ + Transaction as ClientTransaction, + TransactionReceipt as ClientTransactionReceipt, +}; +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, +}; +use starknet_client::writer::objects::transaction::{ + DeclareTransaction as ClientDeclareTransaction, + DeployAccountTransaction as ClientDeployAccountTransaction, + InvokeTransaction as ClientInvokeTransaction, +}; +use starknet_client::writer::{MockStarknetWriter, WriterClientError, WriterClientResult}; +use starknet_client::ClientError; +use starknet_types_core::felt::Felt; +use test_utils::{ + auto_impl_get_test_instance, + get_number_of_variants, + get_rng, + get_test_block, + get_test_body, + get_test_state_diff, + send_request, + GetTestInstance, +}; + +use super::super::api::EventsChunk; +use super::super::block::{Block, GeneralBlockHeader, PendingBlockHeader, ResourcePrice}; +use super::super::broadcasted_transaction::BroadcastedDeclareTransaction; +use super::super::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use super::super::error::{ + unexpected_error, + JsonRpcError, + BLOCK_NOT_FOUND, + CLASS_HASH_NOT_FOUND, + COMPILATION_FAILED, + CONTRACT_NOT_FOUND, + DUPLICATE_TX, + INVALID_CONTINUATION_TOKEN, + INVALID_TRANSACTION_INDEX, + NO_BLOCKS, + PAGE_SIZE_TOO_BIG, + TOO_MANY_KEYS_IN_FILTER, + TRANSACTION_HASH_NOT_FOUND, +}; +use super::super::state::{ + AcceptedStateUpdate, + ClassHashes, + ContractClass, + ContractNonce, + DeployedContract, + PendingStateUpdate, + ReplacedClasses, + StateUpdate, + StorageDiff, + StorageEntry, + ThinStateDiff, +}; +use super::super::transaction::{ + DeployAccountTransaction, + Event, + GeneralTransactionReceipt, + InvokeTransaction, + L1HandlerMsgHash, + L1L2MsgHash, + PendingTransactionFinalityStatus, + PendingTransactionOutput, + PendingTransactionReceipt, + Transaction, + TransactionFinalityStatus, + TransactionOutput, + TransactionReceipt, + TransactionStatus, + TransactionWithHash, + TransactionWithReceipt, + Transactions, + TypedDeployAccountTransaction, + TypedInvokeTransaction, +}; +use super::super::write_api_result::{ + AddDeclareOkResult, + AddDeployAccountOkResult, + AddInvokeOkResult, +}; +use super::api_impl::{JsonRpcServerImpl, BLOCK_HASH_TABLE_ADDRESS}; +use super::{ContinuationToken, EventFilter, GatewayContractClass}; +use crate::api::{BlockHashOrNumber, BlockId, Tag}; +use crate::syncing_state::SyncStatus; +use crate::test_utils::{ + call_and_validate_schema_for_result, + call_api_then_assert_and_validate_schema_for_err, + call_api_then_assert_and_validate_schema_for_result, + get_method_names_from_spec, + get_starknet_spec_api_schema_for_components, + get_starknet_spec_api_schema_for_method_results, + get_test_highest_block, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, + get_test_rpc_server_and_storage_writer, + get_test_rpc_server_and_storage_writer_from_params, + method_name_to_spec_method_name, + raw_call, + validate_schema, + SpecFile, +}; +use crate::v0_7::api::CompiledContractClass; +use crate::version_config::VERSION_0_7 as VERSION; +use crate::{ + internal_server_error, + internal_server_error_with_msg, + run_server, + ContinuationTokenAsStruct, + GENESIS_HASH, +}; + +const NODE_VERSION: &str = "NODE VERSION"; + +#[tokio::test] +async fn spec_version() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_7_specVersion", + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &format!("{VERSION}"), + ) + .await; +} + +#[tokio::test] +async fn chain_id() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + // The result should be equal to the result of the following python code + // hex(int.from_bytes(b'SN_SEPOLIA', byteorder="big", signed=False)) + // taken from starknet documentation: + // https://docs.starknet.io/documentation/develop/Blocks/transactions/#chain-id. + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_7_chainId", + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &String::from("0x534e5f5345504f4c4941"), + ) + .await; +} + +#[tokio::test] +async fn block_hash_and_number() { + let method_name = "starknet_V0_7_blockHashAndNumber"; + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + + // No blocks yet. + call_api_then_assert_and_validate_schema_for_err::<_, BlockHashAndNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &NO_BLOCKS.into(), + ) + .await; + + // Add a block without state diff and check that there are still no blocks. + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockHashAndNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &NO_BLOCKS.into(), + ) + .await; + + // Add a state diff to the block and check that we get the block. + storage_writer + .begin_rw_txn() + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BlockHashAndNumber { + block_hash: block.header.block_hash, + block_number: block.header.block_number, + }, + ) + .await; +} + +#[tokio::test] +async fn block_number() { + let method_name = "starknet_V0_7_blockNumber"; + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + + // No blocks yet. + let expected_err = NO_BLOCKS.into(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_err, + ) + .await; + + // Add a block without state diff and check that there are still no blocks. + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_err::<_, BlockNumber>( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_err, + ) + .await; + + // Add a state diff to the block and check that we get the block. + storage_writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BlockNumber(0), + ) + .await; +} + +#[tokio::test] +async fn syncing() { + const API_METHOD_NAME: &str = "starknet_V0_7_syncing"; + + let shared_highest_block = get_test_highest_block(); + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + None, + Some(shared_highest_block.clone()), + None, + None, + None, + ); + + call_api_then_assert_and_validate_schema_for_result( + &module, + API_METHOD_NAME, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &false, + ) + .await; + + *shared_highest_block.write().await = + Some(BlockHashAndNumber { block_number: BlockNumber(5), ..Default::default() }); + call_api_then_assert_and_validate_schema_for_result( + &module, + API_METHOD_NAME, + vec![], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &SyncStatus { highest_block_num: BlockNumber(5), ..Default::default() }, + ) + .await; +} + +#[tokio::test] +async fn get_block_transaction_count() { + let method_name = "starknet_V0_7_getBlockTransactionCount"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let transaction_count = 5; + let block = get_test_block(transaction_count, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &transaction_count, + ) + .await; + + // Get block by number. + let res = module + .call::<_, usize>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(block.header.block_number))], + ) + .await + .unwrap(); + assert_eq!(res, transaction_count); + + // Ask for the latest block. + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(res, transaction_count); + + // Ask for pending block + let pending_transaction_count = 3; + let mut rng = get_rng(); + pending_data.write().await.block.transactions_mutable().extend( + iter::repeat(ClientTransaction::get_test_instance(&mut rng)) + .take(pending_transaction_count), + ); + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, pending_transaction_count); + + // Ask for pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = module.call::<_, usize>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, 0); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, usize>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, usize>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_block_w_full_transactions() { + let method_name = "starknet_V0_7_getBlockWithTxs"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + + let mut block = get_test_block(1, None, None, None); + let block_hash = BlockHash(random::().into()); + let sequencer_address = SequencerContractAddress(random::().into()); + let timestamp = BlockTimestamp(random::()); + let starknet_version = StarknetVersion("test".to_owned()); + block.header.block_hash = block_hash; + block.header.sequencer = sequencer_address; + block.header.timestamp = timestamp; + block.header.starknet_version = starknet_version.clone(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + let expected_block = Block { + status: Some(BlockStatus::AcceptedOnL2), + header: GeneralBlockHeader::BlockHeader(block.header.into()), + transactions: Transactions::Full(vec![expected_transaction]), + }; + let GeneralBlockHeader::BlockHeader(expected_block_header) = expected_block.clone().header + else { + panic!("Unexpected block_header type. Expected BlockHeader."); + }; + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash( + expected_block_header.block_hash, + )))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_block, + ) + .await; + + // Get block by number. + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(expected_block_header.block_number))], + ) + .await + .unwrap(); + assert_eq!(block, expected_block); + + // Ask for the latest block. + let block = module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(block, expected_block); + + // Ask for a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&expected_block_header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(expected_block_header.block_hash))], + ) + .await + .unwrap(); + assert_eq!(block.status, Some(BlockStatus::AcceptedOnL1)); + + // Ask for an invalid block hash. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Ask for an invalid block number. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Get pending block. + let mut rng = get_rng(); + let (client_transactions, rpc_transactions): (Vec<_>, Vec<_>) = + iter::repeat_with(|| generate_client_transaction_and_rpc_transaction(&mut rng)) + .take(3) + .unzip(); + let pending_sequencer_address = SequencerContractAddress(random::().into()); + let pending_timestamp = BlockTimestamp(random::()); + let pending_l1_gas_price = GasPricePerToken { + price_in_wei: GasPrice(random::()), + price_in_fri: GasPrice(random::()), + }; + let expected_pending_block = Block { + header: GeneralBlockHeader::PendingBlockHeader(PendingBlockHeader { + parent_hash: block_hash, + sequencer_address: pending_sequencer_address, + timestamp: pending_timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: pending_l1_gas_price.price_in_wei, + price_in_fri: pending_l1_gas_price.price_in_fri, + }, + l1_data_gas_price: ResourcePrice::default(), + l1_da_mode: L1DataAvailabilityMode::Calldata, + starknet_version: starknet_version.0.clone(), + }), + status: None, + transactions: Transactions::Full(rpc_transactions), + }; + { + let pending_block = &mut pending_data.write().await.block; + + pending_block.transactions_mutable().extend(client_transactions); + *pending_block.parent_block_hash_mutable() = block_hash; + *pending_block.timestamp_mutable() = pending_timestamp; + *pending_block.sequencer_address_mutable() = pending_sequencer_address; + pending_block.set_l1_gas_price(&pending_l1_gas_price); + *pending_block.starknet_version_mutable() = starknet_version.0; + } + // Using call_api_then_assert_and_validate_schema_for_result in order to validate the schema for + // pending block. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_block, + ) + .await; + + // Get pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res_block = + module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + let GeneralBlockHeader::PendingBlockHeader(pending_block_header) = res_block.header else { + panic!("Unexpected block_header type. Expected PendingBlockHeader.") + }; + assert_eq!(pending_block_header.parent_hash, block_hash); + assert_eq!(pending_block_header.sequencer_address, sequencer_address); + assert_eq!(pending_block_header.timestamp, timestamp); + match res_block.transactions { + Transactions::Hashes(transactions) => assert_eq!(transactions.len(), 0), + Transactions::Full(transactions) => assert_eq!(transactions.len(), 0), + Transactions::FullWithReceipts(transactions) => assert_eq!(transactions.len(), 0), + }; +} + +#[tokio::test] +async fn get_block_w_full_transactions_and_receipts() { + let method_name = "starknet_V0_7_getBlockWithReceipts"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + + let mut block = get_test_block(1, None, None, None); + let block_hash = BlockHash(random::().into()); + let sequencer_address = SequencerContractAddress(random::().into()); + let timestamp = BlockTimestamp(random::()); + let starknet_version = StarknetVersion("test".to_owned()); + let block_number = block.header.block_number; + block.header.block_hash = block_hash; + block.header.sequencer = sequencer_address; + block.header.timestamp = timestamp; + block.header.starknet_version = starknet_version.clone(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = block.body.transactions[0].clone().try_into().unwrap(); + let expected_transaction_hash = block.body.transaction_hashes[0]; + let expected_block_header = GeneralBlockHeader::BlockHeader(block.header.into()); + let expected_status = Some(BlockStatus::AcceptedOnL2); + + // Get block by hash. + let block = call_and_validate_schema_for_result::<_, Block>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + ) + .await; + assert_eq!(block.header, expected_block_header); + assert_eq!(block.status, expected_status); + match block.transactions { + Transactions::FullWithReceipts(transactions_with_receipts) => { + assert_eq!(transactions_with_receipts.len(), 1); + assert_eq!(transactions_with_receipts[0].transaction, expected_transaction); + assert_eq!( + transactions_with_receipts[0].receipt.transaction_hash, + expected_transaction_hash, + ); + } + _ => panic!("Unexpected transactions type {:?}", block.transactions), + } + + // Get block by number. + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(block_number))], + ) + .await + .unwrap(); + assert_eq!(block.header, expected_block_header); + + // Ask for the latest block. + let block = module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(block.header, expected_block_header); + + // Ask for a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let block = module + .call::<_, Block>(method_name, [BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash))]) + .await + .unwrap(); + assert_eq!(block.status, Some(BlockStatus::AcceptedOnL1)); + + // Ask for an invalid block hash. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Ask for an invalid block number. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Get pending block. + let mut rng = get_rng(); + let (client_transactions, client_receipts, rpc_transactions, rpc_receipts): ( + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + ) = itertools::multiunzip( + iter::repeat_with(|| { + generate_client_transaction_client_receipt_rpc_transaction_and_rpc_receipt(&mut rng) + }) + .take(3), + ); + let pending_sequencer_address = SequencerContractAddress(random::().into()); + let pending_timestamp = BlockTimestamp(random::()); + let pending_l1_gas_price = GasPricePerToken { + price_in_wei: GasPrice(rng.next_u64().into()), + price_in_fri: GasPrice(rng.next_u64().into()), + }; + let expected_pending_block = Block { + header: GeneralBlockHeader::PendingBlockHeader(PendingBlockHeader { + parent_hash: block_hash, + sequencer_address: pending_sequencer_address, + timestamp: pending_timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: pending_l1_gas_price.price_in_wei, + price_in_fri: pending_l1_gas_price.price_in_fri, + }, + l1_data_gas_price: ResourcePrice::default(), + l1_da_mode: L1DataAvailabilityMode::Calldata, + starknet_version: starknet_version.0.clone(), + }), + status: None, + transactions: Transactions::FullWithReceipts( + rpc_transactions + .into_iter() + .zip(rpc_receipts.into_iter()) + .map(|(transaction, receipt)| TransactionWithReceipt { + receipt: GeneralTransactionReceipt::PendingTransactionReceipt(receipt).into(), + transaction, + }) + .collect(), + ), + }; + { + let pending_block = &mut pending_data.write().await.block; + + pending_block.transactions_mutable().extend(client_transactions); + pending_block.transaction_receipts_mutable().extend(client_receipts); + *pending_block.parent_block_hash_mutable() = block_hash; + *pending_block.timestamp_mutable() = pending_timestamp; + *pending_block.sequencer_address_mutable() = pending_sequencer_address; + pending_block.set_l1_gas_price(&pending_l1_gas_price); + *pending_block.starknet_version_mutable() = starknet_version.0; + } + // Using call_api_then_assert_and_validate_schema_for_result again in order to validate the + // schema for pending block too. + call_api_then_assert_and_validate_schema_for_result::<_, Block>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_block, + ) + .await; + + // Get pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res_block = + module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + let GeneralBlockHeader::PendingBlockHeader(pending_block_header) = res_block.header else { + panic!("Unexpected block_header type. Expected PendingBlockHeader.") + }; + assert_eq!(pending_block_header.parent_hash, block_hash); + assert_eq!(pending_block_header.sequencer_address, sequencer_address); + assert_eq!(pending_block_header.timestamp, timestamp); + match res_block.transactions { + Transactions::Hashes(transactions) => assert_eq!(transactions.len(), 0), + Transactions::Full(transactions) => assert_eq!(transactions.len(), 0), + Transactions::FullWithReceipts(transactions) => assert_eq!(transactions.len(), 0), + }; +} + +#[tokio::test] +async fn get_block_w_transaction_hashes() { + let method_name = "starknet_V0_7_getBlockWithTxHashes"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + + let mut block = get_test_block(1, None, None, None); + let block_hash = BlockHash(random::().into()); + let sequencer_address = SequencerContractAddress(random::().into()); + let timestamp = BlockTimestamp(random::()); + let starknet_version = StarknetVersion("test".to_owned()); + block.header.block_hash = block_hash; + block.header.sequencer = sequencer_address; + block.header.timestamp = timestamp; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_block = Block { + status: Some(BlockStatus::AcceptedOnL2), + header: GeneralBlockHeader::BlockHeader(block.header.into()), + transactions: Transactions::Hashes(vec![block.body.transaction_hashes[0]]), + }; + let GeneralBlockHeader::BlockHeader(expected_block_header) = expected_block.clone().header + else { + panic!("Unexpected block_header type. Expected BlockHeader."); + }; + + // Get block by hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash( + expected_block_header.block_hash, + )))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_block, + ) + .await; + + // Get block by number. + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(expected_block_header.block_number))], + ) + .await + .unwrap(); + assert_eq!(block, expected_block); + + // Ask for the latest block. + let block = module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Latest)]).await.unwrap(); + assert_eq!(block, expected_block); + + // Ask for a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&expected_block_header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let block = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Hash(expected_block_header.block_hash))], + ) + .await + .unwrap(); + assert_eq!(block.status, Some(BlockStatus::AcceptedOnL1)); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Block>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Block>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Get pending block. + let mut rng = get_rng(); + let (client_transactions, _): (Vec<_>, Vec<_>) = + iter::repeat_with(|| generate_client_transaction_and_rpc_transaction(&mut rng)) + .take(3) + .unzip(); + let pending_sequencer_address = SequencerContractAddress(random::().into()); + let pending_timestamp = BlockTimestamp(random::()); + let pending_l1_gas_price = GasPricePerToken { + price_in_wei: GasPrice(random::()), + price_in_fri: GasPrice(random::()), + }; + let expected_pending_block = Block { + header: GeneralBlockHeader::PendingBlockHeader(PendingBlockHeader { + parent_hash: block_hash, + sequencer_address: pending_sequencer_address, + timestamp: pending_timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: pending_l1_gas_price.price_in_wei, + price_in_fri: pending_l1_gas_price.price_in_fri, + }, + l1_data_gas_price: ResourcePrice::default(), + l1_da_mode: L1DataAvailabilityMode::Calldata, + starknet_version: starknet_version.0.clone(), + }), + status: None, + transactions: Transactions::Hashes( + client_transactions + .iter() + .map(|client_transaction| client_transaction.transaction_hash()) + .collect(), + ), + }; + { + let pending_block = &mut pending_data.write().await.block; + + pending_block.transactions_mutable().extend(client_transactions); + *pending_block.parent_block_hash_mutable() = block_hash; + *pending_block.timestamp_mutable() = pending_timestamp; + *pending_block.sequencer_address_mutable() = pending_sequencer_address; + pending_block.set_l1_gas_price(&pending_l1_gas_price); + *pending_block.starknet_version_mutable() = starknet_version.0; + } + // Using call_api_then_assert_and_validate_schema_for_result in order to validate the schema for + // pending block. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_block, + ) + .await; + + // Get pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res_block = + module.call::<_, Block>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + let GeneralBlockHeader::PendingBlockHeader(pending_block_header) = res_block.header else { + panic!("Unexpected block_header type. Expected PendingBlockHeader.") + }; + assert_eq!(pending_block_header.parent_hash, block_hash); + assert_eq!(pending_block_header.sequencer_address, sequencer_address); + assert_eq!(pending_block_header.timestamp, timestamp); + match res_block.transactions { + Transactions::Hashes(transactions) => assert_eq!(transactions.len(), 0), + Transactions::Full(transactions) => assert_eq!(transactions.len(), 0), + Transactions::FullWithReceipts(transactions) => assert_eq!(transactions.len(), 0), + }; +} + +#[tokio::test] +async fn get_class() { + let method_name = "starknet_V0_7_getClass"; + let pending_classes = get_test_pending_classes(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, None, Some(pending_classes.clone()), None); + let parent_header = BlockHeader::default(); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + ..BlockHeader::default() + }; + let (diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes( + parent_header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + // Deprecated Class + let class_hash = diff.deprecated_declared_classes[0]; + let expected_contract_class = + deprecated_classes.get(&class_hash).unwrap().clone().try_into().unwrap(); + + // Get class by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*class_hash), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_contract_class, + ) + .await; + + // Get class by block number. + let res = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class of pending block + let pending_class_hash = ClassHash(random::().into()); + let pending_class = ApiContractClass::ContractClass( + StarknetApiContractClass::get_test_instance(&mut get_rng()), + ); + pending_classes.write().await.add_class(pending_class_hash, pending_class.clone()); + let res = module + .call::<_, GatewayContractClass>( + method_name, + (BlockId::Tag(Tag::Pending), pending_class_hash), + ) + .await + .unwrap(); + assert_eq!(res, pending_class.try_into().unwrap()); + + // Ask for an invalid class hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ClassHash(felt!("0x7"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CLASS_HASH_NOT_FOUND.into(), + ) + .await; + + // New Class + let (class_hash, contract_class) = classes.get_index(0).unwrap(); + let expected_contract_class = contract_class.clone().into(); + + // Get class by block hash. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class by block number. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *class_hash), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Invalid Call + // Ask for an invalid class hash in the given block. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + ( + BlockId::HashOrNumber(BlockHashOrNumber::Number(parent_header.block_number)), + *class_hash, + ), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == CLASS_HASH_NOT_FOUND.into()); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(ClassHash(felt!("0x7"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))), *class_hash), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_transaction_status() { + let method_name = "starknet_V0_7_getTransactionStatus"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let transaction_hash = block.body.transaction_hashes[0]; + let transaction_version = match block.body.transactions.index(0) { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + let tx = block.body.transaction_outputs.index(0).clone(); + let msg_hash = match tx { + starknet_api::transaction::TransactionOutput::L1Handler(_) => Some(L1L2MsgHash::default()), + _ => None, + }; + let output = TransactionOutput::from((tx, transaction_version, msg_hash)); + let expected_status = TransactionStatus { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + execution_status: output.execution_status().clone(), + }; + let (json_response, res) = + raw_call::<_, _, TransactionStatus>(&module, method_name, &[transaction_hash]).await; + assert_eq!(res.unwrap(), expected_status); + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for a transaction in a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&block.header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let res = module.call::<_, TransactionStatus>(method_name, [transaction_hash]).await.unwrap(); + assert_eq!(res.finality_status, TransactionFinalityStatus::AcceptedOnL1); + + // Add a pending transaction and ask for its status. + let mut rng = get_rng(); + let (client_transaction, client_transaction_receipt, _, expected_receipt) = + generate_client_transaction_client_receipt_rpc_transaction_and_rpc_receipt(&mut rng); + let expected_status = TransactionStatus { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + execution_status: expected_receipt.output.execution_status().clone(), + }; + + { + let pending_block = &mut pending_data.write().await.block; + pending_block.transactions_mutable().push(client_transaction.clone()); + pending_block.transaction_receipts_mutable().push(client_transaction_receipt.clone()); + } + let (json_response, result) = raw_call::<_, _, TransactionStatus>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(result.unwrap(), expected_status); + // Validating schema again since pending has a different schema + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for transaction status when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let (_, res) = raw_call::<_, _, TransactionStatus>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(res.unwrap_err(), TRANSACTION_HASH_NOT_FOUND.into()); + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionStatus>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_transaction_receipt() { + let method_name = "starknet_V0_7_getTransactionReceipt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let transaction_hash = block.body.transaction_hashes[0]; + let transaction_version = match block.body.transactions.index(0) { + StarknetApiTransaction::Declare(tx) => tx.version(), + StarknetApiTransaction::Deploy(tx) => tx.version, + StarknetApiTransaction::DeployAccount(tx) => tx.version(), + StarknetApiTransaction::Invoke(tx) => tx.version(), + StarknetApiTransaction::L1Handler(tx) => tx.version, + }; + let tx = block.body.transactions.index(0).clone(); + let msg_hash = match tx { + starknet_api::transaction::Transaction::L1Handler(tx) => Some(tx.calc_msg_hash()), + _ => None, + }; + let output = TransactionOutput::from(( + block.body.transaction_outputs.index(0).clone(), + transaction_version, + msg_hash, + )); + let expected_receipt = TransactionReceipt { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + transaction_hash, + block_hash: block.header.block_hash, + block_number: block.header.block_number, + output, + }; + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(transaction_hash)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_receipt, + ) + .await; + + // Ask for a transaction in a block that was accepted on L1. + storage_writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&block.header.block_number.unchecked_next()) + .unwrap() + .commit() + .unwrap(); + let res = module.call::<_, TransactionReceipt>(method_name, [transaction_hash]).await.unwrap(); + assert_eq!(res.finality_status, TransactionFinalityStatus::AcceptedOnL1); + + // Add a pending transaction and ask for its receipt. + let mut rng = get_rng(); + let (client_transaction, client_transaction_receipt, _, expected_receipt) = + generate_client_transaction_client_receipt_rpc_transaction_and_rpc_receipt(&mut rng); + + { + let pending_block = &mut pending_data.write().await.block; + pending_block.transactions_mutable().push(client_transaction.clone()); + pending_block.transaction_receipts_mutable().push(client_transaction_receipt.clone()); + } + + let expected_result = GeneralTransactionReceipt::PendingTransactionReceipt(expected_receipt); + let (json_response, result) = raw_call::<_, _, PendingTransactionReceipt>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + // See above for explanation why we compare the json strings. + assert_eq!( + serde_json::to_value(result.unwrap()).unwrap(), + serde_json::to_value(&expected_result).unwrap(), + ); + // Validating schema again since pending has a different schema + assert!(validate_schema( + &get_starknet_spec_api_schema_for_method_results( + &[( + SpecFile::StarknetApiOpenrpc, + &[method_name_to_spec_method_name(method_name).as_str()] + )], + &VERSION, + ), + &json_response["result"], + )); + + // Ask for transaction receipt when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let (_, res) = raw_call::<_, _, TransactionReceipt>( + &module, + method_name, + &[client_transaction_receipt.transaction_hash], + ) + .await; + assert_eq!(res.unwrap_err(), TRANSACTION_HASH_NOT_FOUND.into()); + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionReceipt>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_class_at() { + let method_name = "starknet_V0_7_getClassAt"; + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer_from_params::( + None, + None, + Some(pending_data.clone()), + Some(pending_classes.clone()), + None, + ); + let parent_header = BlockHeader::default(); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + ..BlockHeader::default() + }; + let (mut diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(get_test_state_diff()); + // Add a deployed contract with Cairo 1 class. + let new_class_hash = diff.declared_classes.get_index(0).unwrap().0; + diff.deployed_contracts.insert(ContractAddress(patricia_key!("0x2")), *new_class_hash); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes( + parent_header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let pending_address: ContractAddress = random::().into(); + let pending_class_hash = ClassHash(random::().into()); + let pending_class = ApiContractClass::ContractClass( + StarknetApiContractClass::get_test_instance(&mut get_rng()), + ); + pending_data + .write() + .await + .state_update + .state_diff + .deployed_contracts + .push(ClientDeployedContract { address: pending_address, class_hash: pending_class_hash }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + pending_classes.write().await.add_class(pending_class_hash, pending_class.clone()); + + // Deprecated Class + let class_hash = diff.deprecated_declared_classes.last().unwrap(); + let expected_contract_class = + deprecated_classes.get(class_hash).unwrap().clone().try_into().unwrap(); + assert_eq!(diff.deployed_contracts.get_index(0).unwrap().1, class_hash); + let address = diff.deployed_contracts.get_index(0).unwrap().0; + + // Get class by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_contract_class, + ) + .await; + + // Get class by block number. + let res = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // New Class + let class_hash = diff.declared_classes.get_index(0).unwrap().0; + let expected_contract_class = classes.get(class_hash).unwrap().clone().into(); + assert_eq!(diff.deployed_contracts.get_index(1).unwrap().1, class_hash); + let address = diff.deployed_contracts.get_index(1).unwrap().0; + + // Get class by block hash. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class by block number. + let res = module + .call::<_, ContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, expected_contract_class); + + // Get class hash of pending block. + let res = module + .call::<_, GatewayContractClass>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, pending_class.try_into().unwrap()); + + // Get class hash of pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, ContractClass>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(pending_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Invalid Call + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x12"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid contract in the given block. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + ( + BlockId::HashOrNumber(BlockHashOrNumber::Number(parent_header.block_number)), + *address, + ), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == CONTRACT_NOT_FOUND.into()); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, DeprecatedContractClass>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, DeprecatedContractClass>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_class_hash_at() { + let method_name = "starknet_V0_7_getClassHashAt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + // No need to write the class definitions. + .commit() + .unwrap(); + + let (address, expected_class_hash) = diff.deployed_contracts.get_index(0).unwrap(); + + let pending_address: ContractAddress = random::().into(); + let pending_class_hash = ClassHash(random::().into()); + pending_data + .write() + .await + .state_update + .state_diff + .deployed_contracts + .push(ClientDeployedContract { address: pending_address, class_hash: pending_class_hash }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + + // Get class hash by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_class_hash, + ) + .await; + + // Get class hash by block number. + let res = module + .call::<_, ClassHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Get class hash by latest tag. + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Latest), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Get class hash of pending block. + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, pending_class_hash); + + // Get class hash of pending block when it's replaced. + let replaced_class_hash = ClassHash(random::().into()); + pending_data.write().await.state_update.state_diff.replaced_classes.append(&mut vec![ + ClientReplacedClass { address: *address, class_hash: replaced_class_hash }, + ClientReplacedClass { address: pending_address, class_hash: replaced_class_hash }, + ]); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, replaced_class_hash); + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), pending_address)) + .await + .unwrap(); + assert_eq!(res, replaced_class_hash); + + // Get class hash of pending block when it's not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(pending_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + let res = module + .call::<_, ClassHash>(method_name, (BlockId::Tag(Tag::Pending), *address)) + .await + .unwrap(); + assert_eq!(res, *expected_class_hash); + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x12"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, ClassHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, ClassHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_nonce() { + let method_name = "starknet_V0_7_getNonce"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let (address, expected_nonce) = diff.nonces.get_index(0).unwrap(); + + // Get nonce by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_nonce, + ) + .await; + + // Get nonce by block number. + let res = module + .call::<_, Nonce>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), *address), + ) + .await + .unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block when it wasn't changed in pending block. + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block when it was changed in pending block. + let new_nonce = Nonce(Felt::from(1234_u128)); + pending_data.write().await.state_update.state_diff.nonces.insert(*address, new_nonce); + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, new_nonce); + + // Ask for nonce in pending block where the contract is deployed in the pending block. + let new_pending_contract_address = ContractAddress(patricia_key!("0x1234")); + pending_data + .write() + .await + .state_update + .state_diff + .nonces + .insert(new_pending_contract_address, new_nonce); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(new_pending_contract_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &new_nonce, + ) + .await; + + // Ask for nonce in pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = + module.call::<_, Nonce>(method_name, (BlockId::Tag(Tag::Pending), *address)).await.unwrap(); + assert_eq!(res, *expected_nonce); + + // Ask for nonce in pending block where the contract is deployed in the pending block, and the + // pending block is not up to date. + // Expected outcome: Failure due to contract not found. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(new_pending_contract_address)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, Nonce>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + Box::new(ContractAddress(patricia_key!("0x31"))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Nonce>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(*address), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Nonce>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), *address), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_storage_at() { + let method_name = "starknet_V0_7_getStorageAt"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let header = BlockHeader::default(); + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + .commit() + .unwrap(); + + let (address, storage_entries) = diff.storage_diffs.get_index(0).unwrap(); + let (key, expected_value) = storage_entries.get_index(0).unwrap(); + + // Get storage by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(*address), + Box::new(*key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + expected_value, + ) + .await; + + // Get storage by block number. + let res = module + .call::<_, Felt>( + method_name, + (*address, *key, BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))), + ) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when contract's storage wasn't changed in pending block. + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when it wasn't changed in pending block. + let other_key = random::().into(); + let other_value = random::().into(); + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(*address, vec![ClientStorageEntry { key: other_key, value: other_value }]); + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block when it was changed in pending block. + let res = module + .call::<_, Felt>(method_name, (*address, other_key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, other_value); + + // Ask for storage that was changed both in the pending block and the non-pending block. + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(*address, vec![ClientStorageEntry { key: *key, value: other_value }]); + let res = module + .call::<_, Felt>(method_name, (*address, key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, other_value); + + // Ask for storage in pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = module + .call::<_, Felt>(method_name, (*address, other_key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, Felt::default()); + + // Ask for storage updated both in pending block and non-pending block when the pending block is + // not up to date. + let res = module + .call::<_, Felt>(method_name, (*address, *key, BlockId::Tag(Tag::Pending))) + .await + .unwrap(); + assert_eq!(res, *expected_value); + + // Ask for storage in pending block where the contract is deployed in the pending block, and the + // pending block is not up to date. + // Expected outcome: Failure due to contract not found. + let key = StorageKey(patricia_key!("0x1001")); + let contract_address = ContractAddress(patricia_key!("0x1234")); + pending_data + .write() + .await + .state_update + .state_diff + .storage_diffs + .insert(contract_address, vec![ClientStorageEntry { key, value: Felt::default() }]); + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![Box::new(contract_address), Box::new(key), Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for storage at address 0x1 - the block hash table contract address + let res = module + .call::<_, Felt>( + "starknet_V0_7_getStorageAt", + ( + *BLOCK_HASH_TABLE_ADDRESS, + key, + BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number)), + ), + ) + .await + .unwrap(); + assert_eq!(res, Felt::default()); + + // Ask for an invalid contract. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![ + Box::new(ContractAddress(patricia_key!("0x12"))), + Box::new(key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &CONTRACT_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, Felt>( + &module, + method_name, + vec![ + Box::new(*address), + Box::new(key), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, Felt>( + method_name, + (*address, key, BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +fn generate_client_transaction_client_receipt_rpc_transaction_and_rpc_receipt( + rng: &mut ChaCha8Rng, +) -> (ClientTransaction, ClientTransactionReceipt, Transaction, PendingTransactionReceipt) { + let pending_transaction_hash = TransactionHash(StarkHash::from(rng.next_u64())); + let mut client_transaction_receipt = ClientTransactionReceipt::get_test_instance(rng); + client_transaction_receipt.transaction_hash = pending_transaction_hash; + client_transaction_receipt.execution_resources.n_memory_holes = 1; + client_transaction_receipt.execution_resources.n_steps = 1; + client_transaction_receipt.execution_resources.builtin_instance_counter.retain(|_, v| *v > 0); + // Generating a transaction until we receive a transaction that can have pending output (i.e a + // non-deploy transaction). + let (mut client_transaction, rpc_transaction, output) = loop { + let (client_transaction, rpc_transaction_with_hash) = + generate_client_transaction_and_rpc_transaction(rng); + let starknet_api_output = client_transaction_receipt + .clone() + .into_starknet_api_transaction_output(&client_transaction); + let msg_hash = match &client_transaction { + starknet_client::reader::objects::transaction::Transaction::L1Handler(tx) => { + Some(tx.calc_msg_hash()) + } + _ => None, + }; + let maybe_output = PendingTransactionOutput::try_from(TransactionOutput::from(( + starknet_api_output, + client_transaction.transaction_version(), + msg_hash, + ))); + let Ok(output) = maybe_output else { + continue; + }; + break (client_transaction, rpc_transaction_with_hash.transaction, output); + }; + // rpc_transaction contains no hash so no need to change it. + *client_transaction.transaction_hash_mut() = pending_transaction_hash; + ( + client_transaction, + client_transaction_receipt, + rpc_transaction, + PendingTransactionReceipt { + finality_status: PendingTransactionFinalityStatus::AcceptedOnL2, + transaction_hash: pending_transaction_hash, + output, + }, + ) +} + +fn generate_client_transaction_and_rpc_transaction( + rng: &mut ChaCha8Rng, +) -> (ClientTransaction, TransactionWithHash) { + // TODO(shahak): Remove retry once v3 transactions are supported and the impl of TryInto will + // become impl of Into. + loop { + let client_transaction = ClientTransaction::get_test_instance(rng); + let Ok(starknet_api_transaction): Result = + client_transaction.clone().try_into() + else { + continue; + }; + let Ok(rpc_transaction) = starknet_api_transaction.try_into() else { + continue; + }; + let transaction_hash = client_transaction.transaction_hash(); + break ( + client_transaction, + TransactionWithHash { transaction: rpc_transaction, transaction_hash }, + ); + } +} + +#[tokio::test] +async fn get_transaction_by_hash() { + let method_name = "starknet_V0_7_getTransactionByHash"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let mut block = get_test_block(1, None, None, None); + // Change the transaction hash from 0 to a random value, so that later on we can add a + // transaction with 0 hash to the pending block. + block.body.transaction_hashes[0] = TransactionHash(StarkHash::from(random::())); + storage_writer + .begin_rw_txn() + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(block.body.transaction_hashes[0])], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction, + ) + .await; + + // Ask for a transaction in the pending block. + let (client_transaction, expected_transaction_with_hash) = + generate_client_transaction_and_rpc_transaction(&mut get_rng()); + pending_data.write().await.block.transactions_mutable().push(client_transaction.clone()); + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(client_transaction.transaction_hash())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction_with_hash, + ) + .await; + + // Get pending block when it's not updated. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(client_transaction.transaction_hash())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid transaction. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(TransactionHash(StarkHash::from(1_u8)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TRANSACTION_HASH_NOT_FOUND.into(), + ) + .await; +} + +#[tokio::test] +async fn get_transaction_by_hash_state_only() { + let method_name = "starknet_V0_7_getTransactionByHash"; + let params = [TransactionHash(StarkHash::from(1_u8))]; + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + None, + None, + None, + None, + Some(StorageScope::StateOnly), + ); + + let (_, err) = raw_call::<_, _, TransactionWithHash>(&module, method_name, ¶ms).await; + assert_eq!( + err.unwrap_err(), + internal_server_error_with_msg("Unsupported method in state-only scope.") + ); +} + +#[tokio::test] +async fn get_transaction_by_block_id_and_index() { + let method_name = "starknet_V0_7_getTransactionByBlockIdAndIndex"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let block = get_test_block(1, None, None, None); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + let expected_transaction = TransactionWithHash { + transaction: block.body.transactions[0].clone().try_into().unwrap(), + transaction_hash: block.body.transaction_hashes[0], + }; + + // Get transaction by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash))), + Box::new(TransactionOffsetInBlock(0)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_transaction, + ) + .await; + + // Get transaction by block number. + let res = module + .call::<_, TransactionWithHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(block.header.block_number)), 0), + ) + .await + .unwrap(); + assert_eq!(res, expected_transaction); + + // Get transaction of pending block. + let (client_transaction, expected_transaction_with_hash) = + generate_client_transaction_and_rpc_transaction(&mut get_rng()); + pending_data.write().await.block.transactions_mutable().push(client_transaction); + let res = module + .call::<_, TransactionWithHash>(method_name, (BlockId::Tag(Tag::Pending), 0)) + .await + .unwrap(); + assert_eq!(res, expected_transaction_with_hash); + + // Ask for an invalid transaction index in pending block. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(TransactionOffsetInBlock(1))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; + + // Get transaction of pending block when the pending block is not up to date. + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending)), Box::new(TransactionOffsetInBlock(0))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + ))))), + Box::new(TransactionOffsetInBlock(0)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, TransactionWithHash>( + method_name, + (BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), 0), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Ask for an invalid transaction index. + call_api_then_assert_and_validate_schema_for_err::<_, TransactionWithHash>( + &module, + method_name, + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(block.header.block_hash))), + Box::new(TransactionOffsetInBlock(1)), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_TRANSACTION_INDEX.into(), + ) + .await; +} + +#[tokio::test] +async fn get_state_update() { + let method_name = "starknet_V0_7_getStateUpdate"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let parent_header = BlockHeader::default(); + let expected_pending_old_root = GlobalRoot(felt!("0x1234")); + let header = BlockHeader { + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + parent_hash: parent_header.block_hash, + state_root: expected_pending_old_root, + ..BlockHeader::default() + }; + let diff = starknet_api::state::ThinStateDiff::from(get_test_state_diff()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_header.block_number, &parent_header) + .unwrap() + .append_state_diff( + parent_header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, diff.clone()) + .unwrap() + // No need to write the class definitions + .commit() + .unwrap(); + + let expected_old_root = parent_header.state_root; + let expected_state_diff = ThinStateDiff::from(diff); + let expected_update = StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + block_hash: header.block_hash, + new_root: header.state_root, + old_root: expected_old_root, + state_diff: expected_state_diff.clone(), + }); + + // Get state update by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_update, + ) + .await; + + // Get state update by block number. + let res = module + .call::<_, StateUpdate>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(header.block_number))], + ) + .await + .unwrap(); + assert_eq!(res, expected_update); + + // Get state update of pending block. + let expected_pending_update = StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: expected_old_root, + state_diff: expected_state_diff.clone(), + }); + *pending_data.write().await.block.parent_block_hash_mutable() = header.block_hash; + pending_data.write().await.state_update = ClientPendingStateUpdate { + old_root: expected_old_root, + state_diff: ClientStateDiff { + storage_diffs: IndexMap::from_iter(expected_state_diff.storage_diffs.into_iter().map( + |StorageDiff { address, storage_entries }| { + let storage_entries = Vec::from_iter( + storage_entries + .into_iter() + .map(|StorageEntry { key, value }| ClientStorageEntry { key, value }), + ); + (address, storage_entries) + }, + )), + deployed_contracts: Vec::from_iter( + expected_state_diff.deployed_contracts.into_iter().map( + |DeployedContract { address, class_hash }| ClientDeployedContract { + address, + class_hash, + }, + ), + ), + declared_classes: expected_state_diff + .declared_classes + .into_iter() + .map(|ClassHashes { class_hash, compiled_class_hash }| { + ClientDeclaredClassHashEntry { class_hash, compiled_class_hash } + }) + .collect(), + old_declared_contracts: expected_state_diff.deprecated_declared_classes, + nonces: IndexMap::from_iter( + expected_state_diff + .nonces + .into_iter() + .map(|ContractNonce { contract_address, nonce }| (contract_address, nonce)), + ), + replaced_classes: Vec::from_iter(expected_state_diff.replaced_classes.into_iter().map( + |ReplacedClasses { contract_address, class_hash }| ClientReplacedClass { + address: contract_address, + class_hash, + }, + )), + }, + }; + // Validating schema because the state diff of pending block contains less fields. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::Tag(Tag::Pending))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_pending_update, + ) + .await; + + // Get state update of pending block when the pending block is not up to date. + let expected_pending_update = StateUpdate::PendingStateUpdate(PendingStateUpdate { + old_root: expected_pending_old_root, + ..PendingStateUpdate::default() + }); + *pending_data.write().await.block.parent_block_hash_mutable() = + BlockHash(random::().into()); + let res = + module.call::<_, StateUpdate>(method_name, [BlockId::Tag(Tag::Pending)]).await.unwrap(); + assert_eq!(res, expected_pending_update); + + // Ask for an invalid block hash. + call_api_then_assert_and_validate_schema_for_err::<_, StateUpdate>( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Hash(BlockHash(felt!( + "0x642b629ad8ce233b55798c83bb629a59bf0a0092f67da28d6d66776680d5484" + )))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &BLOCK_NOT_FOUND.into(), + ) + .await; + + // Ask for an invalid block number. + let err = module + .call::<_, StateUpdate>( + method_name, + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2)))], + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); +} + +#[tokio::test] +async fn get_state_update_with_empty_storage_diff() { + let method_name = "starknet_V0_7_getStateUpdate"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let state_diff = starknet_api::state::ThinStateDiff { + storage_diffs: indexmap!(ContractAddress::default() => indexmap![]), + ..Default::default() + }; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_state_diff(BlockNumber(0), state_diff) + .unwrap() + .commit() + .unwrap(); + + // The empty storage diff should be removed in the result. + let expected_state_diff = + ThinStateDiff::from(starknet_api::state::ThinStateDiff::from(StateDiff::default())); + let expected_update = StateUpdate::AcceptedStateUpdate(AcceptedStateUpdate { + state_diff: expected_state_diff.clone(), + ..Default::default() + }); + + // Get state update by block hash. + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))))], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_update, + ) + .await; +} + +#[derive(Clone)] +struct EventMetadata { + pub address: Option, + pub keys: Option>, +} + +const DEFAULT_EVENT_METADATA: EventMetadata = EventMetadata { address: None, keys: None }; + +impl EventMetadata { + pub fn generate_event(&self, rng: &mut ChaCha8Rng) -> StarknetApiEvent { + StarknetApiEvent { + from_address: self.address.unwrap_or_else(|| ContractAddress(rng.next_u64().into())), + content: EventContent { + keys: self.keys.clone().unwrap_or_else(|| vec![EventKey(rng.next_u64().into())]), + data: EventData(vec![rng.next_u64().into()]), + }, + } + } +} + +#[derive(Clone, Default)] +struct BlockMetadata(pub Vec>); + +impl BlockMetadata { + pub fn generate_block( + &self, + rng: &mut ChaCha8Rng, + parent_hash: BlockHash, + block_number: BlockNumber, + ) -> StarknetApiBlock { + // Generate a block with no events, And then add the events manually. + let mut block = get_test_block(self.0.len(), Some(0), None, None); + block.header.parent_hash = parent_hash; + block.header.block_number = block_number; + block.header.block_hash = BlockHash(rng.next_u64().into()); + // Randomize the transaction hashes because get_test_block returns constant hashes + for transaction_hash in &mut block.body.transaction_hashes { + *transaction_hash = TransactionHash(rng.next_u64().into()); + } + + for (output, event_metadatas_of_tx) in + block.body.transaction_outputs.iter_mut().zip(self.0.iter()) + { + let events = match output { + StarknetApiTransactionOutput::Declare(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::Deploy(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::DeployAccount(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::Invoke(transaction) => &mut transaction.events, + StarknetApiTransactionOutput::L1Handler(transaction) => &mut transaction.events, + }; + for event_metadata in event_metadatas_of_tx { + events.push(event_metadata.generate_event(rng)); + } + } + block + } + + pub fn generate_pending_block( + &self, + rng: &mut ChaCha8Rng, + parent_hash: BlockHash, + ) -> PendingBlockOrDeprecated { + let transaction_hashes = iter::repeat_with(|| TransactionHash(rng.next_u64().into())) + .take(self.0.len()) + .collect::>(); + PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: parent_hash, + transactions: transaction_hashes + .iter() + .map(|transaction_hash| { + let mut transaction = ClientTransaction::get_test_instance(rng); + *transaction.transaction_hash_mut() = *transaction_hash; + transaction + }) + .collect(), + transaction_receipts: transaction_hashes + .iter() + .zip(self.0.iter()) + .enumerate() + .map(|(i, (transaction_hash, event_metadatas_of_tx))| ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(i), + transaction_hash: *transaction_hash, + events: event_metadatas_of_tx + .iter() + .map(|event_metadata| event_metadata.generate_event(rng)) + .collect(), + ..Default::default() + }) + .collect(), + ..Default::default() + }) + } +} + +async fn test_get_events( + block_metadatas: Vec, + pending_block_metadata: Option, + is_pending_up_to_date: bool, + mut filter: EventFilter, + expected_result_by_index: Vec<(Vec, Option)>, +) { + let method_name = "starknet_V0_7_getEvents"; + let pending_data = get_test_pending_data(); + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data.clone()), None, None); + let mut rng = get_rng(); + + let mut event_index_to_event = HashMap::::new(); + let mut parent_hash = BlockHash(felt!(GENESIS_HASH)); + let mut rw_txn = storage_writer.begin_rw_txn().unwrap(); + for (i, block_metadata) in block_metadatas.iter().enumerate() { + let block_number = BlockNumber(i as u64); + let block = block_metadata.generate_block(&mut rng, parent_hash, block_number); + + parent_hash = block.header.block_hash; + + for (i_transaction, (output, transaction_hash)) in block + .body + .transaction_outputs + .iter() + .zip(block.body.transaction_hashes.iter().cloned()) + .enumerate() + { + for (i_event, event) in output.events().iter().cloned().enumerate() { + event_index_to_event.insert( + EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(i_transaction)), + EventIndexInTransactionOutput(i_event), + ), + Event { + block_hash: Some(block.header.block_hash), + block_number: Some(block_number), + transaction_hash, + event, + }, + ); + } + } + + rw_txn = rw_txn + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body) + .unwrap() + .append_state_diff( + block.header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap(); + } + rw_txn.commit().unwrap(); + + if let Some(pending_block_metadata) = pending_block_metadata { + if !is_pending_up_to_date { + parent_hash = BlockHash(rng.next_u64().into()); + } + let pending_block = pending_block_metadata.generate_pending_block(&mut rng, parent_hash); + + for (i_transaction, receipt) in pending_block.transaction_receipts().iter().enumerate() { + for (i_event, event) in receipt.events.iter().cloned().enumerate() { + event_index_to_event.insert( + EventIndex( + TransactionIndex( + BlockNumber(block_metadatas.len() as u64), + TransactionOffsetInBlock(i_transaction), + ), + EventIndexInTransactionOutput(i_event), + ), + Event { + block_hash: None, + block_number: None, + transaction_hash: receipt.transaction_hash, + event, + }, + ); + } + } + + pending_data.write().await.block = pending_block; + } + + for (expected_event_indices, expected_continuation_token) in expected_result_by_index { + let expected_result = EventsChunk { + events: expected_event_indices + .iter() + .map(|event_index| event_index_to_event.get(event_index).unwrap()) + .cloned() + .collect(), + continuation_token: expected_continuation_token + .map(|x| ContinuationToken::new(x).unwrap()), + }; + call_api_then_assert_and_validate_schema_for_result( + &module, + method_name, + vec![Box::new(filter.clone())], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_result, + ) + .await; + filter.continuation_token = expected_result.continuation_token; + } +} + +lazy_static! { + static ref BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: Vec = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA], vec![DEFAULT_EVENT_METADATA]]), + // There should be a chunk that starts at the non-first transaction of the second block, in + // order to test the continuation token for pending. + BlockMetadata(vec![ + [DEFAULT_EVENT_METADATA; 3].to_vec(), + [DEFAULT_EVENT_METADATA; 2].to_vec(), + ]), + ]; + static ref EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: EventFilter = + EventFilter { chunk_size: 3, ..Default::default() }; + static ref EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST: Vec<(Vec, Option,)> = vec![ + ( + vec![ + EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(0), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ), + ], + Some(ContinuationTokenAsStruct(EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ))), + ), + ( + vec![ + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(2), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(0), + ), + ], + Some(ContinuationTokenAsStruct(EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(1), + ))), + ), + ( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(1)), + EventIndexInTransactionOutput(1), + )], + None, + ), + ]; +} + +#[tokio::test] +async fn get_events_chunk_across_2_blocks() { + let pending_block_metadata = None; + let is_pending_up_to_date = true; + test_get_events( + BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_chunk_across_block_and_pending_block() { + let mut blocks_metadata = BLOCKS_METADATA_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(); + let pending_block_metadata = Some(blocks_metadata.pop().unwrap()); + let is_pending_up_to_date = true; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_CHUNK_ACROSS_2_BLOCKS_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_address_filter() { + let address = ContractAddress(patricia_key!("0x22")); + let blocks_metadata = vec![BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { address: Some(address), keys: None }, + DEFAULT_EVENT_METADATA, + ]])]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, address: Some(address), ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_address_filter() { + let address = ContractAddress(patricia_key!("0x22")); + // As a special edge case, the function get_events doesn't return events if there are no + // accepted blocks, even if there is a pending block. Therefore, we need to have a block in the + // storage. + let blocks_metadata = vec![BlockMetadata(vec![])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { address: Some(address), keys: None }, + DEFAULT_EVENT_METADATA, + ]])); + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, address: Some(address), ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +lazy_static! { + static ref KEY0_0: EventKey = EventKey(felt!("0x00")); + static ref KEY0_1: EventKey = EventKey(felt!("0x01")); + static ref KEY2_0: EventKey = EventKey(felt!("0x20")); + static ref KEY2_1: EventKey = EventKey(felt!("0x21")); + static ref UNRELATED_KEY: EventKey = EventKey(felt!("0xff")); + static ref BLOCKS_METADATA_FOR_KEYS_FILTER_TEST: Vec = + // Adding an empty block at the start so that in the pending test there will be an accepted + // block. See above for explanation on the special edge case of no accepted blocks. + vec![ + BlockMetadata(vec![]), + BlockMetadata(vec![vec![ + DEFAULT_EVENT_METADATA, + EventMetadata { + address: None, + keys: Some(vec![KEY0_0.clone(), UNRELATED_KEY.clone(), KEY2_1.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![KEY2_0.clone(), UNRELATED_KEY.clone(), KEY2_1.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![KEY0_1.clone(), UNRELATED_KEY.clone(), KEY0_0.clone()]), + }, + EventMetadata { + address: None, + keys: Some(vec![ + KEY0_1.clone(), + UNRELATED_KEY.clone(), + KEY2_0.clone(), + UNRELATED_KEY.clone(), + ]), + }, + EventMetadata { address: None, keys: Some(vec![KEY0_1.clone()]) }, + EventMetadata { address: None, keys: Some(vec![]) }, + ]] + )]; + static ref EVENT_FILTER_FOR_KEYS_FILTER_TEST: EventFilter = EventFilter { + chunk_size: 6, + keys: vec![ + HashSet::from([KEY0_0.clone(), KEY0_1.clone()]), + HashSet::from([]), + HashSet::from([KEY2_0.clone(), KEY2_1.clone()]), + ], + ..Default::default() + }; + static ref EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST: Vec<(Vec, Option,)> = + vec![( + vec![ + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ), + EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(4), + ), + ], + None, + )]; +} + +#[tokio::test] +async fn get_events_keys_filter() { + let pending_block_metadata = None; + let is_pending_up_to_date = true; + test_get_events( + BLOCKS_METADATA_FOR_KEYS_FILTER_TEST.clone(), + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_KEYS_FILTER_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_keys_filter() { + let mut blocks_metadata = BLOCKS_METADATA_FOR_KEYS_FILTER_TEST.clone(); + let pending_block_metadata = Some(blocks_metadata.pop().unwrap()); + let is_pending_up_to_date = true; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EVENT_FILTER_FOR_KEYS_FILTER_TEST.clone(), + EXPECTED_RESULT_BY_INDEX_FOR_KEYS_FILTER_TEST.clone(), + ) + .await; +} + +#[tokio::test] +async fn get_events_from_block() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata.clone(), + pending_block_metadata.clone(), + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + ..Default::default() + }, + expected_result_by_index.clone(), + ) + .await; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::Tag(Tag::Latest)), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_from_pending() { + let blocks_metadata = vec![BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])); + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(1), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::Tag(Tag::Pending)), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_to_block() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + to_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +// TODO(nevo): add a test that returns the block not found error for getEvents +#[tokio::test] +async fn get_events_no_blocks() { + let blocks_metadata = vec![BlockMetadata::default()]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![(vec![], None)]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_no_blocks_in_filter() { + let blocks_metadata = vec![ + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]]), + ]; + let pending_block_metadata = None; + let is_pending_up_to_date = true; + let expected_result_by_index = vec![(vec![], None)]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { + chunk_size: 2, + from_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1)))), + to_block: Some(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ..Default::default() + }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_pending_not_up_to_date() { + // As a special edge case, the function get_events doesn't return events if there are no + // accepted blocks, even if there is a pending block. Therefore, we need to have a block in the + // storage. + let blocks_metadata = vec![BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])]; + let pending_block_metadata = Some(BlockMetadata(vec![vec![DEFAULT_EVENT_METADATA]])); + let is_pending_up_to_date = false; + let expected_result_by_index = vec![( + vec![EventIndex( + TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + )], + None, + )]; + test_get_events( + blocks_metadata, + pending_block_metadata, + is_pending_up_to_date, + EventFilter { chunk_size: 2, ..Default::default() }, + expected_result_by_index, + ) + .await; +} + +#[tokio::test] +async fn get_events_page_size_too_big() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: None, + chunk_size: get_test_rpc_config().max_events_chunk_size + 1, + address: None, + keys: vec![], + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_7_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &PAGE_SIZE_TOO_BIG.into(), + ) + .await; +} + +#[tokio::test] +async fn get_events_too_many_keys() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + let keys = (0..get_test_rpc_config().max_events_keys + 1) + .map(|i| HashSet::from([EventKey(Felt::from(i as u128))])) + .collect(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: None, + chunk_size: 2, + address: None, + keys, + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_7_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &TOO_MANY_KEYS_IN_FILTER.into(), + ) + .await; +} + +#[tokio::test] +async fn get_events_invalid_ct() { + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + let block = starknet_api::block::Block::default(); + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body) + .unwrap() + .append_state_diff(block.header.block_number, starknet_api::state::ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); + + // Create the filter. + let filter = EventFilter { + from_block: None, + to_block: None, + continuation_token: Some(ContinuationToken("junk".to_owned())), + chunk_size: 2, + address: None, + keys: vec![], + }; + + call_api_then_assert_and_validate_schema_for_err::<_, EventsChunk>( + &module, + "starknet_V0_7_getEvents", + vec![Box::new(filter)], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &INVALID_CONTINUATION_TOKEN.into(), + ) + .await; +} + +#[tokio::test] +async fn serialize_returns_valid_json() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let mut rng = get_rng(); + let parent_block = starknet_api::block::Block::default(); + let block = starknet_api::block::Block { + header: BlockHeader { + parent_hash: parent_block.header.block_hash, + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + ..BlockHeader::default() + }, + body: get_test_body(5, Some(5), None, None), + }; + let mut state_diff = StateDiff::get_test_instance(&mut rng); + // In the test instance both declared_classes and deprecated_declared_classes have an entry + // with class hash 0x0, which is illegal. + state_diff.deprecated_declared_classes = IndexMap::from([( + ClassHash(felt!("0x2")), + starknet_api::deprecated_contract_class::ContractClass::get_test_instance(&mut rng), + )]); + // For checking the schema also for deprecated contract classes. + state_diff + .deployed_contracts + .insert(ContractAddress(patricia_key!("0x2")), ClassHash(felt!("0x2"))); + // TODO(yair): handle replaced classes. + state_diff.replaced_classes.clear(); + + let (thin_state_diff, classes, deprecated_classes) = + starknet_api::state::ThinStateDiff::from_state_diff(state_diff.clone()); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(parent_block.header.block_number, &parent_block.header) + .unwrap() + .append_body(parent_block.header.block_number, parent_block.body) + .unwrap() + .append_state_diff( + parent_block.header.block_number, + starknet_api::state::ThinStateDiff::default(), + ) + .unwrap() + .append_classes(parent_block.header.block_number, &[], &[]) + .unwrap() + .append_header(block.header.block_number, &block.header) + .unwrap() + .append_body(block.header.block_number, block.body.clone()) + .unwrap() + .append_state_diff(block.header.block_number, thin_state_diff) + .unwrap() + .append_classes( + block.header.block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .commit() + .unwrap(); + + let gateway_config = get_test_rpc_config(); + let (server_address, _handle) = run_server( + &gateway_config, + get_test_highest_block(), + get_test_pending_data(), + get_test_pending_classes(), + storage_reader, + NODE_VERSION, + ) + .await + .unwrap(); + + let schema = get_starknet_spec_api_schema_for_components( + &[( + SpecFile::StarknetApiOpenrpc, + &[ + "BLOCK_WITH_TXS", + "BLOCK_WITH_TX_HASHES", + "STATE_UPDATE", + "CONTRACT_CLASS", + "DEPRECATED_CONTRACT_CLASS", + "TXN", + "TXN_RECEIPT", + "EVENTS_CHUNK", + ], + )], + &VERSION, + ); + validate_state(&state_diff, server_address, &schema).await; + validate_block(&block.header, server_address, &schema).await; + validate_transaction(block.body.transaction_hashes.index(0), server_address, &schema).await; +} + +async fn validate_state(state_diff: &StateDiff, server_address: SocketAddr, schema: &JSONSchema) { + let res = send_request( + server_address, + "starknet_getStateUpdate", + r#"{"block_number": 1}"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "State update is not valid."); + + let (address, _) = state_diff.deployed_contracts.get_index(0).unwrap(); + let res = send_request( + server_address, + "starknet_getClassAt", + format!(r#"{{"block_number": 1}}, "0x{}""#, hex::encode(address.0.key().to_bytes_be())) + .as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Class is not valid."); + + // TODO(dvir): Remove this after regenesis. + // This checks the deployed deprecated class. + let (address, _) = state_diff.deployed_contracts.get_index(1).unwrap(); + let res = send_request( + server_address, + "starknet_getClassAt", + format!(r#"{{"block_number": 1}}, "0x{}""#, hex::encode(address.0.key().to_bytes_be())) + .as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Class is not valid."); +} + +async fn validate_block(header: &BlockHeader, server_address: SocketAddr, schema: &JSONSchema) { + let res = send_request( + server_address, + "starknet_getBlockWithTxs", + r#"{"block_number": 1}"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Block with transactions is not valid."); + + let res = send_request( + server_address, + "starknet_getBlockWithTxHashes", + format!(r#"{{"block_hash": "0x{}"}}"#, hex::encode(header.block_hash.0.to_bytes_be())) + .as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Block with transaction hashes is not valid."); +} + +async fn validate_transaction( + tx_hash: &TransactionHash, + server_address: SocketAddr, + schema: &JSONSchema, +) { + let res = send_request( + server_address, + "starknet_getTransactionByBlockIdAndIndex", + r#"{"block_number": 1}, 0"#, + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction is not valid."); + + let res = send_request( + server_address, + "starknet_getTransactionByHash", + format!(r#""0x{}""#, hex::encode(tx_hash.0.to_bytes_be())).as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction is not valid."); + + let res = send_request( + server_address, + "starknet_getTransactionReceipt", + format!(r#""0x{}""#, hex::encode(tx_hash.0.to_bytes_be())).as_str(), + VERSION.name, + ) + .await; + assert!(validate_schema(schema, &res["result"]), "Transaction receipt is not valid."); + + let res = + send_request(server_address, "starknet_getEvents", r#"{"chunk_size": 2}"#, VERSION.name) + .await; + assert!(validate_schema(schema, &res["result"]), "Events are not valid."); +} + +// This test checks that the deprecated contract class is returned with the correct state mutability +// field in the function abi entry. If there is no stateMutability field, the gateway should return +// an answer without this field at all, and if it is present, it should be returned as is. +#[tokio::test] +async fn get_deprecated_class_state_mutability() { + // Without state mutability. + let function_abi_without_state_mutability = + FunctionAbiEntry { state_mutability: None, ..Default::default() }; + let function_abi_without_state_mutability = + ContractClassAbiEntry::Function(function_abi_without_state_mutability); + let class_without_state_mutability = starknet_api::deprecated_contract_class::ContractClass { + abi: Some(vec![function_abi_without_state_mutability]), + ..Default::default() + }; + + // With state mutability. + let function_abi_with_state_mutability = FunctionAbiEntry { + state_mutability: Some(FunctionStateMutability::View), + ..Default::default() + }; + let function_abi_with_state_mutability = + ContractClassAbiEntry::Function(function_abi_with_state_mutability); + let class_with_state_mutability = starknet_api::deprecated_contract_class::ContractClass { + abi: Some(vec![function_abi_with_state_mutability]), + ..Default::default() + }; + + let state_diff = starknet_api::state::ThinStateDiff { + deprecated_declared_classes: vec![ClassHash(felt!("0x0")), ClassHash(felt!("0x1"))], + ..Default::default() + }; + + let (module, mut storage_writer) = + get_test_rpc_server_and_storage_writer::(); + let header = BlockHeader::default(); + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(header.block_number, &header) + .unwrap() + .append_state_diff(header.block_number, state_diff) + .unwrap() + .append_classes( + header.block_number, + &[], + &[ + (ClassHash(felt!("0x0")), &class_without_state_mutability), + (ClassHash(felt!("0x1")), &class_with_state_mutability), + ], + ) + .unwrap() + .commit() + .unwrap(); + + // Get class without state mutability. + let res = module + .call::<_, DeprecatedContractClass>( + "starknet_V0_7_getClass", + ( + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), + ClassHash(felt!("0x0")), + ), + ) + .await + .unwrap(); + let res_as_value = serde_json::to_value(res).unwrap(); + let entry = res_as_value["abi"][0].as_object().unwrap(); + assert!(!entry.contains_key("stateMutability")); + + // Get class with state mutability. + let res = module + .call::<_, DeprecatedContractClass>( + "starknet_V0_7_getClass", + ( + BlockId::HashOrNumber(BlockHashOrNumber::Hash(header.block_hash)), + ClassHash(felt!("0x1")), + ), + ) + .await + .unwrap(); + let res_as_value = serde_json::to_value(res).unwrap(); + let entry = res_as_value["abi"][0].as_object().unwrap(); + assert_eq!(entry.get("stateMutability").unwrap().as_str().unwrap(), "view"); +} + +// TODO (Yael 16/06/2024): Add a test case for block_number which is not the latest. +#[tokio::test] +async fn get_compiled_contract_class() { + let cairo1_class_hash = ClassHash(Felt::ONE); + let cairo0_class_hash = ClassHash(Felt::TWO); + let invalid_class_hash = ClassHash(Felt::THREE); + + let method_name = "starknet_V0_7_getCompiledContractClass"; + let (module, mut storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, None, None, None); + let cairo1_contract_class = CasmContractClass::get_test_instance(&mut get_rng()); + let cairo0_contract_class = + StarknetApiDeprecatedContractClass::get_test_instance(&mut get_rng()); + storage_writer + .begin_rw_txn() + .unwrap() + .append_state_diff( + BlockNumber(0), + starknet_api::state::ThinStateDiff { + declared_classes: IndexMap::from([( + cairo1_class_hash, + CompiledClassHash::default(), + )]), + deprecated_declared_classes: vec![cairo0_class_hash], + ..Default::default() + }, + ) + .unwrap() + .append_casm(&cairo1_class_hash, &cairo1_contract_class) + .unwrap() + // Note: there is no need to write the cairo1 contract class here because the + // declared_classes_table is not used in the rpc method. + .append_classes(BlockNumber(0), &[], &[(cairo0_class_hash, &cairo0_contract_class)]) + .unwrap() + .commit() + .unwrap(); + + let res = module + .call::<_, CompiledContractClass>( + method_name, + (BlockId::Tag(Tag::Latest), cairo1_class_hash), + ) + .await + .unwrap(); + assert_eq!(res, CompiledContractClass::V1(cairo1_contract_class)); + + let res = module + .call::<_, CompiledContractClass>( + method_name, + (BlockId::Tag(Tag::Latest), cairo0_class_hash), + ) + .await + .unwrap(); + assert_eq!(res, CompiledContractClass::V0(cairo0_contract_class)); + + // Ask for an invalid class hash, which does no exist in the table. + let err = module + .call::<_, CompiledContractClass>( + method_name, + (BlockId::Tag(Tag::Latest), invalid_class_hash), + ) + .await + .unwrap_err(); + assert_matches!(err, Error::Call(err) if err == CLASS_HASH_NOT_FOUND.into()); +} + +#[async_trait] +trait AddTransactionTest +where + // This bound is a work-around for associated type bounds. It bounds + // `Self::ClientTransaction::Error` to implement `Debug`. + // associated type bounds is described here: + // https://github.com/rust-lang/rfcs/blob/master/text/2289-associated-type-bounds.md + <::ClientTransaction as TryFrom>::Error: Debug, +{ + type Transaction: GetTestInstance + Serialize + Clone + Send + Sync + 'static + Debug; + type ClientTransaction: TryFrom + Send + Debug; + type Response: From + + for<'de> Deserialize<'de> + + Eq + + Debug + + Clone + + Send + + Sync; + type ClientResponse: GetTestInstance + Clone + Send; + + const METHOD_NAME: &'static str; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ); + + async fn test_positive_flow() { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + let client_resp = Self::ClientResponse::get_test_instance(&mut rng); + let expected_resp = Self::Response::from(client_resp.clone()); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Ok(client_resp), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + call_api_then_assert_and_validate_schema_for_result( + &module, + Self::METHOD_NAME, + vec![Box::new(tx)], + &VERSION, + SpecFile::WriteApi, + &expected_resp, + ) + .await; + } + + async fn test_internal_error() { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + let client_error = WriterClientError::ClientError(ClientError::BadResponseStatus { + code: StatusCode::from_u16(404).unwrap(), + message: "This site can’t be reached".to_owned(), + }); + let expected_error = internal_server_error(&client_error); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, expected_error); + } + + async fn test_known_starknet_error( + known_starknet_error_code: KnownStarknetErrorCode, + expected_error: JsonRpcError, + ) { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + const MESSAGE: &str = "message"; + let client_error = + WriterClientError::ClientError(ClientError::StarknetError(StarknetError { + code: StarknetErrorCode::KnownErrorCode(known_starknet_error_code), + message: MESSAGE.to_owned(), + })); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, expected_error.into()); + } + + async fn test_unexpected_error(known_starknet_error_code: KnownStarknetErrorCode) { + let mut rng = get_rng(); + let tx = Self::Transaction::get_test_instance(&mut rng); + const MESSAGE: &str = "message"; + let client_error = + WriterClientError::ClientError(ClientError::StarknetError(StarknetError { + code: StarknetErrorCode::KnownErrorCode(known_starknet_error_code), + message: MESSAGE.to_owned(), + })); + + let mut client_mock = MockStarknetWriter::new(); + Self::expect_add_transaction( + &mut client_mock, + Self::ClientTransaction::try_from(tx.clone()).unwrap(), + Err(client_error), + ); + + let (module, _) = get_test_rpc_server_and_storage_writer_from_params::( + Some(client_mock), + None, + None, + None, + None, + ); + let result = module.call::<_, Self::Response>(Self::METHOD_NAME, [tx]).await; + let jsonrpsee::core::Error::Call(error) = result.unwrap_err() else { + panic!("Got an error which is not a call error"); + }; + assert_eq!(error, unexpected_error(MESSAGE.to_owned()).into()); + } +} + +struct AddInvokeTest {} +impl AddTransactionTest for AddInvokeTest { + type Transaction = TypedInvokeTransaction; + type ClientTransaction = ClientInvokeTransaction; + type Response = AddInvokeOkResult; + type ClientResponse = InvokeResponse; + + const METHOD_NAME: &'static str = "starknet_V0_7_addInvokeTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_invoke_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +struct AddDeployAccountTest {} +impl AddTransactionTest for AddDeployAccountTest { + type Transaction = TypedDeployAccountTransaction; + type ClientTransaction = ClientDeployAccountTransaction; + type Response = AddDeployAccountOkResult; + type ClientResponse = DeployAccountResponse; + + const METHOD_NAME: &'static str = "starknet_V0_7_addDeployAccountTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_deploy_account_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +struct AddDeclareTest {} +impl AddTransactionTest for AddDeclareTest { + type Transaction = BroadcastedDeclareTransaction; + type ClientTransaction = ClientDeclareTransaction; + type Response = AddDeclareOkResult; + type ClientResponse = DeclareResponse; + + const METHOD_NAME: &'static str = "starknet_V0_7_addDeclareTransaction"; + + fn expect_add_transaction( + client_mock: &mut MockStarknetWriter, + client_tx: Self::ClientTransaction, + client_result: WriterClientResult, + ) { + client_mock + .expect_add_declare_transaction() + .times(1) + .with(eq(client_tx)) + .return_once(move |_| client_result); + } +} + +// TODO(shahak): Test starknet error. + +#[tokio::test] +async fn add_invoke_positive_flow() { + AddInvokeTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_invoke_internal_error() { + AddInvokeTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_invoke_known_starknet_error() { + AddInvokeTest::test_known_starknet_error( + KnownStarknetErrorCode::DuplicatedTransaction, + DUPLICATE_TX, + ) + .await; +} + +#[tokio::test] +async fn add_invoke_unexpected_error() { + // Choosing error codes that map under the other transaction types into an expected error in + // order to check that we call invoke's error conversion. + AddInvokeTest::test_unexpected_error(KnownStarknetErrorCode::CompilationFailed).await; + AddInvokeTest::test_unexpected_error(KnownStarknetErrorCode::UndeclaredClass).await; +} + +#[tokio::test] +async fn add_deploy_account_positive_flow() { + AddDeployAccountTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_deploy_account_internal_error() { + AddDeployAccountTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_deploy_account_known_starknet_error() { + // Choosing an error code that maps under the other transaction types into an unexpected error + // in order to check that we call deploy_account's error conversion. + AddDeployAccountTest::test_known_starknet_error( + KnownStarknetErrorCode::UndeclaredClass, + CLASS_HASH_NOT_FOUND, + ) + .await; +} + +#[tokio::test] +async fn add_deploy_account_unexpected_error() { + // Choosing an error code that maps under the other transaction types into an expected error in + // order to check that we call deploy_account's error conversion. + AddDeployAccountTest::test_unexpected_error(KnownStarknetErrorCode::CompilationFailed).await; +} + +#[tokio::test] +async fn add_declare_positive_flow() { + AddDeclareTest::test_positive_flow().await; +} + +#[tokio::test] +async fn add_declare_internal_error() { + AddDeclareTest::test_internal_error().await; +} + +#[tokio::test] +async fn add_declare_known_starknet_error() { + // Choosing an error code that maps under the other transaction types into an unexpected error + // in order to check that we call declare's error conversion. + AddDeclareTest::test_known_starknet_error( + KnownStarknetErrorCode::CompilationFailed, + COMPILATION_FAILED, + ) + .await; +} + +#[tokio::test] +async fn add_declare_unexpected_error() { + // Choosing an error code that maps under the other transaction types into an expected error in + // order to check that we call declare's error conversion. + AddDeclareTest::test_unexpected_error(KnownStarknetErrorCode::UndeclaredClass).await; +} + +#[test] +fn spec_api_methods_coverage() { + let (module, _) = get_test_rpc_server_and_storage_writer::(); + let implemented_methods: Methods = module.into(); + let implemented_method_names = implemented_methods + .method_names() + .map(method_name_to_spec_method_name) + .sorted() + .collect::>(); + let non_implemented_apis = ["starknet_pendingTransactions".to_string()]; + let method_names_in_spec = get_method_names_from_spec(&VERSION) + .iter() + .filter_map(|method| { + let stripped_method_name = method.clone().replace('\"', ""); + if non_implemented_apis.contains(&stripped_method_name) { + None + } else { + Some(stripped_method_name) + } + }) + .sorted() + .collect::>(); + + // Methods in the spec are a subset of the implemented methods. + assert!( + method_names_in_spec.iter().all(|method| implemented_method_names.contains(method)), + "Implemented methods: {:#?}, methods in spec: {:#?}", + implemented_method_names, + method_names_in_spec + ); +} + +auto_impl_get_test_instance! { + pub struct PendingBlockHeader { + pub parent_hash: BlockHash, + pub sequencer_address: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub l1_data_gas_price: ResourcePrice, + pub l1_da_mode: L1DataAvailabilityMode, + pub starknet_version: String, + } + pub struct ResourcePrice { + pub price_in_wei: GasPrice, + pub price_in_fri: GasPrice, + } + pub enum TypedInvokeTransaction { + Invoke(InvokeTransaction) = 0, + } + pub enum TypedDeployAccountTransaction { + DeployAccount(DeployAccountTransaction) = 0, + } +} diff --git a/crates/papyrus_rpc/src/v0_7/block.rs b/crates/papyrus_rpc/src/v0_7/block.rs new file mode 100644 index 00000000000..0fc352f09bc --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/block.rs @@ -0,0 +1,172 @@ +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageError, StorageReader, StorageTxn}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus, BlockTimestamp, GasPrice}; +use starknet_api::core::{GlobalRoot, SequencerContractAddress}; +use starknet_api::data_availability::L1DataAvailabilityMode; + +use super::error::BLOCK_NOT_FOUND; +use super::transaction::Transactions; +use crate::api::{BlockHashOrNumber, BlockId, Tag}; +use crate::{get_latest_block_number, internal_server_error}; + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct BlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub sequencer_address: SequencerContractAddress, + pub new_root: GlobalRoot, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub l1_data_gas_price: ResourcePrice, + pub l1_da_mode: L1DataAvailabilityMode, + pub starknet_version: String, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct PendingBlockHeader { + pub parent_hash: BlockHash, + pub sequencer_address: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_gas_price: ResourcePrice, + pub l1_data_gas_price: ResourcePrice, + pub l1_da_mode: L1DataAvailabilityMode, + pub starknet_version: String, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum GeneralBlockHeader { + BlockHeader(BlockHeader), + PendingBlockHeader(PendingBlockHeader), +} + +impl From for BlockHeader { + fn from(header: starknet_api::block::BlockHeader) -> Self { + BlockHeader { + block_hash: header.block_hash, + parent_hash: header.parent_hash, + block_number: header.block_number, + sequencer_address: header.sequencer, + new_root: header.state_root, + timestamp: header.timestamp, + l1_gas_price: ResourcePrice { + price_in_wei: header.l1_gas_price.price_in_wei, + price_in_fri: header.l1_gas_price.price_in_fri, + }, + l1_data_gas_price: ResourcePrice { + price_in_wei: header.l1_data_gas_price.price_in_wei, + price_in_fri: header.l1_data_gas_price.price_in_fri, + }, + l1_da_mode: header.l1_da_mode, + starknet_version: header.starknet_version.0, + } + } +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ResourcePrice { + pub price_in_wei: GasPrice, + pub price_in_fri: GasPrice, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct Block { + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(flatten)] + pub header: GeneralBlockHeader, + pub transactions: Transactions, +} + +pub fn get_block_header_by_number( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result { + let header = txn + .get_block_header(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + Ok(header) +} + +/// Return the closest block number that corresponds to the given block id and is accepted (i.e not +/// pending). Latest block means the most advanced block that we've downloaded and that we've +/// downloaded its state diff. +pub(crate) fn get_accepted_block_number( + txn: &StorageTxn<'_, Mode>, + block_id: BlockId, +) -> Result { + Ok(match block_id { + BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash)) => { + let block_number = txn + .get_block_number_by_hash(&block_hash) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + // Check that the block has state diff. + let last_block_number = get_latest_block_number(txn)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + if block_number > last_block_number { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND)); + } + block_number + } + BlockId::HashOrNumber(BlockHashOrNumber::Number(block_number)) => { + // Check that the block exists and has state diff. + let last_block_number = get_latest_block_number(txn)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + if block_number > last_block_number { + return Err(ErrorObjectOwned::from(BLOCK_NOT_FOUND)); + } + block_number + } + BlockId::Tag(Tag::Latest | Tag::Pending) => { + get_latest_block_number(txn)?.ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))? + } + }) +} + +/// Validates that a given block wasn't reverted. Given an instance of this class, we can call its +/// `validate` method and it will validate that the block's hash didn't change from the validator's +/// creation. +pub(crate) struct BlockNotRevertedValidator { + block_number: BlockNumber, + old_block_hash: BlockHash, +} + +impl BlockNotRevertedValidator { + pub fn new( + block_number: BlockNumber, + txn: &StorageTxn<'_, Mode>, + ) -> Result { + let header = txn + .get_block_header(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| { + ErrorObjectOwned::from(internal_server_error(StorageError::DBInconsistency { + msg: format!("Missing block header {block_number}"), + })) + })?; + Ok(Self { block_number, old_block_hash: header.block_hash }) + } + + pub fn validate(self, storage_reader: &StorageReader) -> Result<(), ErrorObjectOwned> { + let error = ErrorObjectOwned::from(internal_server_error(format!( + "Block {} was reverted mid-execution.", + self.block_number + ))); + let txn = storage_reader.begin_ro_txn().map_err(internal_server_error)?; + let new_block_hash = txn + .get_block_header(self.block_number) + .map_err(internal_server_error)? + .ok_or(error.clone())? + .block_hash; + if new_block_hash == self.old_block_hash { Ok(()) } else { Err(error) } + } +} diff --git a/crates/papyrus_rpc/src/v0_7/broadcasted_transaction.rs b/crates/papyrus_rpc/src/v0_7/broadcasted_transaction.rs new file mode 100644 index 00000000000..496eea2b8bf --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/broadcasted_transaction.rs @@ -0,0 +1,195 @@ +//! This module contains structs for representing a broadcasted transaction. +//! +//! A broadcasted transaction is a transaction that wasn't accepted yet to Starknet. +//! +//! The broadcasted transaction follows the same structure as described in the [`Starknet specs`] +//! +//! [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + +#[cfg(test)] +#[path = "broadcasted_transaction_test.rs"] +mod broadcasted_transaction_test; + +use papyrus_storage::db::serialization::StorageSerdeError; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::transaction::{ + AccountDeploymentData, + Fee, + PaymasterData, + Tip, + TransactionSignature, + TransactionVersion, +}; +use starknet_client::writer::objects::transaction as client_transaction; +use starknet_client::writer::objects::transaction::DeprecatedContractClass; + +use super::state::ContractClass; +use super::transaction::{DeployAccountTransaction, InvokeTransaction, ResourceBoundsMapping}; +use crate::compression_utils::compress_and_encode; + +/// Transactions that are ready to be broadcasted to the network and are not included in a block. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum BroadcastedTransaction { + #[serde(rename = "DECLARE")] + Declare(BroadcastedDeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), +} + +/// A broadcasted declare transaction. +/// +/// This transaction is equivalent to the component DECLARE_TXN in the +/// [`Starknet specs`] without the V0 variant and with a contract class (DECLARE_TXN allows having +/// either a contract class or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +#[serde(tag = "version")] +pub enum BroadcastedDeclareTransaction { + #[serde(rename = "0x1")] + V1(BroadcastedDeclareV1Transaction), + #[serde(rename = "0x2")] + V2(BroadcastedDeclareV2Transaction), + #[serde(rename = "0x3")] + V3(BroadcastedDeclareV3Transaction), +} + +/// A broadcasted declare transaction of a Cairo-v0 contract. +/// +/// This transaction is equivalent to the component DECLARE_TXN_V1 in the +/// [`Starknet specs`] with a contract class (DECLARE_TXN_V1 allows having either a contract class +/// or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV1Transaction { + pub r#type: DeclareType, + pub contract_class: DeprecatedContractClass, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, +} + +/// A broadcasted declare transaction of a Cairo-v1 contract. +/// +/// This transaction is equivalent to the component DECLARE_TXN_V2 in the +/// [`Starknet specs`] with a contract class (DECLARE_TXN_V2 allows having either a contract class +/// or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Default)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV2Transaction { + pub r#type: DeclareType, + pub contract_class: ContractClass, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct BroadcastedDeclareV3Transaction { + pub r#type: DeclareType, + pub sender_address: ContractAddress, + pub compiled_class_hash: CompiledClassHash, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +/// The type field of a declare transaction. This enum serializes/deserializes into a constant +/// string. +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] +pub enum DeclareType { + #[serde(rename = "DECLARE")] + #[default] + Declare, +} + +impl TryFrom for client_transaction::DeclareTransaction { + type Error = StorageSerdeError; + + fn try_from(value: BroadcastedDeclareTransaction) -> Result { + match value { + BroadcastedDeclareTransaction::V1(declare_v1) => { + Ok(Self::DeclareV1(client_transaction::DeclareV1Transaction { + contract_class: declare_v1.contract_class, + sender_address: declare_v1.sender_address, + nonce: declare_v1.nonce, + max_fee: declare_v1.max_fee, + signature: declare_v1.signature, + version: TransactionVersion::ONE, + r#type: client_transaction::DeclareType::default(), + })) + } + BroadcastedDeclareTransaction::V2(declare_v2) => { + Ok(Self::DeclareV2(client_transaction::DeclareV2Transaction { + contract_class: client_transaction::ContractClass { + compressed_sierra_program: compress_and_encode(serde_json::to_value( + &declare_v2.contract_class.sierra_program, + )?)?, + contract_class_version: declare_v2.contract_class.contract_class_version, + entry_points_by_type: declare_v2 + .contract_class + .entry_points_by_type + .to_hash_map(), + abi: declare_v2.contract_class.abi, + }, + compiled_class_hash: declare_v2.compiled_class_hash, + sender_address: declare_v2.sender_address, + nonce: declare_v2.nonce, + max_fee: declare_v2.max_fee, + signature: declare_v2.signature, + version: TransactionVersion::TWO, + r#type: client_transaction::DeclareType::default(), + })) + } + BroadcastedDeclareTransaction::V3(declare_v3) => { + Ok(Self::DeclareV3(client_transaction::DeclareV3Transaction { + contract_class: client_transaction::ContractClass { + compressed_sierra_program: compress_and_encode(serde_json::to_value( + &declare_v3.contract_class.sierra_program, + )?)?, + contract_class_version: declare_v3.contract_class.contract_class_version, + entry_points_by_type: declare_v3 + .contract_class + .entry_points_by_type + .to_hash_map(), + abi: declare_v3.contract_class.abi, + }, + resource_bounds: declare_v3.resource_bounds.into(), + tip: declare_v3.tip, + signature: declare_v3.signature, + nonce: declare_v3.nonce, + compiled_class_hash: declare_v3.compiled_class_hash, + sender_address: declare_v3.sender_address, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: declare_v3.paymaster_data, + account_deployment_data: declare_v3.account_deployment_data, + version: TransactionVersion::THREE, + r#type: client_transaction::DeclareType::Declare, + })) + } + } + } +} diff --git a/crates/papyrus_rpc/src/v0_7/broadcasted_transaction_test.rs b/crates/papyrus_rpc/src/v0_7/broadcasted_transaction_test.rs new file mode 100644 index 00000000000..3d6d4404fc7 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/broadcasted_transaction_test.rs @@ -0,0 +1,175 @@ +use std::collections::HashMap; + +use jsonschema::JSONSchema; +use lazy_static::lazy_static; +use starknet_api::core::{CompiledClassHash, ContractAddress, Nonce}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::deprecated_contract_class::{ + ContractClassAbiEntry as DeprecatedContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointType as DeprecatedEntryPointType, + EventAbiEntry, + FunctionAbiEntry, + StructAbiEntry, +}; +use starknet_api::state::EntryPoint; +use starknet_api::transaction::{ + AccountDeploymentData, + Fee, + PaymasterData, + ResourceBounds, + Tip, + TransactionSignature, +}; +use starknet_client::writer::objects::transaction::DeprecatedContractClass; +use starknet_types_core::felt::Felt; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, get_rng, GetTestInstance}; + +use super::super::state::{ContractClass, EntryPointByType}; +use super::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedDeclareV2Transaction, + BroadcastedDeclareV3Transaction, + DeclareType, + ResourceBoundsMapping, +}; +use crate::test_utils::{get_starknet_spec_api_schema_for_components, SpecFile}; +use crate::version_config::VERSION_0_7 as Version; + +fn validate_tx_fits_rpc(tx: BroadcastedDeclareTransaction) { + lazy_static! { + static ref SCHEMA: JSONSchema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::StarknetApiOpenrpc, &["BROADCASTED_DECLARE_TXN"])], + &Version + ); + } + assert!(SCHEMA.is_valid(&serde_json::to_value(tx).unwrap())); +} + +auto_impl_get_test_instance! { + pub enum BroadcastedDeclareTransaction { + V1(BroadcastedDeclareV1Transaction) = 0, + V2(BroadcastedDeclareV2Transaction) = 1, + V3(BroadcastedDeclareV3Transaction) = 2, + } + pub struct BroadcastedDeclareV1Transaction { + pub r#type: DeclareType, + pub contract_class: DeprecatedContractClass, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + } + pub struct BroadcastedDeclareV2Transaction { + pub r#type: DeclareType, + pub contract_class: ContractClass, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + } + pub struct BroadcastedDeclareV3Transaction { + pub r#type: DeclareType, + pub sender_address: ContractAddress, + pub compiled_class_hash: CompiledClassHash, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + // TODO(yair): Move out the test instances of ContractClass and EntryPointByType. + pub struct ContractClass { + pub sierra_program: Vec, + pub contract_class_version: String, + pub entry_points_by_type: EntryPointByType, + pub abi: String, + } + + pub struct EntryPointByType { + pub constructor: Vec, + pub external: Vec, + pub l1handler: Vec, + } + pub enum DeclareType { + Declare = 0, + } + + pub struct ResourceBoundsMapping { + pub l1_gas: ResourceBounds, + pub l2_gas: ResourceBounds, + } +} + +#[test] +fn declare_v1_fits_rpc() { + let mut rng = get_rng(); + for has_abi in [true, false] { + let abi = if has_abi { + Some(vec![ + DeprecatedContractClassAbiEntry::Event(EventAbiEntry::get_test_instance(&mut rng)), + DeprecatedContractClassAbiEntry::Function(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::Constructor(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::L1Handler(FunctionAbiEntry::get_test_instance( + &mut rng, + )), + DeprecatedContractClassAbiEntry::Struct(StructAbiEntry::get_test_instance( + &mut rng, + )), + ]) + } else { + None + }; + let tx = BroadcastedDeclareTransaction::V1(BroadcastedDeclareV1Transaction { + contract_class: DeprecatedContractClass { + abi, + entry_points_by_type: HashMap::from([ + ( + DeprecatedEntryPointType::Constructor, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ( + DeprecatedEntryPointType::External, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ( + DeprecatedEntryPointType::L1Handler, + vec![DeprecatedEntryPoint::get_test_instance(&mut rng)], + ), + ]), + ..GetTestInstance::get_test_instance(&mut rng) + }, + ..GetTestInstance::get_test_instance(&mut rng) + }); + validate_tx_fits_rpc(tx); + } +} + +#[test] +fn declare_v2_fits_rpc() { + let mut rng = get_rng(); + let tx = BroadcastedDeclareTransaction::V2(BroadcastedDeclareV2Transaction::get_test_instance( + &mut rng, + )); + validate_tx_fits_rpc(tx); +} + +#[test] +fn declare_v3_fits_rpc() { + let mut rng = get_rng(); + let tx = BroadcastedDeclareTransaction::V3(BroadcastedDeclareV3Transaction::get_test_instance( + &mut rng, + )); + + validate_tx_fits_rpc(tx); +} diff --git a/crates/papyrus_rpc/src/v0_7/deprecated_contract_class.rs b/crates/papyrus_rpc/src/v0_7/deprecated_contract_class.rs new file mode 100644 index 00000000000..0625c917b42 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/deprecated_contract_class.rs @@ -0,0 +1,44 @@ +use std::collections::HashMap; + +use papyrus_storage::db::serialization::StorageSerdeError; +use serde::{Deserialize, Serialize}; +use starknet_api::deprecated_contract_class::{ContractClassAbiEntry, EntryPoint, EntryPointType}; + +use crate::compression_utils::compress_and_encode; + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub abi: Vec, + /// A base64 encoding of the gzip-compressed JSON representation of program. + pub program: String, + /// The selector of each entry point is a unique identifier in the program. + pub entry_points_by_type: HashMap>, +} + +impl TryFrom for ContractClass { + type Error = StorageSerdeError; + fn try_from( + class: starknet_api::deprecated_contract_class::ContractClass, + ) -> Result { + let mut program_value = serde_json::to_value(&class.program)?; + // Remove the 'attributes' key if it is null. + if class.program.attributes == serde_json::value::Value::Null { + program_value.as_object_mut().expect("Expecting json object").remove("attributes"); + } + // Remove the 'compiler_version' key if it is null. + if class.program.compiler_version == serde_json::value::Value::Null { + program_value + .as_object_mut() + .expect("Expecting json object") + .remove("compiler_version"); + } + + let abi = class.abi.unwrap_or_default(); + + Ok(Self { + abi, + program: compress_and_encode(program_value)?, + entry_points_by_type: class.entry_points_by_type, + }) + } +} diff --git a/crates/papyrus_rpc/src/v0_7/error.rs b/crates/papyrus_rpc/src/v0_7/error.rs new file mode 100644 index 00000000000..cbc08c77a70 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/error.rs @@ -0,0 +1,132 @@ +use jsonrpsee::types::ErrorObjectOwned; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug)] +pub struct JsonRpcError { + pub code: i32, + pub message: &'static str, + pub data: Option, +} + +// TODO(yair): Remove allow(dead_code) once all errors are used. +#[allow(dead_code)] +pub const FAILED_TO_RECEIVE_TRANSACTION: JsonRpcError = + JsonRpcError { code: 1, message: "Failed to write transaction", data: None }; + +pub const CONTRACT_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 20, message: "Contract not found", data: None }; + +pub const INVALID_TRANSACTION_HASH: JsonRpcError = + JsonRpcError { code: 25, message: "Invalid transaction hash", data: None }; + +// TODO(shahak): Remove allow(dead_code) once all errors are used. +#[allow(dead_code)] +pub const INVALID_BLOCK_HASH: JsonRpcError = + JsonRpcError { code: 26, message: "Invalid block hash", data: None }; + +pub const BLOCK_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 24, message: "Block not found", data: None }; + +pub const INVALID_TRANSACTION_INDEX: JsonRpcError = + JsonRpcError { code: 27, message: "Invalid transaction index in a block", data: None }; + +pub const CLASS_HASH_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 28, message: "Class hash not found", data: None }; + +pub const TRANSACTION_HASH_NOT_FOUND: JsonRpcError = + JsonRpcError { code: 29, message: "Transaction hash not found", data: None }; + +pub const PAGE_SIZE_TOO_BIG: JsonRpcError = + JsonRpcError { code: 31, message: "Requested page size is too big", data: None }; + +pub const NO_BLOCKS: JsonRpcError = + JsonRpcError { code: 32, message: "There are no blocks", data: None }; + +pub const INVALID_CONTINUATION_TOKEN: JsonRpcError = JsonRpcError { + code: 33, + message: "The supplied continuation token is invalid or unknown", + data: None, +}; + +pub const TOO_MANY_KEYS_IN_FILTER: JsonRpcError = + JsonRpcError { code: 34, message: "Too many keys provided in a filter", data: None }; + +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct ContractError { + pub revert_error: String, +} + +impl From for JsonRpcError { + fn from(contract_error: ContractError) -> Self { + Self { code: 40, message: "Contract error", data: Some(contract_error) } + } +} +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +pub struct TransactionExecutionError { + pub transaction_index: usize, + pub execution_error: String, +} + +impl From for JsonRpcError { + fn from(tx_execution_error: TransactionExecutionError) -> Self { + Self { code: 41, message: "Transaction execution error", data: Some(tx_execution_error) } + } +} +pub const CLASS_ALREADY_DECLARED: JsonRpcError = + JsonRpcError { code: 51, message: "Class already declared", data: None }; + +pub const INVALID_TRANSACTION_NONCE: JsonRpcError = + JsonRpcError { code: 52, message: "Invalid transaction nonce", data: None }; + +pub const INSUFFICIENT_MAX_FEE: JsonRpcError = JsonRpcError { + code: 53, + message: "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)", + data: None, +}; + +pub const INSUFFICIENT_ACCOUNT_BALANCE: JsonRpcError = JsonRpcError { + code: 54, + message: "Account balance is smaller than the transaction's max_fee", + data: None, +}; + +pub fn validation_failure(data: String) -> JsonRpcError { + JsonRpcError { code: 55, message: "Account validation failed", data: Some(data) } +} + +pub const COMPILATION_FAILED: JsonRpcError = + JsonRpcError { code: 56, message: "Compilation failed", data: None }; + +pub const CONTRACT_CLASS_SIZE_IS_TOO_LARGE: JsonRpcError = + JsonRpcError { code: 57, message: "Contract class size it too large", data: None }; + +pub const NON_ACCOUNT: JsonRpcError = + JsonRpcError { code: 58, message: "Sender address in not an account contract", data: None }; + +pub const DUPLICATE_TX: JsonRpcError = JsonRpcError { + code: 59, + message: "A transaction with the same hash already exists in the mempool", + data: None, +}; + +pub const COMPILED_CLASS_HASH_MISMATCH: JsonRpcError = JsonRpcError { + code: 60, + message: "the compiled class hash did not match the one supplied in the transaction", + data: None, +}; + +pub const UNSUPPORTED_TX_VERSION: JsonRpcError = + JsonRpcError { code: 61, message: "the transaction version is not supported", data: None }; + +pub const UNSUPPORTED_CONTRACT_CLASS_VERSION: JsonRpcError = + JsonRpcError { code: 62, message: "the contract class version is not supported", data: None }; + +pub fn unexpected_error(data: String) -> JsonRpcError { + JsonRpcError { code: 63, message: "An unexpected error occurred", data: Some(data) } +} + +impl From> for ErrorObjectOwned { + fn from(err: JsonRpcError) -> Self { + ErrorObjectOwned::owned(err.code, err.message, err.data) + } +} diff --git a/crates/papyrus_rpc/src/v0_7/execution.rs b/crates/papyrus_rpc/src/v0_7/execution.rs new file mode 100644 index 00000000000..2bcda34c6fd --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/execution.rs @@ -0,0 +1,242 @@ +use papyrus_execution::objects::{ + CallType, + FunctionCall, + FunctionInvocation as ExecutionFunctionInvocation, + FunctionInvocationResult as ExecutionFunctionInvocationResult, + OrderedEvent, + OrderedL2ToL1Message, + Retdata, + RevertReason, + TransactionTrace as ExecutionTransactionTrace, +}; +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::deprecated_contract_class::EntryPointType; +use starknet_api::state::ThinStateDiff as StarknetApiThinStateDiff; + +use super::state::ThinStateDiff; +use super::transaction::{ComputationResources, ExecutionResources}; + +// The only difference between this and TransactionTrace in the execution crate is the +// ExecutionResources inside FunctionInvocation. +/// The execution trace of a transaction. +#[allow(missing_docs)] +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum TransactionTrace { + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionTrace), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionTrace), + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionTrace), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionTrace), +} + +/// The execution trace of an L1Handler transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct L1HandlerTransactionTrace { + /// The trace of the funcion call. + pub function_invocation: FunctionInvocation, + /// The state diff induced by this transaction. + pub state_diff: ThinStateDiff, + /// The total execution resources of this transaction. + pub execution_resources: ExecutionResources, +} + +/// The execution trace of an Invoke transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct InvokeTransactionTrace { + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __validate__ call. + pub validate_invocation: Option, + /// The trace of the __execute__ call or the reason in case of reverted transaction. + pub execute_invocation: FunctionInvocationResult, + #[serde(skip_serializing_if = "Option::is_none")] + /// The trace of the __fee_transfer__ call. + pub fee_transfer_invocation: Option, + /// The state diff induced by this transaction. + pub state_diff: ThinStateDiff, + /// The total execution resources of this transaction. + pub execution_resources: ExecutionResources, +} + +/// The execution trace of a Declare transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeclareTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, + /// The state diff induced by this transaction. + pub state_diff: ThinStateDiff, + /// The total execution resources of this transaction. + pub execution_resources: ExecutionResources, +} + +/// The execution trace of a DeployAccount transaction. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct DeployAccountTransactionTrace { + /// The trace of the __validate__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate_invocation: Option, + /// The trace of the __constructor__ call. + pub constructor_invocation: FunctionInvocation, + /// The trace of the __fee_transfer__ call. + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_transfer_invocation: Option, + /// The state diff induced by this transaction. + pub state_diff: ThinStateDiff, + /// The total execution resources of this transaction. + pub execution_resources: ExecutionResources, +} + +/// Wether the function invocation succeeded or reverted. +// Not using `Result` because it is not being serialized according to the spec. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[allow(missing_docs)] +#[serde(untagged)] +pub enum FunctionInvocationResult { + Ok(FunctionInvocation), + Err(RevertReason), +} + +/// The execution trace of a function call. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct FunctionInvocation { + #[serde(flatten)] + /// The details of the function call. + pub function_call: FunctionCall, + /// The address of the invoking contract. 0 for the root invocation. + pub caller_address: ContractAddress, + /// The hash of the class being called. + pub class_hash: ClassHash, + /// The type of the entry point being called. + pub entry_point_type: EntryPointType, + /// library call or regular call. + pub call_type: CallType, + /// The value returned from the function invocation. + pub result: Retdata, + /// The calls made by this invocation. + pub calls: Vec, + /// The events emitted in this invocation. + pub events: Vec, + /// The messages sent by this invocation to L1. + pub messages: Vec, + /// The VM execution resources used by this invocation. + pub execution_resources: ComputationResources, +} + +impl From<(ExecutionTransactionTrace, StarknetApiThinStateDiff)> for TransactionTrace { + fn from((trace, state_diff): (ExecutionTransactionTrace, StarknetApiThinStateDiff)) -> Self { + let mut state_diff = ThinStateDiff::from(state_diff); + // TODO: Investigate why blockifier sometimes returns unsorted state diff + state_diff.sort(); + match trace { + ExecutionTransactionTrace::L1Handler(trace) => { + let execution_resources = + trace.function_invocation.execution_resources.clone().into(); + Self::L1Handler(L1HandlerTransactionTrace { + function_invocation: trace.function_invocation.into(), + state_diff, + execution_resources, + }) + } + ExecutionTransactionTrace::Invoke(trace) => { + let (execute_invocation, execute_execution_resources) = match trace + .execute_invocation + { + ExecutionFunctionInvocationResult::Ok(function_invocation) => { + let execution_resources = function_invocation.execution_resources.clone(); + ( + FunctionInvocationResult::Ok(function_invocation.into()), + ExecutionResources::from(execution_resources), + ) + } + ExecutionFunctionInvocationResult::Err(revert_reason) => ( + FunctionInvocationResult::Err(revert_reason), + ExecutionResources::default(), + ), + }; + + let validate_execution_resources = + trace.validate_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + let fee_transfer_execution_resources = + trace.fee_transfer_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + + Self::Invoke(InvokeTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + execute_invocation, + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + state_diff, + execution_resources: validate_execution_resources.unwrap_or_default() + + execute_execution_resources + + fee_transfer_execution_resources.unwrap_or_default(), + }) + } + ExecutionTransactionTrace::Declare(trace) => { + let validate_execution_resources = + trace.validate_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + let fee_transfer_execution_resources = + trace.fee_transfer_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + Self::Declare(DeclareTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + state_diff, + execution_resources: validate_execution_resources.unwrap_or_default() + + fee_transfer_execution_resources.unwrap_or_default(), + }) + } + ExecutionTransactionTrace::DeployAccount(trace) => { + let validate_execution_resources = + trace.validate_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + let constructor_execution_resources = ExecutionResources::from( + trace.constructor_invocation.execution_resources.clone(), + ); + let fee_transfer_execution_resources = + trace.fee_transfer_invocation.as_ref().map(|invocation| { + ExecutionResources::from(invocation.execution_resources.clone()) + }); + Self::DeployAccount(DeployAccountTransactionTrace { + validate_invocation: trace.validate_invocation.map(Into::into), + constructor_invocation: trace.constructor_invocation.into(), + fee_transfer_invocation: trace.fee_transfer_invocation.map(Into::into), + state_diff, + execution_resources: validate_execution_resources.unwrap_or_default() + + constructor_execution_resources + + fee_transfer_execution_resources.unwrap_or_default(), + }) + } + } + } +} + +impl From for FunctionInvocation { + fn from(invocation: ExecutionFunctionInvocation) -> Self { + Self { + function_call: invocation.function_call, + caller_address: invocation.caller_address, + class_hash: invocation.class_hash, + entry_point_type: invocation.entry_point_type, + call_type: invocation.call_type, + result: invocation.result, + calls: invocation.calls.into_iter().map(Into::into).collect(), + events: invocation.events, + messages: invocation.messages, + execution_resources: invocation.execution_resources.into(), + } + } +} diff --git a/crates/papyrus_rpc/src/v0_7/execution_test.rs b/crates/papyrus_rpc/src/v0_7/execution_test.rs new file mode 100644 index 00000000000..d184501dae2 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/execution_test.rs @@ -0,0 +1,1785 @@ +use std::env; +use std::fs::read_to_string; +use std::path::Path; +use std::sync::Arc; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::indexmap; +use jsonrpsee::core::Error; +use jsonrpsee::RpcModule; +use lazy_static::lazy_static; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses, PendingClassesTrait}; +use papyrus_common::state::{ + DeclaredClassHashEntry, + DeployedContract as CommonDeployedContract, + StorageEntry as CommonStorageEntry, +}; +use papyrus_execution::execution_utils::selector_from_name; +use papyrus_execution::objects::{ + CallType, + FeeEstimation, + FunctionCall, + OrderedEvent, + OrderedL2ToL1Message, + PriceUnit, + Retdata, + RevertReason, +}; +use papyrus_execution::testing_instances::get_storage_var_address; +use papyrus_execution::ExecutableTransactionInput; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::StorageWriter; +use pretty_assertions::assert_eq; +use starknet_api::block::{ + BlockBody, + BlockHash, + BlockHeader, + BlockNumber, + BlockTimestamp, + GasPrice, + GasPricePerToken, +}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, + PatriciaKey, + SequencerContractAddress, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::deprecated_contract_class::{ + ContractClass as SN_API_DeprecatedContractClass, + EntryPointType, +}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{StorageKey, ThinStateDiff as StarknetApiStateDiff}; +use starknet_api::transaction::{ + Calldata, + Fee, + L1HandlerTransaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionVersion, +}; +use starknet_api::{calldata, class_hash, contract_address, felt, patricia_key}; +use starknet_client::reader::objects::pending_data::{ + PendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate, +}; +use starknet_client::reader::objects::state::StateDiff as ClientStateDiff; +use starknet_client::reader::objects::transaction::{ + IntermediateInvokeTransaction as ClientInvokeTransaction, + Transaction as ClientTransaction, + TransactionReceipt as ClientTransactionReceipt, +}; +use starknet_client::reader::PendingData; +use starknet_types_core::felt::Felt; +use test_utils::{ + auto_impl_get_test_instance, + get_number_of_variants, + get_rng, + read_json_file, + GetTestInstance, +}; +use tokio::sync::RwLock; + +use super::api::api_impl::JsonRpcServerImpl; +use super::api::{ + decompress_program, + SimulatedTransaction, + SimulationFlag, + TransactionTraceWithHash, +}; +use super::broadcasted_transaction::{ + BroadcastedDeclareTransaction, + BroadcastedDeclareV1Transaction, + BroadcastedTransaction, +}; +use super::error::{TransactionExecutionError, BLOCK_NOT_FOUND, CONTRACT_NOT_FOUND}; +use super::execution::{ + DeclareTransactionTrace, + DeployAccountTransactionTrace, + FunctionInvocation, + FunctionInvocationResult, + InvokeTransactionTrace, + L1HandlerTransactionTrace, + TransactionTrace, +}; +use super::state::{ + ClassHashes, + ContractNonce, + DeployedContract, + ReplacedClasses, + StorageDiff, + StorageEntry, + ThinStateDiff, +}; +use super::transaction::{ + Builtin, + DeployAccountTransaction, + ExecutionResources, + InvokeTransaction, + InvokeTransactionV1, + MessageFromL1, + TransactionVersion1, +}; +use crate::api::{BlockHashOrNumber, BlockId, CallRequest, Tag}; +use crate::test_utils::{ + call_and_validate_schema_for_result, + call_api_then_assert_and_validate_schema_for_result, + get_starknet_spec_api_schema_for_components, + get_starknet_spec_api_schema_for_method_results, + get_test_pending_classes, + get_test_pending_data, + get_test_rpc_config, + get_test_rpc_server_and_storage_writer, + get_test_rpc_server_and_storage_writer_from_params, + validate_schema, + SpecFile, +}; +use crate::version_config::VERSION_0_7 as VERSION; + +lazy_static! { + pub static ref GAS_PRICE: GasPricePerToken = GasPricePerToken{ + price_in_wei: GasPrice(100 * u128::pow(10, 9)), + price_in_fri: GasPrice(0), + }; + pub static ref DATA_GAS_PRICE: GasPricePerToken = GasPricePerToken{ + price_in_wei: GasPrice(1), + price_in_fri: GasPrice(0), + }; + pub static ref MAX_FEE: Fee = Fee(1000000 * GAS_PRICE.price_in_wei.0); + pub static ref BLOCK_TIMESTAMP: BlockTimestamp = BlockTimestamp(1234); + pub static ref SEQUENCER_ADDRESS: SequencerContractAddress = + SequencerContractAddress(contract_address!("0xa")); + pub static ref DEPRECATED_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1"); + pub static ref CONTRACT_ADDRESS: ContractAddress = contract_address!("0x2"); + pub static ref ACCOUNT_CLASS_HASH: ClassHash = class_hash!("0x333"); + pub static ref ACCOUNT_ADDRESS: ContractAddress = contract_address!("0x444"); + pub static ref TEST_ERC20_CONTRACT_CLASS_HASH: ClassHash = class_hash!("0x1010"); + pub static ref TEST_ERC20_CONTRACT_ADDRESS: ContractAddress = contract_address!("0x1001"); + pub static ref ACCOUNT_INITIAL_BALANCE: Felt = felt!(2 * MAX_FEE.0); + // TODO(yair): verify this is the correct fee, got this value by printing the result of the + // call. + pub static ref EXPECTED_FEE_ESTIMATE: FeeEstimation = FeeEstimation { + gas_consumed: felt!("0x680"), + gas_price: GAS_PRICE.price_in_wei, + data_gas_consumed: Felt::ZERO, + data_gas_price: DATA_GAS_PRICE.price_in_wei, + overall_fee: Fee(166400000000000,), + unit: PriceUnit::Wei, + }; + + pub static ref EXPECTED_FEE_ESTIMATE_SKIP_VALIDATE: FeeEstimation = FeeEstimation { + gas_consumed: felt!("0x680"), + gas_price: GAS_PRICE.price_in_wei, + data_gas_consumed: Felt::ZERO, + data_gas_price: DATA_GAS_PRICE.price_in_wei, + overall_fee: Fee(166400000000000,), + unit: PriceUnit::Wei, + }; + + // A message from L1 contract at address 0x987 to the contract at CONTRACT_ADDRESS that calls + // the entry point "l1_handle" with the value 0x123, the retdata should be 0x123. + pub static ref MESSAGE_FROM_L1: MessageFromL1 = MessageFromL1 { + from_address: EthAddress::try_from(felt!( + "0x987" + )) + .unwrap(), + to_address: *CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("l1_handle"), + payload: calldata![ + felt!("0x123") + ], + }; +} + +#[tokio::test] +async fn execution_call() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let key = felt!(1234_u16); + let value = felt!(18_u8); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_7_call", + vec![ + Box::new(CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("test_storage_read_write"), + calldata: calldata![key, value], + }), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &vec![value], + ) + .await; + + // Calling a non-existent contract. + let err = module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { + contract_address: ContractAddress(patricia_key!("0x1234")), + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap_err(); + + assert_matches!(err, Error::Call(err) if err == CONTRACT_NOT_FOUND.into()); + + // Calling a non-existent block. + let err = module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { + contract_address: ContractAddress(patricia_key!("0x1234")), + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(7))), + ), + ) + .await + .unwrap_err(); + + assert_matches!(err, Error::Call(err) if err == BLOCK_NOT_FOUND.into()); + + // Calling a non-existent function (contract error). + let err = module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("aaa"), + calldata: calldata![key, value], + }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap_err(); + + const CONTRACT_ERROR_CODE: i32 = 40; + assert_matches!(err, Error::Call(err) if err.code() == CONTRACT_ERROR_CODE); + + // Test that the block context is passed correctly to blockifier. + let mut calldata = get_calldata_for_test_execution_info( + BlockNumber(0), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &InvokeTransactionV1::default(), + TransactionHash(StarkHash::ZERO), + Some(Felt::ZERO), + ); + // Calling the contract directly and not through the account contract. + let contract_address = ContractAddress( + PatriciaKey::try_from(Arc::get_mut(&mut calldata.0).unwrap().remove(0)).unwrap(), + ); + let entry_point_selector = EntryPointSelector(Arc::get_mut(&mut calldata.0).unwrap().remove(0)); + let _calldata_length = Arc::get_mut(&mut calldata.0).unwrap().remove(0); + + module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { contract_address, entry_point_selector, calldata }, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap(); +} + +#[tokio::test] +async fn pending_execution_call() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + let key = felt!(1234_u16); + let value = felt!(18_u8); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { + contract_address: *DEPRECATED_CONTRACT_ADDRESS, + entry_point_selector: selector_from_name("test_storage_read_write"), + calldata: calldata![key, value], + }, + BlockId::Tag(Tag::Pending), + ), + ) + .await + .unwrap(); + + assert_eq!(res, vec![value]); + + // Test that the block context is passed correctly to blockifier with a block number that is + // after the latest block in the storage. + let mut calldata = get_calldata_for_test_execution_info( + BlockNumber(1), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &InvokeTransactionV1::default(), + TransactionHash(StarkHash::ZERO), + Some(Felt::ZERO), + ); + // Calling the contract directly and not through the account contract. + let contract_address = ContractAddress( + PatriciaKey::try_from(Arc::get_mut(&mut calldata.0).unwrap().remove(0)).unwrap(), + ); + let entry_point_selector = EntryPointSelector(Arc::get_mut(&mut calldata.0).unwrap().remove(0)); + let _calldata_length = Arc::get_mut(&mut calldata.0).unwrap().remove(0); + + module + .call::<_, Vec>( + "starknet_V0_7_call", + ( + CallRequest { contract_address, entry_point_selector, calldata }, + BlockId::Tag(Tag::Pending), + ), + ) + .await + .unwrap(); +} + +#[tokio::test] +async fn call_estimate_fee() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let account_address = ContractAddress(patricia_key!("0x444")); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_7_estimateFee", + vec![ + Box::new(vec![invoke.clone()]), + Box::>::default(), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &vec![EXPECTED_FEE_ESTIMATE.clone()], + ) + .await; + + // Test that calling the same transaction with a different block context with a different gas + // price produces a different fee. + let res = module + .call::<_, Vec>( + "starknet_V0_7_estimateFee", + ( + vec![invoke.clone()], + Vec::::new(), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(1))), + ), + ) + .await + .unwrap(); + assert_ne!(res, vec![EXPECTED_FEE_ESTIMATE.clone()]); + + // Test that calling the same transaction with a different block context with a different l1 DA + // mode produces a different fee. + let res = module + .call::<_, Vec>( + "starknet_V0_7_estimateFee", + ( + vec![invoke.clone()], + Vec::::new(), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(2))), + ), + ) + .await + .unwrap(); + assert_ne!(res, vec![EXPECTED_FEE_ESTIMATE.clone()]); + + // Test that calling the same transaction with skip_validate produces a lower gas consumed. + // TODO(yair): test with an account contract which has a lengthy validate function. + let res = module + .call::<_, Vec>( + "starknet_V0_7_estimateFee", + ( + vec![invoke], + Vec::::from([SimulationFlag::SkipValidate]), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .unwrap(); + assert!(res.first().unwrap().gas_consumed <= EXPECTED_FEE_ESTIMATE.gas_consumed); + + // Test that reverted transaction fails the fee estimation. + let non_existent_entry_point = + BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("non_existent_ep").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + let res = module + .call::<_, Vec>( + "starknet_V0_7_estimateFee", + ( + vec![non_existent_entry_point], + Vec::::new(), + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + ), + ) + .await + .expect_err("Expecting error"); + let Error::Call(err) = res else { + panic!("Expecting error"); + }; + assert_eq!(err.code(), 41); + let Some(data) = err.data() else { + panic!("Expecting error data"); + }; + let tx_execution_error: TransactionExecutionError = serde_json::from_str(data.get()).unwrap(); + assert_eq!(tx_execution_error.transaction_index, 0); + + // TODO(shahak): Write a new contract and test execution info. The reason we can't do this with + // the current contract is that the transaction hash appears in the calldata and thus it is + // calculated inside the hash. +} + +#[tokio::test] +async fn pending_call_estimate_fee() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + let account_address = ContractAddress(patricia_key!("0x444")); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: account_address, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_estimateFee", + (vec![invoke.clone()], Vec::::new(), BlockId::Tag(Tag::Pending)), + ) + .await + .unwrap(); + assert_eq!(res, vec![EXPECTED_FEE_ESTIMATE.clone()]); + + // TODO(shahak): Write a new contract and test execution info. The reason we can't do this with + // the current contract is that the transaction hash appears in the calldata and thus it is + // calculated inside the hash. +} + +#[tokio::test] +async fn call_simulate() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + test_call_simulate( + &module, + BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0))), + BlockNumber(0), + ) + .await; +} + +#[tokio::test] +async fn pending_call_simulate() { + let pending_data = get_test_pending_data(); + let pending_classes = get_test_pending_classes(); + write_block_0_as_pending(pending_data.clone(), pending_classes.clone()).await; + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >( + None, None, Some(pending_data), Some(pending_classes), None + ); + write_empty_block(storage_writer); + + test_call_simulate(&module, BlockId::Tag(Tag::Pending), BlockNumber(1)).await; +} + +// Test call_simulate. Assumes that the given block is equal to block number 0 that is returned +// from the function `prepare_storage_for_execution`. +async fn test_call_simulate( + module: &RpcModule, + block_id: BlockId, + block_context_number: BlockNumber, +) { + let mut invoke_v1 = InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + }; + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(invoke_v1.clone())); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + module, + "starknet_V0_7_simulateTransactions", + vec![Box::new(block_id), Box::new(vec![invoke]), Box::>::default()], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, Some(_)); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, Some(_)); + + // Test that the block context is passed correctly to blockifier. + let calldata = get_calldata_for_test_execution_info( + block_context_number, + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &invoke_v1, + // Because the transaction hash depends on the calldata and the calldata needs to contain + // the transaction hash, there's no way to put the correct hash here. Instead, we'll check + // that the function `test_get_execution_info` fails on the transaction hash validation. + TransactionHash(StarkHash::ZERO), + None, + ); + invoke_v1.calldata = calldata; + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(invoke_v1)); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_simulateTransactions", + (block_id, vec![invoke], Vec::::new()), + ) + .await + .unwrap(); + + let TransactionTrace::Invoke(invoke_trace) = &res[0].transaction_trace else { + panic!("Got a non-invoke transaction trace from an invoke transaction."); + }; + // As described above, we want to check that `test_get_execution_info` fails on the transaction + // hash validation (which is done after the block context validation). + let FunctionInvocationResult::Err(RevertReason::RevertReason(error_str)) = + &invoke_trace.execute_invocation + else { + panic!("Expected call to test_get_execution_info to fail."); + }; + assert!(error_str.contains("TX_INFO_MISMATCH")); +} + +#[tokio::test] +async fn call_simulate_skip_validate() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_7_simulateTransactions", + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + Box::new(vec![invoke]), + Box::new(vec![SimulationFlag::SkipValidate]), + ], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE_SKIP_VALIDATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, None); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, Some(_)); +} + +#[tokio::test] +async fn call_simulate_skip_fee_charge() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + prepare_storage_for_execution(storage_writer); + + let invoke = BroadcastedTransaction::Invoke(InvokeTransaction::Version1(InvokeTransactionV1 { + max_fee: Fee(1000000 * GAS_PRICE.price_in_wei.0), + version: TransactionVersion1::Version1, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + ..Default::default() + })); + + let mut res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_7_simulateTransactions", + vec![ + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + Box::new(vec![invoke]), + Box::new(vec![SimulationFlag::SkipFeeCharge]), + ], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 1); + + let simulated_tx = res.pop().unwrap(); + + assert_eq!(simulated_tx.fee_estimation, *EXPECTED_FEE_ESTIMATE); + + assert_matches!(simulated_tx.transaction_trace, TransactionTrace::Invoke(_)); + + let TransactionTrace::Invoke(invoke_trace) = simulated_tx.transaction_trace else { + unreachable!(); + }; + + assert_matches!(invoke_trace.validate_invocation, Some(_)); + assert_matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)); + assert_matches!(invoke_trace.fee_transfer_invocation, None); +} + +// TODO(shahak): Add test for trace_transaction that doesn't depend on trace_block_transactions +#[tokio::test] +async fn trace_block_transactions_regular_and_pending() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + let mut writer = prepare_storage_for_execution(storage_writer); + + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let client_tx1 = ClientTransaction::Invoke(ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + nonce: Some(Nonce(felt!(0_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }); + let tx1: starknet_api::transaction::Transaction = client_tx1.clone().try_into().unwrap(); + let client_tx2 = ClientTransaction::Invoke(ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![ + *DEPRECATED_CONTRACT_ADDRESS.0.key(), // Contract address. + selector_from_name("return_result").0, // EP selector. + felt!(1_u8), // Calldata length. + felt!(2_u8) // Calldata: num. + ], + nonce: Some(Nonce(felt!(1_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }); + let tx2: starknet_api::transaction::Transaction = client_tx2.clone().try_into().unwrap(); + + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(3), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x3")), + parent_hash: BlockHash(felt!("0x2")), + ..Default::default() + }, + ) + .unwrap() + .append_body( + BlockNumber(3), + BlockBody { + transactions: vec![tx1, tx2], + transaction_outputs: vec![ + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + ], + transaction_hashes: vec![tx_hash1, tx_hash2], + }, + ) + .unwrap() + .append_state_diff( + BlockNumber(3), + StarknetApiStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + ) + .unwrap() + .append_classes(BlockNumber(3), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + let tx_1_trace = call_and_validate_schema_for_result::<_, TransactionTrace>( + &module, + "starknet_V0_7_traceTransaction", + vec![Box::new(tx_hash1)], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_matches!(tx_1_trace, TransactionTrace::Invoke(_)); + + let tx_2_trace = module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash2]) + .await + .unwrap(); + + assert_matches!(tx_2_trace, TransactionTrace::Invoke(_)); + + let res = call_and_validate_schema_for_result::<_, Vec>( + &module, + "starknet_V0_7_traceBlockTransactions", + vec![Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(3))))], + &VERSION, + SpecFile::TraceApi, + ) + .await; + + assert_eq!(res.len(), 2); + assert_eq!(res[0].trace_root, tx_1_trace); + assert_eq!(res[0].transaction_hash, tx_hash1); + assert_eq!(res[1].trace_root, tx_2_trace); + assert_eq!(res[1].transaction_hash, tx_hash2); + + // Ask for trace of pending block. + // Create a new storage without the last block and put the last block as pending + + let pending_data = get_test_pending_data(); + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Current(PendingBlock { + l1_gas_price: *GAS_PRICE, + l1_data_gas_price: *DATA_GAS_PRICE, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + parent_block_hash: BlockHash(felt!("0x2")), + transactions: vec![client_tx1, client_tx2], + transaction_receipts: vec![ + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash1, + ..Default::default() + }, + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash2, + ..Default::default() + }, + ], + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + }, + }; + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data), None, None); + + prepare_storage_for_execution(storage_writer); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_traceBlockTransactions", + [BlockId::Tag(Tag::Pending)], + ) + .await + .unwrap(); + + assert_eq!(res.len(), 2); + assert_eq!(res[0].trace_root, tx_1_trace); + assert_eq!(res[0].transaction_hash, tx_hash1); + assert_eq!(res[1].trace_root, tx_2_trace); + assert_eq!(res[1].transaction_hash, tx_hash2); + + // Ask for trace of transactions in the pending block. + let pending_tx_1_trace = module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash1]) + .await + .unwrap(); + assert_eq!(pending_tx_1_trace, tx_1_trace); + let pending_tx_2_trace = module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash2]) + .await + .unwrap(); + assert_eq!(pending_tx_2_trace, tx_2_trace); +} + +#[tokio::test] +async fn trace_block_transactions_and_trace_transaction_execution_context() { + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let mut invoke_tx1 = starknet_api::transaction::InvokeTransactionV1 { + max_fee: *MAX_FEE, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Nonce(felt!(0_u128)), + ..Default::default() + }; + let mut invoke_tx2 = starknet_api::transaction::InvokeTransactionV1 { + max_fee: *MAX_FEE, + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Nonce(felt!(1_u128)), + ..Default::default() + }; + + let fix_calldata_of_invoke_tx = + |invoke_tx: &mut starknet_api::transaction::InvokeTransactionV1, tx_hash| { + let tx: super::transaction::Transaction = + starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx.clone()), + ) + .try_into() + .unwrap(); + let super::transaction::Transaction::Invoke(InvokeTransaction::Version1(rpc_invoke_v1)) = + tx + else { + panic!( + "Converting an InvokeV1 client transaction to a starknet api transaction did \ + not yield an InvokeV1 transaction" + ); + }; + invoke_tx.calldata = get_calldata_for_test_execution_info( + BlockNumber(3), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &rpc_invoke_v1, + tx_hash, + None, + ); + }; + fix_calldata_of_invoke_tx(&mut invoke_tx1, tx_hash1); + fix_calldata_of_invoke_tx(&mut invoke_tx2, tx_hash2); + let tx1 = starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx1), + ); + let tx2 = starknet_api::transaction::Transaction::Invoke( + starknet_api::transaction::InvokeTransaction::V1(invoke_tx2), + ); + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + + let mut writer = prepare_storage_for_execution(storage_writer); + + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(3), + &BlockHeader { + block_number: BlockNumber(3), + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x3")), + parent_hash: BlockHash(felt!("0x2")), + ..Default::default() + }, + ) + .unwrap() + .append_body( + BlockNumber(3), + BlockBody { + transactions: vec![tx1, tx2], + transaction_outputs: vec![ + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + starknet_api::transaction::TransactionOutput::Invoke( + starknet_api::transaction::InvokeTransactionOutput::default(), + ), + ], + transaction_hashes: vec![tx_hash1, tx_hash2], + }, + ) + .unwrap() + .append_state_diff( + BlockNumber(3), + StarknetApiStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + ) + .unwrap() + .append_classes(BlockNumber(3), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + let validate_result = |res| { + assert_matches!( + &res, + TransactionTrace::Invoke(invoke_trace) + if matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)) + ); + }; + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash1]) + .await + .unwrap(), + ); + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash2]) + .await + .unwrap(), + ); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_traceBlockTransactions", + [BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(3)))], + ) + .await + .unwrap(); + validate_result(res[0].trace_root.clone()); + validate_result(res[1].trace_root.clone()); +} + +#[tokio::test] +async fn pending_trace_block_transactions_and_trace_transaction_execution_context() { + let tx_hash1 = TransactionHash(felt!("0x1234")); + let tx_hash2 = TransactionHash(felt!("0x5678")); + + let mut client_invoke_tx1 = ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Some(Nonce(felt!(0_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }; + let mut client_invoke_tx2 = ClientInvokeTransaction { + max_fee: Some(*MAX_FEE), + sender_address: *ACCOUNT_ADDRESS, + calldata: calldata![], + nonce: Some(Nonce(felt!(1_u128))), + version: TransactionVersion::ONE, + ..Default::default() + }; + + let fix_calldata_of_client_invoke_tx = |client_invoke_tx: &mut ClientInvokeTransaction, + tx_hash| { + let starknet_api_tx: starknet_api::transaction::Transaction = + ClientTransaction::Invoke(client_invoke_tx.clone()).try_into().unwrap(); + let tx: super::transaction::Transaction = starknet_api_tx.try_into().unwrap(); + let super::transaction::Transaction::Invoke(InvokeTransaction::Version1(invoke_v1)) = tx + else { + panic!( + "Converting an InvokeV1 client transaction to a starknet api transaction did not \ + yield an InvokeV1 transaction" + ); + }; + client_invoke_tx.calldata = get_calldata_for_test_execution_info( + BlockNumber(3), + *BLOCK_TIMESTAMP, + *SEQUENCER_ADDRESS, + &invoke_v1, + tx_hash, + None, + ); + }; + fix_calldata_of_client_invoke_tx(&mut client_invoke_tx1, tx_hash1); + fix_calldata_of_client_invoke_tx(&mut client_invoke_tx2, tx_hash2); + let client_tx1 = ClientTransaction::Invoke(client_invoke_tx1); + let client_tx2 = ClientTransaction::Invoke(client_invoke_tx2); + + let pending_data = get_test_pending_data(); + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Current(PendingBlock { + l1_gas_price: *GAS_PRICE, + l1_data_gas_price: *DATA_GAS_PRICE, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + parent_block_hash: BlockHash(felt!("0x2")), + transactions: vec![client_tx1, client_tx2], + transaction_receipts: vec![ + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash1, + ..Default::default() + }, + ClientTransactionReceipt { + transaction_index: TransactionOffsetInBlock(0), + transaction_hash: tx_hash2, + ..Default::default() + }, + ], + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + nonces: indexmap!(*ACCOUNT_ADDRESS => Nonce(felt!(2_u128))), + ..Default::default() + }, + }, + }; + + let (module, storage_writer) = get_test_rpc_server_and_storage_writer_from_params::< + JsonRpcServerImpl, + >(None, None, Some(pending_data), None, None); + + prepare_storage_for_execution(storage_writer); + + let validate_result = |res| { + assert_matches!( + &res, + TransactionTrace::Invoke(invoke_trace) + if matches!(invoke_trace.execute_invocation, FunctionInvocationResult::Ok(_)) + ); + }; + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash1]) + .await + .unwrap(), + ); + + validate_result( + module + .call::<_, TransactionTrace>("starknet_V0_7_traceTransaction", [tx_hash2]) + .await + .unwrap(), + ); + + let res = module + .call::<_, Vec>( + "starknet_V0_7_traceBlockTransactions", + [BlockId::Tag(Tag::Pending)], + ) + .await + .unwrap(); + validate_result(res[0].trace_root.clone()); + validate_result(res[1].trace_root.clone()); +} + +#[test] +fn message_from_l1_to_l1_handler_tx() { + let l1_handler_tx = L1HandlerTransaction::from(MESSAGE_FROM_L1.clone()); + assert_eq!(l1_handler_tx.version, TransactionVersion::ONE); + assert_eq!(l1_handler_tx.contract_address, *CONTRACT_ADDRESS); + assert_eq!(l1_handler_tx.entry_point_selector, selector_from_name("l1_handle")); + // The first item of calldata is the from_address. + let from_address = EthAddress::try_from(*l1_handler_tx.calldata.0.first().unwrap()).unwrap(); + assert_eq!(from_address, MESSAGE_FROM_L1.from_address); + let rest_of_calldata = &l1_handler_tx.calldata.0[1..]; + assert_eq!(rest_of_calldata, MESSAGE_FROM_L1.payload.0.as_slice()); +} + +#[tokio::test] +async fn call_estimate_message_fee() { + let (module, storage_writer) = get_test_rpc_server_and_storage_writer::(); + prepare_storage_for_execution(storage_writer); + + // TODO(yair): get a l1_handler entry point that actually does something and check that the fee + // is correct. + let expected_fee_estimate = FeeEstimation { + gas_consumed: felt!("0x3937"), + gas_price: GAS_PRICE.price_in_wei, + data_gas_consumed: Felt::ZERO, + data_gas_price: DATA_GAS_PRICE.price_in_wei, + overall_fee: Fee(0), + unit: PriceUnit::default(), + }; + + call_api_then_assert_and_validate_schema_for_result( + &module, + "starknet_V0_7_estimateMessageFee", + vec![ + Box::new(MESSAGE_FROM_L1.clone()), + Box::new(BlockId::HashOrNumber(BlockHashOrNumber::Number(BlockNumber(0)))), + ], + &VERSION, + SpecFile::StarknetApiOpenrpc, + &expected_fee_estimate, + ) + .await; +} + +#[test] +fn broadcasted_to_executable_declare_v1() { + let mut rng = get_rng(); + let mut tx = BroadcastedDeclareV1Transaction::get_test_instance(&mut rng); + tx.contract_class.compressed_program = get_test_compressed_program(); + let broadcasted_declare_v1 = + BroadcastedTransaction::Declare(BroadcastedDeclareTransaction::V1(tx)); + assert_matches!( + broadcasted_declare_v1.try_into(), + Ok(ExecutableTransactionInput::DeclareV1(_tx, _class, _abi_length, _only_query)) + ); +} + +#[test] +fn validate_fee_estimation_schema() { + let mut rng = get_rng(); + let fee_estimate = FeeEstimation::get_test_instance(&mut rng); + let schema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::StarknetApiOpenrpc, &["FEE_ESTIMATE"])], + &VERSION, + ); + let serialized = serde_json::to_value(fee_estimate).unwrap(); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn validate_transaction_trace_with_hash_schema() { + let mut rng = get_rng(); + let txs_with_trace = Vec::::get_test_instance(&mut rng); + let serialized = serde_json::to_value(txs_with_trace).unwrap(); + let schema = get_starknet_spec_api_schema_for_method_results( + &[(SpecFile::TraceApi, &["starknet_traceBlockTransactions"])], + &VERSION, + ); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn validate_transaction_trace_schema() { + let mut rng = get_rng(); + let schema = get_starknet_spec_api_schema_for_components( + &[(SpecFile::TraceApi, &["TRANSACTION_TRACE"])], + &VERSION, + ); + + let invoke_trace = + TransactionTrace::Invoke(InvokeTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(invoke_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let declare_trace = + TransactionTrace::Declare(DeclareTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(declare_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let deploy_account_trace = + TransactionTrace::DeployAccount(DeployAccountTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(deploy_account_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); + + let l1_handler_trace = + TransactionTrace::L1Handler(L1HandlerTransactionTrace::get_test_instance(&mut rng)); + let serialized = serde_json::to_value(l1_handler_trace).unwrap(); + assert!(validate_schema(&schema, &serialized)); +} + +#[test] +fn broadcasted_to_executable_deploy_account() { + let mut rng = get_rng(); + let broadcasted_deploy_account = BroadcastedTransaction::DeployAccount( + DeployAccountTransaction::get_test_instance(&mut rng), + ); + assert_matches!( + broadcasted_deploy_account.try_into(), + Ok(ExecutableTransactionInput::DeployAccount(_tx, _only_query)) + ); +} + +#[test] +fn broadcasted_to_executable_invoke() { + let mut rng = get_rng(); + let broadcasted_deploy_account = + BroadcastedTransaction::Invoke(InvokeTransaction::get_test_instance(&mut rng)); + assert_matches!( + broadcasted_deploy_account.try_into(), + Ok(ExecutableTransactionInput::Invoke(_tx, _only_query)) + ); +} + +#[test] +fn get_decompressed_program() { + let compressed = get_test_compressed_program(); + let decompressed = decompress_program(&compressed); + decompressed.expect("Couldn't decompress program"); +} + +fn get_test_compressed_program() -> String { + let path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("resources") + .join("base64_compressed_program.txt"); + read_to_string(path).expect("Couldn't read compressed program") +} + +auto_impl_get_test_instance! { + pub enum TransactionTrace { + L1Handler(L1HandlerTransactionTrace) = 0, + Invoke(InvokeTransactionTrace) = 1, + Declare(DeclareTransactionTrace) = 2, + DeployAccount(DeployAccountTransactionTrace) = 3, + } + + pub struct L1HandlerTransactionTrace { + pub function_invocation: FunctionInvocation, + pub state_diff: ThinStateDiff, + pub execution_resources: ExecutionResources, + } + + pub struct InvokeTransactionTrace { + pub validate_invocation: Option, + pub execute_invocation: FunctionInvocationResult, + pub fee_transfer_invocation: Option, + pub state_diff: ThinStateDiff, + pub execution_resources: ExecutionResources, + } + + pub struct DeclareTransactionTrace { + pub validate_invocation: Option, + pub fee_transfer_invocation: Option, + pub state_diff: ThinStateDiff, + pub execution_resources: ExecutionResources, + } + + pub struct DeployAccountTransactionTrace { + pub validate_invocation: Option, + pub constructor_invocation: FunctionInvocation, + pub fee_transfer_invocation: Option, + pub state_diff: ThinStateDiff, + pub execution_resources: ExecutionResources, + } + + pub enum FunctionInvocationResult { + Ok(FunctionInvocation) = 0, + Err(RevertReason) = 1, + } + + pub enum Builtin { + RangeCheck = 0, + Pedersen = 1, + Poseidon = 2, + EcOp = 3, + Ecdsa = 4, + Bitwise = 5, + Keccak = 6, + SegmentArena = 7, + } + + pub struct ThinStateDiff { + pub deployed_contracts: Vec, + pub storage_diffs: Vec, + pub declared_classes: Vec, + pub deprecated_declared_classes: Vec, + pub nonces: Vec, + pub replaced_classes: Vec, + } + + pub struct DeployedContract { + pub address: ContractAddress, + pub class_hash: ClassHash, + } + + pub struct ClassHashes { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + } + + pub struct ContractNonce { + pub contract_address: ContractAddress, + pub nonce: Nonce, + } + + pub struct StorageDiff { + pub address: ContractAddress, + pub storage_entries: Vec, + } + + pub struct StorageEntry { + pub key: StorageKey, + pub value: Felt, + } + + pub struct ReplacedClasses { + pub contract_address: ContractAddress, + pub class_hash: ClassHash, + } + + pub struct TransactionTraceWithHash { + pub transaction_hash: TransactionHash, + pub trace_root: TransactionTrace, + } +} + +impl GetTestInstance for FunctionInvocation { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self { + function_call: FunctionCall::get_test_instance(rng), + caller_address: ContractAddress::get_test_instance(rng), + class_hash: ClassHash::get_test_instance(rng), + entry_point_type: EntryPointType::get_test_instance(rng), + call_type: CallType::get_test_instance(rng), + result: Retdata::get_test_instance(rng), + // TODO(shahak): fill with non empty value. + calls: Vec::new(), + events: Vec::::get_test_instance(rng), + messages: Vec::::get_test_instance(rng), + execution_resources: starknet_api::transaction::ExecutionResources::get_test_instance( + rng, + ) + .into(), + } + } +} + +impl GetTestInstance for ExecutionResources { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + starknet_api::transaction::ExecutionResources::get_test_instance(rng).into() + } +} + +/// Get calldata for invoking the function `test_execution_info` in the contract located in +/// `casm.json`. The function `test_execution_info` receives the expected block context and +/// transaction context and validates first the block context and then the transaction context. The +/// returned calldata will also contain the contract address, entry point selector and calldata +/// length so that it can be used from an account contract. If you want to call the function +/// directly, remove the first 3 arguments of the calldata. +fn get_calldata_for_test_execution_info( + expected_block_number: BlockNumber, + expected_block_timestamp: BlockTimestamp, + expected_sequencer_address: SequencerContractAddress, + invoke_tx: &InvokeTransactionV1, + tx_hash: TransactionHash, + override_tx_version: Option, +) -> Calldata { + let entry_point_selector = selector_from_name("test_get_execution_info"); + let expected_block_number = felt!(expected_block_number.0); + let expected_block_timestamp = felt!(expected_block_timestamp.0); + let expected_sequencer_address = *(expected_sequencer_address.0.0.key()); + let expected_caller_address = *(invoke_tx.sender_address.0.key()); + let expected_contract_address = *CONTRACT_ADDRESS.0.key(); + let expected_transaction_version = override_tx_version.unwrap_or(Felt::ONE); + let expected_signature = invoke_tx.signature.0.clone(); + let expected_transaction_hash = tx_hash.0; + let expected_chain_id = felt!(&*(get_test_rpc_config().chain_id.as_hex())); + let expected_nonce = invoke_tx.nonce.0; + let expected_max_fee = felt!(invoke_tx.max_fee.0); + let expected_resource_bounds_length = Felt::ZERO; + let expected_tip = Felt::ZERO; + let expected_paymaster_data = Felt::ZERO; + let expected_nonce_da = Felt::ZERO; + let expected_fee_da = Felt::ZERO; + let expected_account_data = Felt::ZERO; + + let calldata = [ + vec![ + expected_block_number, + expected_block_timestamp, + expected_sequencer_address, + expected_transaction_version, + expected_caller_address, + expected_max_fee, + felt!(expected_signature.len() as u64), + ], + expected_signature, + vec![ + expected_transaction_hash, + expected_chain_id, + expected_nonce, + expected_resource_bounds_length, + expected_tip, + expected_paymaster_data, + expected_nonce_da, + expected_fee_da, + expected_account_data, + expected_caller_address, + expected_contract_address, + entry_point_selector.0, + ], + ] + .iter() + .flatten() + .cloned() + .collect::>(); + + Calldata(Arc::new( + [ + vec![*CONTRACT_ADDRESS.0.key(), entry_point_selector.0, felt!(calldata.len() as u64)], + calldata, + ] + .iter() + .flatten() + .cloned() + .collect::>(), + )) +} + +// Write into the pending block the first block that the function `prepare_storage_for_execution` +// writes to the storage. +async fn write_block_0_as_pending( + pending_data: Arc>, + pending_classes: Arc>, +) { + let class1 = serde_json::from_value::(read_json_file( + "deprecated_class.json", + )) + .unwrap(); + let class_hash1 = class_hash!("0x1"); + + let class2 = starknet_api::state::ContractClass::default(); + let casm = serde_json::from_value::(read_json_file("casm.json")).unwrap(); + let class_hash2 = class_hash!("0x2"); + let compiled_class_hash = CompiledClassHash(StarkHash::default()); + + let account_class = serde_json::from_value(read_json_file("account_class.json")).unwrap(); + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + + let fee_contract_class = serde_json::from_value::( + read_json_file("erc20_fee_contract_class.json"), + ) + .unwrap(); + let minter_var_address = get_storage_var_address("permitted_minter", &[]); + + let mut pending_classes_ref = pending_classes.write().await; + pending_classes_ref.add_class(class_hash2, ApiContractClass::ContractClass(class2)); + pending_classes_ref.add_compiled_class(class_hash2, casm); + pending_classes_ref.add_class(class_hash1, ApiContractClass::DeprecatedContractClass(class1)); + pending_classes_ref + .add_class(*ACCOUNT_CLASS_HASH, ApiContractClass::DeprecatedContractClass(account_class)); + pending_classes_ref.add_class( + *TEST_ERC20_CONTRACT_CLASS_HASH, + ApiContractClass::DeprecatedContractClass(fee_contract_class), + ); + + *pending_data.write().await = PendingData { + block: PendingBlockOrDeprecated::Current(PendingBlock { + l1_gas_price: *GAS_PRICE, + l1_data_gas_price: *DATA_GAS_PRICE, + sequencer_address: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }), + state_update: PendingStateUpdate { + old_root: Default::default(), + state_diff: ClientStateDiff { + deployed_contracts: vec![ + CommonDeployedContract { + address: *DEPRECATED_CONTRACT_ADDRESS, + class_hash: class_hash1, + }, + CommonDeployedContract { address: *CONTRACT_ADDRESS, class_hash: class_hash2 }, + CommonDeployedContract { + address: *ACCOUNT_ADDRESS, + class_hash: *ACCOUNT_CLASS_HASH, + }, + CommonDeployedContract { + address: *TEST_ERC20_CONTRACT_ADDRESS, + class_hash: *TEST_ERC20_CONTRACT_CLASS_HASH, + }, + ], + storage_diffs: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => vec![ + // Give the accounts some balance. + CommonStorageEntry { + key: account_balance_key, value: *ACCOUNT_INITIAL_BALANCE + }, + // Give the first account mint permission (what is this?). + CommonStorageEntry { + key: minter_var_address, value: *ACCOUNT_ADDRESS.0.key() + }, + ], + ), + declared_classes: vec![DeclaredClassHashEntry { + class_hash: class_hash2, + compiled_class_hash, + }], + old_declared_contracts: vec![ + class_hash1, + *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_CLASS_HASH, + ], + nonces: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => Nonce::default(), + *CONTRACT_ADDRESS => Nonce::default(), + *DEPRECATED_CONTRACT_ADDRESS => Nonce::default(), + *ACCOUNT_ADDRESS => Nonce::default(), + ), + replaced_classes: vec![], + }, + }, + } +} + +fn prepare_storage_for_execution(mut storage_writer: StorageWriter) -> StorageWriter { + let class1 = serde_json::from_value::(read_json_file( + "deprecated_class.json", + )) + .unwrap(); + let class_hash1 = class_hash!("0x1"); + + let class2 = starknet_api::state::ContractClass::default(); + let casm = serde_json::from_value::(read_json_file("casm.json")).unwrap(); + let class_hash2 = class_hash!("0x2"); + let compiled_class_hash = CompiledClassHash(StarkHash::default()); + + let account_class = serde_json::from_value(read_json_file("account_class.json")).unwrap(); + let account_balance_key = + get_storage_var_address("ERC20_balances", &[*ACCOUNT_ADDRESS.0.key()]); + + let fee_contract_class = serde_json::from_value::( + read_json_file("erc20_fee_contract_class.json"), + ) + .unwrap(); + let minter_var_address = get_storage_var_address("permitted_minter", &[]); + + let different_gas_price = GasPricePerToken { + price_in_wei: GasPrice(GAS_PRICE.price_in_wei.0 + 100), + price_in_fri: GasPrice(0), + }; + + storage_writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + l1_data_gas_price: *DATA_GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff( + BlockNumber(0), + StarknetApiStateDiff { + deployed_contracts: indexmap!( + *DEPRECATED_CONTRACT_ADDRESS => class_hash1, + *CONTRACT_ADDRESS => class_hash2, + *ACCOUNT_ADDRESS => *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_ADDRESS => *TEST_ERC20_CONTRACT_CLASS_HASH, + ), + storage_diffs: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => indexmap!( + // Give the accounts some balance. + account_balance_key => *ACCOUNT_INITIAL_BALANCE, + // Give the first account mint permission (what is this?). + minter_var_address => *ACCOUNT_ADDRESS.0.key() + ), + ), + declared_classes: indexmap!(class_hash2 => compiled_class_hash), + deprecated_declared_classes: vec![ + class_hash1, + *ACCOUNT_CLASS_HASH, + *TEST_ERC20_CONTRACT_CLASS_HASH, + ], + nonces: indexmap!( + *TEST_ERC20_CONTRACT_ADDRESS => Nonce::default(), + *CONTRACT_ADDRESS => Nonce::default(), + *DEPRECATED_CONTRACT_ADDRESS => Nonce::default(), + *ACCOUNT_ADDRESS => Nonce::default(), + ), + replaced_classes: indexmap!(), + }, + ) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash2, &class2)], + &[ + (class_hash1, &class1), + (*ACCOUNT_CLASS_HASH, &account_class), + (*TEST_ERC20_CONTRACT_CLASS_HASH, &fee_contract_class), + ], + ) + .unwrap() + .append_casm(&class_hash2, &casm) + .unwrap() + .append_header( + BlockNumber(1), + &BlockHeader { + l1_gas_price: different_gas_price, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + block_hash: BlockHash(felt!("0x1")), + block_number: BlockNumber(1), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(1), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(1), StarknetApiStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(1), &[], &[]) + .unwrap() + .append_header( + BlockNumber(2), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + // Test that l1_da_mode affects the fee. + l1_da_mode: L1DataAvailabilityMode::Blob, + block_hash: BlockHash(felt!("0x2")), + block_number: BlockNumber(2), + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(2), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(2), StarknetApiStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(2), &[], &[]) + .unwrap() + .commit() + .unwrap(); + + storage_writer +} + +fn write_empty_block(mut storage_writer: StorageWriter) { + storage_writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + l1_gas_price: *GAS_PRICE, + l1_data_gas_price: *DATA_GAS_PRICE, + sequencer: *SEQUENCER_ADDRESS, + timestamp: *BLOCK_TIMESTAMP, + ..Default::default() + }, + ) + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_state_diff(BlockNumber(0), StarknetApiStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(0), &[], &[]) + .unwrap() + .commit() + .unwrap(); +} diff --git a/crates/papyrus_rpc/src/v0_7/mod.rs b/crates/papyrus_rpc/src/v0_7/mod.rs new file mode 100644 index 00000000000..52fbcd50e87 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/mod.rs @@ -0,0 +1,12 @@ +pub mod api; +pub mod block; +pub mod broadcasted_transaction; +pub mod deprecated_contract_class; +pub mod error; +pub mod execution; +#[cfg(test)] +mod execution_test; +pub mod state; +pub mod transaction; +pub mod write_api_error; +pub mod write_api_result; diff --git a/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap new file mode 100644 index 00000000000..4beaeb0fefb --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_declare_error_snapshot.snap @@ -0,0 +1,164 @@ +--- +source: crates/papyrus_rpc/src/v0_7/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_declare_error) +--- +{ + "51": [ + { + "code": { + "$serde_json::private::Number": "51" + }, + "message": "Class already declared" + }, + { + "code": "StarknetErrorCode.CLASS_ALREADY_DECLARED", + "message": "message" + } + ], + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "56": [ + { + "code": { + "$serde_json::private::Number": "56" + }, + "message": "Compilation failed" + }, + { + "code": "StarknetErrorCode.COMPILATION_FAILED", + "message": "message" + } + ], + "57": [ + { + "code": { + "$serde_json::private::Number": "57" + }, + "message": "Contract class size it too large" + }, + { + "code": "StarknetErrorCode.CONTRACT_CLASS_OBJECT_SIZE_TOO_LARGE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "60": [ + { + "code": { + "$serde_json::private::Number": "60" + }, + "message": "the compiled class hash did not match the one supplied in the transaction" + }, + { + "code": "StarknetErrorCode.INVALID_COMPILED_CLASS_HASH", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "62": [ + { + "code": { + "$serde_json::private::Number": "62" + }, + "message": "the contract class version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_CONTRACT_CLASS_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap new file mode 100644 index 00000000000..a66231312ea --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_deploy_account_error_snapshot.snap @@ -0,0 +1,116 @@ +--- +source: crates/papyrus_rpc/src/v0_7/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_deploy_account_error) +--- +{ + "28": [ + { + "code": { + "$serde_json::private::Number": "28" + }, + "message": "Class hash not found" + }, + { + "code": "StarknetErrorCode.UNDECLARED_CLASS", + "message": "message" + } + ], + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap new file mode 100644 index 00000000000..9a605be3459 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/snapshots/papyrus_rpc__v0_7__write_api_error__write_api_error_test__starknet_error_to_invoke_error_snapshot.snap @@ -0,0 +1,104 @@ +--- +source: crates/papyrus_rpc/src/v0_7/write_api_error_test.rs +expression: get_conversion_snapshot(starknet_error_to_invoke_error) +--- +{ + "52": [ + { + "code": { + "$serde_json::private::Number": "52" + }, + "message": "Invalid transaction nonce" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + "message": "message" + } + ], + "53": [ + { + "code": { + "$serde_json::private::Number": "53" + }, + "message": "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_MAX_FEE", + "message": "message" + } + ], + "54": [ + { + "code": { + "$serde_json::private::Number": "54" + }, + "message": "Account balance is smaller than the transaction's max_fee" + }, + { + "code": "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + "message": "message" + } + ], + "55": [ + { + "code": { + "$serde_json::private::Number": "55" + }, + "data": "message", + "message": "Account validation failed" + }, + { + "code": "StarknetErrorCode.VALIDATE_FAILURE", + "message": "message" + } + ], + "58": [ + { + "code": { + "$serde_json::private::Number": "58" + }, + "message": "Sender address in not an account contract" + }, + { + "code": "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + "message": "message" + } + ], + "59": [ + { + "code": { + "$serde_json::private::Number": "59" + }, + "message": "A transaction with the same hash already exists in the mempool" + }, + { + "code": "StarknetErrorCode.DUPLICATED_TRANSACTION", + "message": "message" + } + ], + "61": [ + { + "code": { + "$serde_json::private::Number": "61" + }, + "message": "the transaction version is not supported" + }, + { + "code": "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + "message": "message" + } + ], + "63": [ + { + "code": { + "$serde_json::private::Number": "63" + }, + "data": "message", + "message": "An unexpected error occurred" + }, + { + "code": "code", + "message": "message" + } + ] +} diff --git a/crates/papyrus_rpc/src/v0_7/state.rs b/crates/papyrus_rpc/src/v0_7/state.rs new file mode 100644 index 00000000000..7730b24c17f --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/state.rs @@ -0,0 +1,242 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockHash; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, GlobalRoot, Nonce}; +use starknet_api::state::{ + EntryPoint, + EntryPointType, + StorageKey, + ThinStateDiff as starknet_api_ThinStateDiff, +}; +use starknet_client::reader::objects::state::{ + DeclaredClassHashEntry as ClientDeclaredClassHashEntry, + DeployedContract as ClientDeployedContract, + ReplacedClass as ClientReplacedClass, + StateDiff as ClientStateDiff, + StorageEntry as ClientStorageEntry, +}; +use starknet_types_core::felt::Felt; + +const CONTRACT_CLASS_VERSION: &str = "0.1.0"; + +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(untagged)] +pub enum StateUpdate { + AcceptedStateUpdate(AcceptedStateUpdate), + PendingStateUpdate(PendingStateUpdate), +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct AcceptedStateUpdate { + pub block_hash: BlockHash, + pub new_root: GlobalRoot, + pub old_root: GlobalRoot, + pub state_diff: ThinStateDiff, +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct PendingStateUpdate { + pub old_root: GlobalRoot, + pub state_diff: ThinStateDiff, +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct ThinStateDiff { + pub deployed_contracts: Vec, + pub storage_diffs: Vec, + pub declared_classes: Vec, + pub deprecated_declared_classes: Vec, + pub nonces: Vec, + pub replaced_classes: Vec, +} + +impl From for ThinStateDiff { + fn from(diff: starknet_api_ThinStateDiff) -> Self { + Self { + deployed_contracts: Vec::from_iter( + diff.deployed_contracts + .into_iter() + .map(|(address, class_hash)| DeployedContract { address, class_hash }), + ), + storage_diffs: Vec::from_iter(diff.storage_diffs.into_iter().map( + |(address, entries)| { + let storage_entries = Vec::from_iter( + entries.into_iter().map(|(key, value)| StorageEntry { key, value }), + ); + StorageDiff { address, storage_entries } + }, + )), + declared_classes: diff + .declared_classes + .into_iter() + .map(|(class_hash, compiled_class_hash)| ClassHashes { + class_hash, + compiled_class_hash, + }) + .collect(), + deprecated_declared_classes: diff.deprecated_declared_classes, + nonces: Vec::from_iter( + diff.nonces + .into_iter() + .map(|(contract_address, nonce)| ContractNonce { contract_address, nonce }), + ), + replaced_classes: Vec::from_iter(diff.replaced_classes.into_iter().map( + |(contract_address, class_hash)| ReplacedClasses { contract_address, class_hash }, + )), + } + } +} + +impl From for ThinStateDiff { + fn from(diff: ClientStateDiff) -> Self { + Self { + deployed_contracts: Vec::from_iter(diff.deployed_contracts.into_iter().map( + |ClientDeployedContract { address, class_hash }| DeployedContract { + address, + class_hash, + }, + )), + storage_diffs: Vec::from_iter(diff.storage_diffs.into_iter().map( + |(address, entries)| { + let storage_entries = Vec::from_iter( + entries + .into_iter() + .map(|ClientStorageEntry { key, value }| StorageEntry { key, value }), + ); + StorageDiff { address, storage_entries } + }, + )), + declared_classes: diff + .declared_classes + .into_iter() + .map(|ClientDeclaredClassHashEntry { class_hash, compiled_class_hash }| { + ClassHashes { class_hash, compiled_class_hash } + }) + .collect(), + deprecated_declared_classes: diff.old_declared_contracts, + nonces: Vec::from_iter( + diff.nonces + .into_iter() + .map(|(contract_address, nonce)| ContractNonce { contract_address, nonce }), + ), + replaced_classes: Vec::from_iter(diff.replaced_classes.into_iter().map( + |ClientReplacedClass { address: contract_address, class_hash }| ReplacedClasses { + contract_address, + class_hash, + }, + )), + } + } +} + +impl ThinStateDiff { + pub fn sort(&mut self) { + // sort_unstable is faster than sort, and we don't have duplicates anyway. + self.deployed_contracts.sort_unstable_by_key(|deployed_contract| deployed_contract.address); + self.storage_diffs.sort_unstable_by_key(|storage_diff| storage_diff.address); + self.declared_classes.sort_unstable_by_key(|class_hashes| class_hashes.class_hash); + self.deprecated_declared_classes.sort_unstable(); + self.nonces.sort_unstable_by_key(|contract_nonce| contract_nonce.contract_address); + self.replaced_classes + .sort_unstable_by_key(|replaced_class| replaced_class.contract_address); + for contract_storage_diffs in &mut self.storage_diffs { + contract_storage_diffs + .storage_entries + .sort_unstable_by_key(|storage_entry| storage_entry.key); + } + } +} + +/// The nonce of a StarkNet contract. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ContractNonce { + pub contract_address: ContractAddress, + pub nonce: Nonce, +} + +/// A deployed contract in StarkNet. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployedContract { + pub address: ContractAddress, + pub class_hash: ClassHash, +} + +/// Storage differences in StarkNet. +// Invariant: Storage keys are strictly increasing. In particular, no key appears twice. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StorageDiff { + pub address: ContractAddress, + pub(super) storage_entries: Vec, +} + +/// A storage entry in a contract. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StorageEntry { + pub key: StorageKey, + pub value: Felt, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct EntryPointByType { + #[serde(rename = "CONSTRUCTOR")] + pub constructor: Vec, + #[serde(rename = "EXTERNAL")] + pub external: Vec, + #[serde(rename = "L1_HANDLER")] + pub l1handler: Vec, +} + +impl EntryPointByType { + pub fn from_hash_map(entry_points_by_type: HashMap>) -> Self { + macro_rules! get_entrypoint_by_type { + ($variant:ident) => { + (*(entry_points_by_type.get(&EntryPointType::$variant).unwrap_or(&vec![]))).to_vec() + }; + } + + Self { + constructor: get_entrypoint_by_type!(Constructor), + external: get_entrypoint_by_type!(External), + l1handler: get_entrypoint_by_type!(L1Handler), + } + } + pub fn to_hash_map(&self) -> HashMap> { + HashMap::from_iter([ + (EntryPointType::Constructor, self.constructor.clone()), + (EntryPointType::External, self.external.clone()), + (EntryPointType::L1Handler, self.l1handler.clone()), + ]) + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub sierra_program: Vec, + pub contract_class_version: String, + pub entry_points_by_type: EntryPointByType, + pub abi: String, +} + +impl From for ContractClass { + fn from(class: starknet_api::state::ContractClass) -> Self { + Self { + sierra_program: class.sierra_program, + contract_class_version: CONTRACT_CLASS_VERSION.to_owned(), + entry_points_by_type: EntryPointByType::from_hash_map(class.entry_points_by_type), + abi: class.abi, + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ClassHashes { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ReplacedClasses { + pub contract_address: ContractAddress, + pub class_hash: ClassHash, +} diff --git a/crates/papyrus_rpc/src/v0_7/transaction.rs b/crates/papyrus_rpc/src/v0_7/transaction.rs new file mode 100644 index 00000000000..94c01af3ab5 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/transaction.rs @@ -0,0 +1,1303 @@ +#[cfg(test)] +#[path = "transaction_test.rs"] +mod transaction_test; + +use std::collections::BTreeMap; +use std::fmt::Display; +use std::num::NonZeroU64; +use std::ops::Add; +use std::sync::Arc; + +use ethers::core::abi::{encode_packed, Token}; +use ethers::core::utils::keccak256; +use jsonrpsee::types::ErrorObjectOwned; +use papyrus_execution::objects::PriceUnit; +use papyrus_storage::body::BodyStorageReader; +use papyrus_storage::db::TransactionKind; +use papyrus_storage::StorageTxn; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use starknet_api::block::{BlockHash, BlockNumber, BlockStatus}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, +}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::serde_utils::bytes_from_hex_str; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + DeployTransaction, + Fee, + L1HandlerTransaction, + MessageToL1, + PaymasterData, + Resource, + ResourceBounds, + Tip, + TransactionExecutionStatus, + TransactionHash, + TransactionSignature, + TransactionVersion, +}; +use starknet_client::writer::objects::transaction as client_transaction; +use starknet_types_core::felt::Felt; + +use super::error::BLOCK_NOT_FOUND; +use crate::internal_server_error; + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion0 { + #[serde(rename = "0x0")] + #[default] + Version0, + #[serde(rename = "0x100000000000000000000000000000000")] + Version0OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion1 { + #[serde(rename = "0x1")] + #[default] + Version1, + #[serde(rename = "0x100000000000000000000000000000001")] + Version1OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion2 { + #[serde(rename = "0x2")] + #[default] + Version2, + #[serde(rename = "0x100000000000000000000000000000002")] + Version2OnlyQuery, +} + +#[derive( + Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, +)] +pub enum TransactionVersion3 { + #[serde(rename = "0x3")] + #[default] + Version3, + #[serde(rename = "0x100000000000000000000000000000003")] + Version3OnlyQuery, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum Transactions { + Hashes(Vec), + Full(Vec), + FullWithReceipts(Vec), +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct DeclareTransactionV0 { + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct DeclareTransactionV1 { + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, +} +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV2 { + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion2, + pub signature: TransactionSignature, +} + +impl From for DeclareTransactionV2 { + fn from(tx: starknet_api::transaction::DeclareTransactionV2) -> Self { + Self { + class_hash: tx.class_hash, + compiled_class_hash: tx.compiled_class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion2::Version2, + signature: tx.signature, + } + } +} + +// The serialization of the struct in SN_API is in capital letters, not following the spec. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ResourceBoundsMapping { + pub l1_gas: ResourceBounds, + pub l2_gas: ResourceBounds, +} + +impl From for starknet_api::transaction::ResourceBoundsMapping { + fn from(value: ResourceBoundsMapping) -> Self { + Self([(Resource::L1Gas, value.l1_gas), (Resource::L2Gas, value.l2_gas)].into()) + } +} + +impl From for ResourceBoundsMapping { + fn from(value: starknet_api::transaction::ResourceBoundsMapping) -> Self { + Self { + l1_gas: value.0.get(&Resource::L1Gas).cloned().unwrap_or_default(), + l2_gas: value.0.get(&Resource::L2Gas).cloned().unwrap_or_default(), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub version: TransactionVersion3, +} + +impl From for DeclareTransactionV3 { + fn from(tx: starknet_api::transaction::DeclareTransactionV3) -> Self { + Self { + resource_bounds: tx.resource_bounds.into(), + tip: tx.tip, + signature: tx.signature, + nonce: tx.nonce, + class_hash: tx.class_hash, + compiled_class_hash: tx.compiled_class_hash, + sender_address: tx.sender_address, + nonce_data_availability_mode: tx.nonce_data_availability_mode, + fee_data_availability_mode: tx.fee_data_availability_mode, + paymaster_data: tx.paymaster_data, + account_deployment_data: tx.account_deployment_data, + version: TransactionVersion3::Version3, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum DeclareTransaction { + Version0(DeclareTransactionV0), + Version1(DeclareTransactionV1), + Version2(DeclareTransactionV2), + Version3(DeclareTransactionV3), +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion1, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV3 { + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion3, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum DeployAccountTransaction { + Version1(DeployAccountTransactionV1), + Version3(DeployAccountTransactionV3), +} + +impl TryFrom for DeployAccountTransaction { + type Error = ErrorObjectOwned; + + fn try_from( + tx: starknet_api::transaction::DeployAccountTransaction, + ) -> Result { + match tx { + starknet_api::transaction::DeployAccountTransaction::V1( + starknet_api::transaction::DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + }, + ) => Ok(Self::Version1(DeployAccountTransactionV1 { + max_fee, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: TransactionVersion1::Version1, + })), + starknet_api::transaction::DeployAccountTransaction::V3( + starknet_api::transaction::DeployAccountTransactionV3 { + resource_bounds, + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + }, + ) => Ok(Self::Version3(DeployAccountTransactionV3 { + signature, + nonce, + class_hash, + contract_address_salt, + constructor_calldata, + version: TransactionVersion3::Version3, + resource_bounds: resource_bounds.into(), + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + })), + } + } +} + +impl From for client_transaction::DeployAccountTransaction { + fn from(tx: DeployAccountTransaction) -> Self { + match tx { + DeployAccountTransaction::Version1(deploy_account_tx) => { + Self::DeployAccountV1(client_transaction::DeployAccountV1Transaction { + contract_address_salt: deploy_account_tx.contract_address_salt, + class_hash: deploy_account_tx.class_hash, + constructor_calldata: deploy_account_tx.constructor_calldata, + nonce: deploy_account_tx.nonce, + max_fee: deploy_account_tx.max_fee, + signature: deploy_account_tx.signature, + version: TransactionVersion::ONE, + r#type: client_transaction::DeployAccountType::DeployAccount, + }) + } + DeployAccountTransaction::Version3(deploy_account_tx) => { + Self::DeployAccountV3(client_transaction::DeployAccountV3Transaction { + contract_address_salt: deploy_account_tx.contract_address_salt, + class_hash: deploy_account_tx.class_hash, + constructor_calldata: deploy_account_tx.constructor_calldata, + nonce: deploy_account_tx.nonce, + signature: deploy_account_tx.signature, + version: TransactionVersion::THREE, + resource_bounds: deploy_account_tx.resource_bounds.into(), + tip: deploy_account_tx.tip, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: deploy_account_tx.paymaster_data, + r#type: client_transaction::DeployAccountType::DeployAccount, + }) + } + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV0) -> Self { + Self::InvokeV0(client_transaction::InvokeV0Transaction { + max_fee: tx.max_fee, + version: TransactionVersion::ZERO, + signature: tx.signature, + contract_address: tx.contract_address, + entry_point_selector: tx.entry_point_selector, + calldata: tx.calldata, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV1) -> Self { + Self::InvokeV1(client_transaction::InvokeV1Transaction { + max_fee: tx.max_fee, + version: TransactionVersion::ONE, + signature: tx.signature, + nonce: tx.nonce, + sender_address: tx.sender_address, + calldata: tx.calldata, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV3 { + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub version: TransactionVersion3, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransactionV3) -> Self { + Self::InvokeV3(client_transaction::InvokeV3Transaction { + sender_address: tx.sender_address, + calldata: tx.calldata, + version: TransactionVersion::THREE, + signature: tx.signature, + nonce: tx.nonce, + resource_bounds: tx.resource_bounds.into(), + tip: tx.tip, + nonce_data_availability_mode: + client_transaction::ReservedDataAvailabilityMode::Reserved, + fee_data_availability_mode: client_transaction::ReservedDataAvailabilityMode::Reserved, + paymaster_data: tx.paymaster_data, + account_deployment_data: tx.account_deployment_data, + r#type: client_transaction::InvokeType::Invoke, + }) + } +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: InvokeTransaction) -> Self { + match tx { + InvokeTransaction::Version0(invoke_tx) => invoke_tx.into(), + InvokeTransaction::Version1(invoke_tx) => invoke_tx.into(), + InvokeTransaction::Version3(invoke_tx) => invoke_tx.into(), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum InvokeTransaction { + Version0(InvokeTransactionV0), + Version1(InvokeTransactionV1), + Version3(InvokeTransactionV3), +} + +impl TryFrom for InvokeTransaction { + type Error = ErrorObjectOwned; + + fn try_from(tx: starknet_api::transaction::InvokeTransaction) -> Result { + match tx { + starknet_api::transaction::InvokeTransaction::V0( + starknet_api::transaction::InvokeTransactionV0 { + max_fee, + signature, + contract_address, + entry_point_selector, + calldata, + }, + ) => Ok(Self::Version0(InvokeTransactionV0 { + max_fee, + version: TransactionVersion0::Version0, + signature, + contract_address, + entry_point_selector, + calldata, + })), + starknet_api::transaction::InvokeTransaction::V1( + starknet_api::transaction::InvokeTransactionV1 { + max_fee, + signature, + nonce, + sender_address, + calldata, + }, + ) => Ok(Self::Version1(InvokeTransactionV1 { + max_fee, + version: TransactionVersion1::Version1, + signature, + nonce, + sender_address, + calldata, + })), + starknet_api::transaction::InvokeTransaction::V3( + starknet_api::transaction::InvokeTransactionV3 { + resource_bounds, + tip, + signature, + nonce, + sender_address, + calldata, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + }, + ) => Ok(Self::Version3(InvokeTransactionV3 { + sender_address, + calldata, + version: TransactionVersion3::Version3, + signature, + nonce, + resource_bounds: resource_bounds.into(), + tip, + nonce_data_availability_mode, + fee_data_availability_mode, + paymaster_data, + account_deployment_data, + })), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionWithHash { + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub transaction: Transaction, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionWithReceipt { + pub receipt: TransactionReceiptInBlock, + pub transaction: Transaction, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum Transaction { + #[serde(rename = "DECLARE")] + Declare(DeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), + #[serde(rename = "DEPLOY")] + Deploy(DeployTransaction), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransaction), +} + +impl Transaction { + pub fn version(&self) -> TransactionVersion { + match self { + Self::Declare(DeclareTransaction::Version0(_)) + | Self::Invoke(InvokeTransaction::Version0(_)) => TransactionVersion::ZERO, + Self::Declare(DeclareTransaction::Version1(_)) + | Self::Invoke(InvokeTransaction::Version1(_)) + | Self::DeployAccount(DeployAccountTransaction::Version1(_)) => TransactionVersion::ONE, + Self::Declare(DeclareTransaction::Version2(_)) => TransactionVersion::TWO, + Self::Declare(DeclareTransaction::Version3(_)) + | Self::Invoke(InvokeTransaction::Version3(_)) + | Self::DeployAccount(DeployAccountTransaction::Version3(_)) => { + TransactionVersion::THREE + } + Self::Deploy(tx) => tx.version, + Self::L1Handler(tx) => tx.version, + } + } +} + +impl TryFrom for Transaction { + type Error = ErrorObjectOwned; + + fn try_from(tx: starknet_api::transaction::Transaction) -> Result { + match tx { + starknet_api::transaction::Transaction::Declare(declare_tx) => match declare_tx { + starknet_api::transaction::DeclareTransaction::V0(tx) => { + Ok(Self::Declare(DeclareTransaction::Version0(DeclareTransactionV0 { + class_hash: tx.class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion0::Version0, + signature: tx.signature, + }))) + } + starknet_api::transaction::DeclareTransaction::V1(tx) => { + Ok(Self::Declare(DeclareTransaction::Version1(DeclareTransactionV1 { + class_hash: tx.class_hash, + sender_address: tx.sender_address, + nonce: tx.nonce, + max_fee: tx.max_fee, + version: TransactionVersion1::Version1, + signature: tx.signature, + }))) + } + starknet_api::transaction::DeclareTransaction::V2(tx) => { + Ok(Self::Declare(DeclareTransaction::Version2(tx.into()))) + } + starknet_api::transaction::DeclareTransaction::V3(tx) => { + Ok(Self::Declare(DeclareTransaction::Version3(tx.into()))) + } + }, + starknet_api::transaction::Transaction::Deploy(deploy_tx) => { + Ok(Transaction::Deploy(deploy_tx)) + } + starknet_api::transaction::Transaction::DeployAccount(deploy_account_tx) => { + Ok(Self::DeployAccount(deploy_account_tx.try_into()?)) + } + starknet_api::transaction::Transaction::Invoke(invoke_tx) => { + Ok(Self::Invoke(invoke_tx.try_into()?)) + } + starknet_api::transaction::Transaction::L1Handler(l1_handler_tx) => { + Ok(Transaction::L1Handler(l1_handler_tx)) + } + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default)] +pub struct TransactionStatus { + pub finality_status: TransactionFinalityStatus, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, +} + +/// Transaction Finality status on starknet. +#[derive( + Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default, +)] +pub enum TransactionFinalityStatus { + /// The transaction passed the validation and entered an actual created block. + #[serde(rename = "ACCEPTED_ON_L2")] + #[default] + AcceptedOnL2, + /// The transaction was accepted on-chain. + #[serde(rename = "ACCEPTED_ON_L1")] + AcceptedOnL1, +} + +/// Transaction Finality status on starknet for transactions in the pending block. +#[derive( + Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default, +)] +pub enum PendingTransactionFinalityStatus { + #[serde(rename = "ACCEPTED_ON_L2")] + #[default] + AcceptedOnL2, +} + +impl From for TransactionFinalityStatus { + fn from(status: BlockStatus) -> Self { + match status { + BlockStatus::AcceptedOnL1 => TransactionFinalityStatus::AcceptedOnL1, + BlockStatus::AcceptedOnL2 => TransactionFinalityStatus::AcceptedOnL2, + BlockStatus::Pending => TransactionFinalityStatus::AcceptedOnL2, /* for backward compatibility pending transactions are considered accepted on L2 */ + // we convert the block status to transaction status only in the creation of + // TransactionReceiptWithStatus before that we verify that the block is not + // rejected so this conversion should never happen + BlockStatus::Rejected => unreachable!("Rejected blocks are not returned by the API"), + } + } +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum GeneralTransactionReceipt { + TransactionReceipt(TransactionReceipt), + PendingTransactionReceipt(PendingTransactionReceipt), +} + +impl GeneralTransactionReceipt { + pub fn transaction_status(&self) -> TransactionStatus { + match self { + GeneralTransactionReceipt::TransactionReceipt(receipt) => TransactionStatus { + execution_status: receipt.output.execution_status().clone(), + finality_status: receipt.finality_status, + }, + GeneralTransactionReceipt::PendingTransactionReceipt(receipt) => TransactionStatus { + execution_status: receipt.output.execution_status().clone(), + finality_status: TransactionFinalityStatus::AcceptedOnL2, + }, + } + } +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionReceipt { + pub finality_status: TransactionFinalityStatus, + pub transaction_hash: TransactionHash, + pub block_hash: BlockHash, + pub block_number: BlockNumber, + #[serde(flatten)] + pub output: TransactionOutput, +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct PendingTransactionReceipt { + pub finality_status: PendingTransactionFinalityStatus, + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub output: PendingTransactionOutput, +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionReceiptInBlock { + pub finality_status: TransactionFinalityStatus, + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub output: TransactionOutput, +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum TransactionOutput { + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionOutput), + #[serde(rename = "DEPLOY")] + Deploy(DeployTransactionOutput), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionOutput), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionOutput), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionOutput), +} + +impl From for TransactionReceiptInBlock { + fn from(value: GeneralTransactionReceipt) -> Self { + match value { + GeneralTransactionReceipt::TransactionReceipt(receipt) => Self { + finality_status: receipt.finality_status, + transaction_hash: receipt.transaction_hash, + output: receipt.output, + }, + GeneralTransactionReceipt::PendingTransactionReceipt(receipt) => Self { + finality_status: match receipt.finality_status { + PendingTransactionFinalityStatus::AcceptedOnL2 => { + TransactionFinalityStatus::AcceptedOnL2 + } + }, + transaction_hash: receipt.transaction_hash, + output: match receipt.output { + PendingTransactionOutput::DeployAccount(deploy_account_output) => { + TransactionOutput::DeployAccount(deploy_account_output) + } + PendingTransactionOutput::Declare(declare_output) => { + TransactionOutput::Declare(declare_output) + } + PendingTransactionOutput::Invoke(invoke_output) => { + TransactionOutput::Invoke(invoke_output) + } + PendingTransactionOutput::L1Handler(l1_handler_output) => { + TransactionOutput::L1Handler(l1_handler_output) + } + }, + }, + } + } +} +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct FeePayment { + pub amount: Fee, + pub unit: PriceUnit, +} + +/// A declare transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy-account transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An invoke transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An L1 handler transaction output. +// Note: execution_resources is not included in the output because it is not used in this version. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct L1HandlerTransactionOutput { + pub actual_fee: FeePayment, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + pub message_hash: L1L2MsgHash, +} + +// Note: This is not the same as the Builtins in starknet_api, the serialization of SegmentArena is +// different. TODO(yair): remove this once a newer version of the API is published. +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub enum Builtin { + #[serde(rename = "range_check_builtin_applications")] + RangeCheck, + #[serde(rename = "pedersen_builtin_applications")] + Pedersen, + #[serde(rename = "poseidon_builtin_applications")] + Poseidon, + #[serde(rename = "ec_op_builtin_applications")] + EcOp, + #[serde(rename = "ecdsa_builtin_applications")] + Ecdsa, + #[serde(rename = "bitwise_builtin_applications")] + Bitwise, + #[serde(rename = "keccak_builtin_applications")] + Keccak, + #[serde(rename = "segment_arena_builtin")] + SegmentArena, +} + +impl TryFrom for Builtin { + type Error = (); + fn try_from(builtin: starknet_api::transaction::Builtin) -> Result { + match builtin { + starknet_api::transaction::Builtin::RangeCheck => Ok(Builtin::RangeCheck), + starknet_api::transaction::Builtin::Pedersen => Ok(Builtin::Pedersen), + starknet_api::transaction::Builtin::Poseidon => Ok(Builtin::Poseidon), + starknet_api::transaction::Builtin::EcOp => Ok(Builtin::EcOp), + starknet_api::transaction::Builtin::Ecdsa => Ok(Builtin::Ecdsa), + starknet_api::transaction::Builtin::Bitwise => Ok(Builtin::Bitwise), + starknet_api::transaction::Builtin::Keccak => Ok(Builtin::Keccak), + starknet_api::transaction::Builtin::SegmentArena => Ok(Builtin::SegmentArena), + // These builtins are not part of the specs. + starknet_api::transaction::Builtin::AddMod + | starknet_api::transaction::Builtin::MulMod + | starknet_api::transaction::Builtin::RangeCheck96 => Err(()), + } + } +} + +#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ExecutionResources { + #[serde(flatten)] + pub computation_resources: ComputationResources, + pub data_availability: DataAvailabilityResources, +} + +#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct ComputationResources { + // TODO(shahak): Change steps here and in SN API to NonZeroU64 + pub steps: u64, + #[serde(flatten)] + // BTreeMap implements Ord. + pub builtin_instance_counter: BTreeMap, + #[serde(skip_serializing_if = "Option::is_none")] + pub memory_holes: Option, +} + +#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DataAvailabilityResources { + pub l1_gas: u64, + pub l1_data_gas: u64, +} + +impl Add for ExecutionResources { + type Output = Self; + fn add(mut self, other: Self) -> Self { + let memory_holes = match ( + self.computation_resources.memory_holes, + other.computation_resources.memory_holes, + ) { + // TODO(shahak): Consider using checked_add and implementing addition as a function and + // not as the trait Add. + (Some(x), Some(y)) => Some(x.saturating_add(y.into())), + _ => self + .computation_resources + .memory_holes + .xor(other.computation_resources.memory_holes), + }; + + for (k, v) in other.computation_resources.builtin_instance_counter.iter() { + match self.computation_resources.builtin_instance_counter.get_mut(k) { + // TODO(shahak): Consider using checked_add and implementing addition as a function + // and not as the trait Add. + Some(v_ref) => *v_ref = (*v_ref).saturating_add((*v).into()), + None => { + self.computation_resources.builtin_instance_counter.insert(k.clone(), *v); + } + } + } + + Self { + computation_resources: ComputationResources { + // TODO(shahak): Consider using checked_add and implementing addition as a function + // and not as the trait Add. + steps: self + .computation_resources + .steps + .saturating_add(other.computation_resources.steps), + builtin_instance_counter: self.computation_resources.builtin_instance_counter, + memory_holes, + }, + data_availability: DataAvailabilityResources { + l1_gas: self.data_availability.l1_gas + other.data_availability.l1_gas, + l1_data_gas: self.data_availability.l1_data_gas + + other.data_availability.l1_data_gas, + }, + } + } +} + +impl From for ExecutionResources { + fn from(value: starknet_api::transaction::ExecutionResources) -> Self { + let l1_gas = value.da_gas_consumed.l1_gas; + let l1_data_gas = value.da_gas_consumed.l1_data_gas; + Self { + computation_resources: value.into(), + data_availability: DataAvailabilityResources { l1_gas, l1_data_gas }, + } + } +} + +impl From for ComputationResources { + fn from(value: starknet_api::transaction::ExecutionResources) -> Self { + Self { + steps: value.steps, + builtin_instance_counter: value + .builtin_instance_counter + .into_iter() + .filter_map(|(k, v)| { + v.try_into().ok().and_then(|v| (k.try_into().ok().map(|k| (k, v)))) + }) + .collect(), + memory_holes: value.memory_holes.try_into().ok(), + } + } +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +// Applying deny_unknown_fields on the inner type instead of on PendingTransactionReceipt because +// of a bug that makes deny_unknown_fields not work well with flatten: +// https://github.com/serde-rs/serde/issues/1358 +#[serde(deny_unknown_fields)] +pub enum PendingTransactionOutput { + #[serde(rename = "DECLARE")] + Declare(DeclareTransactionOutput), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransactionOutput), + #[serde(rename = "INVOKE")] + Invoke(InvokeTransactionOutput), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransactionOutput), +} + +impl PendingTransactionOutput { + pub fn execution_status(&self) -> &TransactionExecutionStatus { + match self { + PendingTransactionOutput::Declare(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::DeployAccount(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::Invoke(tx_output) => &tx_output.execution_status, + PendingTransactionOutput::L1Handler(tx_output) => &tx_output.execution_status, + } + } +} + +impl TransactionOutput { + pub fn execution_status(&self) -> &TransactionExecutionStatus { + match self { + TransactionOutput::Declare(tx_output) => &tx_output.execution_status, + TransactionOutput::Deploy(tx_output) => &tx_output.execution_status, + TransactionOutput::DeployAccount(tx_output) => &tx_output.execution_status, + TransactionOutput::Invoke(tx_output) => &tx_output.execution_status, + TransactionOutput::L1Handler(tx_output) => &tx_output.execution_status, + } + } +} + +impl From<(starknet_api::transaction::TransactionOutput, TransactionVersion, Option)> + for TransactionOutput +{ + #[cfg_attr(coverage_nightly, coverage_attribute)] + fn from( + tx_output_msg_hash: ( + starknet_api::transaction::TransactionOutput, + TransactionVersion, + Option, + ), + ) -> Self { + let (tx_output, tx_version, maybe_msg_hash) = tx_output_msg_hash; + // TODO: consider supporting match instead. + let actual_fee = if tx_version == TransactionVersion::ZERO + || tx_version == TransactionVersion::ONE + || tx_version == TransactionVersion::TWO + { + FeePayment { amount: tx_output.actual_fee(), unit: PriceUnit::Wei } + } else { + // TransactionVersion::THREE + FeePayment { amount: tx_output.actual_fee(), unit: PriceUnit::Fri } + }; + + match tx_output { + starknet_api::transaction::TransactionOutput::Declare(declare_tx_output) => { + TransactionOutput::Declare(DeclareTransactionOutput { + actual_fee, + messages_sent: declare_tx_output.messages_sent, + events: declare_tx_output.events, + execution_status: declare_tx_output.execution_status, + execution_resources: declare_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::Deploy(deploy_tx_output) => { + TransactionOutput::Deploy(DeployTransactionOutput { + actual_fee, + messages_sent: deploy_tx_output.messages_sent, + events: deploy_tx_output.events, + contract_address: deploy_tx_output.contract_address, + execution_status: deploy_tx_output.execution_status, + execution_resources: deploy_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::DeployAccount(deploy_tx_output) => { + TransactionOutput::DeployAccount(DeployAccountTransactionOutput { + actual_fee, + messages_sent: deploy_tx_output.messages_sent, + events: deploy_tx_output.events, + contract_address: deploy_tx_output.contract_address, + execution_status: deploy_tx_output.execution_status, + execution_resources: deploy_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::Invoke(invoke_tx_output) => { + TransactionOutput::Invoke(InvokeTransactionOutput { + actual_fee, + messages_sent: invoke_tx_output.messages_sent, + events: invoke_tx_output.events, + execution_status: invoke_tx_output.execution_status, + execution_resources: invoke_tx_output.execution_resources.into(), + }) + } + starknet_api::transaction::TransactionOutput::L1Handler(l1_handler_tx_output) => { + TransactionOutput::L1Handler(L1HandlerTransactionOutput { + actual_fee, + messages_sent: l1_handler_tx_output.messages_sent, + events: l1_handler_tx_output.events, + execution_status: l1_handler_tx_output.execution_status, + execution_resources: l1_handler_tx_output.execution_resources.into(), + message_hash: maybe_msg_hash + .expect("Missing message hash to construct L1Handler output."), + }) + } + } + } +} + +impl TryFrom for PendingTransactionOutput { + type Error = ErrorObjectOwned; + + fn try_from(tx_output: TransactionOutput) -> Result { + match tx_output { + TransactionOutput::Declare(declare_tx_output) => { + Ok(PendingTransactionOutput::Declare(declare_tx_output)) + } + TransactionOutput::Deploy(_) => { + Err(internal_server_error("Got a pending deploy transaction.")) + } + TransactionOutput::DeployAccount(deploy_tx_output) => { + Ok(PendingTransactionOutput::DeployAccount(deploy_tx_output)) + } + TransactionOutput::Invoke(invoke_tx_output) => { + Ok(PendingTransactionOutput::Invoke(invoke_tx_output)) + } + TransactionOutput::L1Handler(l1_handler_tx_output) => { + Ok(PendingTransactionOutput::L1Handler(l1_handler_tx_output)) + } + } + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct Event { + // Can't have a different struct for pending events because then that struct will need to have + // deny_unknown_fields. And there's a bug in serde that forbids having deny_unknown_fields with + // flatten: https://github.com/serde-rs/serde/issues/1701 + // TODO(shahak): Create a PendingEvent struct when the serde bug is solved. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub block_hash: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub block_number: Option, + pub transaction_hash: TransactionHash, + #[serde(flatten)] + pub event: starknet_api::transaction::Event, +} + +pub fn get_block_txs_by_number< + Mode: TransactionKind, + Transaction: TryFrom, +>( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result, ErrorObjectOwned> { + let transactions = txn + .get_block_transactions(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + transactions.into_iter().map(Transaction::try_from).collect() +} + +pub fn get_block_tx_hashes_by_number( + txn: &StorageTxn<'_, Mode>, + block_number: BlockNumber, +) -> Result, ErrorObjectOwned> { + let transaction_hashes = txn + .get_block_transaction_hashes(block_number) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(BLOCK_NOT_FOUND))?; + + Ok(transaction_hashes) +} + +/// The hash of a L1 -> L2 message. +// The hash is Keccak256, so it doesn't necessarily fit in a Felt. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub struct L1L2MsgHash(pub [u8; 32]); + +impl Display for L1L2MsgHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "0x{}", hex::encode(self.0)) + } +} + +impl Serialize for L1L2MsgHash { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(format!("{}", self).as_str()) + } +} + +impl<'de> Deserialize<'de> for L1L2MsgHash { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(Self(bytes_from_hex_str::<32, true>(s.as_str()).map_err(serde::de::Error::custom)?)) + } +} + +pub trait L1HandlerMsgHash { + fn calc_msg_hash(&self) -> L1L2MsgHash; +} + +impl L1HandlerMsgHash for L1HandlerTransaction { + fn calc_msg_hash(&self) -> L1L2MsgHash { + l1_handler_message_hash( + &self.contract_address, + self.nonce, + &self.entry_point_selector, + &self.calldata, + ) + } +} + +impl L1HandlerMsgHash for starknet_client::reader::objects::transaction::L1HandlerTransaction { + fn calc_msg_hash(&self) -> L1L2MsgHash { + l1_handler_message_hash( + &self.contract_address, + self.nonce, + &self.entry_point_selector, + &self.calldata, + ) + } +} + +/// Calculating the message hash of L1 -> L2 message. +/// `` +fn l1_handler_message_hash( + contract_address: &ContractAddress, + nonce: Nonce, + entry_point_selector: &EntryPointSelector, + calldata: &Calldata, +) -> L1L2MsgHash { + let (from_address, payload) = + calldata.0.split_first().expect("Invalid calldata, expected at least from_address"); + + let from_address = Token::Bytes(from_address.to_bytes_be().to_vec()); + let to_address = Token::Bytes(contract_address.0.key().to_bytes_be().to_vec()); + let nonce = Token::Bytes(nonce.to_bytes_be().to_vec()); + let selector = Token::Bytes(entry_point_selector.0.to_bytes_be().to_vec()); + let payload_length_as_felt = Felt::from(payload.len() as u64); + let payload_length = Token::Bytes(payload_length_as_felt.to_bytes_be().to_vec()); + + let mut payload: Vec<_> = + payload.iter().map(|felt| Token::Bytes(felt.to_bytes_be().to_vec())).collect(); + + let mut to_encode = vec![from_address, to_address, nonce, selector, payload_length]; + to_encode.append(&mut payload); + let encoded = encode_packed(to_encode.as_slice()).expect("Should be able to encode"); + + L1L2MsgHash(keccak256(encoded)) +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct MessageFromL1 { + // TODO: fix serialization of EthAddress in SN_API to fit the spec. + #[serde(serialize_with = "serialize_eth_address")] + pub from_address: EthAddress, + pub to_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub payload: Calldata, +} + +// Serialize EthAddress to a 40 character hex string with a 0x prefix. +fn serialize_eth_address(eth_address: &EthAddress, serializer: S) -> Result +where + S: serde::Serializer, +{ + let hex_string = hex::encode(eth_address.0.as_bytes()); + let fixed_size_hex_string = format!("0x{:0<40}", hex_string); + serializer.serialize_str(fixed_size_hex_string.as_str()) +} + +impl From for L1HandlerTransaction { + fn from(message: MessageFromL1) -> Self { + let sender_as_felt = eth_address_to_felt(message.from_address); + let mut calldata = vec![sender_as_felt]; + calldata.extend_from_slice(&message.payload.0); + let calldata = Calldata(Arc::new(calldata)); + Self { + version: TransactionVersion::ONE, + contract_address: message.to_address, + entry_point_selector: message.entry_point_selector, + calldata, + ..Default::default() + } + } +} + +// TODO(yair): move to SN_API and implement as From. +fn eth_address_to_felt(eth_address: EthAddress) -> Felt { + let eth_address_as_bytes = eth_address.0.to_fixed_bytes(); + let mut bytes: [u8; 32] = [0; 32]; + bytes[12..32].copy_from_slice(ð_address_as_bytes); + Felt::from_bytes_be(&bytes) +} + +/// An InvokeTransactionV1 that has the type field. This enum can be used to serialize/deserialize +/// invoke v1 transactions directly while `InvokeTransactionV1` can be serialized/deserialized only +/// from the `Transaction` enum. +/// This allows RPC methods to receive an invoke v1 transaction directly. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum TypedInvokeTransaction { + #[serde(rename = "INVOKE")] + Invoke(InvokeTransaction), +} + +impl From for client_transaction::InvokeTransaction { + fn from(tx: TypedInvokeTransaction) -> Self { + let TypedInvokeTransaction::Invoke(tx) = tx; + tx.into() + } +} + +/// A DeployAccountTransaction that has the type field. This enum can be used to +/// serialize/deserialize deploy account transactions directly while `DeployAccountTransaction` can +/// be serialized/deserialized only from the `Transaction` enum. +/// This allows RPC methods to receive a deploy account transaction directly. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(tag = "type")] +pub enum TypedDeployAccountTransaction { + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(DeployAccountTransaction), +} + +impl From for client_transaction::DeployAccountTransaction { + fn from(tx: TypedDeployAccountTransaction) -> Self { + let TypedDeployAccountTransaction::DeployAccount(tx) = tx; + tx.into() + } +} diff --git a/crates/papyrus_rpc/src/v0_7/transaction_test.rs b/crates/papyrus_rpc/src/v0_7/transaction_test.rs new file mode 100644 index 00000000000..9b60a118049 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/transaction_test.rs @@ -0,0 +1,230 @@ +use pretty_assertions::assert_eq; +use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, Nonce, PatriciaKey}; +use starknet_api::data_availability::DataAvailabilityMode; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + Fee, + L1HandlerTransaction, + PaymasterData, + Tip, + Transaction, + TransactionSignature, + TransactionVersion, +}; +use starknet_api::{calldata, contract_address, felt, patricia_key}; +use starknet_client::writer::objects::transaction as client_transaction; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, get_rng, GetTestInstance}; + +use super::super::transaction::{L1HandlerMsgHash, L1L2MsgHash}; +use super::{ + DeployAccountTransaction, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + InvokeTransaction, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + ResourceBoundsMapping, + TransactionVersion0, + TransactionVersion1, + TransactionVersion3, +}; + +lazy_static::lazy_static! { + // A transaction from MAINNET with tx hash 0x439e12f67962c353182d72b4af12c3f11eaba4b36e552aebcdcd6db66971bdb. + static ref L1_HANDLER_TX: L1HandlerTransaction = L1HandlerTransaction { + version: TransactionVersion::ZERO, + nonce: Nonce(felt!("0x18e94d")), + contract_address: contract_address!( + "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82" + ), + entry_point_selector: EntryPointSelector(felt!( + "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19" + )), + calldata: calldata![ + felt!("0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419"), + felt!("0x455448"), + felt!("0xc27947400e26e534e677afc2e9b2ec1bab14fc89"), + felt!("0x4af4754baf89f1b8b449215a8ea7ce558824a33a5393eaa3829658549f2bfa2"), + felt!("0x9184e72a000"), + felt!("0x0") + ], + }; +} + +// The msg hash of the L1Handler transaction. +const MSG_HASH: &str = "0x99b2a7830e1c860734b308d90bb05b0e09ecda0a2b243ecddb12c50bdebaa3a9"; + +auto_impl_get_test_instance! { + pub enum DeployAccountTransaction { + Version1(DeployAccountTransactionV1) = 0, + Version3(DeployAccountTransactionV3) = 1, + } + pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion1, + } + pub struct DeployAccountTransactionV3 { + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub version: TransactionVersion3, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + pub enum InvokeTransaction { + Version0(InvokeTransactionV0) = 0, + Version1(InvokeTransactionV1) = 1, + Version3(InvokeTransactionV3) = 2, + } + pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub version: TransactionVersion0, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub version: TransactionVersion1, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + } + pub struct InvokeTransactionV3 { + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub version: TransactionVersion3, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + } + pub enum TransactionVersion0 { + Version0 = 0, + } + pub enum TransactionVersion1 { + Version1 = 0, + } + pub enum TransactionVersion3 { + Version3 = 0, + } +} + +// TODO: check the conversion against the expected GW transaction. +#[test] +fn test_gateway_trascation_from_starknet_api_transaction() { + let mut rng = get_rng(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV0V1::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V0(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV0V1::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V1(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::DeclareTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V3(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::DeclareTransactionV2::default(); + let _transaction: super::Transaction = + Transaction::Declare(starknet_api::transaction::DeclareTransaction::V2(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::InvokeTransactionV0::default(); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V0(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = starknet_api::transaction::InvokeTransactionV1::default(); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V1(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::InvokeTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Invoke(starknet_api::transaction::InvokeTransaction::V3(inner_transaction)) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::L1HandlerTransaction::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::L1Handler(inner_transaction).try_into().unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployTransaction::get_test_instance(&mut rng); + let _transaction: super::Transaction = + Transaction::Deploy(inner_transaction).try_into().unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployAccountTransactionV1::get_test_instance(&mut rng); + let _transaction: super::Transaction = Transaction::DeployAccount( + starknet_api::transaction::DeployAccountTransaction::V1(inner_transaction), + ) + .try_into() + .unwrap(); + + let inner_transaction = + starknet_api::transaction::DeployAccountTransactionV3::get_test_instance(&mut rng); + let _transaction: super::Transaction = Transaction::DeployAccount( + starknet_api::transaction::DeployAccountTransaction::V3(inner_transaction), + ) + .try_into() + .unwrap(); +} + +#[test] +fn test_invoke_transaction_to_client_transaction() { + let _invoke_transaction: client_transaction::InvokeTransaction = + InvokeTransactionV1::get_test_instance(&mut get_rng()).into(); + + let _invoke_transaction: client_transaction::InvokeTransaction = + InvokeTransactionV3::get_test_instance(&mut get_rng()).into(); +} + +#[test] +fn l1handler_msg_hash() { + let msg_hash = format!("{}", L1_HANDLER_TX.calc_msg_hash()); + assert_eq!(msg_hash, MSG_HASH); +} + +#[test] +fn l1handler_msg_hash_serde() { + let ser = serde_json::to_string(MSG_HASH).unwrap(); + assert_eq!(ser, "\"0x99b2a7830e1c860734b308d90bb05b0e09ecda0a2b243ecddb12c50bdebaa3a9\""); + let des = serde_json::from_str::(&ser).unwrap(); + let expected_hash = L1_HANDLER_TX.calc_msg_hash(); + assert_eq!(des, expected_hash); +} diff --git a/crates/papyrus_rpc/src/v0_7/write_api_error.rs b/crates/papyrus_rpc/src/v0_7/write_api_error.rs new file mode 100644 index 00000000000..ba977c04112 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/write_api_error.rs @@ -0,0 +1,85 @@ +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +use super::error::{ + unexpected_error, + validation_failure, + JsonRpcError, + CLASS_ALREADY_DECLARED, + CLASS_HASH_NOT_FOUND, + COMPILATION_FAILED, + COMPILED_CLASS_HASH_MISMATCH, + CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + DUPLICATE_TX, + INSUFFICIENT_ACCOUNT_BALANCE, + INSUFFICIENT_MAX_FEE, + INVALID_TRANSACTION_NONCE, + NON_ACCOUNT, + UNSUPPORTED_CONTRACT_CLASS_VERSION, + UNSUPPORTED_TX_VERSION, +}; + +#[cfg(test)] +#[path = "write_api_error_test.rs"] +mod write_api_error_test; + +pub(crate) fn starknet_error_to_invoke_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // EntryPointNotFoundInContract is not thrown in __execute__ since that is + // considered as a reverted transaction. It is also not thrown in __validate__ since + // every error there is considered a ValidateFailure. This means that if + // EntryPointNotFoundInContract is thrown then it failed because it couldn't find + // __validate__ or __execute__ and that means the contract is not an account contract. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} + +pub(crate) fn starknet_error_to_declare_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::ClassAlreadyDeclared => CLASS_ALREADY_DECLARED, + KnownStarknetErrorCode::CompilationFailed => COMPILATION_FAILED, + KnownStarknetErrorCode::ContractBytecodeSizeTooLarge => CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + KnownStarknetErrorCode::ContractClassObjectSizeTooLarge => CONTRACT_CLASS_SIZE_IS_TOO_LARGE, + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // See explanation on this mapping in AddInvokeError. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidCompiledClassHash => COMPILED_CLASS_HASH_MISMATCH, + KnownStarknetErrorCode::InvalidContractClassVersion => UNSUPPORTED_CONTRACT_CLASS_VERSION, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} + +pub(crate) fn starknet_error_to_deploy_account_error(error: StarknetError) -> JsonRpcError { + let StarknetErrorCode::KnownErrorCode(known_error_code) = error.code else { + return unexpected_error(error.message); + }; + match known_error_code { + KnownStarknetErrorCode::DuplicatedTransaction => DUPLICATE_TX, + // See explanation on this mapping in AddInvokeError. + KnownStarknetErrorCode::EntryPointNotFoundInContract => NON_ACCOUNT, + KnownStarknetErrorCode::InsufficientAccountBalance => INSUFFICIENT_ACCOUNT_BALANCE, + KnownStarknetErrorCode::InsufficientMaxFee => INSUFFICIENT_MAX_FEE, + KnownStarknetErrorCode::InvalidTransactionNonce => INVALID_TRANSACTION_NONCE, + KnownStarknetErrorCode::InvalidTransactionVersion => UNSUPPORTED_TX_VERSION, + KnownStarknetErrorCode::UndeclaredClass => CLASS_HASH_NOT_FOUND, + KnownStarknetErrorCode::ValidateFailure => validation_failure(error.message), + _ => unexpected_error(error.message), + } +} diff --git a/crates/papyrus_rpc/src/v0_7/write_api_error_test.rs b/crates/papyrus_rpc/src/v0_7/write_api_error_test.rs new file mode 100644 index 00000000000..26a2eaf2852 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/write_api_error_test.rs @@ -0,0 +1,92 @@ +use std::collections::BTreeMap; + +use enum_iterator::all; +use jsonrpsee::types::ErrorObjectOwned; +use starknet_client::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +use super::super::error::JsonRpcError; +use super::{ + starknet_error_to_declare_error, + starknet_error_to_deploy_account_error, + starknet_error_to_invoke_error, +}; +use crate::test_utils::{get_starknet_spec_api_schema_for_method_errors, SpecFile}; +use crate::version_config::VERSION_0_7 as Version; + +const MESSAGE: &str = "message"; +const UNKNOWN_CODE: &str = "code"; + +fn starknet_errors() -> impl Iterator { + all::() + .map(StarknetErrorCode::KnownErrorCode) + .chain([StarknetErrorCode::UnknownErrorCode(UNKNOWN_CODE.to_owned())]) + .map(|error_code| StarknetError { code: error_code, message: MESSAGE.to_owned() }) +} + +fn test_error_from_conversion_fits_rpc JsonRpcError>( + f: F, + spec_method: &str, +) { + let schema = get_starknet_spec_api_schema_for_method_errors( + &[(SpecFile::WriteApi, &[spec_method])], + &Version, + ); + for starknet_error in starknet_errors() { + // Converting into ErrorObjectOwned since it has serialization. + let rpc_error: ErrorObjectOwned = f(starknet_error).into(); + let mut json_value = serde_json::to_value(rpc_error).unwrap(); + json_value.as_object_mut().unwrap().retain(|_, v| !v.is_null()); + assert!(schema.is_valid(&json_value)); + } +} + +#[test] +fn starknet_error_to_invoke_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_invoke_error, + "starknet_addInvokeTransaction", + ); +} + +#[test] +fn starknet_error_to_declare_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_declare_error, + "starknet_addDeclareTransaction", + ); +} + +#[test] +fn starknet_error_to_deploy_account_error_result_fits_specs() { + test_error_from_conversion_fits_rpc( + starknet_error_to_deploy_account_error, + "starknet_addDeployAccountTransaction", + ); +} + +fn get_conversion_snapshot JsonRpcError>( + f: F, +) -> serde_json::Value { + // Using BTreeMap to keep the keys sorted. + let mut rpc_error_code_to_errors = BTreeMap::new(); + for starknet_error in starknet_errors() { + let rpc_error: ErrorObjectOwned = f(starknet_error.clone()).into(); + rpc_error_code_to_errors.insert(rpc_error.code(), (rpc_error, starknet_error)); + } + serde_json::to_value(rpc_error_code_to_errors).unwrap() +} + +#[test] +fn starknet_error_to_invoke_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_invoke_error)); +} + +#[test] +fn starknet_error_to_declare_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_declare_error)); +} + +#[test] +fn starknet_error_to_deploy_account_error_snapshot() { + insta::assert_json_snapshot!(get_conversion_snapshot(starknet_error_to_deploy_account_error)); +} diff --git a/crates/papyrus_rpc/src/v0_7/write_api_result.rs b/crates/papyrus_rpc/src/v0_7/write_api_result.rs new file mode 100644 index 00000000000..ddc54e96f97 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/write_api_result.rs @@ -0,0 +1,50 @@ +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::transaction::TransactionHash; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, +}; + +#[cfg(test)] +#[path = "write_api_result_test.rs"] +mod write_api_result_test; + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddInvokeOkResult { + pub transaction_hash: TransactionHash, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddDeclareOkResult { + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct AddDeployAccountOkResult { + pub transaction_hash: TransactionHash, + pub contract_address: ContractAddress, +} + +impl From for AddInvokeOkResult { + fn from(response: InvokeResponse) -> Self { + Self { transaction_hash: response.transaction_hash } + } +} + +impl From for AddDeclareOkResult { + fn from(response: DeclareResponse) -> Self { + Self { transaction_hash: response.transaction_hash, class_hash: response.class_hash } + } +} + +impl From for AddDeployAccountOkResult { + fn from(response: DeployAccountResponse) -> Self { + Self { transaction_hash: response.transaction_hash, contract_address: response.address } + } +} diff --git a/crates/papyrus_rpc/src/v0_7/write_api_result_test.rs b/crates/papyrus_rpc/src/v0_7/write_api_result_test.rs new file mode 100644 index 00000000000..cf85cc0ee61 --- /dev/null +++ b/crates/papyrus_rpc/src/v0_7/write_api_result_test.rs @@ -0,0 +1,90 @@ +use serde::Serialize; +use starknet_api::core::{ClassHash, ContractAddress, PatriciaKey}; +use starknet_api::felt; +use starknet_api::transaction::TransactionHash; +use starknet_client::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, + SuccessfulStarknetErrorCode, +}; +use test_utils::{auto_impl_get_test_instance, get_rng, GetTestInstance}; + +use super::{AddDeclareOkResult, AddDeployAccountOkResult, AddInvokeOkResult}; +use crate::test_utils::{get_starknet_spec_api_schema_for_method_results, SpecFile}; +use crate::version_config::VERSION_0_7 as VERSION; + +auto_impl_get_test_instance! { + pub struct AddInvokeOkResult { + pub transaction_hash: TransactionHash, + } + pub struct AddDeclareOkResult { + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, + } + pub struct AddDeployAccountOkResult { + pub transaction_hash: TransactionHash, + pub contract_address: ContractAddress, + } +} + +fn test_ok_result_fits_rpc(spec_method: &str) { + let schema = get_starknet_spec_api_schema_for_method_results( + &[(SpecFile::WriteApi, &[spec_method])], + &VERSION, + ); + let result = AddOkResult::get_test_instance(&mut get_rng()); + assert!(schema.is_valid(&serde_json::to_value(result).unwrap())); +} + +#[test] +fn add_invoke_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addInvokeTransaction"); +} + +#[test] +fn add_declare_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addDeclareTransaction"); +} + +#[test] +fn add_deploy_account_ok_result_fits_rpc() { + test_ok_result_fits_rpc::("starknet_addDeployAccountTransaction"); +} + +#[test] +fn add_invoke_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let ok_result = AddInvokeOkResult::from(InvokeResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + }); + let expected_ok_result = AddInvokeOkResult { transaction_hash }; + assert_eq!(expected_ok_result, ok_result); +} + +#[test] +fn add_declare_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let class_hash = ClassHash(felt!("0xabcde")); + let ok_result = AddDeclareOkResult::from(DeclareResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + class_hash, + }); + let expected_ok_result = AddDeclareOkResult { transaction_hash, class_hash }; + assert_eq!(expected_ok_result, ok_result); +} + +#[test] +fn add_deploy_account_ok_result_from_response() { + let transaction_hash = TransactionHash(felt!("0x12345")); + let contract_address = ContractAddress(PatriciaKey::try_from(felt!("0xabcde")).unwrap()); + let ok_result = AddDeployAccountOkResult::from(DeployAccountResponse { + code: SuccessfulStarknetErrorCode::default(), + transaction_hash, + address: contract_address, + }); + let expected_ok_result = AddDeployAccountOkResult { transaction_hash, contract_address }; + assert_eq!(expected_ok_result, ok_result); +} diff --git a/crates/papyrus_rpc/src/version_config.rs b/crates/papyrus_rpc/src/version_config.rs new file mode 100644 index 00000000000..8619670049f --- /dev/null +++ b/crates/papyrus_rpc/src/version_config.rs @@ -0,0 +1,38 @@ +#[cfg(test)] +#[path = "version_config_test.rs"] +mod version_config_test; + +use std::fmt; + +pub const VERSION_PATTERN: &str = "[Vv][0-9]+_[0-9]+(_[0-9]+)?"; + +#[derive(Eq, PartialEq, Hash)] +/// Labels the jsonRPC versions we have such that there can be multiple versions that are supported, +/// and there can be multiple versions that are deprecated. +/// Supported -> method exposed via the http path "/version_id" (e.g. http://host:port/V0_3_0) +/// Deprecated -> method not exposed. +#[derive(Clone, Copy, Debug)] +pub enum VersionState { + Supported, + Deprecated, +} + +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] +pub struct VersionId { + // TODO(yair): change to enum so that the match in get_methods_from_supported_apis can be + // exhaustive. + pub name: &'static str, + pub patch: u8, +} + +impl fmt::Display for VersionId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}_{}", self.name, self.patch) + } +} + +/// latest version must be set as supported +pub const VERSION_CONFIG: &[(VersionId, VersionState)] = + &[(VERSION_0_6, VersionState::Supported), (VERSION_0_7, VersionState::Supported)]; +pub const VERSION_0_6: VersionId = VersionId { name: "V0_6", patch: 0 }; +pub const VERSION_0_7: VersionId = VersionId { name: "V0_7", patch: 0 }; diff --git a/crates/papyrus_rpc/src/version_config_test.rs b/crates/papyrus_rpc/src/version_config_test.rs new file mode 100644 index 00000000000..f1e3f349b02 --- /dev/null +++ b/crates/papyrus_rpc/src/version_config_test.rs @@ -0,0 +1,19 @@ +use std::collections::HashMap; + +use pretty_assertions::assert_eq; + +use super::{VersionState, VERSION_CONFIG}; + +#[tokio::test] +async fn validate_version_configuration() { + let mut config_type_counter = + HashMap::from([(&VersionState::Supported, 0), (&VersionState::Deprecated, 0)]); + let mut config_version_counter = HashMap::new(); + VERSION_CONFIG.iter().for_each(|config| { + let (version_id, version_state) = config; + config_type_counter.entry(version_state).and_modify(|counter| *counter += 1); + config_version_counter.entry(*version_id).and_modify(|counter| *counter += 1).or_insert(1); + }); + // verify each version is listed once + config_version_counter.iter().for_each(|version_counter| assert_eq!(*version_counter.1, 1)) +} diff --git a/crates/papyrus_rpc/tests/gateway_integration_test.rs b/crates/papyrus_rpc/tests/gateway_integration_test.rs new file mode 100644 index 00000000000..2b8e238cc0e --- /dev/null +++ b/crates/papyrus_rpc/tests/gateway_integration_test.rs @@ -0,0 +1,132 @@ +use std::env; + +use jsonrpsee::core::client::ClientT; +use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; +use jsonrpsee::rpc_params; +use papyrus_common::transaction_hash::get_transaction_hash; +use papyrus_common::TransactionOptions; +use papyrus_rpc::{ + AddInvokeOkResultRPC0_6, + InvokeTransactionRPC0_6, + InvokeTransactionV1RPC0_6, + TransactionVersion1RPC0_6, +}; +use starknet_api::core::{ChainId, ContractAddress, EntryPointSelector, Nonce, PatriciaKey}; +use starknet_api::transaction::{Calldata, Fee, Transaction, TransactionSignature}; +use starknet_api::{calldata, contract_address, felt, patricia_key}; +use starknet_client::writer::objects::transaction::InvokeTransaction as SNClientInvokeTransaction; +use starknet_core::crypto::ecdsa_sign; +use starknet_core::types::FieldElement; +use starknet_types_core::felt::Felt; + +const ETH_TO_WEI: u128 = u128::pow(10, 18); +const MAX_FEE: u128 = ETH_TO_WEI / 1000; +const INSUFFICIENT_FUNDS_STATUS_CODE: i32 = 2; +const L2_ETH_CONTRACT_ADDRESS: &str = + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +const BALANCE_OF_ENTRY_POINT_SELECTOR: &str = + "0x2e4263afad30923c891518314c3c95dbe830a16874e8abc5777a9a20b54c76e"; +const TRANSFER_ENTRY_POINT_SELECTOR: &str = + "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e"; +const USER_A_ADDRESS: &str = "0x2eda087f4edf190224eac3fdf7f762d83052f7c83fdda674e6e97e1f596a819"; +const USER_B_ADDRESS: &str = "0x02d23bb72da2a2c7cce1577a013c3139b4f51d2b32be2ee7825f33428f572a9d"; + +// Returns the eth balance for the given account via the given node client. +async fn get_eth_balance(client: &HttpClient, account: ContractAddress) -> Felt { + let balance = client + .request::, _>( + "starknet_call", + rpc_params!( + ( + L2_ETH_CONTRACT_ADDRESS, + EntryPointSelector(felt!(BALANCE_OF_ENTRY_POINT_SELECTOR)), + calldata![*account.0.key()], + ), + "latest" + ), + ) + .await + .expect("Call to balanceOf failed."); + balance[0] +} + +#[tokio::test] +#[ignore] +// Sends a 'transfer of eth from user A to user B' transaction to a node instance synced with +// Starknet integration testnet. The node is expected to resend the transaction to Starknet +// successfully. +async fn test_gw_integration_testnet() { + let node_url = env::var("INTEGRATION_TESTNET_NODE_URL") + .expect("Node url must be given in INTEGRATION_TESTNET_NODE_URL environment variable."); + let client = + HttpClientBuilder::default().build(format!("https://{}:443/rpc/v0_6", node_url)).unwrap(); + let sender_address = contract_address!(USER_A_ADDRESS); + // Sender balance sufficient balance should be maintained outside of this test. + let sender_balance = get_eth_balance(&client, sender_address).await; + if sender_balance <= MAX_FEE.into() { + println!("Sender balance is too low. Please fund account {}.", USER_A_ADDRESS); + std::process::exit(INSUFFICIENT_FUNDS_STATUS_CODE); + } + + // TODO(tzahi): Switch to "pending" once supported and add an assertion for the status of the + // sent tx and balance update in the end of this test. + let nonce = client + .request::("starknet_getNonce", rpc_params!["latest", sender_address]) + .await + .unwrap(); + let receiver_address = contract_address!(USER_B_ADDRESS); + + // Create an invoke transaction for Eth transfer with a signature placeholder. + let mut invoke_tx = InvokeTransactionV1RPC0_6 { + max_fee: Fee(MAX_FEE), + signature: TransactionSignature::default(), + nonce, + sender_address, + version: TransactionVersion1RPC0_6::default(), + calldata: calldata![ + felt!(1_u8), // OpenZeppelin call array len (number of calls in this tx). + // Call Array (4 elements per array struct element). + felt!(L2_ETH_CONTRACT_ADDRESS), // to + EntryPointSelector(felt!(TRANSFER_ENTRY_POINT_SELECTOR)).0, // selector. + felt!(0_u8), // data offset (in the calldata array) + felt!(3_u8), /* data len (of this call in the entire + * calldata array) */ + // Call data. + felt!(3_u8), // Call data len. + // calldata for transfer - receiver and amount (uint256 = 2 felts). + *receiver_address.0.key(), + felt![1_u8], // LSB + felt![0_u8] + ], + }; + + // Update the signature. + let hash = get_transaction_hash( + &Transaction::Invoke(InvokeTransactionRPC0_6::Version1(invoke_tx.clone()).into()), + &ChainId::Sepolia, + &TransactionOptions::default(), + ) + .unwrap(); + let signature = ecdsa_sign( + &FieldElement::from_hex_be(&env::var("SENDER_PRIVATE_KEY").expect( + "Sender private key must be given in SENDER_PRIVATE_KEY environment variable.", + )) + .unwrap(), + &FieldElement::from_bytes_be(&hash.0.to_bytes_be()).unwrap(), + ) + .unwrap(); + invoke_tx.signature = TransactionSignature(vec![ + Felt::from_bytes_be(&signature.r.to_bytes_be()), + Felt::from_bytes_be(&signature.s.to_bytes_be()), + ]); + + let invoke_res = client + .request::( + "starknet_addInvokeTransaction", + rpc_params!(SNClientInvokeTransaction::from(invoke_tx)), + ) + .await + .unwrap_or_else(|err| panic!("Failed to add tx '{hash}' with nonce '{nonce:?}'.: {err}")); + + println!("Invoke Tx result: {:?}", invoke_res); +} diff --git a/crates/papyrus_storage/Cargo.toml b/crates/papyrus_storage/Cargo.toml new file mode 100644 index 00000000000..69b17151b85 --- /dev/null +++ b/crates/papyrus_storage/Cargo.toml @@ -0,0 +1,78 @@ +[package] +name = "papyrus_storage" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "A storage implementation for a Starknet node." + +[features] +testing = ["tempfile"] +document_calls = ["lazy_static"] + +[[bin]] +name = "dump_declared_classes" +required-features = ["clap"] +path = "src/bin/dump_declared_classes.rs" + +[[bin]] +name = "storage_benchmark" +required-features = ["clap", "statistical"] +path = "src/bin/storage_benchmark.rs" + +[dependencies] +byteorder.workspace = true +cairo-lang-starknet-classes.workspace = true +cairo-lang-casm = { workspace = true, features = ["parity-scale-codec"] } +cairo-lang-utils.workspace = true +human_bytes.workspace = true +indexmap = { workspace = true, features = ["serde"] } +integer-encoding.workspace = true +lazy_static = { workspace = true, optional = true } +libmdbx = { workspace = true, features = ["lifetimed-bytes"] } +memmap2.workspace = true +metrics.workspace = true +num-bigint.workspace = true +page_size.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_proc_macros = { path = "../papyrus_proc_macros", version = "0.4.0-rc.0" } +parity-scale-codec.workspace = true +primitive-types.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +starknet_api.workspace = true +starknet-types-core = { workspace = true, features = ["papyrus-serialization"] } +tempfile = { workspace = true, optional = true } +thiserror.workspace = true +tracing = { workspace = true, features = ["log"] } +validator = { workspace = true, features = ["derive"] } +zstd.workspace = true + +# Binaries dependencies +clap = { workspace = true, optional = true } +statistical = { workspace = true, optional = true } + + +[dev-dependencies] +assert_matches.workspace = true +cairo-lang-casm = { workspace = true, features = [ + "parity-scale-codec", + "schemars", +] } +camelpaste.workspace = true +insta = { workspace = true, features = ["yaml"] } +metrics-exporter-prometheus.workspace = true +num-traits.workspace = true +paste.workspace = true +pretty_assertions.workspace = true +prometheus-parse.workspace = true +rand.workspace = true +rand_chacha.workspace = true +schemars = { workspace = true, features = ["preserve_order"] } +simple_logger.workspace = true +tempfile = { workspace = true } +test-case.workspace = true +test-log.workspace = true +test_utils = { path = "../test_utils" } +tokio = { workspace = true, features = ["full", "sync"] } diff --git a/crates/papyrus_storage/README.md b/crates/papyrus_storage/README.md new file mode 100644 index 00000000000..e58a8e50901 --- /dev/null +++ b/crates/papyrus_storage/README.md @@ -0,0 +1,5 @@ +# papyrus-storage + +## Description + +papyrus-storage provides a writing and reading interface for various Starknet data structures to a database, designed specifically for Papyrus, a Starknet node. diff --git a/crates/papyrus_storage/resources/class.json b/crates/papyrus_storage/resources/class.json new file mode 100644 index 00000000000..253f4eff78a --- /dev/null +++ b/crates/papyrus_storage/resources/class.json @@ -0,0 +1,10573 @@ +{ + "contract_class_version": "0.1.0", + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x4", + "0x3", + "0x9fb", + "0x605", + "0xdd", + "0x52616e6765436865636b", + "0x800000000000000100000000000000000000000000000000", + "0x75313238", + "0x800000000000000700000000000000000000000000000000", + "0x537472756374", + "0x800000000000000700000000000000000000000000000003", + "0x0", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x1", + "0x553132384d756c47756172616e746565", + "0x800000000000000f00000000000000000000000000000001", + "0x456e756d", + "0x1909a2057b9c1373b889e003e050a09f431d8108e0659d03444ced99a6eea68", + "0x4", + "0x7538", + "0xc048ae671041dedb3ca1f250ad42a27aeddf8a7f491e553e7f2a70ff2e1800", + "0x6", + "0x45635374617465", + "0x4172726179", + "0x800000000000000300000000000000000000000000000001", + "0xc", + "0x536e617073686f74", + "0x800000000000000700000000000000000000000000000001", + "0x9", + "0x800000000000000700000000000000000000000000000002", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0xa", + "0x66656c74323532", + "0x1166fe35572d4e7764dac0caf1fd7fc591901fd01156db2561a07b68ab8dca2", + "0x800000000000000700000000000000000000000000000004", + "0xb", + "0xd", + "0x16a4c8d7c05909052238a862d8cc3e7975bf05a07b3a69c6b28951083a6d672", + "0x800000000000000300000000000000000000000000000003", + "0xf", + "0x24dcf3525a56e5b3859c521c7facf7812fc97631a3084d277859a564fb9fdbd", + "0xe", + "0x10", + "0x556e696e697469616c697a6564", + "0x800000000000000200000000000000000000000000000001", + "0x1ca27f4a416836d321a19551a437aeb9946fde25373762126dda39b53c0bd11", + "0x753634", + "0x3342418ef16b3e2799b906b1e4e89dbb9b111332dd44f72458ce44f9895b508", + "0x14", + "0x426f78", + "0x15", + "0x38b0179dda7eba3d95708820abf10d3d4f66e97d9a9013dc38d712dce2af15", + "0x16", + "0x18", + "0x2360086d8de14207bc705f7c51c3fc6bb6de6b826f1a4576e4db739d8b5edaf", + "0x1a", + "0x4563506f696e74", + "0x4e6f6e5a65726f", + "0x1c", + "0x65", + "0x1e", + "0x13d20f70b017632fd676250ec387876342924ff0d0d3c80e55961780f4e8f", + "0x1f", + "0x20", + "0x22", + "0x3ae40d407f8074730e48241717c3dd78b7128d346cf81094e31806a3a5bdf", + "0x23", + "0x753332", + "0x39a088813bcc109470bd475058810a7465bd632650a449e0ab3aee56f2e4e69", + "0x25", + "0x2f23416cc60464d4158423619ba713070eb82b686c9d621a22c67bd37f6e0a9", + "0x27", + "0x1597b831feeb60c71f259624b79cf66995ea4f7e383403583674ab9c33b9cec", + "0x19", + "0x800000000000000700000000000000000000000000000005", + "0x29", + "0xf98f4a6c1a3c4d9e27bc29334f4348768bffb65b1bb9b7ce0f91a525e1d84d", + "0x2a", + "0x6c", + "0xfeece2ea7edbbbebeeb5f270b77f64c680a68a089b794478dd9eca75e0196a", + "0x2c", + "0x1289347a53bd537cb2be622dc3ef1bae97ae391de352ed7871b08a409f130a8", + "0x19b9ae4ba181a54f9e7af894a81b44a60aea4c9803939708d6cc212759ee94c", + "0x2fffb69a24c0eccf3220a0a3685e1cefee1b1f63c6dcbe4030d1d50aa7a7b42", + "0x101dc0399934cc08fa0d6f6f2daead4e4a38cabeea1c743e1fc28d2d6e58e99", + "0x800000000000000300000000000000000000000000000002", + "0x31", + "0x5b9304f5e1c8e3109707ef96fc2ba4cf5360d21752ceb905d488f0aef67c7", + "0x32", + "0x17cc0d253de5ad59018ea04339445145fdcc7ecede2a33ec110184f1cefd2be", + "0x1bbd4b0c9742f41f0e556432056bba4255e26798f7858b7f11339dac76012b1", + "0x34", + "0x35", + "0x173c3aeee6bc7c98ea5205564f937f20718df97f0d752272ed3716e3e3d088b", + "0x36", + "0x66", + "0x1c85cfe38772db9df99e2b01984abc87d868a6ed1abf1013cf120a0f3457fe1", + "0x38", + "0x436c61737348617368", + "0x14a7ddbb1150a2edc3d078a24d9dd07049784d38d10f9253fc3ece33c2f46a3", + "0x3a", + "0x90d0203c41ad646d024845257a6eceb2f8b59b29ce7420dd518053d2edeedc", + "0x3288d594b9a45d15bb2fcb7903f06cdb06b27f0ba88186ec4cfaa98307cb972", + "0x2d7b9ba5597ffc180f5bbd030da76b84ecf1e4f1311043a0a15295f29ccc1b0", + "0x3d", + "0x161ee0e6962e56453b5d68e09d1cabe5633858c1ba3a7e73fee8c70867eced0", + "0x18672a8f646efb247fea41bb961b82efc61071ff1bf295f077ed3f7f5fbe1ec", + "0x40", + "0x248e8fae2f16a35027771ffd74d6a6f3c379424b55843563a18f566bba3d905", + "0x53746f7261676541646472657373", + "0x53746f726167654261736541646472657373", + "0x436f6e747261637441646472657373", + "0x3808c701a5d13e100ab11b6c02f91f752ecae7e420d21b56c90ec0a475cc7e5", + "0x45", + "0x46", + "0x47", + "0xe688ac0888a7171e23d265a0ea68699a0ab1f7192e9651213e940c13b80319", + "0x48", + "0x4a", + "0x1c61d0f622cd5a7f54eaac1e4af6d7e31f8c6d9acb92684f4e78963157c263b", + "0x4b", + "0x1f5d91ca543c7f9a0585a1c8beffc7a207d4af73ee640223a154b1da196a40d", + "0x4d", + "0x4f", + "0x50", + "0x800000000000000300000000000000000000000000000004", + "0x104eb68e98232f2362ae8fd62c9465a5910d805fa88b305d1f7721b8727f04", + "0x52", + "0x33db04f8bf393d7a10f45b3b9adce8d5f333d7a13db7a3ff2d5d3171e0b03a4", + "0x28f8d296e28032baef1f420f78ea9d933102ba47a50b1c5f80fc8a3a1041da", + "0x6d21884c4651d3ca8ce4f3cad5c986babe287f99c59302cfa7b0bbf79ae179", + "0x55", + "0x2ec7c338575592f1c8dfc7277475fb507fa6dbe32e91ed4877edd750118badf", + "0x5d18937d10b5347a398f158c0087055a32385cb792a13447ae8cf78756ac03", + "0x26ee0aadcf9d5ca1f9dc79dd0c46ccb60ebe57085963750610cd67a59d50975", + "0x13152081fc9f5c0c9940e9b41ae0cdb53f68d70078cf676f50239842e0b52d0", + "0x3ae507569ecac2989ca90094d2595cd0ef5cbfc283eced198c7ab0e2e1397f8", + "0x3eba5f295a6f9a28c0e58874daaae7a01414aee71fed3a4f321c9ee5d8a357f", + "0x3b49669d6f61e22f521612046d7c2d3fcbd59faee13c997508cc6dd42c50d4d", + "0x33a44665fba067e31d08b2c13820c7aab471d4b6b0c5578a7ce7f0fb50260ec", + "0x281341dd9f4ac08d5a12a917325719d2acb34fda2c86607606e585c3832b026", + "0x711cec3aa770776575f4905535364c29e2abc42bb005a5a0f1729791f8da8a", + "0x1deefea9d0c16c2eb738021b7529472d18d2684fe3fc6f066df8bd982fc0d75", + "0x80000000000000070000000000000000000000000000000e", + "0x156c60808ca6240a5f664e67b7c5c245c75d99dc1786f4326631a816f77178", + "0x54", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x61", + "0x800000000000000300000000000000000000000000000005", + "0x24d1fd89b67292dedf95c26145ffde2e9f0bfe5cf06b20b04b05b51fbb0033b", + "0x63", + "0x3693aea200ee3080885d21614d01b9532a8670f69e658a94addaadd72e9aca", + "0x3c7ee94100b5c63828928ad04b4ee403391886571321a2f8f2e58d1b6141cde", + "0x67", + "0xa7", + "0x800000000000000700000000000000000000000000000006", + "0x7d4d99e9ed8d285b5c61b493cedb63976bc3d9da867933d829f49ce838b5e7", + "0x6b", + "0x2ca39cde64b91db1514d78c135ee79d71b3b57fffee52f1a3ef96618a34d8c8", + "0x6d", + "0x18508a22cd4cf1437b721f596cd2277fc0a5e4dcd247b107ef2ef5fd2752cf7", + "0x6f", + "0x8416421239ce8805ed9d27e6ddae62a97ab5d01883bb8f5246b4742a44b429", + "0x70", + "0x13a34c3a07fb12ab04f8961d12c1cac659a74ffde34a7bada0708a1103ce365", + "0x800000000000000f00000000000000000000000000000003", + "0x72", + "0x2c9020782f9525cb15d3f132b6086816a5dabefb1a0437054202fb171c75145", + "0x73", + "0x27b05fbc8418f9db2745f2ae71e4af5fac6811448414afa4f894aa3b8c68ce2", + "0x75", + "0x1c8505637721e9ff545656181cd5571862c272c7063ad675b57401799d34587", + "0x76", + "0x135087deb84076d911a865705036d6031bdc60a0efa11ee97ca7e0fbfee376c", + "0x78", + "0x29dcb52dff8b4a828c533d9fa3b99ec6edf0b67728df2a286ab21ac76176500", + "0x79", + "0x15cb9d83db8ab255128a341c754cfa20b8c39f9b71e1035c358b97e36aa69c4", + "0x7b", + "0x29ad92e55ab8088ed8e3d2827639508b79913a70e9dc213ebffd77f5bc69c3d", + "0x7c", + "0x3096c001e81cc138a13933bbc6e499779a1fe08346f38449c473a7956dbdcec", + "0x7e", + "0x3c0dae5c4b3564a789109132738a600f194ecd06a3252657c655a1b742e71a3", + "0x7f", + "0x1db896f0b05cfa6707983a0f413233717fbee8a5dc1f78a4250d2d6267c5930", + "0x81", + "0x9ecd72f6c3f1e25b229d98babf09e1c73a432451cce99b16397a57a0ad5209", + "0x82", + "0xd27204ee93f77fb1714731cc4bb4ea705fe77800afad081d36a66e2c8fbbff", + "0x84", + "0x153eba592a63c38cda70751d13e87acb197c7345bfebbc315b0a51e3c8135ea", + "0x85", + "0x87", + "0x212c0191d31f49f0f3dfb855d91d40f886e0cb5f1dac8834b67820dc5346a20", + "0x89", + "0x1814137beace2d8dcf2ed91c08ef2f9c05067d77bc0ca16bbbbb3f4e25e27b2", + "0x8b", + "0x23b3001b4b3b7f9e1b6498723467af80e066e8cf805c10c103bd93ad4f02bc0", + "0x8c", + "0x224a57ba2504f0018c4fd92c0f0e6ef13a37bf8d3d6479b8faa16fc36f624d2", + "0x8e", + "0x2bcddf47e99bd2b365b672ce4ab3c5daf69bca568e14d0c1ccc9cee29ffaf43", + "0x91", + "0x3bf35e9f5398ac00dd0d96dba9e1f1fd0d8c12f1e9cce4e7abdd660163733b2", + "0x800000000000000f00000000000000000000000000000002", + "0xcc5e86243f861d2d64b08c35db21013e773ac5cf10097946fe0011304886d5", + "0x94", + "0x23204b4adf3854c5fba975a31d32de6ddf23cbf2f59f33b548a4903d33f6eef", + "0x28af69a60ef73f46d9a506e15d44c1a38e349b1b80cf4a6b70d56c9fe7a9203", + "0x97", + "0x107532bc0d80b6ebbe945434585c46cebc10c524181721cf8e2201f0910307", + "0x98", + "0x1735eb34ffeaf8accaa4abeaef6521748bab5d1302d7967492fda631b0d8660", + "0x1ee471fea880cdb75aff7b143b1653e4803b9dca47f4fcdd349d11fec9d7a16", + "0x9b", + "0x341d38eba34b7f63af136a2fa0264203bb537421424d8af22f13c0486c6bd62", + "0x9d", + "0x103a42e181f130718945bf95d02f3ba8a4b02e42a52022215a4b71dc9d7dc64", + "0x9e", + "0x156b6b29ca961a0da2cfe5b86b7d70df78ddc905131c6ded2cd9024ceb26b4e", + "0x3d37ad6eafb32512d2dd95a2917f6bf14858de22c27a1114392429f2e5c15d7", + "0x25abf8fd76a01c7e2544d26b0a2e29212b05a36781e0330b46d878e43b307d1", + "0xa4", + "0x348a62b7a38c0673e61e888d83a3ac1bf334ee7361a8514593d3d9532ed8b39", + "0xa36a0a15af8cf1727a3a4fd9137671f23256b1f42299af56605a6910c522ce", + "0xa8", + "0x3e1934b18d91949ab9afdbdd1866a30ccca06c2b1e6581582c6b27f8b4f6555", + "0xab", + "0x29d7d57c04a880978e7b3689f6218e507f3be17588744b58dc17762447ad0e7", + "0xae", + "0x28d3252c9df96ada7602e4debae27c6fdfcd09d9f2ea8a09e99e56efab1307f", + "0xaf", + "0x3ab802bcce3a9ca953b0e1f31a5b29eb27a9b727c891e24300e1b5cc57387ba", + "0xb1", + "0x2857c8eed09aa950d2bc411e245e9f97cbb8625661593905246875ea75c45cb", + "0x306ee1b3df3368a2d9762b655e64321cb3d06bfe8688fa5ec7fc954c936371a", + "0xb4", + "0x800000000000000f00000000000000000000000000000009", + "0x1552851bac512fea401910db633a4f5871c9a0e9765a5b07cb2142c85b684c1", + "0xb6", + "0x580bfb4857efc49e54c7e93e36506161857cae277315f915e9a36cf0d7cc21", + "0xb7", + "0x1c25c9665833e285eaa79ed5e2438c2487467dbe5b2f1e0ac47b57996671144", + "0xb9", + "0x11771f2d3e7dc3ed5afe7eae405dfd127619490dec57ceaa021ac8bc2b9b315", + "0xa853c166304d20fb0711becf2cbdf482dee3cac4e9717d040b7a7ab1df7eec", + "0xbd", + "0x506564657273656e", + "0x1b8ede3ee9a223bf2a237d374233c99c13677364744717814226e9174a88067", + "0x3d092b7967b0fdc524ce95075d03229cfc59ee514c4a7ded5c90b2b37408b0c", + "0xc0", + "0xc1", + "0x10cfbfe828407532cf9f305abb44380ee6893535051d5b10b0f73ebdae0aa08", + "0xc2", + "0x45634f70", + "0xc5", + "0xbf", + "0x10203be321c62a7bd4c060d69539c1fbe065baa9e253c74d2cc48be163e259", + "0x17b6ecc31946835b0d9d92c2dd7a9c14f29af0371571ae74a1b228828b2242", + "0xc9", + "0x34f9bd7c6cb2dd4263175964ad75f1ff1461ddc332fbfb274e0fb2a5d7ab968", + "0xca", + "0x11c6d8087e00642489f92d2821ad6ebd6532ad1a3b6d12833da6d6810391511", + "0x74584e9f10ffb1a40aa5a3582e203f6758defc4a497d1a2d5a89f274a320e9", + "0xce", + "0x1d0c38954feffa7920ed6c6d5e3231a98e72f2f9f770df7e1f662b96a81b646", + "0xd0", + "0x53797374656d", + "0xd2", + "0x179de9c76344467236b20ddfcbd854b82e7eb901c82c7d76f8293262f0aa4f8", + "0xd5", + "0x4275696c74696e436f737473", + "0x9931c641b913035ae674b400b61a51476d506bbe8bba2ff8a6272790aba9e6", + "0xd4", + "0x28f184fd9e4406cc4475e4faaa80e83b54a57026386ee7d5fc4fa8f347e327d", + "0xd9", + "0xc1f0cb41289e2f6a79051e9af1ead07112b46ff17a492a90b3944dc53a51c8", + "0xda", + "0x4761734275696c74696e", + "0x441", + "0x7265766f6b655f61705f747261636b696e67", + "0x77697468647261775f676173", + "0x6272616e63685f616c69676e", + "0x73746f72655f74656d70", + "0xdc", + "0x66756e6374696f6e5f63616c6c", + "0x3", + "0x21", + "0x656e756d5f6d61746368", + "0xdb", + "0x7374727563745f6465636f6e737472756374", + "0x61727261795f6c656e", + "0x736e617073686f745f74616b65", + "0x64726f70", + "0x7533325f636f6e7374", + "0x2", + "0x72656e616d65", + "0x7533325f6571", + "0x61727261795f6e6577", + "0x66656c743235325f636f6e7374", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x61727261795f617070656e64", + "0x7374727563745f636f6e737472756374", + "0x656e756d5f696e6974", + "0xd8", + "0x6765745f6275696c74696e5f636f737473", + "0xd7", + "0x77697468647261775f6761735f616c6c", + "0xd6", + "0x4f7574206f6620676173", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x616c6c6f635f6c6f63616c", + "0x66696e616c697a655f6c6f63616c73", + "0xd3", + "0x24", + "0x73746f72655f6c6f63616c", + "0xd1", + "0xcf", + "0x26", + "0xcc", + "0xcb", + "0x28", + "0xc8", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0xcd", + "0xc3", + "0xc6", + "0xc7", + "0xc4", + "0x2b", + "0xbe", + "0x2d", + "0x2e", + "0xbb", + "0x2f", + "0xba", + "0x30", + "0xbc", + "0x33", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0xb8", + "0x37", + "0x39", + "0x3b", + "0x3c", + "0x3e", + "0x3f", + "0xb5", + "0x41", + "0xb3", + "0x42", + "0x417267656e744163636f756e74", + "0x43", + "0xb2", + "0x7533325f746f5f66656c74323532", + "0x44", + "0xb0", + "0x302e332e31", + "0x49", + "0x64697361626c655f61705f747261636b696e67", + "0x61727261795f736e617073686f745f706f705f66726f6e74", + "0xad", + "0x6a756d70", + "0x756e626f78", + "0x4c", + "0xac", + "0x636f6e74726163745f616464726573735f746f5f66656c74323532", + "0x66656c743235325f737562", + "0x66656c743235325f69735f7a65726f", + "0xa9", + "0x656e61626c655f61705f747261636b696e67", + "0xaa", + "0x100000000000000000000000000000003", + "0x100000000000000000000000000000001", + "0x617267656e742f696e76616c69642d74782d76657273696f6e", + "0x617267656e742f756e737570706f727465642d7061796d6173746572", + "0x4e", + "0x56414c4944", + "0x617267656e742f6e6f6e2d6e756c6c2d63616c6c6572", + "0xa6", + "0xa5", + "0x647570", + "0x51", + "0x53", + "0xa1", + "0xa0", + "0x9f", + "0xa3", + "0xa2", + "0x414e595f43414c4c4552", + "0x9c", + "0x7536345f6f766572666c6f77696e675f737562", + "0x617267656e742f696e76616c69642d74696d657374616d70", + "0x626f6f6c5f6e6f745f696d706c", + "0x617267656e742f6475706c6963617465642d6f7574736964652d6e6f6e6365", + "0x537461726b4e6574204d657373616765", + "0x706564657273656e", + "0x1bfc207425a47a5dfa1a50a4f5241203f50624ca5fdf5e18755765416b8e288", + "0x4163636f756e742e657865637574655f66726f6d5f6f757473696465", + "0x9a", + "0x99", + "0x617267656e742f696e76616c69642d63616c6c6572", + "0x636c6173735f686173685f7472795f66726f6d5f66656c74323532", + "0x96", + "0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd", + "0x617267656e742f696e76616c69642d696d706c656d656e746174696f6e", + "0x7265706c6163655f636c6173735f73797363616c6c", + "0x95", + "0x93", + "0x92", + "0x617267656e742f6f6e6c792d73656c66", + "0x90", + "0x617267656e742f6e756c6c2d6f776e6572", + "0x62", + "0x617267656e742f6261636b75702d73686f756c642d62652d6e756c6c", + "0x64", + "0x8f", + "0x636c6173735f686173685f636f6e7374", + "0x8d", + "0x617267656e742f696e76616c69642d63616c6c73", + "0x68", + "0x8a", + "0x100000000000000000000000000000002", + "0x617267656e742f696e76616c69642d6465636c6172652d76657273696f6e", + "0x69", + "0x617267656e742f696e76616c69642d6465706c6f792d6163636f756e742d76", + "0x6a", + "0x86", + "0x7536345f636f6e7374", + "0x6e", + "0x83", + "0x88", + "0x71", + "0x80", + "0x7d", + "0x7a", + "0x74", + "0x77", + "0x617267656e742f677561726469616e2d7265717569726564", + "0x617267656e742f63616e6e6f742d6f766572726964652d657363617065", + "0x93a80", + "0x617267656e742f696e76616c69642d657363617065", + "0x7536345f746f5f66656c74323532", + "0x75385f636f6e7374", + "0x75385f746f5f66656c74323532", + "0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055", + "0x68cfd18b92d1907b8ba3cc324900277f5a3622099431ea85dd8089255e4181", + "0x1ffc9a7", + "0xa66bd575", + "0x3943f10f", + "0x617267656e742f696e76616c69642d7369676e6174757265", + "0x7374727563745f736e617073686f745f6465636f6e737472756374", + "0x26e71b81ea2af0a2b5c6bfceb639b4fc6faae9d8de072a61fc913d3301ff56b", + "0x617267656e742f696e76616c69642d63616c6c64617461", + "0x617267656e742f696e76616c69642d677561726469616e2d736967", + "0x395b662db8770f18d407bbbfeebf45fffec4a7fa4f6c7cee13d084055a9387d", + "0x29ce6d1019e7bef00e94df2973d8d36e9e9b6c5f8783275441c9e466cb8b43", + "0x617267656e742f696e76616c69642d6f776e65722d736967", + "0x3ad2979f59dc1535593f6af33e41945239f4811966bcd49314582a892ebcee8", + "0x1a1e41f464a235695e5050a846a26ca22ecc27acac54be5f6666848031efb8f", + "0x617267656e742f666f7262696464656e2d63616c6c", + "0x656d69745f6576656e745f73797363616c6c", + "0x21adb5788e32c84f69a1863d85ef9394b7bf761a0ce1190f826984e5075c371", + "0x7536345f7472795f66726f6d5f66656c74323532", + "0x73746f726167655f616464726573735f66726f6d5f62617365", + "0x73746f726167655f726561645f73797363616c6c", + "0x11ff76fe3f640fa6f3d60bbd94a3b9d47141a2c96f87fdcfbeb2af1d03f7050", + "0x7", + "0x626f6f6c5f746f5f66656c74323532", + "0x73746f726167655f77726974655f73797363616c6c", + "0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283", + "0x6c6962726172795f63616c6c5f73797363616c6c", + "0x52657475726e6564206461746120746f6f2073686f7274", + "0x526573756c743a3a756e77726170206661696c65642e", + "0x73746f726167655f626173655f616464726573735f636f6e7374", + "0x1ccc09c8a19948e048de7add6929589945e25f22059c7345aaf7837188d8d05", + "0x31e7534f8ddb1628d6e07db5c743e33403b9a0b57508a93f4c49582040a2f71", + "0x1c0f41bf28d630c8a0bd10f3a5d5c0d1619cf96cfdb7da51b112c420ced36c9", + "0xf920571b9f85bdd92a867cfdc73319d0f8836f0e69e06e4c5566b6203f75cc", + "0x4e6f6e20436c61737348617368", + "0x636c6173735f686173685f746f5f66656c74323532", + "0x617267656e742f6e6f2d6d756c746963616c6c2d746f2d73656c66", + "0x1746f7542cac71b5c88f0b2301e87cd9b0896dab1c83b8b515762697e521040", + "0x13f17de67551ae34866d4aa875cbace82f3a041eaa58b1d9e34568b0d0561b", + "0x7536345f6571", + "0x109831a1d023b114d1da4655340bd1bb108c4ddf1bba00f9330573c23f34989", + "0x3a3f1aae7e2c4017af981d69ebf959c39e6f1c53b8ffa09a3ed92f40f524ec7", + "0x7536345f6f766572666c6f77696e675f616464", + "0x7536345f616464204f766572666c6f77", + "0x53746f7265553332202d206e6f6e20753332", + "0x6765745f657865637574696f6e5f696e666f5f76325f73797363616c6c", + "0x61727261795f676574", + "0x496e646578206f7574206f6620626f756e6473", + "0x753132385f636f6e7374", + "0xb1a2bc2ec50000", + "0x753132385f6f766572666c6f77696e675f737562", + "0x617267656e742f6d61782d6665652d746f6f2d68696768", + "0x617267656e742f696e76616c69642d64612d6d6f6465", + "0x617267656e742f696e76616c69642d6465706c6f796d656e742d64617461", + "0xde0b6b3a7640000", + "0x2b5e3af16b1880000", + "0x5", + "0x7533325f6f766572666c6f77696e675f737562", + "0x617267656e742f6d61782d6573636170652d617474656d707473", + "0x617267656e742f7469702d746f6f2d68696768", + "0x7533325f6f766572666c6f77696e675f616464", + "0x7533325f616464204f766572666c6f77", + "0x63616c6c5f636f6e74726163745f73797363616c6c", + "0x66656c743235325f616464", + "0x617267656e742f6d756c746963616c6c2d6661696c6564", + "0x1d9ca8a89626bead91b5cb4275a622219e9443975b34f3fdbc683e8621231a9", + "0x1dcde06aabdbca2f80aa51392b345d7549d7757aa855f7e37f5d335ac8243b1", + "0x1eb8543121901145815b1fa94ab7062e6ecb788bee88efa299b9866bab0bd64", + "0x3c93161122e8fd7a48238feee22dd3d7d49a69099523547d4a7cc7c460fc9c4", + "0x250670a8d933a7d458c994fc396264aba18fc1f1b9136990bb0923a27eaa060", + "0x2811029a978f84c1f4c4fc70c0891f83642ded105942eda119ddc941376122e", + "0x11a96d42fc514f9d4f6f7083acbde6629ff1d2753bf6d25156be7b03e5e1207", + "0x67753421a99564465b580dcc61f1e7befc7fd138c447dae233bba1d477458c", + "0xd885f12a9241174cd02e71d9c751eec91ebc58dffa0addd86642969cbe006f", + "0x2e200b0f001d9c2e6cb94ab8cc4907810f7fe134eca20d8d02224ac5e94e01f", + "0x2b2db2ed38136ca6c54b95187166f98ea84503db8768617a558705b508fec82", + "0x38f6a5b87c23cee6e7294bcc3302e95019f70f81586ff3cac38581f5ca96381", + "0xca58956845fecb30a8cb3efe23582630dbe8b80cc1fb8fd5d5e866b1356ad", + "0x617267656e742f696e76616c69642d7369676e61747572652d6c656e677468", + "0x61727261795f736c696365", + "0x32b90df821786fc0a5a5492c92e3241a5e680e5d53cd88c2bfdd094a70c90f5", + "0xad292db4ff05a993c318438c1b6c8a8303266af2da151aa28ccece6726f1f1", + "0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f", + "0x65635f706f696e745f66726f6d5f785f6e7a", + "0x1d", + "0x756e777261705f6e6f6e5f7a65726f", + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + "0x65635f706f696e745f7472795f6e65775f6e7a", + "0x65635f706f696e745f69735f7a65726f", + "0x65635f706f696e745f756e77726170", + "0x2679d68052ccd03a53755ca9169677965fbd93e489df62f5f40d4f03c24f7a4", + "0x1b", + "0x53746f7265553634202d206e6f6e20753634", + "0x8", + "0x7533325f7472795f66726f6d5f66656c74323532", + "0x17", + "0x757063617374", + "0x4c325f474153", + "0x753132385f6f766572666c6f77696e675f616464", + "0x13", + "0x753132385f616464204f766572666c6f77", + "0x61727261795f706f705f66726f6e74", + "0x11", + "0xf00de1fccbb286f9a020ba8821ee936b1deea42a5c485c11ccdc82c8bebb3a", + "0x65635f73746174655f696e6974", + "0x65635f73746174655f6164645f6d756c", + "0x65635f73746174655f7472795f66696e616c697a655f6e7a", + "0x65635f706f696e745f7a65726f", + "0x65635f73746174655f616464", + "0x65635f6e6567", + "0x75385f6f766572666c6f77696e675f616464", + "0x75385f616464204f766572666c6f77", + "0x753132385f6d756c204f766572666c6f77", + "0x753132385f67756172616e7465655f6d756c", + "0x753132385f746f5f66656c74323532", + "0x753132385f6d756c5f67756172616e7465655f766572696679", + "0x49e3", + "0xffffffffffffffff", + "0x12", + "0x119", + "0x111", + "0x101", + "0xf2", + "0xeb", + "0xe4", + "0x1c6", + "0x1b5", + "0x1ac", + "0x19b", + "0x157", + "0x18b", + "0x183", + "0x2af", + "0x2a2", + "0x28d", + "0x280", + "0x26b", + "0x210", + "0x257", + "0x24e", + "0x245", + "0x343", + "0x33b", + "0x32b", + "0x2e9", + "0x31c", + "0x314", + "0x3c6", + "0x3b6", + "0x374", + "0x3a7", + "0x39f", + "0x47d", + "0x46c", + "0x463", + "0x452", + "0x405", + "0x442", + "0x43b", + "0x434", + "0x518", + "0x510", + "0x500", + "0x4b5", + "0x4f1", + "0x4ea", + "0x4e3", + "0x59b", + "0x58b", + "0x549", + "0x57c", + "0x574", + "0x669", + "0x659", + "0x648", + "0x636", + "0x623", + "0x5db", + "0x611", + "0x609", + "0x71d", + "0x70c", + "0x6fa", + "0x6e7", + "0x6a5", + "0x6d5", + "0x6cc", + "0x793", + "0x784", + "0x74e", + "0x776", + "0x76f", + "0x807", + "0x7f8", + "0x7c2", + "0x7ea", + "0x7e3", + "0x87b", + "0x86c", + "0x836", + "0x85e", + "0x857", + "0x8ef", + "0x8e0", + "0x8aa", + "0x8d2", + "0x8cb", + "0x94d", + "0x919", + "0x940", + "0x939", + "0x9ab", + "0x977", + "0x99e", + "0x997", + "0xa09", + "0x9d5", + "0x9fc", + "0x9f5", + "0xa6f", + "0xa33", + "0xa62", + "0xa5b", + "0xad5", + "0xa99", + "0xac8", + "0xac1", + "0xb3b", + "0xaff", + "0xb2e", + "0xb27", + "0xba1", + "0xb65", + "0xb94", + "0xb8d", + "0xbfa", + "0xbcb", + "0xbed", + "0xc48", + "0xc24", + "0xc3b", + "0xcad", + "0xc72", + "0xca0", + "0xc99", + "0xd12", + "0xcd7", + "0xd05", + "0xcfe", + "0xd78", + "0xd3c", + "0xd6b", + "0xd64", + "0xde7", + "0xdd8", + "0xda7", + "0xdca", + "0xe35", + "0xe11", + "0xe28", + "0xe83", + "0xe5f", + "0xe76", + "0xef2", + "0xee3", + "0xeb2", + "0xed5", + "0xf9e", + "0xf8d", + "0xf84", + "0xf73", + "0xf2f", + "0xf63", + "0xf5b", + "0x102b", + "0x101c", + "0x100c", + "0xfd4", + "0xffd", + "0xff6", + "0x1041", + "0x1046", + "0x1062", + "0x105c", + "0x1187", + "0x1176", + "0x116c", + "0x10ab", + "0x10c2", + "0x10bb", + "0x10c0", + "0x10db", + "0x10d3", + "0x10d8", + "0x10e1", + "0x1104", + "0x10f0", + "0x1107", + "0x115f", + "0x113a", + "0x1157", + "0xde", + "0xdf", + "0xe0", + "0xe1", + "0xe2", + "0xe3", + "0x1282", + "0x1270", + "0x1265", + "0x11d8", + "0x11ef", + "0x11e8", + "0x11ed", + "0x1208", + "0x1200", + "0x1205", + "0x120e", + "0x1230", + "0x121d", + "0x1233", + "0xe5", + "0xe6", + "0xe7", + "0xe8", + "0x125b", + "0xe9", + "0xea", + "0xec", + "0xed", + "0xee", + "0x1253", + "0xef", + "0xf0", + "0xf1", + "0xf3", + "0xf4", + "0x12a7", + "0xf5", + "0xf6", + "0xf7", + "0xf8", + "0x12b4", + "0x12b9", + "0x12c3", + "0xf9", + "0xfa", + "0xfb", + "0x12d2", + "0x12d7", + "0x12f3", + "0xfc", + "0x12ed", + "0xfd", + "0xfe", + "0xff", + "0x100", + "0x102", + "0x131c", + "0x1310", + "0x1314", + "0x103", + "0x104", + "0x105", + "0x106", + "0x107", + "0x108", + "0x109", + "0x10a", + "0x13ca", + "0x10b", + "0x13be", + "0x133d", + "0x1342", + "0x13ae", + "0x10c", + "0x10d", + "0x13a6", + "0x10e", + "0x1355", + "0x135a", + "0x1396", + "0x138e", + "0x10f", + "0x110", + "0x1384", + "0x112", + "0x1378", + "0x113", + "0x114", + "0x115", + "0x116", + "0x117", + "0x118", + "0x11a", + "0x11b", + "0x11c", + "0x139f", + "0x13b7", + "0x11d", + "0x11e", + "0x11f", + "0x120", + "0x13f8", + "0x121", + "0x1414", + "0x162e", + "0x160f", + "0x122", + "0x123", + "0x15f7", + "0x124", + "0x125", + "0x126", + "0x1432", + "0x127", + "0x1448", + "0x1457", + "0x128", + "0x129", + "0x12a", + "0x12b", + "0x12c", + "0x15d8", + "0x12d", + "0x148f", + "0x12e", + "0x12f", + "0x130", + "0x131", + "0x132", + "0x133", + "0x134", + "0x135", + "0x136", + "0x137", + "0x15bc", + "0x138", + "0x139", + "0x13a", + "0x13b", + "0x13c", + "0x13d", + "0x13e", + "0x13f", + "0x140", + "0x141", + "0x142", + "0x143", + "0x144", + "0x15a0", + "0x145", + "0x1586", + "0x146", + "0x1578", + "0x147", + "0x148", + "0x1565", + "0x1552", + "0x149", + "0x1548", + "0x14a", + "0x14b", + "0x16d1", + "0x16c6", + "0x16bd", + "0x16f6", + "0x14c", + "0x14d", + "0x14e", + "0x14f", + "0x150", + "0x1705", + "0x1709", + "0x1722", + "0x151", + "0x171b", + "0x152", + "0x153", + "0x154", + "0x17d5", + "0x17ca", + "0x17b9", + "0x155", + "0x156", + "0x158", + "0x159", + "0x17af", + "0x1764", + "0x15a", + "0x15b", + "0x15c", + "0x15d", + "0x176f", + "0x15e", + "0x15f", + "0x1774", + "0x160", + "0x161", + "0x162", + "0x17a5", + "0x163", + "0x164", + "0x165", + "0x166", + "0x179c", + "0x167", + "0x168", + "0x169", + "0x16a", + "0x1794", + "0x16b", + "0x16c", + "0x16d", + "0x16e", + "0x16f", + "0x170", + "0x171", + "0x17f9", + "0x172", + "0x1a6b", + "0x1a5d", + "0x1a49", + "0x173", + "0x174", + "0x1a35", + "0x1841", + "0x1846", + "0x1865", + "0x175", + "0x176", + "0x177", + "0x178", + "0x1a21", + "0x18b6", + "0x179", + "0x17a", + "0x18a2", + "0x1887", + "0x17b", + "0x18bb", + "0x17c", + "0x17d", + "0x17e", + "0x17f", + "0x1a0d", + "0x180", + "0x181", + "0x182", + "0x194e", + "0x18da", + "0x18df", + "0x1939", + "0x184", + "0x185", + "0x1925", + "0x1910", + "0x186", + "0x187", + "0x188", + "0x189", + "0x1904", + "0x18a", + "0x1956", + "0x1a00", + "0x19f5", + "0x19e2", + "0x18c", + "0x198c", + "0x18d", + "0x19d7", + "0x18e", + "0x18f", + "0x19cd", + "0x190", + "0x19c5", + "0x19bd", + "0x191", + "0x1b50", + "0x1a9e", + "0x1ab5", + "0x192", + "0x1aae", + "0x1ab3", + "0x1ace", + "0x1ac6", + "0x1acb", + "0x1ad4", + "0x1af5", + "0x193", + "0x1ae3", + "0x1af8", + "0x194", + "0x1b45", + "0x1b29", + "0x195", + "0x1b3d", + "0x1c34", + "0x1b82", + "0x1b99", + "0x1b92", + "0x1b97", + "0x1bb2", + "0x1baa", + "0x1baf", + "0x1bb8", + "0x1bd9", + "0x1bc7", + "0x1bdc", + "0x196", + "0x1c29", + "0x1c0d", + "0x1c21", + "0x197", + "0x1dfc", + "0x1deb", + "0x1dd4", + "0x198", + "0x1dc8", + "0x199", + "0x19a", + "0x1db5", + "0x19c", + "0x19d", + "0x19e", + "0x1da2", + "0x19f", + "0x1a0", + "0x1a1", + "0x1a2", + "0x1a3", + "0x1a4", + "0x1ce5", + "0x1a5", + "0x1a6", + "0x1a7", + "0x1a8", + "0x1cd2", + "0x1a9", + "0x1aa", + "0x1ab", + "0x1cc6", + "0x1ad", + "0x1cbb", + "0x1ccd", + "0x1ae", + "0x1af", + "0x1b0", + "0x1b1", + "0x1b2", + "0x1b3", + "0x1ced", + "0x1b4", + "0x1d90", + "0x1b6", + "0x1b7", + "0x1d7e", + "0x1b8", + "0x1b9", + "0x1d6b", + "0x1ba", + "0x1bb", + "0x1bc", + "0x1d59", + "0x1bd", + "0x1be", + "0x1bf", + "0x1c0", + "0x1d4e", + "0x1c1", + "0x1c2", + "0x1c3", + "0x1d44", + "0x1d3b", + "0x1c4", + "0x1c5", + "0x1c7", + "0x1f86", + "0x1f7c", + "0x1f6c", + "0x1e6d", + "0x1e5d", + "0x1e46", + "0x1e72", + "0x1f5c", + "0x1f4c", + "0x1ee1", + "0x1ed1", + "0x1ec5", + "0x1ebd", + "0x1ecc", + "0x1ee9", + "0x1f3d", + "0x1f2e", + "0x1c8", + "0x1c9", + "0x1f1f", + "0x1ca", + "0x1cb", + "0x1cc", + "0x1cd", + "0x1f18", + "0x210c", + "0x2102", + "0x20f2", + "0x20e9", + "0x1fd3", + "0x1fd8", + "0x1fec", + "0x1ce", + "0x20d9", + "0x20c9", + "0x205e", + "0x204e", + "0x2042", + "0x203a", + "0x2049", + "0x2066", + "0x20ba", + "0x20ab", + "0x1cf", + "0x1d0", + "0x209c", + "0x1d1", + "0x1d2", + "0x1d3", + "0x1d4", + "0x2095", + "0x229e", + "0x2294", + "0x2284", + "0x2274", + "0x2183", + "0x2173", + "0x216d", + "0x1d5", + "0x2189", + "0x2264", + "0x2254", + "0x21f6", + "0x21e6", + "0x21da", + "0x21d2", + "0x21e1", + "0x21fe", + "0x224b", + "0x1d6", + "0x1d7", + "0x2242", + "0x2232", + "0x1d8", + "0x1d9", + "0x1da", + "0x222b", + "0x23cd", + "0x23c3", + "0x23b3", + "0x23a3", + "0x2393", + "0x2335", + "0x2325", + "0x2319", + "0x2311", + "0x2320", + "0x233d", + "0x238a", + "0x2381", + "0x2371", + "0x1db", + "0x1dc", + "0x1dd", + "0x236a", + "0x2533", + "0x2528", + "0x2517", + "0x2506", + "0x24f5", + "0x1de", + "0x242e", + "0x1df", + "0x24e5", + "0x24d5", + "0x24c4", + "0x24b4", + "0x1e0", + "0x1e1", + "0x1e2", + "0x24ab", + "0x24a3", + "0x249c", + "0x248e", + "0x264c", + "0x2643", + "0x2634", + "0x2625", + "0x2615", + "0x2590", + "0x2606", + "0x25f7", + "0x25e8", + "0x1e3", + "0x1e4", + "0x1e5", + "0x25e1", + "0x25d3", + "0x27af", + "0x27a6", + "0x2797", + "0x2788", + "0x2779", + "0x26ad", + "0x276a", + "0x275b", + "0x271d", + "0x270e", + "0x2702", + "0x26fb", + "0x2709", + "0x2725", + "0x274d", + "0x273f", + "0x27cb", + "0x27e5", + "0x27ff", + "0x281b", + "0x1e6", + "0x1e7", + "0x1e8", + "0x1e9", + "0x1ea", + "0x1eb", + "0x1ec", + "0x1ed", + "0x1ee", + "0x1ef", + "0x1f0", + "0x1f1", + "0x1f2", + "0x1f3", + "0x1f4", + "0x1f5", + "0x1f6", + "0x286c", + "0x1f7", + "0x1f8", + "0x1f9", + "0x1fa", + "0x1fb", + "0x2889", + "0x28bc", + "0x28b2", + "0x1fc", + "0x1fd", + "0x1fe", + "0x1ff", + "0x200", + "0x201", + "0x202", + "0x203", + "0x28d8", + "0x2921", + "0x28e5", + "0x2920", + "0x204", + "0x28f2", + "0x291f", + "0x205", + "0x28ff", + "0x291e", + "0x206", + "0x290c", + "0x291d", + "0x207", + "0x2917", + "0x291c", + "0x292a", + "0x292e", + "0x295c", + "0x294d", + "0x208", + "0x2979", + "0x297e", + "0x2992", + "0x29fd", + "0x29ed", + "0x29dd", + "0x209", + "0x20a", + "0x20b", + "0x29d5", + "0x29ce", + "0x20c", + "0x20d", + "0x2a53", + "0x2a1e", + "0x20e", + "0x20f", + "0x2a4b", + "0x211", + "0x212", + "0x2a41", + "0x213", + "0x2a3b", + "0x214", + "0x215", + "0x2a74", + "0x216", + "0x217", + "0x218", + "0x219", + "0x21a", + "0x21b", + "0x21c", + "0x21d", + "0x21e", + "0x2a8c", + "0x21f", + "0x220", + "0x221", + "0x222", + "0x223", + "0x224", + "0x31d2", + "0x225", + "0x226", + "0x227", + "0x2ad1", + "0x228", + "0x229", + "0x2ac6", + "0x31a3", + "0x22a", + "0x22b", + "0x22c", + "0x31c0", + "0x22d", + "0x22e", + "0x22f", + "0x230", + "0x231", + "0x232", + "0x3198", + "0x233", + "0x2c70", + "0x2b7e", + "0x234", + "0x2b6a", + "0x235", + "0x236", + "0x237", + "0x2b56", + "0x238", + "0x2b43", + "0x2b31", + "0x2b86", + "0x239", + "0x2c5d", + "0x2bab", + "0x23a", + "0x2bc2", + "0x2bc7", + "0x2bdd", + "0x2c51", + "0x2c03", + "0x2c08", + "0x2c1e", + "0x23b", + "0x2c48", + "0x2c3d", + "0x23c", + "0x23d", + "0x2e19", + "0x2cf6", + "0x2ce2", + "0x2cce", + "0x2cbb", + "0x2ca9", + "0x2cfe", + "0x2d1c", + "0x2e0e", + "0x2d42", + "0x2d47", + "0x2d5d", + "0x2dfb", + "0x2de0", + "0x2d8a", + "0x2d8f", + "0x2dac", + "0x2dd7", + "0x2dcc", + "0x23e", + "0x2fa8", + "0x2e9e", + "0x23f", + "0x2e8a", + "0x2e76", + "0x2e63", + "0x2e51", + "0x2ea6", + "0x2f95", + "0x2ecb", + "0x2f14", + "0x2f01", + "0x2ee7", + "0x2f19", + "0x240", + "0x241", + "0x242", + "0x243", + "0x244", + "0x246", + "0x247", + "0x248", + "0x249", + "0x24a", + "0x2f89", + "0x24b", + "0x24c", + "0x24d", + "0x24f", + "0x250", + "0x251", + "0x252", + "0x253", + "0x254", + "0x255", + "0x256", + "0x258", + "0x259", + "0x25a", + "0x2f3b", + "0x25b", + "0x25c", + "0x25d", + "0x25e", + "0x2f40", + "0x25f", + "0x260", + "0x261", + "0x262", + "0x2f56", + "0x263", + "0x264", + "0x265", + "0x266", + "0x267", + "0x268", + "0x269", + "0x26a", + "0x26c", + "0x26d", + "0x26e", + "0x26f", + "0x270", + "0x271", + "0x2f80", + "0x272", + "0x273", + "0x274", + "0x2f75", + "0x275", + "0x276", + "0x277", + "0x278", + "0x279", + "0x27a", + "0x27b", + "0x27c", + "0x27d", + "0x27e", + "0x27f", + "0x281", + "0x282", + "0x283", + "0x284", + "0x285", + "0x286", + "0x287", + "0x288", + "0x289", + "0x3160", + "0x28a", + "0x28b", + "0x302c", + "0x28c", + "0x28e", + "0x28f", + "0x290", + "0x291", + "0x292", + "0x293", + "0x294", + "0x295", + "0x296", + "0x297", + "0x298", + "0x299", + "0x29a", + "0x29b", + "0x3018", + "0x29c", + "0x29d", + "0x29e", + "0x29f", + "0x2a0", + "0x2a1", + "0x3004", + "0x2a3", + "0x2a4", + "0x2a5", + "0x2a6", + "0x2a7", + "0x2ff1", + "0x2a8", + "0x2a9", + "0x2aa", + "0x2ab", + "0x2ac", + "0x2ad", + "0x2fdf", + "0x2ae", + "0x2b0", + "0x2b1", + "0x2b2", + "0x2b3", + "0x2b4", + "0x2b5", + "0x3034", + "0x2b6", + "0x2b7", + "0x2b8", + "0x2b9", + "0x2ba", + "0x2bb", + "0x2bc", + "0x2bd", + "0x2be", + "0x2bf", + "0x2c0", + "0x2c1", + "0x2c2", + "0x2c3", + "0x2c4", + "0x3052", + "0x2c5", + "0x2c6", + "0x2c7", + "0x2c8", + "0x2c9", + "0x2ca", + "0x2cb", + "0x2cc", + "0x2cd", + "0x2ce", + "0x2cf", + "0x2d0", + "0x2d1", + "0x2d2", + "0x2d3", + "0x2d4", + "0x2d5", + "0x2d6", + "0x2d7", + "0x2d8", + "0x3155", + "0x2d9", + "0x2da", + "0x2db", + "0x2dc", + "0x2dd", + "0x2de", + "0x2df", + "0x2e0", + "0x2e1", + "0x2e2", + "0x2e3", + "0x2e4", + "0x2e5", + "0x2e6", + "0x2e7", + "0x2e8", + "0x3078", + "0x2ea", + "0x2eb", + "0x2ec", + "0x307d", + "0x2ed", + "0x2ee", + "0x2ef", + "0x2f0", + "0x3093", + "0x2f1", + "0x2f2", + "0x2f3", + "0x2f4", + "0x2f5", + "0x2f6", + "0x2f7", + "0x2f8", + "0x2f9", + "0x2fa", + "0x2fb", + "0x2fc", + "0x2fd", + "0x2fe", + "0x2ff", + "0x300", + "0x301", + "0x302", + "0x303", + "0x304", + "0x305", + "0x306", + "0x3142", + "0x307", + "0x308", + "0x309", + "0x30a", + "0x30b", + "0x30c", + "0x30d", + "0x30e", + "0x30f", + "0x310", + "0x311", + "0x312", + "0x313", + "0x3127", + "0x30f0", + "0x315", + "0x316", + "0x317", + "0x318", + "0x319", + "0x31a", + "0x31b", + "0x30dd", + "0x31d", + "0x31e", + "0x31f", + "0x320", + "0x321", + "0x322", + "0x323", + "0x324", + "0x325", + "0x30c3", + "0x326", + "0x327", + "0x328", + "0x329", + "0x30f5", + "0x32a", + "0x32c", + "0x32d", + "0x32e", + "0x32f", + "0x330", + "0x331", + "0x332", + "0x333", + "0x334", + "0x335", + "0x336", + "0x337", + "0x338", + "0x339", + "0x311e", + "0x33a", + "0x33c", + "0x3113", + "0x33d", + "0x33e", + "0x33f", + "0x340", + "0x341", + "0x342", + "0x344", + "0x345", + "0x346", + "0x347", + "0x348", + "0x349", + "0x34a", + "0x34b", + "0x34c", + "0x34d", + "0x34e", + "0x34f", + "0x350", + "0x351", + "0x352", + "0x353", + "0x354", + "0x355", + "0x356", + "0x357", + "0x358", + "0x359", + "0x35a", + "0x35b", + "0x35c", + "0x35d", + "0x317a", + "0x35e", + "0x35f", + "0x360", + "0x361", + "0x317f", + "0x362", + "0x363", + "0x364", + "0x365", + "0x3195", + "0x366", + "0x367", + "0x368", + "0x369", + "0x36a", + "0x36b", + "0x36c", + "0x31a0", + "0x36d", + "0x36e", + "0x36f", + "0x370", + "0x371", + "0x372", + "0x373", + "0x31b7", + "0x375", + "0x376", + "0x377", + "0x378", + "0x379", + "0x37a", + "0x37b", + "0x31fb", + "0x323e", + "0x3224", + "0x3229", + "0x3235", + "0x3292", + "0x3256", + "0x325b", + "0x3284", + "0x327d", + "0x3277", + "0x328b", + "0x32da", + "0x32b2", + "0x32d0", + "0x32ca", + "0x3372", + "0x3367", + "0x330c", + "0x335c", + "0x333b", + "0x3331", + "0x3335", + "0x334c", + "0x3354", + "0x338e", + "0x3387", + "0x339a", + "0x339f", + "0x33a8", + "0x33ad", + "0x33d7", + "0x33d1", + "0x33c9", + "0x33f1", + "0x3423", + "0x3418", + "0x341d", + "0x3428", + "0x3434", + "0x344e", + "0x34c4", + "0x34de", + "0x34e3", + "0x34ef", + "0x350d", + "0x3512", + "0x352e", + "0x3521", + "0x353f", + "0x357f", + "0x3565", + "0x356a", + "0x3576", + "0x35de", + "0x35a5", + "0x35aa", + "0x35d6", + "0x35cf", + "0x35c1", + "0x3624", + "0x35f5", + "0x35fa", + "0x3616", + "0x3610", + "0x361d", + "0x363f", + "0x3644", + "0x364e", + "0x3661", + "0x3666", + "0x3670", + "0x3683", + "0x3688", + "0x3692", + "0x36bb", + "0x36ad", + "0x36c1", + "0x36cc", + "0x36e7", + "0x36ec", + "0x36fd", + "0x3702", + "0x370c", + "0x374f", + "0x3735", + "0x373a", + "0x3746", + "0x37b3", + "0x3765", + "0x376a", + "0x37a8", + "0x3791", + "0x37a2", + "0x3860", + "0x3855", + "0x37e7", + "0x384a", + "0x381b", + "0x3815", + "0x383d", + "0x3842", + "0x3837", + "0x387e", + "0x3883", + "0x389a", + "0x3925", + "0x3917", + "0x390a", + "0x38fe", + "0x3951", + "0x394a", + "0x39a7", + "0x399f", + "0x3992", + "0x398a", + "0x397f", + "0x39d3", + "0x39f3", + "0x3a13", + "0x39bd", + "0x39c4", + "0x39cb", + "0x39d1", + "0x3a32", + "0x39dc", + "0x39e4", + "0x39eb", + "0x39f1", + "0x39fc", + "0x3a03", + "0x3a0b", + "0x3a11", + "0x3a1c", + "0x3a23", + "0x3a2a", + "0x3a31", + "0x3a55", + "0x3a4d", + "0x3a9e", + "0x3a84", + "0x3a89", + "0x3a95", + "0x3ab6", + "0x3abb", + "0x3ac5", + "0x3adc", + "0x3ae1", + "0x3aeb", + "0x3b01", + "0x3b06", + "0x3b10", + "0x3b53", + "0x3b39", + "0x3b3e", + "0x3b4a", + "0x3b97", + "0x3b7d", + "0x3b82", + "0x3b8e", + "0x3bae", + "0x3bb3", + "0x3bbd", + "0x3c00", + "0x3be6", + "0x3beb", + "0x3bf7", + "0x3c17", + "0x3c1c", + "0x3c26", + "0x3c69", + "0x3c4f", + "0x3c54", + "0x3c60", + "0x3c77", + "0x3c7b", + "0x3c86", + "0x3cc7", + "0x3cad", + "0x3cb2", + "0x3cbe", + "0x3d0b", + "0x3cf1", + "0x3cf6", + "0x3d02", + "0x3d4f", + "0x3d35", + "0x3d3a", + "0x3d46", + "0x3d93", + "0x3d79", + "0x3d7e", + "0x3d8a", + "0x3dbe", + "0x3db0", + "0x3dc4", + "0x3dcf", + "0x3df9", + "0x3deb", + "0x3dff", + "0x3e0a", + "0x3e1f", + "0x3e2c", + "0x3e39", + "0x3e45", + "0x3e83", + "0x3e69", + "0x3e6e", + "0x3e7a", + "0x3ec7", + "0x3ebd", + "0x3eb5", + "0x3eab", + "0x3ed8", + "0x3edd", + "0x3ee7", + "0x3ef4", + "0x4045", + "0x3f29", + "0x3f40", + "0x3f39", + "0x3f3e", + "0x3f8b", + "0x3f54", + "0x3f61", + "0x3f7a", + "0x3f6a", + "0x3ffa", + "0x3f9e", + "0x3fac", + "0x3fb9", + "0x3fd6", + "0x403d", + "0x4034", + "0x4024", + "0x4015", + "0x400b", + "0x4053", + "0x4057", + "0x4062", + "0x4087", + "0x4113", + "0x4108", + "0x40fc", + "0x40e7", + "0x40dc", + "0x40f4", + "0x413e", + "0x418f", + "0x4184", + "0x4179", + "0x4213", + "0x41aa", + "0x41af", + "0x4207", + "0x41e4", + "0x41dd", + "0x4200", + "0x4237", + "0x4250", + "0x425e", + "0x426c", + "0x427a", + "0x4288", + "0x4295", + "0x42a3", + "0x42b1", + "0x42bf", + "0x42cd", + "0x42db", + "0x42e8", + "0x424a", + "0x37c", + "0x37d", + "0x37e", + "0x37f", + "0x380", + "0x381", + "0x382", + "0x383", + "0x384", + "0x42f5", + "0x385", + "0x4315", + "0x4371", + "0x386", + "0x4340", + "0x387", + "0x388", + "0x389", + "0x38a", + "0x4365", + "0x4359", + "0x38b", + "0x38c", + "0x38d", + "0x438e", + "0x38e", + "0x38f", + "0x390", + "0x391", + "0x392", + "0x393", + "0x394", + "0x43a8", + "0x395", + "0x4405", + "0x43be", + "0x43c3", + "0x396", + "0x43f6", + "0x397", + "0x43ec", + "0x43e5", + "0x398", + "0x399", + "0x39a", + "0x39b", + "0x39c", + "0x39d", + "0x39e", + "0x441c", + "0x4429", + "0x442e", + "0x4454", + "0x444a", + "0x444f", + "0x3a0", + "0x3a1", + "0x4462", + "0x3a2", + "0x3a3", + "0x4474", + "0x4480", + "0x4485", + "0x3a4", + "0x448c", + "0x3a5", + "0x44a9", + "0x44ae", + "0x44bc", + "0x3a6", + "0x44ce", + "0x44e0", + "0x455d", + "0x3a8", + "0x3a9", + "0x4552", + "0x3aa", + "0x3ab", + "0x3ac", + "0x4546", + "0x3ad", + "0x3ae", + "0x3af", + "0x4504", + "0x3b0", + "0x3b1", + "0x3b2", + "0x3b3", + "0x4517", + "0x452a", + "0x4528", + "0x3b4", + "0x4531", + "0x4540", + "0x453e", + "0x3b5", + "0x45c6", + "0x45b6", + "0x3b7", + "0x45a9", + "0x3b8", + "0x3b9", + "0x3ba", + "0x459e", + "0x3bb", + "0x4593", + "0x3bc", + "0x3bd", + "0x3be", + "0x3bf", + "0x3c0", + "0x3c1", + "0x3c2", + "0x3c3", + "0x3c4", + "0x45d7", + "0x462a", + "0x461d", + "0x4613", + "0x460a", + "0x3c5", + "0x3c7", + "0x3c8", + "0x3c9", + "0x3ca", + "0x3cb", + "0x3cc", + "0x3cd", + "0x3ce", + "0x464d", + "0x3cf", + "0x3d0", + "0x3d1", + "0x3d2", + "0x3d3", + "0x4668", + "0x3d4", + "0x3d5", + "0x466d", + "0x3d6", + "0x3d7", + "0x4674", + "0x3d8", + "0x3d9", + "0x4687", + "0x4730", + "0x3da", + "0x3db", + "0x469b", + "0x3dc", + "0x3dd", + "0x3de", + "0x46a0", + "0x3df", + "0x3e0", + "0x3e1", + "0x4725", + "0x3e2", + "0x3e3", + "0x3e4", + "0x3e5", + "0x3e6", + "0x3e7", + "0x3e8", + "0x4718", + "0x470c", + "0x3e9", + "0x46f0", + "0x46e5", + "0x46db", + "0x46f5", + "0x3ea", + "0x3eb", + "0x4706", + "0x3ec", + "0x3ed", + "0x3ee", + "0x3ef", + "0x4746", + "0x3f0", + "0x3f1", + "0x474a", + "0x3f2", + "0x3f3", + "0x3f4", + "0x4755", + "0x3f5", + "0x3f6", + "0x3f7", + "0x3f8", + "0x3f9", + "0x4761", + "0x3fa", + "0x4771", + "0x3fb", + "0x3fc", + "0x3fd", + "0x3fe", + "0x47b1", + "0x3ff", + "0x478a", + "0x478f", + "0x47a7", + "0x47a1", + "0x400", + "0x401", + "0x402", + "0x403", + "0x404", + "0x406", + "0x47ed", + "0x407", + "0x408", + "0x409", + "0x40a", + "0x40b", + "0x40c", + "0x40d", + "0x40e", + "0x40f", + "0x410", + "0x411", + "0x412", + "0x413", + "0x414", + "0x415", + "0x416", + "0x48ad", + "0x417", + "0x418", + "0x419", + "0x48bd", + "0x48cd", + "0x41a", + "0x41b", + "0x41c", + "0x41d", + "0x48c8", + "0x48cb", + "0x41e", + "0x48d4", + "0x48da", + "0x41f", + "0x420", + "0x48e6", + "0x48e9", + "0x48f0", + "0x421", + "0x422", + "0x48fd", + "0x423", + "0x424", + "0x4901", + "0x425", + "0x426", + "0x427", + "0x490c", + "0x428", + "0x429", + "0x42a", + "0x42b", + "0x42c", + "0x42d", + "0x491c", + "0x42e", + "0x42f", + "0x492f", + "0x430", + "0x431", + "0x4952", + "0x49a7", + "0x4970", + "0x4975", + "0x4998", + "0x4991", + "0x432", + "0x433", + "0x435", + "0x436", + "0x49be", + "0x437", + "0x438", + "0x439", + "0x43a", + "0x43c", + "0x49d6", + "0x43d", + "0x43e", + "0x49dc", + "0x43f", + "0x440", + "0x48d", + "0x527", + "0x5aa", + "0x678", + "0x72d", + "0x7a1", + "0x815", + "0x889", + "0x8fd", + "0x95b", + "0x9b9", + "0xa17", + "0xa7d", + "0xae3", + "0xb49", + "0xbaf", + "0xc08", + "0xc56", + "0xcbb", + "0xd20", + "0xd86", + "0xdf5", + "0xe43", + "0xe91", + "0xf00", + "0xfae", + "0x1039", + "0x106c", + "0x1191", + "0x1196", + "0x128d", + "0x12ad", + "0x12ca", + "0x12fd", + "0x1324", + "0x13d6", + "0x1646", + "0x16dc", + "0x16fe", + "0x1710", + "0x1728", + "0x17df", + "0x17ff", + "0x1a78", + "0x1b59", + "0x1c3d", + "0x1e0c", + "0x1f8f", + "0x2115", + "0x22a7", + "0x23d6", + "0x253d", + "0x2654", + "0x27b7", + "0x27d1", + "0x27eb", + "0x2805", + "0x2822", + "0x2838", + "0x283f", + "0x2856", + "0x2873", + "0x2890", + "0x28c3", + "0x28cc", + "0x2922", + "0x292f", + "0x2964", + "0x2a0d", + "0x2a62", + "0x2a7a", + "0x2a92", + "0x31e4", + "0x3202", + "0x3246", + "0x32a1", + "0x32e9", + "0x337c", + "0x3394", + "0x33a0", + "0x33e1", + "0x33f7", + "0x343c", + "0x3454", + "0x34cd", + "0x34f8", + "0x3534", + "0x3543", + "0x3587", + "0x35e7", + "0x3632", + "0x3654", + "0x3676", + "0x3698", + "0x36d3", + "0x36ed", + "0x3713", + "0x3757", + "0x37c1", + "0x386a", + "0x3932", + "0x3958", + "0x39b2", + "0x3a33", + "0x3a5d", + "0x3a63", + "0x3aa6", + "0x3acc", + "0x3af2", + "0x3b17", + "0x3b5b", + "0x3b9f", + "0x3bc4", + "0x3c08", + "0x3c2d", + "0x3c71", + "0x3c8b", + "0x3ccf", + "0x3d13", + "0x3d57", + "0x3d9b", + "0x3dd6", + "0x3e11", + "0x3e47", + "0x3e8b", + "0x3ed1", + "0x3eed", + "0x3eff", + "0x404d", + "0x4067", + "0x411e", + "0x419a", + "0x4224", + "0x4227", + "0x42ef", + "0x42fb", + "0x431b", + "0x437c", + "0x4394", + "0x43a2", + "0x43ae", + "0x4416", + "0x4422", + "0x445b", + "0x446b", + "0x446e", + "0x447a", + "0x4486", + "0x4492", + "0x4495", + "0x44af", + "0x4567", + "0x45d1", + "0x45dd", + "0x45e3", + "0x4637", + "0x463a", + "0x463d", + "0x4640", + "0x4643", + "0x4646", + "0x4656", + "0x4659", + "0x465c", + "0x465f", + "0x4662", + "0x466e", + "0x467a", + "0x467e", + "0x4681", + "0x468d", + "0x4740", + "0x475a", + "0x476a", + "0x477c", + "0x47bf", + "0x47d0", + "0x47f4", + "0x4804", + "0x4814", + "0x481d", + "0x4826", + "0x482b", + "0x4834", + "0x483d", + "0x4846", + "0x484f", + "0x4857", + "0x485f", + "0x48b6", + "0x48ce", + "0x48ea", + "0x48f7", + "0x4911", + "0x4928", + "0x4938", + "0x4958", + "0x4962", + "0x49b7", + "0x49c7", + "0x49df", + "0x26655", + "0xc00800700b00500200a009009009009008007006005004003002001000", + "0x1300401201100901100901000700600c00400f00e00900900900d007006", + "0x901d00701900500401c01b00901a007019005018009017016015009014", + "0x900800702200502100700b00501500902000901f00900800701e005015", + "0x902900700600c01800902802702600902500902400702200c018009023", + "0xc02e00901702d00900902c00901500902b00701e00500402a009009009", + "0x900800701900503100901701602e00901401300e00903000902f007006", + "0x1603700901401303600901703500403402600903300903200702200c011", + "0x701900501500901702d03b00902802703a009039007019005038009017", + "0x904100904000700600c00403f02600903e00903d00702200c03c009008", + "0x904400701900502600904300904200702200c009009008007019005041", + "0x904900904800702200c00e009009009009009047009008007046005045", + "0x904100904d00702200c01800904c00904b00702200c04a00901702d026", + "0x702200c02c00902c00904f00700600c00e00904100904e00700600c018", + "0x502600905400905300702200c05200900800705100501800900e009050", + "0x705100501800905700905600702200c01500901500902c00905500701e", + "0x905c00700600c05b00901702d02600905a00905900702200c058009008", + "0x901500906100702200c01800906000905f00702200c00405e00e00905d", + "0x702200c00e00906400906300700600c00e00900e00906200700600c018", + "0x906600702200c01500902000903b00900800701e00501800901f009065", + "0x701e00500406b00406a00406901800906400906800702200c026009067", + "0x702200c06f00900800701900506e00901702d06d00902c00902c00906c", + "0xc07200900800701900501f00901f009008007006005026009071009070", + "0x1300e00907600907500700600c01f00901702d026009074009073007022", + "0x901800901800900800707900507800902802707700901701601f009014", + "0x701900501500901500907c00700600502600907b00907a00702200c00e", + "0x501500902c00908000700600507f00901500907e00700600507800907d", + "0x501500908300701900501500908200701900501500902c009081007006", + "0x908700701900501500908600701900501500908500701900508400700b", + "0xc01500908a007019005015009089007019005060009088007019005015", + "0x909400909300909200909100909000908f00908e00908d00908c00708b", + "0x901500907700903b00900800709a005099009098009097009096009095", + "0x1601800901500906d00909d00707900502600909c00909b00702200c00e", + "0x902802702600909f00909e00702200c05d009008007019005037009017", + "0x906d0090a300906f0090a20070a10050a000901702d05b009028027041", + "0x702200c0260090a50090a400702200c04c00900800701900501500906d", + "0x90a90090a800702200c0a700901f00900800702200500e0090370090a6", + "0x90ae0090ad00702200c00e0090ac0090080070ab0050aa00700b005026", + "0x90b20090b100702200c00e0090b00090080070ab0050af00700b005026", + "0x90b60090b500702200c00e0090b40090080070ab0050b300700b005026", + "0x90ba0090b900702200c00e0090b80090080070ab0050b700700b005026", + "0x90be0090bd00702200c00e0090bc0090080070ab0050bb00700b005026", + "0x90c20090c100702200c00e0090c00090080070ab0050bf00700b005026", + "0xc0c400900800701900500e00900e00900e00900e0090c300704600c026", + "0x70060050c70090280270150090080070190050260090c60090c5007022", + "0x70ab0050ca00700b0050260090c90090c800702200c00e00903b009008", + "0xc0600090080070190050260090cd0090cc00702200c00e0090cb009008", + "0x702200c0180090080070510050380090280270260090cf0090ce007022", + "0x702200c00e0090080070d30050600090d20070190050260090d10090d0", + "0x90080070ab0050d700700b0050600090d60070190050260090d50090d4", + "0x90150090150090db00701e0050260090da0090d900702200c00e0090d8", + "0x90de00700600c0260090dd0090dc00702200c02c009008007019005015", + "0xc0260090e10090e000702200c0df00901f00900800700600500e00903b", + "0x2706d00902802700e00906d0090e300700600c00e00902c0090e2007006", + "0x90280270260090e50090e400702200c07700900800705100502c009028", + "0x901500901500901500901f00900900906d0090150090e600708b005077", + "0x702200c0a300900800701900501f00904100904100901f009009009047", + "0x90e900702200c06d0090080070190050150090170350260090e80090e7", + "0x50c400905700900800700600500e00903c0090eb00700600c0260090ea", + "0xc0410090080070190050260090ee0090ed00702200c0ec009008007019", + "0x70190050110090110090110090f100701e0050260090f00090ef007022", + "0x90b40090cb0090f50070f40050260090f30090f200702200c057009008", + "0xc00e0090f60090080070ab0050bc0090b80090d80090c00090ac0090b0", + "0x90f900702200c0180090f60090080070220050260090f80090f7007022", + "0x900800701900506000902802700e0090600090fb00700600c0260090fa", + "0x901500906d0090ff0070a10050020fe0260090fd0090fc00702200c064", + "0x901f00900800700600500e00910100910000700600c03b00902c00902c", + "0x2710600902802700210510100902802702600910400910300702200c102", + "0x500e00901800910900702200c0260090c700910800702200c107009028", + "0x910d00700600c02600910c00910b00702200c10a00901f009008007022", + "0x910e00702200c00e00901800900800702200501500902802700e009015", + "0x11202600911100911000702200c0770090f600900800702200502600910f", + "0xc0150090f600900800700600501f009008007019005113009028027002", + "0x702200c02600911800911700702200c004116026009115009114007022", + "0x911c00911b00702200c11a00901f00900800702200500e009038009119", + "0x912212300900912200700900912200712100712000711f11e00211d026", + "0x912911a00900912711c00900912912800900912712612500912401f009", + "0x912f00712e00912d04100900912c04100900912b01500900912a01f009", + "0x13312e00913201500900913103800900912c007130041009009122041009", + "0x13700912e136026009009135023009009135015009009134015009009122", + "0x13900900912200713813700900912211300900912210600900912200912e", + "0x91350ac0090091350b00090091350b40090091350cb00900913500713a", + "0x91220f60090091350bc0090091350b80090091350d80090091350c0009", + "0x912b0f600900912c11500900912913b00900912703c125009124038009", + "0x912b00e00900912c03e12500912401800900912201500900912c015009", + "0x712e13700912e13611800900913501f00900913501800900912c018009", + "0x912c00713f11300900913e13d12e00913201f00900912c13c12e009132", + "0x912b111009009129143009009127113009009142141125009124140009", + "0x912914400900912704112500912407800900912207700900912c077009", + "0x912401500900914214600900912714512500912401500900913e10f009", + "0x91240f600900912b10a00900912710c009009129147009009127043125", + "0x913e14b00900912c14a12e0091320c7009009129149009009127148125", + "0x912914c00900912704712500912410100900913e10600900913e107009", + "0x912c14e00900912c14d00900912c101009009142102009009127104009", + "0x9142106009009142049125009124101009009122107009009122101009", + "0x912915100900912704c12500912415012500912414f00900912c107009", + "0x913e15212500912406400900912206400900912c06400900912b0fd009", + "0x912206000900912c060009009142154009009127153125009124060009", + "0x912401b0090091220fa009009129156009009127155125009124060009", + "0x913215912500912405412500912405212500912415800900912c157125", + "0x91240f800900912c15c00900912705712500912415b12e00913215a12e", + "0x912415e12500912405d12500912415d12500912405a125009124058125", + "0x912416112500912406412500912416012500912415f125009124060125", + "0x912205700900912c05700900912b0f3009009129163009009127162125", + "0x912216500900912c16500900912b164125009124067125009124057009", + "0x912916900900912716812500912416712e009132166125009124165009", + "0xee00900912916c00900912706d12500912416b12500912400716a0f0009", + "0x6f12500912406e1250091240ec0090091220ec00900912c0ec00900912b", + "0x917000716f07212500912416e12500912407112500912416d12e009132", + "0x12e13600e00900913500717217100900912200712e17100912e136015009", + "0x1500900912f03700900913101500900917317100900912700912e171009", + "0x12e13612800900912200712e12800912e13611c009009135074125009124", + "0x912917500900912717412500912400912e11a00912e13600912e128009", + "0x712e00913200717606d00900912f06d00900912c06d00900912b0ea009", + "0xa00090091730e8009009129179009009127076125009124007178007177", + "0x12e13600717a12512e00913204700900912c00900900912c0a0009009129", + "0x912700712e06400912e13600912e00913217b00900912c00912e064009", + "0x912e13b00912e13617e12e00913217d12e00913217c12e009132064009", + "0x3b00900912203b00900913503800900912b17f12e00913213b009009122", + "0x13b00912e13611500900913518112e0091320f8009009129180125009124", + "0x912e14300912e13618300900912c07700900913e18212e00913200712e", + "0x770090091420e5009009129184009009127077125009124143009009122", + "0x11100900913507812500912408e00900912208e00900913507f009009135", + "0x912407f00900912201f00900912a07800900918500712e14300912e136", + "0x14400912e13614400900912200712e14400912e13610f009009135186125", + "0x912400912e14600912e13614600900912200712e14600912e13600912e", + "0x14700912e13614700900912200712e14700912e13610c00900913507b125", + "0x14900912e1360c700900913518712500912400912e10a00912e13600912e", + "0x6d00900913e02c00900913e00912e14900912e13614900900912200712e", + "0x18900900912707f12500912406d00900914218800900912708d125009124", + "0xdf0090091270e100900912918a00900912708e12500912402c009009142", + "0x712e14c00912e13610400900913500712e10200912e136101009009135", + "0x912e14c00912e13600912e10200912e13602c00900912c14c009009122", + "0x6d00900918510100900912918c00900912c00e00900912f18b00900912c", + "0xdd00900912918e00900912708f12500912406d00900912218d12e009132", + "0x912b0f600900912919012e00913203b00900912c00718f02c009009185", + "0xb400900912c0cb00900912c0071910901250091240150090091850d8009", + "0xac00900912c0c000900912c0d800900912c0b800900912c0bc00900912c", + "0x19312e00913202000900913510100900912b19212e0091320b000900912c", + "0x912b19700900913519612e00913219512e009132007194020009009129", + "0x912400e12e00913219700900912919700900912f19700900912c197009", + "0x912919800900912709312500912403b009009185092125009124091125", + "0x712e15100912e1360fd00900913519912e0091320da00900912c0da009", + "0x15400912e13600719a06400900912f00912e15100912e136151009009122", + "0x19b00900913506000900918500912e15400912e13615400900912200712e", + "0x15600912e13619d12e00913209412500912419b00900912219c12e009132", + "0x12e13605200900912200712e05200912e13600719e15600900912200912e", + "0x970090091350d500900912c19f00900912709512500912400912e052009", + "0x971250091241a00090091221a0009009135096125009124097009009122", + "0x913200712e15600912e1360fa0090091350d10090091291a1009009127", + "0x912b03800900913e09812500912401b0090091850ea00900912c1a212e", + "0x91240b000900912b1a412e0091321a300900912c0991250091240b4009", + "0x912b1a612e0091320ac00900912f09c1250091240ac00900912b1a5125", + "0x91a906000900912b0cf0090091291a80090091271a71250091240cb009", + "0x91350cd0090091291aa00900912705b12500912403712500912400712e", + "0x91420cd00900912c0f600900912f09f125009124098009009122098009", + "0x912c0c900900912c1ad0090091271ac1250091241ab12e009132038009", + "0x91321b01250091241af12e0091321ae12e00913212e12e00913203a009", + "0x91290a31250091240c000900912b1b21250091240c700900913e1b112e", + "0x912b0c60090091291b300900912704a12500912402c009009122057009", + "0xa51250091240c40090091220c400900912c00712e0c400912e1360c4009", + "0xc400912e1361b60090091271b512500912405700900913500712e0091b4", + "0x912c0a91250091240930090091350c20090091290a712500912412512e", + "0x12300900912f00700900912f15c00900912200912e15c00912e1361b7009", + "0x1ba0090091270ac1250091241b90090091271b812500912411300900912f", + "0x1bb0090091270c70090091420ae1250091240ba0090091290be009009129", + "0x990090091351bc1250091240940090091220940090091350b6009009129", + "0x912c00712e15c00912e1360f80090091350b0125009124099009009122", + "0x91350b20090091291bd0090091270b21250091240be00900912c0c7009", + "0x91270b41250091241be12e0091321bd125009124095009009122095009", + "0x91320b61250091240960090091220960090091350ae0090091291bc009", + "0x912408f00900912208f0090091351bb1250091241c012e0091b41bf12e", + "0x12e12e0c400912e1360ba1250091240900090091220900090091350b8125", + "0x920090091351ba1250091240910090091220910090091351c112e009132", + "0x912200712e16300912e1360f30090091350bc125009124092009009122", + "0x91c30071c202c00900912f05700900918500912e16300912e136163009", + "0x912916500900918516500900913500912e0091c312512e0091c300712e", + "0xf00090091350be1250091240071c401100900912f01100900912c165009", + "0x1b912500912400912e16900912e13616900900912200712e16900912e136", + "0x12e13616c00900912200712e16c00912e1360ee0090091350ec009009135", + "0x1c612e0091321c512e0091320c01250091240ec00900912900912e16c009", + "0x8d0090091351ca12e0091321c912e0091321c812e0091321c712e009132", + "0x11a00912e1360b200900912c0b600900912c0c212500912408d009009122", + "0x91340a70090091270a90090091291b80090091271b612500912400712e", + "0x912904a0090091730a50090091291b50090091270c4125009124037009", + "0x712e17500912e1360ea0090091350a300900912c06f00900912c04a009", + "0x712e17900912e1360e800900913500912e17500912e136175009009122", + "0x912904100900913e05b00900913e00912e17900912e136179009009122", + "0x91221b000900912c1b200900912c00912e00912d03700900912a03b009", + "0x914205b00900917309f0090091291ac0090091270c612500912403a009", + "0x912b1cc12e00913201b00900912c0370090091cb05b00900918505b009", + "0x912c0c71250091241b31250091240410090091420410090091850b8009", + "0x91321cf12e0091321ce12e0091321b71250091241cd12e00913205b009", + "0x91321d212e0091321d112e0091320c91250091240bc00900912b1d012e", + "0x91271ad12500912407700900912201f0090091311d412e0091321d312e", + "0x18400900912200712e18400912e1360e500900913509c0090091291a7009", + "0x91221a500900912c1a500900912b0cb12500912400912e18400912e136", + "0x1aa1250091240071d507b0090091291870090091270cd1250091241a5009", + "0x18000912e13601f00900917007f00900912907800900913e0d5009009129", + "0x18000900912707800900914200912e18000912e13618000900912200712e", + "0x7f00900912c18600900912c07800900912c0cf12500912401f009009173", + "0x91290740090091291740090091271a812500912400712e10a00912e136", + "0x12e13618800900912200712e18800912e1360071d60f6009009185072009", + "0x18900912e13618900900912200712e18900912e1360071d700912e188009", + "0x912200712e18a00912e1360e100900913500712e0df00912e13600912e", + "0x91271a312500912400912e18a00912e13600912e0df00912e13618a009", + "0x12e1360dd00900913506e00900912906e00900917307100900912916e009", + "0x71d80d112500912400912e18e00912e13618e00900912200712e18e009", + "0x912400912e16600912e13616600900912200712e16600912e1360071d9", + "0x91271a012500912402000900912203b00900912f1010090091851a1125", + "0x71dc1db12e00913202000900912c0670090091291da12e009132164009", + "0x19800912e13619800900912200712e19800912e1360da0090091350071dd", + "0x912200712e16200912e1360071df1de12e00913219b00900912900912e", + "0x1180090091291370090091270d512500912400912e16200912e136162009", + "0x19b1250091241e112e0091321e012e00913216100900912719f125009124", + "0x912e19f00912e13619f00900912200712e19f00912e1360d5009009135", + "0x912200712e1a100912e1360d10090091351a00090091290d8125009124", + "0x1680090091221e312e0091e21a000900912c00912e1a100912e1361a1009", + "0xda12500912400912e16000912e13616000900912200712e16000912e136", + "0x15f00912e1361981250091241e612e0091e21e512e0091e21e412e0091e2", + "0x1a800900912200912e1a800912e1361e712e00913215f00900912200712e", + "0x712e1a800912e1360cf00900913519712500912400912e15f00912e136", + "0x1aa00900912200712e1aa00912e1360cd0090091350071e806000900912f", + "0x712e15e00912e1360370090091700dd12500912400912e1aa00912e136", + "0x912405b00900912215e00900912700912e15e00912e13615e009009122", + "0xc90090091291ad00900912200912e1ad00912e1361e912e00913218e125", + "0x91e20df1250091241ea12e00913200712e1ad00912e1360c9009009135", + "0x912205a00900912915d0090091270e112500912416b0090091221eb12e", + "0x1b300912e1360c60090091350071ec02c00900912b18a125009124058009", + "0x912700912e0c400912e13600912e1b300912e1361b300900912200712e", + "0x912915900900912718812500912418912500912400e00900912b0c4009", + "0x1b600912e1361b600900912200712e1b600912e1360c2009009135054009", + "0x12e1360be0090091351ed12e0091e218c1250091240c400900912f00912e", + "0x91351ee12e0091e200912e1b900912e1361b900900912200712e1b9009", + "0x913500912e1ba00912e1361ba00900912200712e1ba00912e1360ba009", + "0x912400912e1bb00912e1361bb00900912200712e1bb00912e1360b6009", + "0x1bd00900912200712e1bd00912e1360b20090091350e512500912418b125", + "0x712e1bc00912e1360ae00900913518412500912400912e1bd00912e136", + "0x15700912e1360071ef18312500912400912e1bc00912e1361bc009009122", + "0xa01250091241f012e00913200912e15700912e13615700900912200712e", + "0x1751250091240ea12500912417b1250091241791250091240e8125009124", + "0x12e1361f112e00913215300900912200712e15300912e136155009009127", + "0xee12500912401800900912f0ec12500912417112500912400912e153009", + "0x712e1b800912e1360a900900913500712e0a700912e136037009009135", + "0x12e1360071f200912e1b800912e13600912e0a700912e1361b8009009122", + "0x913516c12500912400912e15200912e13615200900912200712e152009", + "0x91f300912e1b500912e1361b500900912200712e1b500912e1360a5009", + "0x1f412e0091321ac00900912200712e1ac00912e13609f009009135037009", + "0x71f71f612e0091f504700900912200900900912200912e1ac00912e136", + "0xf012500912400712e0091f51fa12e0091321f912e0091321f812e009132", + "0x148009009127169125009124009009009185049009009129150009009127", + "0x91320071fe1fd12e00912d1fc12e0091f50430090091291fb12e0091f5", + "0x912200712e14500912e13600720120012e00913204300900912c1ff12e", + "0x1f00900918516512500912420212e00913200912e14500912e136145009", + "0x1410090091270f312500912401b00900912f01f00900912b12e12e00912d", + "0x1a700912e13609c00900913500720401f00900913400720303e009009129", + "0x16312500912420512e00913200912e1a700912e1361a700900912200712e", + "0x91320f612500912420612e0091321a500900912700912e1a500912e136", + "0x20812e00913218700900912200912e18700912e1360f812500912420712e", + "0x15612500912420a12e0091320fa12500912420912e00913215c125009124", + "0x20d12e00913215812500912420c12e00913215412500912420b12e009132", + "0x10712500912420f12e00913215112500912420e12e0091320fd125009124", + "0x21212e00913210212500912421112e00913210112500912421012e009132", + "0x912f05200900912700712e18700912e13607b009009135104125009124", + "0x17400900912200912e17400912e13621312e00913200e12e00912d01f009", + "0x913500712e17400912e136074009009135072009009135015009009214", + "0x913200912e16e00912e13616e00900912200712e16e00912e136071009", + "0x14c12500912403b00900914203b00900913e16600900912700721621512e", + "0x912e16400912e13616400900912200712e16400912e136067009009135", + "0x912200712e16100912e13616200900912712600900912c020009009185", + "0x912716000900912701b12e1a500912e13600912e16100912e136161009", + "0x921a21900900912200721821712e00913201f12e1a500912e13615f009", + "0x14f12500912403600900912200721d21c12e00913221b12e009132036009", + "0x14d12500912410612500912403600900918500721f03600900912c00721e", + "0x912714e12500912401100900912200722001100900918516b009009185", + "0x15d00912e13605a00900913500712e05800912e136033009009129221009", + "0x15d00912e13616b00900912c00912e05800912e13615d00900912200712e", + "0x712e15900912e13605400900913505800900912722212e00913200912e", + "0x1a500912e13601112e1a500912e13600912e15900912e136159009009122", + "0x1812e1a500912e13622312e1a500912e13601512e1a500912e1361db12e", + "0x1a500912e13612512e1a500912e13612e12e1a500912e136157009009127", + "0x15500900912200712e15500912e1360072241fd12e1a500912e13600e12e", + "0x15200900912700712e1a500912e13615300900912700912e15500912e136", + "0x912204500900912200712e22500912e13602e009009170047009009129", + "0x2e00900917322500900912704700900913500912e22500912e136225009", + "0x912f00900902c00912e22602e00900912902e00900918502e009009122", + "0x15000900912200912e15000912e13622712e009132149125009124009009", + "0x22900912e13600722802e00900912c00712e15000912e136049009009135", + "0x10a12500912422a12e00913200912e22900912e13622900900912200712e", + "0x912e14800912e13614800900912200712e14800912e136043009009135", + "0x912200712e14100912e13603e0090091350150090091f3145009009127", + "0x8d00900912908d00900918501500900922b00912e14100912e136141009", + "0x10c12500912401800900914208e00900912908e00900918501800900913e", + "0x9100900912909000900912909000900918508f00900912908f009009185", + "0x9600900912909500900912909400900912909300900912c092009009129", + "0x146125009124099009009129098009009129147125009124097009009129", + "0x722f00722e1fd12e00913202500900912922d12e00913222c009009127", + "0x12e13600723400723300723221900900912c007231007230223009009122", + "0x912423512e00913200912e1db00912e1361db00900912200712e1db009", + "0x22100912e13622100900912200712e22100912e13603300900913514b125", + "0x918522900900912723612e0091321fd00900912710f12500912400912e", + "0x22c00900912200712e22c00912e13602500900913507f00900912f07f009", + "0x1441250091241250090091220072371db00900912700912e22c00912e136", + "0x1fd00900912200712e1fd00912e13600723812e00900912912e009009135", + "0x12e00712e00900700723b00900700700723a00723900912e1fd00912e136", + "0x91fd00912500700723b00900712e0072231db12e0be0111fd12e23b12e", + "0x700e00923b00900e0091fd00701100923b00901100900e0071fd00923b", + "0x1bd01500923b12e01f0091db00701f01b01812523b00900e0111fd125011", + "0x901800702302512e23b00901500922300700723b00900712e007020009", + "0x23b00902500901b00700723b00900712e00722c00909f02600923b12e023", + "0x702e02c12e23b00922900901500722900923b00923c00901f00723c009", + "0x12e23b00903000901500703000923b00900702500700723b00902c009020", + "0x902300704500923b00902e00902300700723b009225009020007031225", + "0x23b12e03304512e22c00704500923b00904500902600703300923b009031", + "0x900722900700723b00902600923c00700723b00900712e007007145007", + "0x3000703600923b00903600902e00703600923b00900702c00722100923b", + "0x921903812e03100703800923b00900722500721900923b00903622112e", + "0x701800923b00901800912500703b00923b00903a00904500703a00923b", + "0x912500922100701b00923b00901b00900e00700900923b009009009033", + "0x12e00703b12501b0090181fd00903b00923b00903b00903600712500923b", + "0x712600923b00912600903800712600923b00900721900700723b009007", + "0x723b00900712e00704114112e09003e03c12e23b12e12601b01812503a", + "0x923b00900703c00704300923b00900712600714500923b00900703b007", + "0x23b00900704100704900923b00900714100704700923b00900703e007148", + "0x14522314800715200923b00900704300704c00923b009007145007150009", + "0x703c00923b00903c00912500715300923b00915204c150049047148043", + "0x912500922100703e00923b00903e00900e00700900923b009009009033", + "0x2615312503e00903c01104900702600923b00902600904700712500923b", + "0x705800907805700923b12e1590091500071590540521571551fd23b009", + "0x15d12e23b00905700904c00705a00923b00900722900700723b00900712e", + "0x915500706015e12e23b00905d00915300700723b00915d00915200705d", + "0x5a00923b00905a00915700706000923b00906000902e00700723b00915e", + "0x915900700723b00916000905400716015f12e23b00905a06012e052007", + "0x923b00916100905800700723b00906400905700716106412e23b00915f", + "0x912500716400923b00906700915d00706700923b00916200905a007162", + "0x923b00905200900e00715700923b00915700903300715500923b009155", + "0x1551fd00916400923b00916400903600705400923b009054009221007052", + "0x12500716600923b00905800904500700723b00900712e007164054052157", + "0x23b00905200900e00715700923b00915700903300715500923b009155009", + "0x1fd00916600923b00916600903600705400923b009054009221007052009", + "0x22900700723b00902600923c00700723b00900712e007166054052157155", + "0x16b00923b00916b00902e00716b00923b00900705d00716800923b009007", + "0x6e12e03100706e00923b00900722500706d00923b00916b16812e030007", + "0x923b00914100912500707100923b00906f00904500706f00923b00906d", + "0x922100704100923b00904100900e00700900923b009009009033007141", + "0x711250410091411fd00907100923b00907100903600712500923b009125", + "0x723b00902500915e00700723b00922c00905400700723b00900712e007", + "0x23b00907200902e00707200923b00900706000716e00923b009007229007", + "0x3100717400923b00900722500707400923b00907216e12e030007072009", + "0x901800912500718000923b00907600904500707600923b00907417412e", + "0x701b00923b00901b00900e00700900923b00900900903300701800923b", + "0x1b0090181fd00918000923b00918000903600712500923b009125009221", + "0x1800912500707700923b00902000904500700723b00900712e007180125", + "0x1b00923b00901b00900e00700900923b00900900903300701800923b009", + "0x90181fd00907700923b00907700903600712500923b009125009221007", + "0x900722900700723b00900e00915e00700723b00900712e00707712501b", + "0x3000718600923b00918600902e00718600923b00900705d00707800923b", + "0x907b18712e03100718700923b00900722500707b00923b00918607812e", + "0x71db00923b0091db00912500707f00923b00908d00904500708d00923b", + "0x912500922100722300923b00922300900e00700900923b009009009033", + "0x15f00707f1252230091db1fd00907f00923b00907f00903600712500923b", + "0x12e00900700723b00900700700700723b0090071600071fd00923b009007", + "0x912500700723b00900712e00701822312e23d1db01112e23b12e009007", + "0x923b0091250091fd0071db00923b0091db00900e00701100923b009011", + "0x923b12e0150091db00701501f01b12523b0091251db011125011007125", + "0x702602312e23b00902000922300700723b00900712e00702500923e020", + "0x2300901b00700723b00900712e00723c00923f22c00923b12e026009018", + "0x2e12e23b00902c00901500702c00923b00922900901f00722900923b009", + "0x922500901500722500923b00900702500700723b00902e009020007030", + "0x703300923b00903000902300700723b00903100902000704503112e23b", + "0x22103312e22c00703300923b00903300902600722100923b009045009023", + "0x23c00700723b0091fd00906400700723b00900712e0070070f600723b12e", + "0x721900923b00900702c00703600923b00900722900700723b00922c009", + "0x900722500703800923b00921903612e03000721900923b00921900902e", + "0x12600923b00903b00904500703b00923b00903803a12e03100703a00923b", + "0x12e00922100701f00923b00901f00900e00701b00923b00901b009125007", + "0x12e00712612e01f01b00e00912600923b00912600903600712e00923b009", + "0x703c00923b00903c00903800703c00923b00900721900700723b009007", + "0x723b00900712e00714504112e24014103e12e23b12e03c01f01b12503a", + "0x923b00900703c00714800923b00900712600704300923b00900703b007", + "0x23b00900704100715000923b00900714100704900923b00900703e007047", + "0x4322314800715300923b00900704300715200923b00900714500704c009", + "0x703e00923b00903e00912500715500923b00915315204c150049047148", + "0x922c00904700712e00923b00912e00922100714100923b00914100900e", + "0x16200705400e05215700e23b00922c15512e14103e1fd16100722c00923b", + "0x12e00705700924115900923b12e05400906700700e00923b00900e1fd12e", + "0x15d05a12e23b00915900916400705800923b00900722900700723b009007", + "0x5d00916800715e05d12e23b00915d00916600700723b00905a009152007", + "0x705200923b00905200900e00715700923b00915700912500700723b009", + "0x5215700e06d00705800923b00905800915700715e00923b00915e00916b", + "0x716100924206400923b12e16000906e00716015f06012523b00905815e", + "0x23b00906700905400706716212e23b00906400906f00700723b00900712e", + "0x905800700723b00916400905700716616412e23b009162009159007007", + "0x923b00916b00915d00716b00923b00916800905a00716800923b009166", + "0x922100715f00923b00915f00900e00706000923b00906000912500706d", + "0x706d00e15f06000e00906d00923b00906d00903600700e00923b00900e", + "0x923b00906000912500706e00923b00916100904500700723b00900712e", + "0x903600700e00923b00900e00922100715f00923b00915f00900e007060", + "0x904500700723b00900712e00706e00e15f06000e00906e00923b00906e", + "0x923b00905200900e00715700923b00915700912500706f00923b009057", + "0x15700e00906f00923b00906f00903600700e00923b00900e009221007052", + "0x22c00923c00700723b0091fd00906400700723b00900712e00706f00e052", + "0x902e00716e00923b00900705d00707100923b00900722900700723b009", + "0x923b00900722500707200923b00916e07112e03000716e00923b00916e", + "0x12500707600923b00917400904500717400923b00907207412e031007074", + "0x23b00912e00922100714500923b00914500900e00704100923b009041009", + "0x900712e00707612e14504100e00907600923b00907600903600712e009", + "0x2300915e00700723b0091fd00906400700723b00923c00905400700723b", + "0x902e00707700923b00900706000718000923b00900722900700723b009", + "0x923b00900722500707800923b00907718012e03000707700923b009077", + "0x12500718700923b00907b00904500707b00923b00907818612e031007186", + "0x23b00912e00922100701f00923b00901f00900e00701b00923b00901b009", + "0x900712e00718712e01f01b00e00918700923b00918700903600712e009", + "0x912500708d00923b00902500904500700723b0091fd00906400700723b", + "0x923b00912e00922100701f00923b00901f00900e00701b00923b00901b", + "0x23b00900712e00708d12e01f01b00e00908d00923b00908d00903600712e", + "0x23b00900722900700723b00912500915e00700723b0091fd009064007007", + "0x12e03000708e00923b00908e00902e00708e00923b00900705d00707f009", + "0x23b00908f09012e03100709000923b00900722500708f00923b00908e07f", + "0xe00722300923b00922300912500709200923b009091009045007091009", + "0x23b00909200903600712e00923b00912e00922100701800923b009018009", + "0x23b00900716000701100923b00900707100709212e01822300e009092009", + "0x1812e2432231db12e23b12e12e00712e00900700723b009007007007007", + "0x900e00916e00700e00923b00900e0091fd00700723b00900712e00701b", + "0x1fd00923b12e0150090720071db00923b0091db00912500701501f12e23b", + "0x900e0071db00923b0091db00912500700723b00900712e007020009244", + "0x23b0091fd01112e07400701f00923b00901f0091fd00722300923b009223", + "0x23b12e02600907600702602302512523b00901f2231db1251740071fd009", + "0x2c22912e23b00922c00918000700723b00900712e00723c00924522c009", + "0x901b00700723b00900712e00703000924602e00923b12e02c009077007", + "0x12e23b00903100901500703100923b00922500901f00722500923b009229", + "0x22100901500722100923b00900702500700723b009045009020007033045", + "0x3800923b00903300902300700723b00903600902000721903612e23b009", + "0x3812e22c00703800923b00903800902600703a00923b009219009023007", + "0x700723b00902e00905700700723b00900712e00700724700723b12e03a", + "0x12600923b00900702c00703b00923b00900722900700723b0091fd009155", + "0x722500703c00923b00912603b12e03000712600923b00912600902e007", + "0x923b00914100904500714100923b00903c03e12e03100703e00923b009", + "0x900e00700900923b00900900903300702500923b009025009125007041", + "0x923b00904100903600712500923b00912500922100702300923b009023", + "0x923b00900721900700723b00900712e0070411250230090251fd009041", + "0x14804312e23b12e14502302512503a00714500923b009145009038007145", + "0x712600715000923b00900703b00700723b00900712e00704904712e248", + "0x14100715300923b00900703e00715200923b00900703c00704c00923b009", + "0x705200923b00900714500715700923b00900704100715500923b009007", + "0x923b00905405215715515315204c15022314800705400923b009007043", + "0x912500700723b00905700915200705805712e23b009159009078007159", + "0x923b00914800900e00700900923b00900900903300704300923b009043", + "0x91570071fd00923b0091fd00902e00712500923b009125009221007148", + "0x15d05a1fd23b00902e1fd0581251480090431db18600702e00923b00902e", + "0x723b00900712e00716000924915f00923b12e06000907b00706015e05d", + "0x916100915300716100923b00915f00918700706400923b009007229007", + "0x706700923b00906700902e00700723b00916200915500706716212e23b", + "0x905400716616412e23b00906406712e05200706400923b009064009157", + "0x723b00916800905700716b16812e23b00916400915900700723b009166", + "0x6e00915d00706e00923b00906d00905a00706d00923b00916b009058007", + "0x15d00923b00915d00903300705a00923b00905a00912500706f00923b009", + "0x6f00903600715e00923b00915e00922100705d00923b00905d00900e007", + "0x904500700723b00900712e00706f15e05d15d05a1fd00906f00923b009", + "0x923b00915d00903300705a00923b00905a00912500707100923b009160", + "0x903600715e00923b00915e00922100705d00923b00905d00900e00715d", + "0x5700700723b00900712e00707115e05d15d05a1fd00907100923b009071", + "0x716e00923b00900722900700723b0091fd00915500700723b00902e009", + "0x907216e12e03000707200923b00907200902e00707200923b00900705d", + "0x707600923b00907417412e03100717400923b00900722500707400923b", + "0x900900903300704700923b00904700912500718000923b009076009045", + "0x712500923b00912500922100704900923b00904900900e00700900923b", + "0x723b00900712e0071801250490090471fd00918000923b009180009036", + "0x23b0091fd00915500700723b00922900915e00700723b009030009054007", + "0x907800902e00707800923b00900708d00707700923b009007229007007", + "0x707b00923b00900722500718600923b00907807712e03000707800923b", + "0x2500912500708d00923b00918700904500718700923b00918607b12e031", + "0x2300923b00902300900e00700900923b00900900903300702500923b009", + "0x90251fd00908d00923b00908d00903600712500923b009125009221007", + "0x23c00904500700723b0091fd00915500700723b00900712e00708d125023", + "0x900923b00900900903300702500923b00902500912500707f00923b009", + "0x7f00903600712500923b00912500922100702300923b00902300900e007", + "0x905400700723b00900712e00707f1250230090251fd00907f00923b009", + "0x22900700723b00901100907f00700723b00901f00915e00700723b009020", + "0x8f00923b00908f00902e00708f00923b00900706000708e00923b009007", + "0x9112e03100709100923b00900722500709000923b00908f08e12e030007", + "0x923b0091db00912500709300923b00909200904500709200923b009090", + "0x922100722300923b00922300900e00700900923b0090090090330071db", + "0x931252230091db1fd00909300923b00909300903600712500923b009125", + "0x723b00901100907f00700723b00900e00915e00700723b00900712e007", + "0x23b00909500902e00709500923b00900705d00709400923b009007229007", + "0x3100709700923b00900722500709600923b00909509412e030007095009", + "0x901800912500709900923b00909800904500709800923b00909609712e", + "0x701b00923b00901b00900e00700900923b00900900903300701800923b", + "0x1b0090181fd00909900923b00909900903600712500923b009125009221", + "0x900708f00701800923b00900715f0071db00923b00900708e007099125", + "0x900700700700723b00900716000702000923b00900709000701f00923b", + "0x900712e00722c02612e24a02302512e23b12e12500912e00900700723b", + "0x1fd00702300923b00902300900e00702500923b00902500912500700723b", + "0x9200702c22923c12523b0091fd0230251250910071fd00923b0091fd009", + "0x902e00909300700723b00900712e00703000924b02e00923b12e02c009", + "0x23b00900712e00704500924c01500923b12e03100909400703122512e23b", + "0x91fd00722900923b00922900900e00723c00923b00923c009125007007", + "0x22522923c12517400701500923b00901502012e09500722500923b009225", + "0x712e00703800924d21900923b12e03600907600703622103312523b009", + "0x12600923b12e03b00907700703b03a12e23b00921900918000700723b009", + "0x901f00703e00923b00903a00901b00700723b00900712e00703c00924e", + "0x23b00904100902000714504112e23b00914100901500714100923b00903e", + "0x902000704714812e23b00904300901500704300923b009007025007007", + "0x15000923b00904700902300704900923b00914500902300700723b009148", + "0x12e00700724f00723b12e15004912e22c00704900923b009049009026007", + "0x6400700723b0091db00909700700723b00901f00909600700723b009007", + "0x700723b00901500909800700723b00912600905700700723b009018009", + "0x923b00915200902e00715200923b00900702c00704c00923b009007229", + "0x12e03100715500923b00900722500715300923b00915204c12e030007152", + "0x23b00900700909900705200923b00915700904500715700923b009153155", + "0xe00712e00923b00912e00903300703300923b009033009125007007009", + "0x23b00905200903600700e00923b00900e00922100722100923b009221009", + "0x900721900700723b00900712e00705200e22112e033007011009052009", + "0x12e23b12e05422103312503a00705400923b00905400903800705400923b", + "0x715d00923b00900703b00700723b00900712e00705a05812e250057159", + "0x6000923b00900703e00715e00923b00900703c00705d00923b009007126", + "0x923b00900714500716000923b00900704100715f00923b009007141007", + "0x916106416015f06015e05d15d22314800716100923b009007043007064", + "0x712e00923b00912e00903300715900923b00915900912500716200923b", + "0x900e00922100700700923b00900700909900705700923b00905700900e", + "0x712600923b00912600915700701500923b0090150091a500700e00923b", + "0x716622301116401b06701123b00912601516200e00705712e15922309c", + "0x12e16200701100923b0090111db12e03700701b00923b00901b01f12e1a7", + "0x712e00716b00925116800923b12e16600906700722300923b009223018", + "0x706f06e12e23b00916800916400706d00923b00900722900700723b009", + "0x907100916800716e07112e23b00906f00916600700723b00906e009152", + "0x16b00716400923b00916400900e00706700923b00906700912500700723b", + "0x16e16406700e06d00706d00923b00906d00915700716e00923b00916e009", + "0x12e00718000925207600923b12e17400906e00717407407212523b00906d", + "0x723b00907800905400707807712e23b00907600906f00700723b009007", + "0x7b00905800700723b00918600905700707b18612e23b009077009159007", + "0x7f00923b00908d00915d00708d00923b00918700905a00718700923b009", + "0x1b00903300707200923b00907200912500701100923b009011009099007", + "0x22300923b00922300922100707400923b00907400900e00701b00923b009", + "0x900712e00707f22307401b07201101100907f00923b00907f009036007", + "0x12500701100923b00901100909900708e00923b00918000904500700723b", + "0x23b00907400900e00701b00923b00901b00903300707200923b009072009", + "0x1100908e00923b00908e00903600722300923b009223009221007074009", + "0x8f00923b00916b00904500700723b00900712e00708e22307401b072011", + "0x1b00903300706700923b00906700912500701100923b009011009099007", + "0x22300923b00922300922100716400923b00916400900e00701b00923b009", + "0x900712e00708f22316401b06701101100908f00923b00908f009036007", + "0x1800906400700723b0091db00909700700723b00901f00909600700723b", + "0x722900700723b00901500909800700723b00912600905700700723b009", + "0x709100923b00909100902e00709100923b00900705d00709000923b009", + "0x9209312e03100709300923b00900722500709200923b00909109012e030", + "0x700923b00900700909900709500923b00909400904500709400923b009", + "0x5a00900e00712e00923b00912e00903300705800923b009058009125007", + "0x9500923b00909500903600700e00923b00900e00922100705a00923b009", + "0x23b00903c00905400700723b00900712e00709500e05a12e058007011009", + "0x901800906400700723b0091db00909700700723b00901f009096007007", + "0x900722900700723b00901500909800700723b00903a00915e00700723b", + "0x3000709700923b00909700902e00709700923b00900708d00709600923b", + "0x909809912e03100709900923b00900722500709800923b00909709612e", + "0x700700923b00900700909900709c00923b0091a50090450071a500923b", + "0x922100900e00712e00923b00912e00903300703300923b009033009125", + "0x909c00923b00909c00903600700e00923b00900e00922100722100923b", + "0x723b00901f00909600700723b00900712e00709c00e22112e033007011", + "0x23b00901500909800700723b00901800906400700723b0091db009097007", + "0x912500700700923b0090070090990071a700923b009038009045007007", + "0x923b00922100900e00712e00923b00912e00903300703300923b009033", + "0x70110091a700923b0091a700903600700e00923b00900e009221007221", + "0x6400700723b00904500905400700723b00900712e0071a700e22112e033", + "0x700723b0091db00909700700723b00901f00909600700723b009018009", + "0x3700923b00900722900700723b00902000905b00700723b00922500915e", + "0x5b03712e03000705b00923b00905b00902e00705b00923b009007060007", + "0x1b000923b00909f1ac12e0310071ac00923b00900722500709f00923b009", + "0x23c00912500700700923b0090070090990071b200923b0091b0009045007", + "0x22900923b00922900900e00712e00923b00912e00903300723c00923b009", + "0x23c0070110091b200923b0091b200903600700e00923b00900e009221007", + "0x909600700723b00901800906400700723b00900712e0071b200e22912e", + "0x4500700723b00902000905b00700723b0091db00909700700723b00901f", + "0x23b00923c00912500700700923b0090070090990070a300923b009030009", + "0x22100722900923b00922900900e00712e00923b00912e00903300723c009", + "0x22912e23c0070110090a300923b0090a300903600700e00923b00900e009", + "0x901800906400700723b00902000905b00700723b00900712e0070a300e", + "0x1fd00915e00700723b0091db00909700700723b00901f00909600700723b", + "0x902e0070a500923b00900705d00704a00923b00900722900700723b009", + "0x923b0090072250071b500923b0090a504a12e0300070a500923b0090a5", + "0x990071b800923b0090a90090450070a900923b0091b50a712e0310070a7", + "0x23b00912e00903300702600923b00902600912500700700923b009007009", + "0x3600700e00923b00900e00922100722c00923b00922c00900e00712e009", + "0x723b0090070070071b800e22c12e0260070110091b800923b0091b8009", + "0x723b00900712e0072231db12e2530111fd12e23b12e12e00912e009007", + "0xe0091fd00701100923b00901100900e0071fd00923b0091fd009125007", + "0x1f00909200701f01b01812523b00900e0111fd12509100700e00923b009", + "0x12e23b00901500909300700723b00900712e00702000925401500923b12e", + "0x700723b00900712e00722c00925502600923b12e023009094007023025", + "0x922900901500722900923b00923c00901f00723c00923b00902500901b", + "0x1500703000923b00900702500700723b00902c00902000702e02c12e23b", + "0x23b00902e00902300700723b00922500902000703122512e23b009030009", + "0x22c00704500923b00904500902600703300923b009031009023007045009", + "0x23b00902600909800700723b00900712e00700725600723b12e03304512e", + "0x903600902e00703600923b00900702c00722100923b009007229007007", + "0x703800923b00900722500721900923b00903622112e03000703600923b", + "0x700909900703b00923b00903a00904500703a00923b00921903812e031", + "0x1b00923b00901b00900e00701800923b00901800912500700700923b009", + "0x180071fd00903b00923b00903b00903600712500923b009125009221007", + "0x12600903800712600923b00900721900700723b00900712e00703b12501b", + "0x704114112e25703e03c12e23b12e12601b01812503a00712600923b009", + "0x704300923b00900712600714500923b00900703b00700723b00900712e", + "0x4900923b00900714100704700923b00900703e00714800923b00900703c", + "0x923b00900704300704c00923b00900714500715000923b009007041007", + "0x15300907800715300923b00915204c150049047148043145223148007152", + "0x3c00923b00903c00912500700723b00915500915200715715512e23b009", + "0x12500922100700700923b00900700909900703e00923b00903e00900e007", + "0x15712500703e03c01109f00702600923b0090260091a500712500923b009", + "0x15d00925805a00923b12e05800907b0070580571590540521fd23b009026", + "0x923b00905a00918700705d00923b00900722900700723b00900712e007", + "0x902e00700723b00906000915500715f06012e23b00915e00915300715e", + "0x23b00905d15f12e05200705d00923b00905d00915700715f00923b00915f", + "0x716216112e23b00916000915900700723b00906400905400706416012e", + "0x23b00906700905a00706700923b00916200905800700723b009161009057", + "0x12500715900923b00915900909900716600923b00916400915d007164009", + "0x23b00905700922100705400923b00905400900e00705200923b009052009", + "0x712e0071660570540521591fd00916600923b009166009036007057009", + "0x715900923b00915900909900716800923b00915d00904500700723b009", + "0x905700922100705400923b00905400900e00705200923b009052009125", + "0x12e0071680570540521591fd00916800923b00916800903600705700923b", + "0x5d00716b00923b00900722900700723b00902600909800700723b009007", + "0x23b00906d16b12e03000706d00923b00906d00902e00706d00923b009007", + "0x4500707100923b00906e06f12e03100706f00923b00900722500706e009", + "0x23b00914100912500700700923b00900700909900716e00923b009071009", + "0x3600712500923b00912500922100704100923b00904100900e007141009", + "0x700723b00900712e00716e1250411410071fd00916e00923b00916e009", + "0x7200923b00900722900700723b00902500915e00700723b00922c009054", + "0x7407212e03000707400923b00907400902e00707400923b009007060007", + "0x18000923b00917407612e03100707600923b00900722500717400923b009", + "0x1800912500700700923b00900700909900707700923b009180009045007", + "0x12500923b00912500922100701b00923b00901b00900e00701800923b009", + "0x23b00900712e00707712501b0180071fd00907700923b009077009036007", + "0x912500700700923b00900700909900707800923b009020009045007007", + "0x923b00912500922100701b00923b00901b00900e00701800923b009018", + "0x900712e00707812501b0180071fd00907800923b009078009036007125", + "0x900705d00718600923b00900722900700723b00900e00915e00700723b", + "0x18700923b00907b18612e03000707b00923b00907b00902e00707b00923b", + "0x7f00904500707f00923b00918708d12e03100708d00923b009007225007", + "0x1db00923b0091db00912500700700923b00900700909900708e00923b009", + "0x8e00903600712500923b00912500922100722300923b00922300900e007", + "0x12e00900700723b00900700700708e1252231db0071fd00908e00923b009", + "0x91fd00700723b00900712e0072231db12e2590111fd12e23b12e12e009", + "0x23b0091fd00912500701b01812e23b00900e00916e00700e00923b00900e", + "0x700723b00900712e00701500925a01f00923b12e01b0090720071fd009", + "0x902500901500702500923b00902000901f00702000923b00901800901b", + "0x1500722c00923b00900702500700723b00902300902000702602312e23b", + "0x23b00902600902300700723b00923c00902000722923c12e23b00922c009", + "0x22c00702c00923b00902c00902600702e00923b00922900902300702c009", + "0x23b00901f00915500700723b00900712e00700725b00723b12e02e02c12e", + "0x922500902e00722500923b00900702c00703000923b009007229007007", + "0x704500923b00900722500703100923b00922503012e03000722500923b", + "0x700909900722100923b00903300904500703300923b00903104512e031", + "0x1100923b00901100900e0071fd00923b0091fd00912500700700923b009", + "0x1fd0071fd00922100923b00922100903600712500923b009125009221007", + "0x3600903800703600923b00900721900700723b00900712e007221125011", + "0x703b03a12e25c03821912e23b12e0360111fd12503a00703600923b009", + "0x703c00923b00900712600712600923b00900703b00700723b00900712e", + "0x4100923b00900714100714100923b00900703e00703e00923b00900703c", + "0x923b00900704300704300923b00900714500714500923b009007041007", + "0x4700907800704700923b00914804314504114103e03c126223148007148", + "0x21900923b00921900912500700723b00904900915200715004912e23b009", + "0x12500922100700700923b00900700909900703800923b00903800900e007", + "0x1501250070382190111ac00701f00923b00901f00902e00712500923b009", + "0x5400925d05200923b12e1570091b000715715515315204c1fd23b00901f", + "0x923b0090520091b200715900923b00900722900700723b00900712e007", + "0x90a500700723b00905800904a00705a05812e23b0090570090a3007057", + "0x23b00915905a12e1b500715900923b00915900915700705a00923b00905a", + "0x706015e12e23b00915d00915900700723b00905d00905400705d15d12e", + "0x23b00915f00905a00715f00923b00906000905800700723b00915e009057", + "0x12500715300923b00915300909900706400923b00916000915d007160009", + "0x23b00915500922100715200923b00915200900e00704c00923b00904c009", + "0x712e00706415515204c1531fd00906400923b009064009036007155009", + "0x715300923b00915300909900716100923b00905400904500700723b009", + "0x915500922100715200923b00915200900e00704c00923b00904c009125", + "0x12e00716115515204c1531fd00916100923b00916100903600715500923b", + "0x5d00716200923b00900722900700723b00901f00915500700723b009007", + "0x23b00906716212e03000706700923b00906700902e00706700923b009007", + "0x4500716800923b00916416612e03100716600923b009007225007164009", + "0x23b00903a00912500700700923b00900700909900716b00923b009168009", + "0x3600712500923b00912500922100703b00923b00903b00900e00703a009", + "0x700723b00900712e00716b12503b03a0071fd00916b00923b00916b009", + "0x6d00923b00900722900700723b00901800915e00700723b009015009054", + "0x6e06d12e03000706e00923b00906e00902e00706e00923b009007060007", + "0x16e00923b00906f07112e03100707100923b00900722500706f00923b009", + "0x1fd00912500700700923b00900700909900707200923b00916e009045007", + "0x12500923b00912500922100701100923b00901100900e0071fd00923b009", + "0x23b00900712e0070721250111fd0071fd00907200923b009072009036007", + "0x23b00900705d00707400923b00900722900700723b00900e00915e007007", + "0x707600923b00917407412e03000717400923b00917400902e007174009", + "0x907700904500707700923b00907618012e03100718000923b009007225", + "0x71db00923b0091db00912500700700923b00900700909900707800923b", + "0x907800903600712500923b00912500922100722300923b00922300900e", + "0x70a70071fd00923b00900715f0070781252231db0071fd00907800923b", + "0x712e00900700723b00900700700700723b0090071600071db00923b009", + "0x22300912500700723b00900712e00701f01b12e25e01822312e23b12e009", + "0x12523b00912522312e0a900712500923b0091250091fd00722300923b009", + "0x723b00900712e00702300925f01100923b12e0250091b8007025020015", + "0x200091fd00701800923b00901800900e00701500923b009015009125007", + "0x902001801512517400701100923b0090111db12e0ac00702000923b009", + "0x900712e00702c00926022900923b12e23c00907600723c22c02612523b", + "0x26122500923b12e03000907700703002e12e23b00922900918000700723b", + "0x4500901f00704500923b00902e00901b00700723b00900712e007031009", + "0x723b00922100902000703622112e23b00903300901500703300923b009", + "0x3800902000703a03812e23b00921900901500721900923b009007025007", + "0x712600923b00903a00902300703b00923b00903600902300700723b009", + "0x712e00700726200723b12e12603b12e22c00703b00923b00903b009026", + "0x90ae00700723b00922500905700700723b0091fd00906400700723b009", + "0x2e00703e00923b00900702c00703c00923b00900722900700723b009011", + "0x23b00900722500714100923b00903e03c12e03000703e00923b00903e009", + "0x704300923b00914500904500714500923b00914104112e031007041009", + "0x912e00922100722c00923b00922c00900e00702600923b009026009125", + "0x712e00704312e22c02600e00904300923b00904300903600712e00923b", + "0x3a00714800923b00914800903800714800923b00900721900700723b009", + "0x700723b00900712e00704c15012e26304904712e23b12e14822c026125", + "0x15500923b00900703c00715300923b00900712600715200923b00900703b", + "0x923b00900704100705200923b00900714100715700923b00900703e007", + "0x15315222314800705700923b00900704300715900923b009007145007054", + "0xe00704700923b00904700912500705800923b009057159054052157155", + "0x23b0090110091bc00712e00923b00912e00922100704900923b009049009", + "0x922501105812e0490470110b000722500923b009225009157007011009", + "0x12e05d0090b200700e00923b00900e1fd12e16200705d00e15d05a00e23b", + "0x715f00923b00900722900700723b00900712e00706000926415e00923b", + "0x906400915900700723b00916000915200706416012e23b00915e0091bd", + "0x705a00923b00905a00912500700723b00916100905700716216112e23b", + "0x915f00915700716200923b0091620090b400715d00923b00915d00900e", + "0x16600906e00716616406712523b00915f16215d05a00e0b600715f00923b", + "0x12e23b00916800906f00700723b00900712e00716b00926516800923b12e", + "0x5700707106f12e23b00906d00915900700723b00906e00905400706e06d", + "0x923b00916e00905a00716e00923b00907100905800700723b00906f009", + "0x900e00706700923b00906700912500707400923b00907200915d007072", + "0x923b00907400903600700e00923b00900e00922100716400923b009164", + "0x923b00916b00904500700723b00900712e00707400e16406700e009074", + "0x922100716400923b00916400900e00706700923b009067009125007174", + "0x717400e16406700e00917400923b00917400903600700e00923b00900e", + "0x923b00905a00912500707600923b00906000904500700723b00900712e", + "0x903600700e00923b00900e00922100715d00923b00915d00900e00705a", + "0x906400700723b00900712e00707600e15d05a00e00907600923b009076", + "0x22900700723b0090110090ae00700723b00922500905700700723b0091fd", + "0x7700923b00907700902e00707700923b00900705d00718000923b009007", + "0x18612e03100718600923b00900722500707800923b00907718012e030007", + "0x923b00915000912500718700923b00907b00904500707b00923b009078", + "0x903600712e00923b00912e00922100704c00923b00904c00900e007150", + "0x905400700723b00900712e00718712e04c15000e00918700923b009187", + "0xae00700723b00902e00915e00700723b0091fd00906400700723b009031", + "0x707f00923b00900708d00708d00923b00900722900700723b009011009", + "0x900722500708e00923b00907f08d12e03000707f00923b00907f00902e", + "0x9100923b00909000904500709000923b00908e08f12e03100708f00923b", + "0x12e00922100722c00923b00922c00900e00702600923b009026009125007", + "0x12e00709112e22c02600e00909100923b00909100903600712e00923b009", + "0x4500700723b0090110090ae00700723b0091fd00906400700723b009007", + "0x23b00922c00900e00702600923b00902600912500709200923b00902c009", + "0xe00909200923b00909200903600712e00923b00912e00922100722c009", + "0x906400700723b00902300905400700723b00900712e00709212e22c026", + "0x22900700723b0091db0091bb00700723b00902000915e00700723b0091fd", + "0x9400923b00909400902e00709400923b00900706000709300923b009007", + "0x9612e03100709600923b00900722500709500923b00909409312e030007", + "0x923b00901500912500709800923b00909700904500709700923b009095", + "0x903600712e00923b00912e00922100701800923b00901800900e007015", + "0x906400700723b00900712e00709812e01801500e00909800923b009098", + "0x22900700723b0091db0091bb00700723b00912500915e00700723b0091fd", + "0x1a500923b0091a500902e0071a500923b00900705d00709900923b009007", + "0x1a712e0310071a700923b00900722500709c00923b0091a509912e030007", + "0x923b00901b00912500705b00923b00903700904500703700923b00909c", + "0x903600712e00923b00912e00922100701f00923b00901f00900e00701b", + "0x1600071fd00923b00900715f00705b12e01f01b00e00905b00923b00905b", + "0x1db01112e23b12e00900712e00900700723b00900700700700723b009007", + "0xe00701100923b00901100912500700723b00900712e00701822312e266", + "0x1251db01112517400712500923b0091250091fd0071db00923b0091db009", + "0x712e00702500926702000923b12e01500907600701501f01b12523b009", + "0x22c00923b12e02600907700702602312e23b00902000918000700723b009", + "0x901f00722900923b00902300901b00700723b00900712e00723c009268", + "0x23b00902e00902000703002e12e23b00902c00901500702c00923b009229", + "0x902000704503112e23b00922500901500722500923b009007025007007", + "0x22100923b00904500902300703300923b00903000902300700723b009031", + "0x12e00700726900723b12e22103312e22c00703300923b009033009026007", + "0x22900700723b00922c00905700700723b0091fd00906400700723b009007", + "0x21900923b00921900902e00721900923b00900702c00703600923b009007", + "0x3a12e03100703a00923b00900722500703800923b00921903612e030007", + "0x923b00901b00912500712600923b00903b00904500703b00923b009038", + "0x903600712e00923b00912e00922100701f00923b00901f00900e00701b", + "0x721900700723b00900712e00712612e01f01b00e00912600923b009126", + "0x23b12e03c01f01b12503a00703c00923b00903c00903800703c00923b009", + "0x4300923b00900703b00700723b00900712e00714504112e26a14103e12e", + "0x923b00900703e00704700923b00900703c00714800923b009007126007", + "0x23b00900714500704c00923b00900704100715000923b009007141007049", + "0x15315204c15004904714804322314800715300923b009007043007152009", + "0x14100923b00914100900e00703e00923b00903e00912500715500923b009", + "0x3e1fd0b800722c00923b00922c00915700712e00923b00912e009221007", + "0xe00923b00900e1fd12e16200705400e05215700e23b00922c15512e141", + "0x722900700723b00900712e00705700926b15900923b12e0540090b2007", + "0x723b00905a00915200715d05a12e23b0091590091bd00705800923b009", + "0x15700912500700723b00905d00905700715e05d12e23b00915d009159007", + "0x15e00923b00915e0090b400705200923b00905200900e00715700923b009", + "0x15f06012523b00905815e05215700e0b600705800923b009058009157007", + "0x6f00700723b00900712e00716100926c06400923b12e16000906e007160", + "0x23b00916200915900700723b00906700905400706716212e23b009064009", + "0x5a00716800923b00916600905800700723b00916400905700716616412e", + "0x23b00906000912500706d00923b00916b00915d00716b00923b009168009", + "0x3600700e00923b00900e00922100715f00923b00915f00900e007060009", + "0x4500700723b00900712e00706d00e15f06000e00906d00923b00906d009", + "0x23b00915f00900e00706000923b00906000912500706e00923b009161009", + "0xe00906e00923b00906e00903600700e00923b00900e00922100715f009", + "0x12500706f00923b00905700904500700723b00900712e00706e00e15f060", + "0x23b00900e00922100705200923b00905200900e00715700923b009157009", + "0x900712e00706f00e05215700e00906f00923b00906f00903600700e009", + "0x900722900700723b00922c00905700700723b0091fd00906400700723b", + "0x3000716e00923b00916e00902e00716e00923b00900705d00707100923b", + "0x907207412e03100707400923b00900722500707200923b00916e07112e", + "0x704100923b00904100912500707600923b00917400904500717400923b", + "0x907600903600712e00923b00912e00922100714500923b00914500900e", + "0x923c00905400700723b00900712e00707612e14504100e00907600923b", + "0x900722900700723b00902300915e00700723b0091fd00906400700723b", + "0x3000707700923b00907700902e00707700923b00900706000718000923b", + "0x907818612e03100718600923b00900722500707800923b00907718012e", + "0x701b00923b00901b00912500718700923b00907b00904500707b00923b", + "0x918700903600712e00923b00912e00922100701f00923b00901f00900e", + "0x91fd00906400700723b00900712e00718712e01f01b00e00918700923b", + "0xe00701b00923b00901b00912500708d00923b00902500904500700723b", + "0x23b00908d00903600712e00923b00912e00922100701f00923b00901f009", + "0x23b0091fd00906400700723b00900712e00708d12e01f01b00e00908d009", + "0x23b00900705d00707f00923b00900722900700723b00912500915e007007", + "0x708f00923b00908e07f12e03000708e00923b00908e00902e00708e009", + "0x909100904500709100923b00908f09012e03100709000923b009007225", + "0x701800923b00901800900e00722300923b00922300912500709200923b", + "0x12e01822300e00909200923b00909200903600712e00923b00912e009221", + "0x1db12e26d0111fd12e23b12e12e00712e00900700723b009007007007092", + "0x900e00916e00700e00923b00900e0091fd00700723b00900712e007223", + "0x1f00923b12e01b0090720071fd00923b0091fd00912500701b01812e23b", + "0x901f00702000923b00901800901b00700723b00900712e00701500926e", + "0x23b00902300902000702602312e23b00902500901500702500923b009020", + "0x902000722923c12e23b00922c00901500722c00923b009007025007007", + "0x2e00923b00922900902300702c00923b00902600902300700723b00923c", + "0x12e00700726f00723b12e02e02c12e22c00702c00923b00902c009026007", + "0x2c00703000923b00900722900700723b00901f00915500700723b009007", + "0x23b00922503012e03000722500923b00922500902e00722500923b009007", + "0x4500703300923b00903104512e03100704500923b009007225007031009", + "0x23b0090090090330071fd00923b0091fd00912500722100923b009033009", + "0x3600712500923b00912500922100701100923b00901100900e007009009", + "0x700723b00900712e0072211250110091fd1fd00922100923b009221009", + "0x360111fd12503a00703600923b00903600903800703600923b009007219", + "0x23b00900703b00700723b00900712e00703b03a12e27003821912e23b12e", + "0x900703e00703e00923b00900703c00703c00923b009007126007126009", + "0x714500714500923b00900704100704100923b00900714100714100923b", + "0x14504114103e03c12622314800714800923b00900704300704300923b009", + "0x904900915200715004912e23b00904700907800704700923b009148043", + "0xe00700900923b00900900903300721900923b00921900912500700723b", + "0x23b00901f00902e00712500923b00912500922100703800923b009038009", + "0x715715515315204c1fd23b00901f1501250380092190110ba00701f009", + "0x900722900700723b00900712e00705400927105200923b12e15700907b", + "0x5a05812e23b00905700915300705700923b00905200918700715900923b", + "0x915900915700705a00923b00905a00902e00700723b009058009155007", + "0x723b00905d00905400705d15d12e23b00915905a12e05200715900923b", + "0x6000905800700723b00915e00905700706015e12e23b00915d009159007", + "0x6400923b00916000915d00716000923b00915f00905a00715f00923b009", + "0x15300900e00715200923b00915200903300704c00923b00904c009125007", + "0x6400923b00906400903600715500923b00915500922100715300923b009", + "0x923b00905400904500700723b00900712e00706415515315204c1fd009", + "0x900e00715200923b00915200903300704c00923b00904c009125007161", + "0x923b00916100903600715500923b00915500922100715300923b009153", + "0x23b00901f00915500700723b00900712e00716115515315204c1fd009161", + "0x906700902e00706700923b00900705d00716200923b009007229007007", + "0x716600923b00900722500716400923b00906716212e03000706700923b", + "0x3a00912500716b00923b00916800904500716800923b00916416612e031", + "0x3b00923b00903b00900e00700900923b00900900903300703a00923b009", + "0x903a1fd00916b00923b00916b00903600712500923b009125009221007", + "0x1800915e00700723b00901500905400700723b00900712e00716b12503b", + "0x902e00706e00923b00900706000706d00923b00900722900700723b009", + "0x923b00900722500706f00923b00906e06d12e03000706e00923b00906e", + "0x12500707200923b00916e00904500716e00923b00906f07112e031007071", + "0x23b00901100900e00700900923b0090090090330071fd00923b0091fd009", + "0x1fd00907200923b00907200903600712500923b009125009221007011009", + "0x22900700723b00900e00915e00700723b00900712e0070721250110091fd", + "0x17400923b00917400902e00717400923b00900705d00707400923b009007", + "0x18012e03100718000923b00900722500707600923b00917407412e030007", + "0x923b0091db00912500707800923b00907700904500707700923b009076", + "0x922100722300923b00922300900e00700900923b0090090090330071db", + "0x781252230091db1fd00907800923b00907800903600712500923b009125", + "0x2231db12e2720111fd12e23b12e12e00712e00900700723b009007007007", + "0x23b00900e00916e00700e00923b00900e0091fd00700723b00900712e007", + "0x27301f00923b12e01b0090720071fd00923b0091fd00912500701b01812e", + "0x1800916e00701800923b0090180091fd00700723b00900712e007015009", + "0x900712e00702600927402300923b12e02500907200702502012e23b009", + "0x723c22c12e23b00902000916e00702000923b0090200091fd00700723b", + "0x22c0091fd00700723b00900712e00702c00927522900923b12e23c009072", + "0x923b12e03000907200703002e12e23b00922c00916e00722c00923b009", + "0x1f00704500923b00902e00901b00700723b00900712e007031009276225", + "0x922100902000703622112e23b00903300901500703300923b009045009", + "0x2000703a03812e23b00921900901500721900923b00900702500700723b", + "0x923b00903a00902300703b00923b00903600902300700723b009038009", + "0x700727700723b12e12603b12e22c00703b00923b00903b009026007126", + "0x700723b00922900915500700723b00922500915500700723b00900712e", + "0x3c00923b00900722900700723b00901f00915500700723b009023009155", + "0x3e03c12e03000703e00923b00903e00902e00703e00923b00900702c007", + "0x14500923b00914104112e03100704100923b00900722500714100923b009", + "0x90090330071fd00923b0091fd00912500704300923b009145009045007", + "0x12500923b00912500922100701100923b00901100900e00700900923b009", + "0x23b00900712e0070431250110091fd1fd00904300923b009043009036007", + "0x1fd12503a00714800923b00914800903800714800923b009007219007007", + "0x703b00700723b00900712e00704c15012e27804904712e23b12e148011", + "0x3e00715500923b00900703c00715300923b00900712600715200923b009", + "0x705400923b00900704100705200923b00900714100715700923b009007", + "0x15715515315222314800705700923b00900704300715900923b009007145", + "0x915200715d05a12e23b00905800907800705800923b009057159054052", + "0x900923b00900900903300704700923b00904700912500700723b00905a", + "0x1f00902e00712500923b00912500922100704900923b00904900900e007", + "0x22900923b00922900902e00702300923b00902300902e00701f00923b009", + "0x22522902301f15d1250490090470181ba00722500923b00922500902e007", + "0x716100927906400923b12e16000907b00716015f06015e05d1fd23b009", + "0x6700923b00906400918700716200923b00900722900700723b00900712e", + "0x16600902e00700723b00916400915500716616412e23b009067009153007", + "0x12e23b00916216612e05200716200923b00916200915700716600923b009", + "0x5700706e06d12e23b00916800915900700723b00916b00905400716b168", + "0x923b00906f00905a00706f00923b00906e00905800700723b00906d009", + "0x903300705d00923b00905d00912500716e00923b00907100915d007071", + "0x923b00915f00922100706000923b00906000900e00715e00923b00915e", + "0x900712e00716e15f06015e05d1fd00916e00923b00916e00903600715f", + "0x3300705d00923b00905d00912500707200923b00916100904500700723b", + "0x23b00915f00922100706000923b00906000900e00715e00923b00915e009", + "0x712e00707215f06015e05d1fd00907200923b00907200903600715f009", + "0x915500700723b00922900915500700723b00922500915500700723b009", + "0x5d00707400923b00900722900700723b00901f00915500700723b009023", + "0x23b00917407412e03000717400923b00917400902e00717400923b009007", + "0x4500707700923b00907618012e03100718000923b009007225007076009", + "0x23b00900900903300715000923b00915000912500707800923b009077009", + "0x3600712500923b00912500922100704c00923b00904c00900e007009009", + "0x700723b00900712e00707812504c0091501fd00907800923b009078009", + "0x723b00922900915500700723b00902e00915e00700723b009031009054", + "0x923b00900722900700723b00901f00915500700723b009023009155007", + "0x18612e03000707b00923b00907b00902e00707b00923b0090070bc007186", + "0x923b00918708d12e03100708d00923b00900722500718700923b00907b", + "0x90330071fd00923b0091fd00912500708e00923b00907f00904500707f", + "0x923b00912500922100701100923b00901100900e00700900923b009009", + "0x900712e00708e1250110091fd1fd00908e00923b00908e009036007125", + "0x22c00915e00700723b00901f00915500700723b00902c00905400700723b", + "0x70be00708f00923b00900722900700723b00902300915500700723b009", + "0x923b00909008f12e03000709000923b00909000902e00709000923b009", + "0x904500709300923b00909109212e03100709200923b009007225007091", + "0x923b0090090090330071fd00923b0091fd00912500709400923b009093", + "0x903600712500923b00912500922100701100923b00901100900e007009", + "0x5400700723b00900712e0070941250110091fd1fd00909400923b009094", + "0x700723b00902000915e00700723b00901f00915500700723b009026009", + "0x923b00909600902e00709600923b00900708d00709500923b009007229", + "0x12e03100709800923b00900722500709700923b00909609512e030007096", + "0x23b0091fd0091250071a500923b00909900904500709900923b009097098", + "0x22100701100923b00901100900e00700900923b0090090090330071fd009", + "0x1250110091fd1fd0091a500923b0091a500903600712500923b009125009", + "0x23b00901800915e00700723b00901500905400700723b00900712e0071a5", + "0x91a700902e0071a700923b00900706000709c00923b009007229007007", + "0x705b00923b00900722500703700923b0091a709c12e0300071a700923b", + "0x1fd0091250071ac00923b00909f00904500709f00923b00903705b12e031", + "0x1100923b00901100900e00700900923b0090090090330071fd00923b009", + "0x91fd1fd0091ac00923b0091ac00903600712500923b009125009221007", + "0x900722900700723b00900e00915e00700723b00900712e0071ac125011", + "0x300071b200923b0091b200902e0071b200923b00900705d0071b000923b", + "0x90a304a12e03100704a00923b0090072250070a300923b0091b21b012e", + "0x71db00923b0091db0091250071b500923b0090a50090450070a500923b", + "0x912500922100722300923b00922300900e00700900923b009009009033", + "0x70071b51252230091db1fd0091b500923b0091b500903600712500923b", + "0x12e00701822312e27a1db01112e23b12e12500912e00900700723b009007", + "0x1b12e23b0091fd00916e0071fd00923b0091fd0091fd00700723b009007", + "0x2000927b01500923b12e01f00907200701100923b00901100912500701f", + "0x23b00901b00916e00701b00923b00901b0091fd00700723b00900712e007", + "0x723b00900712e00722c00927c02600923b12e02300907200702302512e", + "0x907200722923c12e23b00902500916e00702500923b0090250091fd007", + "0x23b00923c00901b00700723b00900712e00702e00927d02c00923b12e229", + "0x704503112e23b00922500901500722500923b00903000901f007030009", + "0x12e23b00903300901500703300923b00900702500700723b009031009020", + "0x902300721900923b00904500902300700723b009221009020007036221", + "0x23b12e03821912e22c00721900923b00921900902600703800923b009036", + "0x2600915500700723b00902c00915500700723b00900712e00700727e007", + "0x702c00703a00923b00900722900700723b00901500915500700723b009", + "0x923b00903b03a12e03000703b00923b00903b00902e00703b00923b009", + "0x904500703e00923b00912603c12e03100703c00923b009007225007126", + "0x923b00901100912500700700923b00900700909900714100923b00903e", + "0x92210071db00923b0091db00900e00712e00923b00912e009033007011", + "0xe1db12e01100701100914100923b00914100903600700e00923b00900e", + "0x23b00904100903800704100923b00900721900700723b00900712e007141", + "0x712e00704714812e27f04314512e23b12e0411db01112503a007041009", + "0x703c00715000923b00900712600704900923b00900703b00700723b009", + "0x4100715300923b00900714100715200923b00900703e00704c00923b009", + "0x705200923b00900704300715700923b00900714500715500923b009007", + "0x23b00914500912500705400923b00905215715515315204c150049223148", + "0x9900704300923b00904300900e00712e00923b00912e009033007145009", + "0x23b00901500902e00700e00923b00900e00922100700700923b009007009", + "0x1b900702c00923b00902c00902e00702600923b00902600902e007015009", + "0x705d15d05a05805715901123b00902c02601505400e00704312e145018", + "0x15e0090c200700723b00900712e00706000928015e00923b12e05d0090c0", + "0x706416012e23b00915f00915900715f00923b00900722900700723b009", + "0x23b00916100905a00716100923b00906400905800700723b009160009057", + "0x12500705a00923b00905a00909900706700923b00916200915d007162009", + "0x23b00905800900e00705700923b00905700903300715900923b009159009", + "0x1100906700923b00906700903600715d00923b00915d009221007058009", + "0x16400923b00906000904500700723b00900712e00706715d05805715905a", + "0x5700903300715900923b00915900912500705a00923b00905a009099007", + "0x15d00923b00915d00922100705800923b00905800900e00705700923b009", + "0x900712e00716415d05805715905a01100916400923b009164009036007", + "0x1500915500700723b00902600915500700723b00902c00915500700723b", + "0x902e00716800923b00900705d00716600923b00900722900700723b009", + "0x923b00900722500716b00923b00916816612e03000716800923b009168", + "0x9900706f00923b00906e00904500706e00923b00916b06d12e03100706d", + "0x23b00912e00903300714800923b00914800912500700700923b009007009", + "0x3600700e00923b00900e00922100704700923b00904700900e00712e009", + "0x723b00900712e00706f00e04712e14800701100906f00923b00906f009", + "0x23b00902600915500700723b00923c00915e00700723b00902e009054007", + "0x23b0090070be00707100923b00900722900700723b009015009155007007", + "0x707200923b00916e07112e03000716e00923b00916e00902e00716e009", + "0x917400904500717400923b00907207412e03100707400923b009007225", + "0x701100923b00901100912500700700923b00900700909900707600923b", + "0x900e0092210071db00923b0091db00900e00712e00923b00912e009033", + "0x707600e1db12e01100701100907600923b00907600903600700e00923b", + "0x700723b00901500915500700723b00922c00905400700723b00900712e", + "0x7700923b00900708d00718000923b00900722900700723b00902500915e", + "0x722500707800923b00907718012e03000707700923b00907700902e007", + "0x923b00907b00904500707b00923b00907818612e03100718600923b009", + "0x903300701100923b00901100912500700700923b009007009099007187", + "0x923b00900e0092210071db00923b0091db00900e00712e00923b00912e", + "0x712e00718700e1db12e01100701100918700923b00918700903600700e", + "0x722900700723b00901b00915e00700723b00902000905400700723b009", + "0x707f00923b00907f00902e00707f00923b00900706000708d00923b009", + "0x8e08f12e03100708f00923b00900722500708e00923b00907f08d12e030", + "0x700923b00900700909900709100923b00909000904500709000923b009", + "0x1db00900e00712e00923b00912e00903300701100923b009011009125007", + "0x9100923b00909100903600700e00923b00900e0092210071db00923b009", + "0x23b0091fd00915e00700723b00900712e00709100e1db12e011007011009", + "0x909300902e00709300923b00900705d00709200923b009007229007007", + "0x709500923b00900722500709400923b00909309212e03000709300923b", + "0x700909900709700923b00909600904500709600923b00909409512e031", + "0x12e00923b00912e00903300722300923b00922300912500700700923b009", + "0x9700903600700e00923b00900e00922100701800923b00901800900e007", + "0x900700723b00900700700709700e01812e22300701100909700923b009", + "0x1fd00700723b00900712e0071db01112e2811fd00e12e23b12e00900712e", + "0x900e00912500701822312e23b00912500916e00712500923b009125009", + "0x723b00900712e00701f00928201b00923b12e01800907200700e00923b", + "0x2000901500702000923b00901500901f00701500923b00922300901b007", + "0x702600923b00900702500700723b00902500902000702302512e23b009", + "0x902300902300700723b00922c00902000723c22c12e23b009026009015", + "0x722900923b00922900902600702c00923b00923c00902300722900923b", + "0x901b00915500700723b00900712e00700728300723b12e02c22912e22c", + "0x3000902e00703000923b00900702c00702e00923b00900722900700723b", + "0x3100923b00900722500722500923b00903002e12e03000703000923b009", + "0x912500703300923b00904500904500704500923b00922503112e031007", + "0x923b00912e0092210071fd00923b0091fd00900e00700e00923b00900e", + "0x23b00900712e00703312e1fd00e00e00903300923b00903300903600712e", + "0xe12503a00722100923b00922100903800722100923b009007219007007", + "0x703b00700723b00900712e00703a03812e28421903612e23b12e2211fd", + "0x3e00703c00923b00900703c00712600923b00900712600703b00923b009", + "0x704100923b00900704100714100923b00900714100703e00923b009007", + "0x3e03c12603b22314800704300923b00900704300714500923b009007145", + "0x21900900e00703600923b00903600912500714800923b009043145041141", + "0x1b00923b00901b00902e00712e00923b00912e00922100721900923b009", + "0x12e04c0090c000704c15004904700e23b00901b14812e2190361fd1b6007", + "0x700723b0091520090c200700723b00900712e00715300928515200923b", + "0x915700905700705215712e23b00915500915900715500923b009007229", + "0x15d00715900923b00905400905a00705400923b00905200905800700723b", + "0x23b00904900900e00704700923b00904700912500705700923b009159009", + "0xe00905700923b00905700903600715000923b009150009221007049009", + "0x12500705800923b00915300904500700723b00900712e007057150049047", + "0x23b00915000922100704900923b00904900900e00704700923b009047009", + "0x900712e00705815004904700e00905800923b009058009036007150009", + "0x900705d00705a00923b00900722900700723b00901b00915500700723b", + "0x5d00923b00915d05a12e03000715d00923b00915d00902e00715d00923b", + "0x6000904500706000923b00905d15e12e03100715e00923b009007225007", + "0x3a00923b00903a00900e00703800923b00903800912500715f00923b009", + "0x3a03800e00915f00923b00915f00903600712e00923b00912e009221007", + "0x922300915e00700723b00901f00905400700723b00900712e00715f12e", + "0x6400902e00706400923b00900706000716000923b00900722900700723b", + "0x16200923b00900722500716100923b00906416012e03000706400923b009", + "0x912500716400923b00906700904500706700923b00916116212e031007", + "0x923b00912e0092210071fd00923b0091fd00900e00700e00923b00900e", + "0x23b00900712e00716412e1fd00e00e00916400923b00916400903600712e", + "0x23b00900705d00716600923b00900722900700723b00912500915e007007", + "0x716b00923b00916816612e03000716800923b00916800902e007168009", + "0x906e00904500706e00923b00916b06d12e03100706d00923b009007225", + "0x71db00923b0091db00900e00701100923b00901100912500706f00923b", + "0x12e1db01100e00906f00923b00906f00903600712e00923b00912e009221", + "0x1112e2861fd00e12e23b12e00900712e00900700723b00900700700706f", + "0x912500916e00712500923b0091250091fd00700723b00900712e0071db", + "0x1b00923b12e01800907200700e00923b00900e00912500701822312e23b", + "0x901f00701500923b00922300901b00700723b00900712e00701f009287", + "0x23b00902500902000702302512e23b00902000901500702000923b009015", + "0x902000723c22c12e23b00902600901500702600923b009007025007007", + "0x2c00923b00923c00902300722900923b00902300902300700723b00922c", + "0x12e00700728800723b12e02c22912e22c00722900923b009229009026007", + "0x2c00702e00923b00900722900700723b00901b00915500700723b009007", + "0x23b00903002e12e03000703000923b00903000902e00703000923b009007", + "0x4500704500923b00922503112e03100703100923b009007225007225009", + "0x23b0091fd00900e00700e00923b00900e00912500703300923b009045009", + "0xe00903300923b00903300903600712e00923b00912e0092210071fd009", + "0x903800722100923b00900721900700723b00900712e00703312e1fd00e", + "0x3a03812e28921903612e23b12e2211fd00e12503a00722100923b009221", + "0x12600923b00900712600703b00923b00900703b00700723b00900712e007", + "0x923b00900714100703e00923b00900703e00703c00923b00900703c007", + "0x23b00900704300714500923b00900714500704100923b009007041007141", + "0x912500714800923b00904314504114103e03c12603b223148007043009", + "0x923b00912e00922100721900923b00921900900e00703600923b009036", + "0xe23b00901b14812e2190361fd0c400701b00923b00901b00902e00712e", + "0x23b00900712e00715300928a15200923b12e04c0090c000704c150049047", + "0x915500915900715500923b00900722900700723b0091520090c2007007", + "0x705400923b00905200905800700723b00915700905700705215712e23b", + "0x904700912500705700923b00915900915d00715900923b00905400905a", + "0x715000923b00915000922100704900923b00904900900e00704700923b", + "0x700723b00900712e00705715004904700e00905700923b009057009036", + "0x904900900e00704700923b00904700912500705800923b009153009045", + "0x905800923b00905800903600715000923b00915000922100704900923b", + "0x22900700723b00901b00915500700723b00900712e00705815004904700e", + "0x15d00923b00915d00902e00715d00923b00900705d00705a00923b009007", + "0x15e12e03100715e00923b00900722500705d00923b00915d05a12e030007", + "0x923b00903800912500715f00923b00906000904500706000923b00905d", + "0x903600712e00923b00912e00922100703a00923b00903a00900e007038", + "0x905400700723b00900712e00715f12e03a03800e00915f00923b00915f", + "0x6000716000923b00900722900700723b00922300915e00700723b00901f", + "0x23b00906416012e03000706400923b00906400902e00706400923b009007", + "0x4500706700923b00916116212e03100716200923b009007225007161009", + "0x23b0091fd00900e00700e00923b00900e00912500716400923b009067009", + "0xe00916400923b00916400903600712e00923b00912e0092210071fd009", + "0x722900700723b00912500915e00700723b00900712e00716412e1fd00e", + "0x716800923b00916800902e00716800923b00900705d00716600923b009", + "0x16b06d12e03100706d00923b00900722500716b00923b00916816612e030", + "0x1100923b00901100912500706f00923b00906e00904500706e00923b009", + "0x6f00903600712e00923b00912e0092210071db00923b0091db00900e007", + "0x712e00900700723b00900700700706f12e1db01100e00906f00923b009", + "0x1250091fd00700723b00900712e0071db01112e28b1fd00e12e23b12e009", + "0x923b00900e00912500701822312e23b00912500916e00712500923b009", + "0x1b00700723b00900712e00701f00928c01b00923b12e01800907200700e", + "0x23b00902000901500702000923b00901500901f00701500923b009223009", + "0x901500702600923b00900702500700723b00902500902000702302512e", + "0x923b00902300902300700723b00922c00902000723c22c12e23b009026", + "0x12e22c00722900923b00922900902600702c00923b00923c009023007229", + "0x723b00901b00915500700723b00900712e00700728d00723b12e02c229", + "0x23b00903000902e00703000923b00900702c00702e00923b009007229007", + "0x3100703100923b00900722500722500923b00903002e12e030007030009", + "0x900e00912500703300923b00904500904500704500923b00922503112e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00703312e1fd00e00e00903300923b009033009036", + "0x2211fd00e12503a00722100923b00922100903800722100923b009007219", + "0x23b00900703b00700723b00900712e00703a03812e28e21903612e23b12e", + "0x900703e00703c00923b00900703c00712600923b00900712600703b009", + "0x714500704100923b00900704100714100923b00900714100703e00923b", + "0x4114103e03c12603b22314800704300923b00900704300714500923b009", + "0x23b00921900900e00703600923b00903600912500714800923b009043145", + "0xc600701b00923b00901b00902e00712e00923b00912e009221007219009", + "0x923b12e04c0090c000704c15004904700e23b00901b14812e2190361fd", + "0x722900700723b0091520090c200700723b00900712e00715300928f152", + "0x723b00915700905700705215712e23b00915500915900715500923b009", + "0x15900915d00715900923b00905400905a00705400923b009052009058007", + "0x4900923b00904900900e00704700923b00904700912500705700923b009", + "0x4904700e00905700923b00905700903600715000923b009150009221007", + "0x4700912500705800923b00915300904500700723b00900712e007057150", + "0x15000923b00915000922100704900923b00904900900e00704700923b009", + "0x723b00900712e00705815004904700e00905800923b009058009036007", + "0x923b00900705d00705a00923b00900722900700723b00901b009155007", + "0x22500705d00923b00915d05a12e03000715d00923b00915d00902e00715d", + "0x23b00906000904500706000923b00905d15e12e03100715e00923b009007", + "0x22100703a00923b00903a00900e00703800923b00903800912500715f009", + "0x15f12e03a03800e00915f00923b00915f00903600712e00923b00912e009", + "0x723b00922300915e00700723b00901f00905400700723b00900712e007", + "0x23b00906400902e00706400923b00900706000716000923b009007229007", + "0x3100716200923b00900722500716100923b00906416012e030007064009", + "0x900e00912500716400923b00906700904500706700923b00916116212e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00716412e1fd00e00e00916400923b009164009036", + "0x16800923b00900705d00716600923b00900722900700723b00912500915e", + "0x722500716b00923b00916816612e03000716800923b00916800902e007", + "0x923b00906e00904500706e00923b00916b06d12e03100706d00923b009", + "0x92210071db00923b0091db00900e00701100923b00901100912500706f", + "0x706f12e1db01100e00906f00923b00906f00903600712e00923b00912e", + "0x71db01112e2901fd00e12e23b12e00900712e00900700723b009007007", + "0x12e23b00912500916e00712500923b0091250091fd00700723b00900712e", + "0x929101b00923b12e01800907200700e00923b00900e009125007018223", + "0x901500901f00701500923b00922300901b00700723b00900712e00701f", + "0x700723b00902500902000702302512e23b00902000901500702000923b", + "0x922c00902000723c22c12e23b00902600901500702600923b009007025", + "0x2600702c00923b00923c00902300722900923b00902300902300700723b", + "0x900712e00700729200723b12e02c22912e22c00722900923b009229009", + "0x900702c00702e00923b00900722900700723b00901b00915500700723b", + "0x22500923b00903002e12e03000703000923b00903000902e00703000923b", + "0x4500904500704500923b00922503112e03100703100923b009007225007", + "0x1fd00923b0091fd00900e00700e00923b00900e00912500703300923b009", + "0x1fd00e00e00903300923b00903300903600712e00923b00912e009221007", + "0x922100903800722100923b00900721900700723b00900712e00703312e", + "0x12e00703a03812e29321903612e23b12e2211fd00e12503a00722100923b", + "0x3c00712600923b00900712600703b00923b00900703b00700723b009007", + "0x714100923b00900714100703e00923b00900703e00703c00923b009007", + "0x4300923b00900704300714500923b00900714500704100923b009007041", + "0x903600912500714800923b00904314504114103e03c12603b223148007", + "0x712e00923b00912e00922100721900923b00921900900e00703600923b", + "0x4904700e23b00901b14812e2190361fd1b300701b00923b00901b00902e", + "0x700723b00900712e00715300929415200923b12e04c0090c000704c150", + "0x12e23b00915500915900715500923b00900722900700723b0091520090c2", + "0x905a00705400923b00905200905800700723b009157009057007052157", + "0x923b00904700912500705700923b00915900915d00715900923b009054", + "0x903600715000923b00915000922100704900923b00904900900e007047", + "0x904500700723b00900712e00705715004904700e00905700923b009057", + "0x923b00904900900e00704700923b00904700912500705800923b009153", + "0x4700e00905800923b00905800903600715000923b009150009221007049", + "0x900722900700723b00901b00915500700723b00900712e007058150049", + "0x3000715d00923b00915d00902e00715d00923b00900705d00705a00923b", + "0x905d15e12e03100715e00923b00900722500705d00923b00915d05a12e", + "0x703800923b00903800912500715f00923b00906000904500706000923b", + "0x915f00903600712e00923b00912e00922100703a00923b00903a00900e", + "0x901f00905400700723b00900712e00715f12e03a03800e00915f00923b", + "0x900706000716000923b00900722900700723b00922300915e00700723b", + "0x16100923b00906416012e03000706400923b00906400902e00706400923b", + "0x6700904500706700923b00916116212e03100716200923b009007225007", + "0x1fd00923b0091fd00900e00700e00923b00900e00912500716400923b009", + "0x1fd00e00e00916400923b00916400903600712e00923b00912e009221007", + "0x23b00900722900700723b00912500915e00700723b00900712e00716412e", + "0x12e03000716800923b00916800902e00716800923b00900705d007166009", + "0x23b00916b06d12e03100706d00923b00900722500716b00923b009168166", + "0xe00701100923b00901100912500706f00923b00906e00904500706e009", + "0x23b00906f00903600712e00923b00912e0092210071db00923b0091db009", + "0x12e00900712e00900700723b00900700700706f12e1db01100e00906f009", + "0x23b00912500901b00700723b00900712e0071db01112e2951fd00e12e23b", + "0x701f01b12e23b00901800901500701800923b00922300901f007223009", + "0x12e23b00901500901500701500923b00900702500700723b00901b009020", + "0x902300702300923b00901f00902300700723b009020009020007025020", + "0x923b00900e00912500702300923b00902300902600702600923b009025", + "0x722900700723b00900712e00700729600723b12e02602312e22c00700e", + "0x723c00923b00923c00902e00723c00923b00900702c00722c00923b009", + "0x22902c12e03100702c00923b00900722500722900923b00923c22c12e030", + "0xe00923b00900e00912500703000923b00902e00904500702e00923b009", + "0x3000903600712e00923b00912e0092210071fd00923b0091fd00900e007", + "0x900721900700723b00900712e00703012e1fd00e00e00903000923b009", + "0x12e23b12e2251fd00e12503a00722500923b00922500903800722500923b", + "0x703600923b00900703b00700723b00900712e00722103312e297045031", + "0x3a00923b00900703e00703800923b00900703c00721900923b009007126", + "0x923b00900714500712600923b00900704100703b00923b009007141007", + "0x903e03c12603b03a03821903622314800703e00923b00900704300703c", + "0x704500923b00904500900e00703100923b00903100912500714100923b", + "0x4314504100e23b00914112e04503100e0c700712e00923b00912e009221", + "0xc200700723b00900712e00704900929804700923b12e1480090c0007148", + "0x4c12e23b00915000915900715000923b00900722900700723b009047009", + "0x15300905a00715300923b00915200905800700723b00904c009057007152", + "0x4100923b00904100912500715700923b00915500915d00715500923b009", + "0x15700903600704300923b00904300922100714500923b00914500900e007", + "0x4900904500700723b00900712e00715704314504100e00915700923b009", + "0x14500923b00914500900e00704100923b00904100912500705200923b009", + "0x14504100e00905200923b00905200903600704300923b009043009221007", + "0x23b00900705d00705400923b00900722900700723b00900712e007052043", + "0x705700923b00915905412e03000715900923b00915900902e007159009", + "0x905a00904500705a00923b00905705812e03100705800923b009007225", + "0x722100923b00922100900e00703300923b00903300912500715d00923b", + "0x12e22103300e00915d00923b00915d00903600712e00923b00912e009221", + "0x923b00900722900700723b00912500915e00700723b00900712e00715d", + "0x5d12e03000715e00923b00915e00902e00715e00923b00900705d00705d", + "0x923b00906015f12e03100715f00923b00900722500706000923b00915e", + "0x900e00701100923b00901100912500706400923b009160009045007160", + "0x923b00906400903600712e00923b00912e0092210071db00923b0091db", + "0x23b12e00900712e00900700723b00900700700706412e1db01100e009064", + "0x923b00912500901b00700723b00900712e0071db01112e2991fd00e12e", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b00900702500700723b00901b009", + "0x2500902300702300923b00901f00902300700723b009020009020007025", + "0xe00923b00900e00912500702300923b00902300902600702600923b009", + "0x900722900700723b00900712e00700729a00723b12e02602312e22c007", + "0x3000723c00923b00923c00902e00723c00923b00900702c00722c00923b", + "0x922902c12e03100702c00923b00900722500722900923b00923c22c12e", + "0x700e00923b00900e00912500703000923b00902e00904500702e00923b", + "0x903000903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703012e1fd00e00e00903000923b", + "0x3112e23b12e2251fd00e12503a00722500923b009225009038007225009", + "0x12600703600923b00900703b00700723b00900712e00722103312e29b045", + "0x703a00923b00900703e00703800923b00900703c00721900923b009007", + "0x3c00923b00900714500712600923b00900704100703b00923b009007141", + "0x23b00903e03c12603b03a03821903622314800703e00923b009007043007", + "0x22100704500923b00904500900e00703100923b009031009125007141009", + "0x14804314504100e23b00914112e04503100e1b700712e00923b00912e009", + "0x90c200700723b00900712e00704900929c04700923b12e1480090c0007", + "0x15204c12e23b00915000915900715000923b00900722900700723b009047", + "0x915300905a00715300923b00915200905800700723b00904c009057007", + "0x704100923b00904100912500715700923b00915500915d00715500923b", + "0x915700903600704300923b00904300922100714500923b00914500900e", + "0x904900904500700723b00900712e00715704314504100e00915700923b", + "0x714500923b00914500900e00704100923b00904100912500705200923b", + "0x4314504100e00905200923b00905200903600704300923b009043009221", + "0x923b00900705d00705400923b00900722900700723b00900712e007052", + "0x22500705700923b00915905412e03000715900923b00915900902e007159", + "0x23b00905a00904500705a00923b00905705812e03100705800923b009007", + "0x22100722100923b00922100900e00703300923b00903300912500715d009", + "0x15d12e22103300e00915d00923b00915d00903600712e00923b00912e009", + "0x5d00923b00900722900700723b00912500915e00700723b00900712e007", + "0x15e05d12e03000715e00923b00915e00902e00715e00923b00900705d007", + "0x16000923b00906015f12e03100715f00923b00900722500706000923b009", + "0x1db00900e00701100923b00901100912500706400923b009160009045007", + "0x6400923b00906400903600712e00923b00912e0092210071db00923b009", + "0x12e23b12e00900712e00900700723b00900700700706412e1db01100e009", + "0x22300923b00912500901b00700723b00900712e0071db01112e29d1fd00e", + "0x902000701f01b12e23b00901800901500701800923b00922300901f007", + "0x2502012e23b00901500901500701500923b00900702500700723b00901b", + "0x902500902300702300923b00901f00902300700723b009020009020007", + "0x700e00923b00900e00912500702300923b00902300902600702600923b", + "0x23b00900722900700723b00900712e00700729e00723b12e02602312e22c", + "0x12e03000723c00923b00923c00902e00723c00923b00900702c00722c009", + "0x23b00922902c12e03100702c00923b00900722500722900923b00923c22c", + "0xe00700e00923b00900e00912500703000923b00902e00904500702e009", + "0x23b00903000903600712e00923b00912e0092210071fd00923b0091fd009", + "0x923b00900721900700723b00900712e00703012e1fd00e00e009030009", + "0x4503112e23b12e2251fd00e12503a00722500923b009225009038007225", + "0x712600703600923b00900703b00700723b00900712e00722103312e29f", + "0x14100703a00923b00900703e00703800923b00900703c00721900923b009", + "0x703c00923b00900714500712600923b00900704100703b00923b009007", + "0x923b00903e03c12603b03a03821903622314800703e00923b009007043", + "0x922100704500923b00904500900e00703100923b009031009125007141", + "0x714804314504100e23b00914112e04503100e0c900712e00923b00912e", + "0x470090c200700723b00900712e0070490092a004700923b12e1480090c0", + "0x715204c12e23b00915000915900715000923b00900722900700723b009", + "0x23b00915300905a00715300923b00915200905800700723b00904c009057", + "0xe00704100923b00904100912500715700923b00915500915d007155009", + "0x23b00915700903600704300923b00904300922100714500923b009145009", + "0x23b00904900904500700723b00900712e00715704314504100e009157009", + "0x22100714500923b00914500900e00704100923b009041009125007052009", + "0x5204314504100e00905200923b00905200903600704300923b009043009", + "0x15900923b00900705d00705400923b00900722900700723b00900712e007", + "0x722500705700923b00915905412e03000715900923b00915900902e007", + "0x923b00905a00904500705a00923b00905705812e03100705800923b009", + "0x922100722100923b00922100900e00703300923b00903300912500715d", + "0x715d12e22103300e00915d00923b00915d00903600712e00923b00912e", + "0x705d00923b00900722900700723b00912500915e00700723b00900712e", + "0x915e05d12e03000715e00923b00915e00902e00715e00923b00900705d", + "0x716000923b00906015f12e03100715f00923b00900722500706000923b", + "0x91db00900e00701100923b00901100912500706400923b009160009045", + "0x906400923b00906400903600712e00923b00912e0092210071db00923b", + "0xe12e23b12e00900712e00900700723b00900700700706412e1db01100e", + "0x722300923b00912500901b00700723b00900712e0071db01112e2a11fd", + "0x1b00902000701f01b12e23b00901800901500701800923b00922300901f", + "0x702502012e23b00901500901500701500923b00900702500700723b009", + "0x23b00902500902300702300923b00901f00902300700723b009020009020", + "0x22c00700e00923b00900e00912500702300923b009023009026007026009", + "0x923b00900722900700723b00900712e0070072a200723b12e02602312e", + "0x22c12e03000723c00923b00923c00902e00723c00923b00900702c00722c", + "0x923b00922902c12e03100702c00923b00900722500722900923b00923c", + "0x900e00700e00923b00900e00912500703000923b00902e00904500702e", + "0x923b00903000903600712e00923b00912e0092210071fd00923b0091fd", + "0x22500923b00900721900700723b00900712e00703012e1fd00e00e009030", + "0x2a304503112e23b12e2251fd00e12503a00722500923b009225009038007", + "0x900712600703600923b00900703b00700723b00900712e00722103312e", + "0x714100703a00923b00900703e00703800923b00900703c00721900923b", + "0x4300703c00923b00900714500712600923b00900704100703b00923b009", + "0x14100923b00903e03c12603b03a03821903622314800703e00923b009007", + "0x4500900e00700723b00904100915200714504112e23b009141009078007", + "0x23b00914512e0451251ad00712e00923b00912e00922100704500923b009", + "0x4900923b12e04700907b00703100923b009031009125007047148043125", + "0x4900918700704c00923b00900722900700723b00900712e0071500092a4", + "0x723b00915300915500715515312e23b00915200915300715200923b009", + "0x15512e05200704c00923b00904c00915700715500923b00915500902e007", + "0x12e23b00915700915900700723b00905200905400705215712e23b00904c", + "0x905a00705700923b00915900905800700723b009054009057007159054", + "0x923b00903100912500705a00923b00905800915d00705800923b009057", + "0x903600714800923b00914800922100704300923b00904300900e007031", + "0x904500700723b00900712e00705a14804303100e00905a00923b00905a", + "0x923b00904300900e00703100923b00903100912500715d00923b009150", + "0x3100e00915d00923b00915d00903600714800923b009148009221007043", + "0x900705d00705d00923b00900722900700723b00900712e00715d148043", + "0x6000923b00915e05d12e03000715e00923b00915e00902e00715e00923b", + "0x16000904500716000923b00906015f12e03100715f00923b009007225007", + "0x22100923b00922100900e00703300923b00903300912500706400923b009", + "0x22103300e00906400923b00906400903600712e00923b00912e009221007", + "0x23b00900722900700723b00912500915e00700723b00900712e00706412e", + "0x12e03000716200923b00916200902e00716200923b00900705d007161009", + "0x23b00906716412e03100716400923b00900722500706700923b009162161", + "0xe00701100923b00901100912500716800923b009166009045007166009", + "0x23b00916800903600712e00923b00912e0092210071db00923b0091db009", + "0x12e00900712e00900700723b00900700700716812e1db01100e009168009", + "0x23b00912500901b00700723b00900712e0071db01112e2a51fd00e12e23b", + "0x701f01b12e23b00901800901500701800923b00922300901f007223009", + "0x12e23b00901500901500701500923b00900702500700723b00901b009020", + "0x902300702300923b00901f00902300700723b009020009020007025020", + "0x923b00900e00912500702300923b00902300902600702600923b009025", + "0x722900700723b00900712e0070072a600723b12e02602312e22c00700e", + "0x723c00923b00923c00902e00723c00923b00900702c00722c00923b009", + "0x22902c12e03100702c00923b00900722500722900923b00923c22c12e030", + "0xe00923b00900e00912500703000923b00902e00904500702e00923b009", + "0x3000903600712e00923b00912e0092210071fd00923b0091fd00900e007", + "0x900721900700723b00900712e00703012e1fd00e00e00903000923b009", + "0x12e23b12e2251fd00e12503a00722500923b00922500903800722500923b", + "0x703600923b00900703b00700723b00900712e00722103312e2a7045031", + "0x3a00923b00900703e00703800923b00900703c00721900923b009007126", + "0x923b00900714500712600923b00900704100703b00923b009007141007", + "0x903e03c12603b03a03821903622314800703e00923b00900704300703c", + "0x700723b00904100915200714504112e23b00914100907800714100923b", + "0x12e0451250cb00712e00923b00912e00922100704500923b00904500900e", + "0x12e04700907b00703100923b00903100912500704714804312523b009145", + "0x704c00923b00900722900700723b00900712e0071500092a804900923b", + "0x15300915500715515312e23b00915200915300715200923b009049009187", + "0x704c00923b00904c00915700715500923b00915500902e00700723b009", + "0x15700915900700723b00905200905400705215712e23b00904c15512e052", + "0x5700923b00915900905800700723b00905400905700715905412e23b009", + "0x3100912500705a00923b00905800915d00705800923b00905700905a007", + "0x14800923b00914800922100704300923b00904300900e00703100923b009", + "0x723b00900712e00705a14804303100e00905a00923b00905a009036007", + "0x4300900e00703100923b00903100912500715d00923b009150009045007", + "0x15d00923b00915d00903600714800923b00914800922100704300923b009", + "0x705d00923b00900722900700723b00900712e00715d14804303100e009", + "0x915e05d12e03000715e00923b00915e00902e00715e00923b00900705d", + "0x716000923b00906015f12e03100715f00923b00900722500706000923b", + "0x922100900e00703300923b00903300912500706400923b009160009045", + "0x906400923b00906400903600712e00923b00912e00922100722100923b", + "0x22900700723b00912500915e00700723b00900712e00706412e22103300e", + "0x16200923b00916200902e00716200923b00900705d00716100923b009007", + "0x16412e03100716400923b00900722500706700923b00916216112e030007", + "0x923b00901100912500716800923b00916600904500716600923b009067", + "0x903600712e00923b00912e0092210071db00923b0091db00900e007011", + "0x12e00900700723b00900700700716812e1db01100e00916800923b009168", + "0x901b00700723b00900712e0071db01112e2a91fd00e12e23b12e009007", + "0x12e23b00901800901500701800923b00922300901f00722300923b009125", + "0x1500901500701500923b00900702500700723b00901b00902000701f01b", + "0x2300923b00901f00902300700723b00902000902000702502012e23b009", + "0xe00912500702300923b00902300902600702600923b009025009023007", + "0x723b00900712e0070072aa00723b12e02602312e22c00700e00923b009", + "0x23b00923c00902e00723c00923b00900702c00722c00923b009007229007", + "0x3100702c00923b00900722500722900923b00923c22c12e03000723c009", + "0x900e00912500703000923b00902e00904500702e00923b00922902c12e", + "0x712e00923b00912e0092210071fd00923b0091fd00900e00700e00923b", + "0x700723b00900712e00703012e1fd00e00e00903000923b009030009036", + "0x2251fd00e12503a00722500923b00922500903800722500923b009007219", + "0x23b00900703b00700723b00900712e00722103312e2ab04503112e23b12e", + "0x900703e00703800923b00900703c00721900923b009007126007036009", + "0x714500712600923b00900704100703b00923b00900714100703a00923b", + "0x12603b03a03821903622314800703e00923b00900704300703c00923b009", + "0x904100915200714504112e23b00914100907800714100923b00903e03c", + "0xcd00712e00923b00912e00922100704500923b00904500900e00700723b", + "0x7b00703100923b00903100912500704714804312523b00914512e045125", + "0x23b00900722900700723b00900712e0071500092ac04900923b12e047009", + "0x715515312e23b00915200915300715200923b00904900918700704c009", + "0x23b00904c00915700715500923b00915500902e00700723b009153009155", + "0x700723b00905200905400705215712e23b00904c15512e05200704c009", + "0x915900905800700723b00905400905700715905412e23b009157009159", + "0x705a00923b00905800915d00705800923b00905700905a00705700923b", + "0x914800922100704300923b00904300900e00703100923b009031009125", + "0x712e00705a14804303100e00905a00923b00905a00903600714800923b", + "0x703100923b00903100912500715d00923b00915000904500700723b009", + "0x915d00903600714800923b00914800922100704300923b00904300900e", + "0x23b00900722900700723b00900712e00715d14804303100e00915d00923b", + "0x12e03000715e00923b00915e00902e00715e00923b00900705d00705d009", + "0x23b00906015f12e03100715f00923b00900722500706000923b00915e05d", + "0xe00703300923b00903300912500706400923b009160009045007160009", + "0x23b00906400903600712e00923b00912e00922100722100923b009221009", + "0x23b00912500915e00700723b00900712e00706412e22103300e009064009", + "0x916200902e00716200923b00900705d00716100923b009007229007007", + "0x716400923b00900722500706700923b00916216112e03000716200923b", + "0x1100912500716800923b00916600904500716600923b00906716412e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700716812e1db01100e00916800923b009168009036007", + "0x723b00900712e0071db01112e2ad1fd00e12e23b12e00900712e009007", + "0x1800901500701800923b00922300901f00722300923b00912500901b007", + "0x701500923b00900702500700723b00901b00902000701f01b12e23b009", + "0x901f00902300700723b00902000902000702502012e23b009015009015", + "0x702300923b00902300902600702600923b00902500902300702300923b", + "0x712e0070072ae00723b12e02602312e22c00700e00923b00900e009125", + "0x902e00723c00923b00900702c00722c00923b00900722900700723b009", + "0x923b00900722500722900923b00923c22c12e03000723c00923b00923c", + "0x12500703000923b00902e00904500702e00923b00922902c12e03100702c", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00703012e1fd00e00e00903000923b00903000903600712e009", + "0x12503a00722500923b00922500903800722500923b00900721900700723b", + "0x3b00700723b00900712e00722103312e2af04503112e23b12e2251fd00e", + "0x703800923b00900703c00721900923b00900712600703600923b009007", + "0x12600923b00900704100703b00923b00900714100703a00923b00900703e", + "0x3821903622314800703e00923b00900704300703c00923b009007145007", + "0x15200714504112e23b00914100907800714100923b00903e03c12603b03a", + "0x923b00904500900e00703100923b00903100912500700723b009041009", + "0x4300e23b00914512e04503100e1aa00712e00923b00912e009221007045", + "0x723b00900712e00704c0092b015000923b12e0490090cf007049047148", + "0x91530091a300715300923b0091500091a800715200923b009007229007", + "0x715700923b0091570091a100700723b0091550090d100715715512e23b", + "0x905400705405212e23b00915215712e1a000715200923b009152009157", + "0x723b00915900905700705715912e23b00905200915900700723b009054", + "0x5a00915d00705a00923b00905800905a00705800923b009057009058007", + "0x14800923b00914800900e00704300923b00904300912500715d00923b009", + "0x14804300e00915d00923b00915d00903600704700923b009047009221007", + "0x4300912500705d00923b00904c00904500700723b00900712e00715d047", + "0x4700923b00904700922100714800923b00914800900e00704300923b009", + "0x723b00900712e00705d04714804300e00905d00923b00905d009036007", + "0x23b00906000902e00706000923b00900705d00715e00923b009007229007", + "0x3100716000923b00900722500715f00923b00906015e12e030007060009", + "0x903300912500716100923b00906400904500706400923b00915f16012e", + "0x712e00923b00912e00922100722100923b00922100900e00703300923b", + "0x700723b00900712e00716112e22103300e00916100923b009161009036", + "0x6700923b00900705d00716200923b00900722900700723b00912500915e", + "0x722500716400923b00906716212e03000706700923b00906700902e007", + "0x923b00916800904500716800923b00916416612e03100716600923b009", + "0x92210071db00923b0091db00900e00701100923b00901100912500716b", + "0x716b12e1db01100e00916b00923b00916b00903600712e00923b00912e", + "0x71db01112e2b11fd00e12e23b12e00900712e00900700723b009007007", + "0x923b00922300901f00722300923b00912500901b00700723b00900712e", + "0x702500700723b00901b00902000701f01b12e23b009018009015007018", + "0x723b00902000902000702502012e23b00901500901500701500923b009", + "0x2300902600702600923b00902500902300702300923b00901f009023007", + "0x723b12e02602312e22c00700e00923b00900e00912500702300923b009", + "0x23b00900702c00722c00923b00900722900700723b00900712e0070072b2", + "0x722900923b00923c22c12e03000723c00923b00923c00902e00723c009", + "0x902e00904500702e00923b00922902c12e03100702c00923b009007225", + "0x71fd00923b0091fd00900e00700e00923b00900e00912500703000923b", + "0x12e1fd00e00e00903000923b00903000903600712e00923b00912e009221", + "0x23b00922500903800722500923b00900721900700723b00900712e007030", + "0x712e00722103312e2b304503112e23b12e2251fd00e12503a007225009", + "0x703c00721900923b00900712600703600923b00900703b00700723b009", + "0x4100703b00923b00900714100703a00923b00900703e00703800923b009", + "0x703e00923b00900704300703c00923b00900714500712600923b009007", + "0x23b00914100907800714100923b00903e03c12603b03a038219036223148", + "0x22900704300923b0091450090d500700723b00904100915200714504112e", + "0x23b00904700919b00704904712e23b00904300919f00714800923b009007", + "0x12e0da00714800923b00914800915700704900923b0090490090d8007007", + "0x23b00915000915900700723b00904c00905400704c15012e23b009148049", + "0x5a00715500923b00915300905800700723b00915200905700715315212e", + "0x23b00903100912500705200923b00915700915d00715700923b009155009", + "0x3600712e00923b00912e00922100704500923b00904500900e007031009", + "0x22900700723b00900712e00705212e04503100e00905200923b009052009", + "0x15900923b00915900902e00715900923b00900705d00705400923b009007", + "0x5812e03100705800923b00900722500705700923b00915905412e030007", + "0x923b00903300912500715d00923b00905a00904500705a00923b009057", + "0x903600712e00923b00912e00922100722100923b00922100900e007033", + "0x915e00700723b00900712e00715d12e22103300e00915d00923b00915d", + "0x2e00715e00923b00900705d00705d00923b00900722900700723b009125", + "0x23b00900722500706000923b00915e05d12e03000715e00923b00915e009", + "0x706400923b00916000904500716000923b00906015f12e03100715f009", + "0x912e0092210071db00923b0091db00900e00701100923b009011009125", + "0x700700706412e1db01100e00906400923b00906400903600712e00923b", + "0x712e0071db01112e2b41fd00e12e23b12e00900712e00900700723b009", + "0x701800923b00922300901f00722300923b00912500901b00700723b009", + "0x23b00900702500700723b00901b00902000701f01b12e23b009018009015", + "0x2300700723b00902000902000702502012e23b009015009015007015009", + "0x23b00902300902600702600923b00902500902300702300923b00901f009", + "0x72b500723b12e02602312e22c00700e00923b00900e009125007023009", + "0x23c00923b00900702c00722c00923b00900722900700723b00900712e007", + "0x722500722900923b00923c22c12e03000723c00923b00923c00902e007", + "0x923b00902e00904500702e00923b00922902c12e03100702c00923b009", + "0x92210071fd00923b0091fd00900e00700e00923b00900e009125007030", + "0x703012e1fd00e00e00903000923b00903000903600712e00923b00912e", + "0x22500923b00922500903800722500923b00900721900700723b00900712e", + "0x23b00900712e00722103312e2b604503112e23b12e2251fd00e12503a007", + "0x921900915300721900923b00900719800703600923b009007229007007", + "0x703a00923b00903a00902e00700723b00903800915500703a03812e23b", + "0x905400712603b12e23b00903603a12e05200703600923b009036009157", + "0x723b00903c00905700703e03c12e23b00903b00915900700723b009126", + "0x4100915d00704100923b00914100905a00714100923b00903e009058007", + "0x4500923b00904500900e00703100923b00903100912500714500923b009", + "0x4503100e00914500923b00914500903600712e00923b00912e009221007", + "0x23b00900705d00704300923b00900722900700723b00900712e00714512e", + "0x704700923b00914804312e03000714800923b00914800902e007148009", + "0x915000904500715000923b00904704912e03100704900923b009007225", + "0x722100923b00922100900e00703300923b00903300912500704c00923b", + "0x12e22103300e00904c00923b00904c00903600712e00923b00912e009221", + "0x923b00900722900700723b00912500915e00700723b00900712e00704c", + "0x15212e03000715300923b00915300902e00715300923b00900705d007152", + "0x923b00915515712e03100715700923b00900722500715500923b009153", + "0x900e00701100923b00901100912500705400923b009052009045007052", + "0x923b00905400903600712e00923b00912e0092210071db00923b0091db", + "0x23b12e00900712e00900700723b00900700700705412e1db01100e009054", + "0x923b00912500901b00700723b00900712e0071db01112e2b71fd00e12e", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b00900702500700723b00901b009", + "0x2500902300702300923b00901f00902300700723b009020009020007025", + "0xe00923b00900e00912500702300923b00902300902600702600923b009", + "0x900722900700723b00900712e0070072b800723b12e02602312e22c007", + "0x3000723c00923b00923c00902e00723c00923b00900702c00722c00923b", + "0x922902c12e03100702c00923b00900722500722900923b00923c22c12e", + "0x700e00923b00900e00912500703000923b00902e00904500702e00923b", + "0x903000903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703012e1fd00e00e00903000923b", + "0x3112e23b12e2251fd00e12503a00722500923b009225009038007225009", + "0x12600703600923b00900703b00700723b00900712e00722103312e2b9045", + "0x703a00923b00900703e00703800923b00900703c00721900923b009007", + "0x3c00923b00900714500712600923b00900704100703b00923b009007141", + "0x23b00903e03c12603b03a03821903622314800703e00923b009007043007", + "0x12500700723b00904100915200714504112e23b009141009078007141009", + "0x23b00912e00922100704500923b00904500900e00703100923b009031009", + "0x490090dd00704904714804300e23b00914512e04503100e19700712e009", + "0x15200923b00900722900700723b00900712e00704c0092ba15000923b12e", + "0x902000715715512e23b00915300901500715300923b00915000918e007", + "0x5400923b0090520090df00705200923b00915700902300700723b009155", + "0x5700705805712e23b00915900915900715900923b00905415212e030007", + "0x923b00905a00905a00705a00923b00905800905800700723b009057009", + "0x900e00704300923b00904300912500705d00923b00915d00915d00715d", + "0x923b00905d00903600704700923b00904700922100714800923b009148", + "0x923b00904c00904500700723b00900712e00705d04714804300e00905d", + "0x922100714800923b00914800900e00704300923b00904300912500715e", + "0x715e04714804300e00915e00923b00915e00903600704700923b009047", + "0x715f00923b00900705d00706000923b00900722900700723b00900712e", + "0x900722500716000923b00915f06012e03000715f00923b00915f00902e", + "0x16200923b00916100904500716100923b00916006412e03100706400923b", + "0x12e00922100722100923b00922100900e00703300923b009033009125007", + "0x12e00716212e22103300e00916200923b00916200903600712e00923b009", + "0x5d00706700923b00900722900700723b00912500915e00700723b009007", + "0x23b00916406712e03000716400923b00916400902e00716400923b009007", + "0x4500716b00923b00916616812e03100716800923b009007225007166009", + "0x23b0091db00900e00701100923b00901100912500706d00923b00916b009", + "0xe00906d00923b00906d00903600712e00923b00912e0092210071db009", + "0x1fd00e12e23b12e00900712e00900700723b00900700700706d12e1db011", + "0x1f00722300923b00912500901b00700723b00900712e0071db01112e2bb", + "0x901b00902000701f01b12e23b00901800901500701800923b009223009", + "0x2000702502012e23b00901500901500701500923b00900702500700723b", + "0x923b00902500902300702300923b00901f00902300700723b009020009", + "0x12e22c00700e00923b00900e00912500702300923b009023009026007026", + "0x22c00923b00900722900700723b00900712e0070072bc00723b12e026023", + "0x23c22c12e03000723c00923b00923c00902e00723c00923b00900702c007", + "0x2e00923b00922902c12e03100702c00923b00900722500722900923b009", + "0x1fd00900e00700e00923b00900e00912500703000923b00902e009045007", + "0x3000923b00903000903600712e00923b00912e0092210071fd00923b009", + "0x722500923b00900721900700723b00900712e00703012e1fd00e00e009", + "0x12e2bd04503112e23b12e2251fd00e12503a00722500923b009225009038", + "0x23b00900712600703600923b00900703b00700723b00900712e007221033", + "0x900714100703a00923b00900703e00703800923b00900703c007219009", + "0x704300703c00923b00900714500712600923b00900704100703b00923b", + "0x714100923b00903e03c12603b03a03821903622314800703e00923b009", + "0x903100912500700723b00904100915200714504112e23b009141009078", + "0x712e00923b00912e00922100704500923b00904500900e00703100923b", + "0x923b12e0490090dd00704904714804300e23b00914512e04503100e0e1", + "0x918e00715200923b00900722900700723b00900712e00704c0092be150", + "0x23b00915500902000715715512e23b00915300901500715300923b009150", + "0x12e03000705400923b0090520090df00705200923b009157009023007007", + "0x905700905700705805712e23b00915900915900715900923b009054152", + "0x15d00715d00923b00905a00905a00705a00923b00905800905800700723b", + "0x23b00914800900e00704300923b00904300912500705d00923b00915d009", + "0xe00905d00923b00905d00903600704700923b009047009221007148009", + "0x12500715e00923b00904c00904500700723b00900712e00705d047148043", + "0x23b00904700922100714800923b00914800900e00704300923b009043009", + "0x900712e00715e04714804300e00915e00923b00915e009036007047009", + "0x15f00902e00715f00923b00900705d00706000923b00900722900700723b", + "0x6400923b00900722500716000923b00915f06012e03000715f00923b009", + "0x912500716200923b00916100904500716100923b00916006412e031007", + "0x923b00912e00922100722100923b00922100900e00703300923b009033", + "0x23b00900712e00716212e22103300e00916200923b00916200903600712e", + "0x23b00900705d00706700923b00900722900700723b00912500915e007007", + "0x716600923b00916406712e03000716400923b00916400902e007164009", + "0x916b00904500716b00923b00916616812e03100716800923b009007225", + "0x71db00923b0091db00900e00701100923b00901100912500706d00923b", + "0x12e1db01100e00906d00923b00906d00903600712e00923b00912e009221", + "0x1112e2bf1fd00e12e23b12e00900712e00900700723b00900700700706d", + "0x922300901f00722300923b00912500901b00700723b00900712e0071db", + "0x700723b00901b00902000701f01b12e23b00901800901500701800923b", + "0x902000902000702502012e23b00901500901500701500923b009007025", + "0x2600702600923b00902500902300702300923b00901f00902300700723b", + "0x12e02602312e22c00700e00923b00900e00912500702300923b009023009", + "0x702c00722c00923b00900722900700723b00900712e0070072c000723b", + "0x923b00923c22c12e03000723c00923b00923c00902e00723c00923b009", + "0x904500702e00923b00922902c12e03100702c00923b009007225007229", + "0x923b0091fd00900e00700e00923b00900e00912500703000923b00902e", + "0xe00e00903000923b00903000903600712e00923b00912e0092210071fd", + "0x22500903800722500923b00900721900700723b00900712e00703012e1fd", + "0x722103312e2c104503112e23b12e2251fd00e12503a00722500923b009", + "0x721900923b00900712600703600923b00900703b00700723b00900712e", + "0x3b00923b00900714100703a00923b00900703e00703800923b00900703c", + "0x923b00900704300703c00923b00900714500712600923b009007041007", + "0x14100907800714100923b00903e03c12603b03a03821903622314800703e", + "0x3100923b00903100912500700723b00904100915200714504112e23b009", + "0x3100e18a00712e00923b00912e00922100704500923b00904500900e007", + "0x92c215000923b12e04900918900704904714804300e23b00914512e045", + "0x23b00915000918800715200923b00900722900700723b00900712e00704c", + "0xe500700723b00915500918b00715715512e23b00915300918c007153009", + "0x915215712e18400715200923b00915200915700715700923b009157009", + "0x5715912e23b00905200915900700723b00905400905400705405212e23b", + "0x905800905a00705800923b00905700905800700723b009159009057007", + "0x704300923b00904300912500715d00923b00905a00915d00705a00923b", + "0x915d00903600704700923b00904700922100714800923b00914800900e", + "0x904c00904500700723b00900712e00715d04714804300e00915d00923b", + "0x714800923b00914800900e00704300923b00904300912500705d00923b", + "0x4714804300e00905d00923b00905d00903600704700923b009047009221", + "0x923b00900705d00715e00923b00900722900700723b00900712e00705d", + "0x22500715f00923b00906015e12e03000706000923b00906000902e007060", + "0x23b00906400904500706400923b00915f16012e03100716000923b009007", + "0x22100722100923b00922100900e00703300923b009033009125007161009", + "0x16112e22103300e00916100923b00916100903600712e00923b00912e009", + "0x16200923b00900722900700723b00912500915e00700723b00900712e007", + "0x6716212e03000706700923b00906700902e00706700923b00900705d007", + "0x16800923b00916416612e03100716600923b00900722500716400923b009", + "0x1db00900e00701100923b00901100912500716b00923b009168009045007", + "0x16b00923b00916b00903600712e00923b00912e0092210071db00923b009", + "0x12e23b12e00900712e00900700723b00900700700716b12e1db01100e009", + "0x12500923b0091250091fd00700723b00900712e0071db01112e2c31fd00e", + "0x907200700e00923b00900e00912500701822312e23b00912500916e007", + "0x23b00922300901b00700723b00900712e00701f0092c401b00923b12e018", + "0x702302512e23b00902000901500702000923b00901500901f007015009", + "0x12e23b00902600901500702600923b00900702500700723b009025009020", + "0x902300722900923b00902300902300700723b00922c00902000723c22c", + "0x23b12e02c22912e22c00722900923b00922900902600702c00923b00923c", + "0x900722900700723b00901b00915500700723b00900712e0070072c5007", + "0x3000703000923b00903000902e00703000923b00900702c00702e00923b", + "0x922503112e03100703100923b00900722500722500923b00903002e12e", + "0x700e00923b00900e00912500703300923b00904500904500704500923b", + "0x903300903600712e00923b00912e0092210071fd00923b0091fd00900e", + "0x23b00900721900700723b00900712e00703312e1fd00e00e00903300923b", + "0x3612e23b12e2211fd00e12503a00722100923b009221009038007221009", + "0x12600703b00923b00900703b00700723b00900712e00703a03812e2c6219", + "0x703e00923b00900703e00703c00923b00900703c00712600923b009007", + "0x14500923b00900714500704100923b00900704100714100923b009007141", + "0x23b00904314504114103e03c12603b22314800704300923b009007043007", + "0x2e00700723b00904700915200704904712e23b009148009078007148009", + "0x23b00900722900715000923b00901b04912e18300701b00923b00901b009", + "0xa500700723b00915200904a00715315212e23b0091500090a300704c009", + "0x904c15312e1b500704c00923b00904c00915700715300923b009153009", + "0x5405212e23b00915500915900700723b00915700905400715715512e23b", + "0x915900905a00715900923b00905400905800700723b009052009057007", + "0x703600923b00903600912500705800923b00905700915d00705700923b", + "0x905800903600712e00923b00912e00922100721900923b00921900900e", + "0x901b00915500700723b00900712e00705812e21903600e00905800923b", + "0x15d00902e00715d00923b00900705d00705a00923b00900722900700723b", + "0x15e00923b00900722500705d00923b00915d05a12e03000715d00923b009", + "0x912500715f00923b00906000904500706000923b00905d15e12e031007", + "0x923b00912e00922100703a00923b00903a00900e00703800923b009038", + "0x23b00900712e00715f12e03a03800e00915f00923b00915f00903600712e", + "0x23b00900722900700723b00922300915e00700723b00901f009054007007", + "0x12e03000706400923b00906400902e00706400923b009007060007160009", + "0x23b00916116212e03100716200923b00900722500716100923b009064160", + "0xe00700e00923b00900e00912500716400923b009067009045007067009", + "0x23b00916400903600712e00923b00912e0092210071fd00923b0091fd009", + "0x23b00912500915e00700723b00900712e00716412e1fd00e00e009164009", + "0x916800902e00716800923b00900705d00716600923b009007229007007", + "0x706d00923b00900722500716b00923b00916816612e03000716800923b", + "0x1100912500706f00923b00906e00904500706e00923b00916b06d12e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700706f12e1db01100e00906f00923b00906f009036007", + "0x723b00900712e0071db01112e2c71fd00e12e23b12e00900712e009007", + "0x1800901500701800923b00922300901f00722300923b00912500901b007", + "0x701500923b00900702500700723b00901b00902000701f01b12e23b009", + "0x901f00902300700723b00902000902000702502012e23b009015009015", + "0x702300923b00902300902600702600923b00902500902300702300923b", + "0x712e0070072c800723b12e02602312e22c00700e00923b00900e009125", + "0x902e00723c00923b00900702c00722c00923b00900722900700723b009", + "0x923b00900722500722900923b00923c22c12e03000723c00923b00923c", + "0x12500703000923b00902e00904500702e00923b00922902c12e03100702c", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00703012e1fd00e00e00903000923b00903000903600712e009", + "0x12503a00722500923b00922500903800722500923b00900721900700723b", + "0x22900700723b00900712e00722103312e2c904503112e23b12e2251fd00e", + "0x3812e23b00921900915300721900923b0090070a000703600923b009007", + "0x3600915700703a00923b00903a00902e00700723b00903800915500703a", + "0x23b00912600905400712603b12e23b00903603a12e05200703600923b009", + "0x905800700723b00903c00905700703e03c12e23b00903b009159007007", + "0x923b00904100915d00704100923b00914100905a00714100923b00903e", + "0x922100704500923b00904500900e00703100923b009031009125007145", + "0x714512e04503100e00914500923b00914500903600712e00923b00912e", + "0x714800923b00900705d00704300923b00900722900700723b00900712e", + "0x900722500704700923b00914804312e03000714800923b00914800902e", + "0x4c00923b00915000904500715000923b00904704912e03100704900923b", + "0x12e00922100722100923b00922100900e00703300923b009033009125007", + "0x12e00704c12e22103300e00904c00923b00904c00903600712e00923b009", + "0x5d00715200923b00900722900700723b00912500915e00700723b009007", + "0x23b00915315212e03000715300923b00915300902e00715300923b009007", + "0x4500705200923b00915515712e03100715700923b009007225007155009", + "0x23b0091db00900e00701100923b00901100912500705400923b009052009", + "0xe00905400923b00905400903600712e00923b00912e0092210071db009", + "0x1fd00e12e23b12e00900712e00900700723b00900700700705412e1db011", + "0x1f00722300923b00912500901b00700723b00900712e0071db01112e2ca", + "0x901b00902000701f01b12e23b00901800901500701800923b009223009", + "0x2000702502012e23b00901500901500701500923b00900702500700723b", + "0x923b00902500902300702300923b00901f00902300700723b009020009", + "0x12e22c00700e00923b00900e00912500702300923b009023009026007026", + "0x22c00923b00900722900700723b00900712e0070072cb00723b12e026023", + "0x23c22c12e03000723c00923b00923c00902e00723c00923b00900702c007", + "0x2e00923b00922902c12e03100702c00923b00900722500722900923b009", + "0x1fd00900e00700e00923b00900e00912500703000923b00902e009045007", + "0x3000923b00903000903600712e00923b00912e0092210071fd00923b009", + "0x722500923b00900721900700723b00900712e00703012e1fd00e00e009", + "0x12e2cc04503112e23b12e2251fd00e12503a00722500923b009225009038", + "0x23b00900719800703600923b00900722900700723b00900712e007221033", + "0x2e00700723b00903800915500703a03812e23b009219009153007219009", + "0x903603a12e05200703600923b00903600915700703a00923b00903a009", + "0x3e03c12e23b00903b00915900700723b00912600905400712603b12e23b", + "0x914100905a00714100923b00903e00905800700723b00903c009057007", + "0x703100923b00903100912500714500923b00904100915d00704100923b", + "0x914500903600712e00923b00912e00922100704500923b00904500900e", + "0x23b00900722900700723b00900712e00714512e04503100e00914500923b", + "0x12e03000714800923b00914800902e00714800923b00900705d007043009", + "0x23b00904704912e03100704900923b00900722500704700923b009148043", + "0xe00703300923b00903300912500704c00923b009150009045007150009", + "0x23b00904c00903600712e00923b00912e00922100722100923b009221009", + "0x23b00912500915e00700723b00900712e00704c12e22103300e00904c009", + "0x915300902e00715300923b00900705d00715200923b009007229007007", + "0x715700923b00900722500715500923b00915315212e03000715300923b", + "0x1100912500705400923b00905200904500705200923b00915515712e031", + "0x12e00923b00912e0092210071db00923b0091db00900e00701100923b009", + "0x723b00900700700705412e1db01100e00905400923b009054009036007", + "0x723b00900712e0071db01112e2cd1fd00e12e23b12e00900712e009007", + "0x912500701822312e23b00912500916e00712500923b0091250091fd007", + "0x900712e00701f0092ce01b00923b12e01800907200700e00923b00900e", + "0x1500702000923b00901500901f00701500923b00922300901b00700723b", + "0x923b00900702500700723b00902500902000702302512e23b009020009", + "0x902300700723b00922c00902000723c22c12e23b009026009015007026", + "0x923b00922900902600702c00923b00923c00902300722900923b009023", + "0x915500700723b00900712e0070072cf00723b12e02c22912e22c007229", + "0x2e00703000923b00900702c00702e00923b00900722900700723b00901b", + "0x23b00900722500722500923b00903002e12e03000703000923b009030009", + "0x703300923b00904500904500704500923b00922503112e031007031009", + "0x912e0092210071fd00923b0091fd00900e00700e00923b00900e009125", + "0x712e00703312e1fd00e00e00903300923b00903300903600712e00923b", + "0x3a00722100923b00922100903800722100923b00900721900700723b009", + "0x700723b00900712e00703a03812e2d021903612e23b12e2211fd00e125", + "0x3c00923b00900703c00712600923b00900712600703b00923b00900703b", + "0x923b00900704100714100923b00900714100703e00923b00900703e007", + "0x12603b22314800704300923b00900704300714500923b009007145007041", + "0x704904712e23b00914800907800714800923b00904314504114103e03c", + "0x901b04912e0e800701b00923b00901b00902e00700723b009047009152", + "0x715315212e23b00915000915300704c00923b00900722900715000923b", + "0x23b00904c00915700715300923b00915300902e00700723b009152009155", + "0x700723b00915700905400715715512e23b00904c15312e05200704c009", + "0x905400905800700723b00905200905700705405212e23b009155009159", + "0x705800923b00905700915d00705700923b00915900905a00715900923b", + "0x912e00922100721900923b00921900900e00703600923b009036009125", + "0x712e00705812e21903600e00905800923b00905800903600712e00923b", + "0x705d00705a00923b00900722900700723b00901b00915500700723b009", + "0x923b00915d05a12e03000715d00923b00915d00902e00715d00923b009", + "0x904500706000923b00905d15e12e03100715e00923b00900722500705d", + "0x923b00903a00900e00703800923b00903800912500715f00923b009060", + "0x3800e00915f00923b00915f00903600712e00923b00912e00922100703a", + "0x22300915e00700723b00901f00905400700723b00900712e00715f12e03a", + "0x902e00706400923b00900706000716000923b00900722900700723b009", + "0x923b00900722500716100923b00906416012e03000706400923b009064", + "0x12500716400923b00906700904500706700923b00916116212e031007162", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00716412e1fd00e00e00916400923b00916400903600712e009", + "0x900705d00716600923b00900722900700723b00912500915e00700723b", + "0x16b00923b00916816612e03000716800923b00916800902e00716800923b", + "0x6e00904500706e00923b00916b06d12e03100706d00923b009007225007", + "0x1db00923b0091db00900e00701100923b00901100912500706f00923b009", + "0x1db01100e00906f00923b00906f00903600712e00923b00912e009221007", + "0x23b00900700700700723b00900716000701100923b00900707100706f12e", + "0x23b00900712e00701b01812e2d12231db12e23b12e12e00712e009007007", + "0x12500701501f12e23b00900e00916e00700e00923b00900e0091fd007007", + "0x712e0070200092d21fd00923b12e0150090720071db00923b0091db009", + "0x722300923b00922300900e0071db00923b0091db00912500700723b009", + "0x1db1251740071fd00923b0091fd01112e07400701f00923b00901f0091fd", + "0x723c0092d322c00923b12e02600907600702602302512523b00901f223", + "0x23b12e02c00907700702c22912e23b00922c00918000700723b00900712e", + "0x722500923b00922900901b00700723b00900712e0070300092d402e009", + "0x4500902000703304512e23b00903100901500703100923b00922500901f", + "0x721903612e23b00922100901500722100923b00900702500700723b009", + "0x23b00921900902300703800923b00903300902300700723b009036009020", + "0x72d500723b12e03a03812e22c00703800923b00903800902600703a009", + "0x723b0091fd00915500700723b00902e00905700700723b00900712e007", + "0x23b00912600902e00712600923b00900702c00703b00923b009007229007", + "0x3100703e00923b00900722500703c00923b00912603b12e030007126009", + "0x902500912500704100923b00914100904500714100923b00903c03e12e", + "0x702300923b00902300900e00700900923b00900900903300702500923b", + "0x230090251fd00904100923b00904100903600712500923b009125009221", + "0x914500903800714500923b00900721900700723b00900712e007041125", + "0x12e00704904712e2d614804312e23b12e14502302512503a00714500923b", + "0x3c00704c00923b00900712600715000923b00900703b00700723b009007", + "0x715500923b00900714100715300923b00900703e00715200923b009007", + "0x5400923b00900704300705200923b00900714500715700923b009007041", + "0x915900907800715900923b00905405215715515315204c150223148007", + "0x704300923b00904300912500700723b00905700915200705805712e23b", + "0x912500922100714800923b00914800900e00700900923b009009009033", + "0x702e00923b00902e0091570071fd00923b0091fd00902e00712500923b", + "0x907b00706015e05d15d05a1fd23b00902e1fd0581251480090431db179", + "0x923b00900722900700723b00900712e0071600092d715f00923b12e060", + "0x15500706716212e23b00916100915300716100923b00915f009187007064", + "0x923b00906400915700706700923b00906700902e00700723b009162009", + "0x15900700723b00916600905400716616412e23b00906406712e052007064", + "0x23b00916b00905800700723b00916800905700716b16812e23b009164009", + "0x12500706f00923b00906e00915d00706e00923b00906d00905a00706d009", + "0x23b00905d00900e00715d00923b00915d00903300705a00923b00905a009", + "0x1fd00906f00923b00906f00903600715e00923b00915e00922100705d009", + "0x707100923b00916000904500700723b00900712e00706f15e05d15d05a", + "0x905d00900e00715d00923b00915d00903300705a00923b00905a009125", + "0x907100923b00907100903600715e00923b00915e00922100705d00923b", + "0x700723b00902e00905700700723b00900712e00707115e05d15d05a1fd", + "0x7200923b00900705d00716e00923b00900722900700723b0091fd009155", + "0x722500707400923b00907216e12e03000707200923b00907200902e007", + "0x923b00907600904500707600923b00907417412e03100717400923b009", + "0x900e00700900923b00900900903300704700923b009047009125007180", + "0x923b00918000903600712500923b00912500922100704900923b009049", + "0x23b00903000905400700723b00900712e0071801250490090471fd009180", + "0x23b00900722900700723b0091fd00915500700723b00922900915e007007", + "0x12e03000707800923b00907800902e00707800923b00900708d007077009", + "0x23b00918607b12e03100707b00923b00900722500718600923b009078077", + "0x3300702500923b00902500912500708d00923b009187009045007187009", + "0x23b00912500922100702300923b00902300900e00700900923b009009009", + "0x712e00708d1250230090251fd00908d00923b00908d009036007125009", + "0x12500707f00923b00923c00904500700723b0091fd00915500700723b009", + "0x23b00902300900e00700900923b00900900903300702500923b009025009", + "0x1fd00907f00923b00907f00903600712500923b009125009221007023009", + "0x15e00700723b00902000905400700723b00900712e00707f125023009025", + "0x708e00923b00900722900700723b00901100907f00700723b00901f009", + "0x908f08e12e03000708f00923b00908f00902e00708f00923b009007060", + "0x709200923b00909009112e03100709100923b00900722500709000923b", + "0x90090090330071db00923b0091db00912500709300923b009092009045", + "0x712500923b00912500922100722300923b00922300900e00700900923b", + "0x723b00900712e0070931252230091db1fd00909300923b009093009036", + "0x923b00900722900700723b00901100907f00700723b00900e00915e007", + "0x9412e03000709500923b00909500902e00709500923b00900705d007094", + "0x923b00909609712e03100709700923b00900722500709600923b009095", + "0x903300701800923b00901800912500709900923b009098009045007098", + "0x923b00912500922100701b00923b00901b00900e00700900923b009009", + "0x900700700709912501b0090181fd00909900923b009099009036007125", + "0x900712e0071db01112e2d81fd00e12e23b12e00900712e00900700723b", + "0x701822312e23b00912500916e00712500923b0091250091fd00700723b", + "0x12e00701f0092d901b00923b12e01800907200700e00923b00900e009125", + "0x1512e23b00922300916e00722300923b0092230091fd00700723b009007", + "0x1b00700723b00900712e0070230092da02500923b12e020009072007020", + "0x23b00922c00901500722c00923b00902600901f00702600923b009015009", + "0x901500702c00923b00900702500700723b00923c00902000722923c12e", + "0x923b00922900902300700723b00902e00902000703002e12e23b00902c", + "0x12e22c00722500923b00922500902600703100923b009030009023007225", + "0x723b00902500915500700723b00900712e0070072db00723b12e031225", + "0x923b00900702c00704500923b00900722900700723b00901b009155007", + "0x22500722100923b00903304512e03000703300923b00903300902e007033", + "0x23b00921900904500721900923b00922103612e03100703600923b009007", + "0x2210071fd00923b0091fd00900e00700e00923b00900e009125007038009", + "0x3812e1fd00e00e00903800923b00903800903600712e00923b00912e009", + "0x923b00903a00903800703a00923b00900721900700723b00900712e007", + "0x900712e00703e03c12e2dc12603b12e23b12e03a1fd00e12503a00703a", + "0x900703c00704100923b00900712600714100923b00900703b00700723b", + "0x704100714800923b00900714100704300923b00900703e00714500923b", + "0x14800715000923b00900704300704900923b00900714500704700923b009", + "0x923b00903b00912500704c00923b009150049047148043145041141223", + "0x902e00712e00923b00912e00922100712600923b00912600900e00703b", + "0x4c12e12603b01117b00702500923b00902500902e00701b00923b00901b", + "0x540092dd05200923b12e1570090c000715715515315200e23b00902501b", + "0x15900923b00900722900700723b0090520090c200700723b00900712e007", + "0x5800905800700723b00905700905700705805712e23b009159009159007", + "0x5d00923b00915d00915d00715d00923b00905a00905a00705a00923b009", + "0x15500922100715300923b00915300900e00715200923b009152009125007", + "0x12e00705d15515315200e00905d00923b00905d00903600715500923b009", + "0x15200923b00915200912500715e00923b00905400904500700723b009007", + "0x15e00903600715500923b00915500922100715300923b00915300900e007", + "0x2500915500700723b00900712e00715e15515315200e00915e00923b009", + "0x705d00706000923b00900722900700723b00901b00915500700723b009", + "0x923b00915f06012e03000715f00923b00915f00902e00715f00923b009", + "0x904500716100923b00916006412e03100706400923b009007225007160", + "0x923b00903e00900e00703c00923b00903c00912500716200923b009161", + "0x3c00e00916200923b00916200903600712e00923b00912e00922100703e", + "0x1500915e00700723b00902300905400700723b00900712e00716212e03e", + "0x708d00706700923b00900722900700723b00901b00915500700723b009", + "0x923b00916406712e03000716400923b00916400902e00716400923b009", + "0x904500716b00923b00916616812e03100716800923b009007225007166", + "0x923b0091fd00900e00700e00923b00900e00912500706d00923b00916b", + "0xe00e00906d00923b00906d00903600712e00923b00912e0092210071fd", + "0x22300915e00700723b00901f00905400700723b00900712e00706d12e1fd", + "0x902e00706f00923b00900706000706e00923b00900722900700723b009", + "0x923b00900722500707100923b00906f06e12e03000706f00923b00906f", + "0x12500707400923b00907200904500707200923b00907116e12e03100716e", + "0x23b00912e0092210071fd00923b0091fd00900e00700e00923b00900e009", + "0x900712e00707412e1fd00e00e00907400923b00907400903600712e009", + "0x900705d00717400923b00900722900700723b00912500915e00700723b", + "0x18000923b00907617412e03000707600923b00907600902e00707600923b", + "0x7800904500707800923b00918007712e03100707700923b009007225007", + "0x1db00923b0091db00900e00701100923b00901100912500718600923b009", + "0x1db01100e00918600923b00918600903600712e00923b00912e009221007", + "0x12500917500712500923b00912e00901b00700723b0090070ea00718612e", + "0x23b0091fd00917100700723b00900712e0070110092de1fd00e12e23b12e", + "0xee00701800923b0091db0090ec00722300923b00900e0090b40071db009", + "0x90f000701b00923b00900716c00700723b00900712e0070072df009007", + "0x923b00901f0090ec00722300923b0090110090b400701f00923b00901b", + "0x916900701500923b0090150091fd00701500923b009223009058007018", + "0x23b00902000916500700723b00900712e0070250092e002000923b12e018", + "0x912500722c00923b00902300916300702600923b0090070f3007023009", + "0x923b0090150091fd00700900923b00900900900e00700700923b009007", + "0x1fd0f600722c00923b00922c00902e00702600923b009026009047007015", + "0x2e102e00923b12e02c0091db00702c22923c12523b00922c026015009007", + "0x12e0f800703122512e23b00902e00922300700723b00900712e007030009", + "0x23b00923c00912500703300923b00904500915c00704500923b009031225", + "0x12500903300923b0090330090fa00722900923b00922900900e00723c009", + "0x912500722100923b00903000915600700723b00900712e00703322923c", + "0x923b0092210090fa00722900923b00922900900e00723c00923b00923c", + "0x700723b00902500905400700723b00900712e00722122923c125009221", + "0x921901512e0f800721900923b00903600915400703600923b00900716c", + "0x700700923b00900700912500703a00923b00903800915c00703800923b", + "0x3a00900712500903a00923b00903a0090fa00700900923b00900900900e", + "0x23b00912500922100712e00923b00912e00900e00700723b0090070ea007", + "0x923b12e2230090fd0072231db01112523b00912512e12e158007125009", + "0x10700701f00923b00901800915100700723b00900712e00701b0092e2018", + "0x23b00902000910200700723b00901500910100702001512e23b00901f009", + "0x722c02612e23b00902300915300702300923b009025009104007025009", + "0x23b00923c00915300723c00923b00922c00916300700723b009026009155", + "0x915300702e00923b00900714c00700723b00922900915500702c22912e", + "0x923b00902c00916300700723b00903000915500722503012e23b00902e", + "0x2e00703300923b00904503112e14f00704500923b009225009163007031", + "0x900712e0072210092e300723b12e03300910600703300923b009033009", + "0x14d0071db00923b0091db00922100701100923b00901100900e00700723b", + "0x3b0092e403a00923b12e03800914e00703821903612523b0091db01112e", + "0x23b00912600910a00712600923b00903a00914900700723b00900712e007", + "0x15204c15004904714804314504114103e02023b00903c00910c00703c009", + "0x14800915500700723b00904100914700700723b009141009101007155153", + "0x914700700723b00904900914600700723b00904700915500700723b009", + "0x2000700723b00915200902000700723b00904c00915e00700723b009150", + "0x15712e23b00903e00915300700723b00915500915e00700723b009153009", + "0x915500705715912e23b00905400915300705400923b00900714b007052", + "0x5a00923b00905700916300705800923b00905200916300700723b009159", + "0x710f00715d00923b00905a05812e14f00705800923b00905800902e007", + "0x714500923b0091450091fd00715d00923b00915d00902e00700723b009", + "0x12e15d00910600715700923b00915700902e00704300923b00904300902e", + "0x14400715e00923b00900716c00700723b00900712e00705d0092e500723b", + "0x23b0090600090a500715f00923b00915700902e00706000923b00915e009", + "0x23b00905d00911100700723b00900712e0070072e60090070ee007160009", + "0x915300716200923b00900714300716106412e23b009157009153007007", + "0x923b00916100916300700723b00906700915500716406712e23b009162", + "0x2e00716b00923b00916816612e14f00716800923b009164009163007166", + "0x900712e00706d0092e700723b12e16b00910600716b00923b00916b009", + "0x90a500706f00923b00906e00914400706e00923b00900716c00700723b", + "0x911100700723b00900712e0070072e80090070ee00707100923b00906f", + "0x707200923b00916e00911300716e00923b00900716c00700723b00906d", + "0x90710090a500715f00923b00906400902e00707100923b0090720090a5", + "0x723b00900712e0071740092e907400923b12e16000914000716000923b", + "0x900711800718007612e23b00915f00915300700723b009074009054007", + "0x700723b00907800915500718607812e23b00907700915300707700923b", + "0x18707b12e14f00718700923b00918600916300707b00923b009180009163", + "0x2ea00723b12e08d00910600708d00923b00908d00902e00708d00923b009", + "0x908e00914400708e00923b00900716c00700723b00900712e00707f009", + "0x712e0070072eb0090070ee00709000923b00908f0090a500708f00923b", + "0x911300709100923b00900716c00700723b00907f00911100700723b009", + "0x923b00907600902e00709000923b0090920090a500709200923b009091", + "0x23b00900712e0070072ec0090070ee00709400923b0090900090a5007093", + "0x909500914400709500923b00900716c00700723b009174009054007007", + "0x709400923b0090960090a500709300923b00915f00902e00709600923b", + "0x9700905400700723b00900712e0070980092ed09700923b12e094009140", + "0x700723b0090990091550071a509912e23b00909300915300700723b009", + "0x91a70091550070371a712e23b00909c00915300709c00923b009007115", + "0x14f00709f00923b00903700916300705b00923b0091a500916300700723b", + "0x12e1ac0091060071ac00923b0091ac00902e0071ac00923b00909f05b12e", + "0x712e0070072ef0090070ee00700723b00900712e0071b00092ee00723b", + "0x1fd00923c00700723b0091b000911100700723b0090070ea00700723b009", + "0x915500700723b00914500915e00700723b00900e00915200700723b009", + "0x2e0070a300923b00900713b0071b200923b00900722900700723b009043", + "0x23b00900722500704a00923b0090a31b212e0300070a300923b0090a3009", + "0x70a700923b0091b50091390071b500923b00904a0a512e0310070a5009", + "0x903600900e00700900923b00900900903300700700923b009007009125", + "0x90a700923b0090a700913700721900923b00921900922100703600923b", + "0x700723b00909800905400700723b00900712e0070a72190360090071fd", + "0x23b00921900922100703600923b00903600900e00700723b009093009155", + "0x923b12e0ac00914e0070ac1b80a912523b00921903612e14d007219009", + "0x10a0070b000923b0090ae00914900700723b00900712e0071bc0092f00ae", + "0x1ba0ba0b81bb0b60b41bd02023b0090b200910c0070b200923b0090b0009", + "0x723b0090b400910100700723b0091bd0091550071b60c20c01b90be0bc", + "0x23b0090b800915500700723b0091bb00915e00700723b0090b6009147007", + "0x90bc00914600700723b0091ba00915500700723b0090ba009155007007", + "0xc200902000700723b0090c000902000700723b0090be00914700700723b", + "0xb40070c400923b0091b900901b00700723b0091b600915e00700723b009", + "0x23b0090c60090150070c600923b0090c400901f0070c400923b0090c4009", + "0x90150071b700923b00900702500700723b0091b30090200070c71b312e", + "0x923b0090c700902300700723b0090c90090200071ad0c912e23b0091b7", + "0x12e22c0070cb00923b0090cb0090260070cd00923b0091ad0090230070cb", + "0x700723b0090070ea00700723b00900712e0070072f100723b12e0cd0cb", + "0x723b00900e00915200700723b00904300915500700723b00914500915e", + "0x923b00900711a0071aa00923b00900722900700723b0091fd00923c007", + "0x2250071a800923b0090cf1aa12e0300070cf00923b0090cf00902e0070cf", + "0x23b0090d10091390070d100923b0091a81a312e0310071a300923b009007", + "0xe00700900923b00900900903300700700923b0090070091250071a1009", + "0x23b0091a10091370071b800923b0091b80092210070a900923b0090a9009", + "0x23b0090070ea00700723b00900712e0071a11b80a90090071fd0091a1009", + "0x912800700723b0091a000923c0070d51a012e23b0091fd00911c007007", + "0xd800923b00919b00911300719b00923b00900716c00719f00923b0090d5", + "0xa900900e00700900923b00900900903300700700923b009007009125007", + "0x19f00923b00919f0091230071b800923b0091b80092210070a900923b009", + "0xd80090a500714500923b0091450091fd00704300923b00904300902e007", + "0xda1fd23b0090d814504319f00e1b80a90090070180000070d800923b009", + "0x23b00900712e0070e10092f20df00923b12e18e0090c000718e0dd197198", + "0x72f400700723b00918900905400718918a12e23b0090df0092f3007007", + "0x923b00918c0092f600718c00923b00918818a12e2f500718800923b009", + "0x900e00719800923b0091980090330070da00923b0090da00912500718b", + "0x923b00918b0091370070dd00923b0090dd00922100719700923b009197", + "0x23b0090e100913900700723b00900712e00718b0dd1971980da1fd00918b", + "0xe00719800923b0091980090330070da00923b0090da0091250070e5009", + "0x23b0090e50091370070dd00923b0090dd00922100719700923b009197009", + "0x23b0090070ea00700723b00900712e0070e50dd1971980da1fd0090e5009", + "0x900e00915200700723b00904300915500700723b00914500915e007007", + "0x912500718400923b0091bc00913900700723b0091fd00923c00700723b", + "0x923b0090a900900e00700900923b00900900903300700700923b009007", + "0x71fd00918400923b0091840091370071b800923b0091b80092210070a9", + "0x915200700723b0091fd00923c00700723b00900712e0071841b80a9009", + "0x700923b00900700912500718300923b00903b00913900700723b00900e", + "0x21900922100703600923b00903600900e00700900923b009009009033007", + "0x71832190360090071fd00918300923b00918300913700721900923b009", + "0x700723b0091fd00923c00700723b00922100911100700723b00900712e", + "0xe800923b0090072f70070a000923b00900722900700723b00900e009152", + "0x722500717900923b0090e80a012e0300070e800923b0090e800902e007", + "0x923b0090ea0091390070ea00923b00917917b12e03100717b00923b009", + "0x900e00700900923b00900900903300700700923b009007009125007175", + "0x923b0091750091370071db00923b0091db00922100701100923b009011", + "0x23b0091fd00923c00700723b00900712e0071751db0110090071fd009175", + "0x700912500717100923b00901b00913900700723b00900e009152007007", + "0x1100923b00901100900e00700900923b00900900903300700700923b009", + "0x90071fd00917100923b0091710091370071db00923b0091db009221007", + "0x12500923b00912e00912e03000712e00923b0090070091630071711db011", + "0x700e12512e00912500923b00912500915700700e00923b00900716c007", + "0x700723b00900716000722300923b00900707100701100923b0090072f8", + "0x923b00912e00922100700900923b00900900900e00700723b0090070ea", + "0x1500923b12e01f0090fd00701f01b01812523b00912e00912e15800712e", + "0x910700702500923b00901500915100700723b00900712e0070200092f9", + "0x923b00902600910200700723b00902300910100702602312e23b009025", + "0x15500702c22912e23b00923c00915300723c00923b00922c00910400722c", + "0x12e23b00902e00915300702e00923b00902c00916300700723b009229009", + "0x3100915300703100923b00900714c00700723b009030009155007225030", + "0x22100923b00922500916300700723b00904500915500703304512e23b009", + "0x902e00721900923b00903622112e14f00703600923b009033009163007", + "0x23b00900712e0070380092fa00723b12e21900910600721900923b009219", + "0x12e14d00701b00923b00901b00922100701800923b00901800900e007007", + "0x703e0092fb03c00923b12e12600914e00712603b03a12523b00901b018", + "0x923b00914100910a00714100923b00903c00914900700723b00900712e", + "0x15715515315204c1500491db04714804314502023b00904100910c007041", + "0x904700915e00700723b00914800914700700723b009043009101007052", + "0x4c00914600700723b00915000915500700723b00904900915500700723b", + "0x902000700723b00915300915e00700723b00915200914700700723b009", + "0x15300700723b00905200915e00700723b00915700902000700723b009155", + "0x23b00905700915300705700923b00900714b00715905412e23b009145009", + "0x16300715d00923b00915900916300700723b00905800915500705a05812e", + "0x905d15d12e14f00715d00923b00915d00902e00705d00923b00905a009", + "0x12e07400715e00923b00915e00902e00700723b00900710f00715e00923b", + "0x23b12e15e00910600705400923b00905400902e0071db00923b0091db223", + "0x914400715f00923b00900716c00700723b00900712e0070600092fc007", + "0x923b0091600090a500706400923b00905400902e00716000923b00915f", + "0x723b00906000911100700723b00900712e0070072fd0090070ee007161", + "0x16400915300716400923b00900714300706716212e23b009054009153007", + "0x16b00923b00906700916300700723b00916600915500716816612e23b009", + "0x902e00706e00923b00906d16b12e14f00706d00923b009168009163007", + "0x23b00900712e00706f0092fe00723b12e06e00910600706e00923b00906e", + "0x16e0090a500716e00923b00907100914400707100923b00900716c007007", + "0x6f00911100700723b00900712e0070072ff0090070ee00707200923b009", + "0xa500717400923b00907400911300707400923b00900716c00700723b009", + "0x23b0090720090a500706400923b00916200902e00707200923b009174009", + "0x700723b00900712e00718000930007600923b12e161009140007161009", + "0x23b00900711800707807712e23b00906400915300700723b009076009054", + "0x16300700723b00907b00915500718707b12e23b009186009153007186009", + "0x907f08d12e14f00707f00923b00918700916300708d00923b009078009", + "0x930100723b12e08e00910600708e00923b00908e00902e00708e00923b", + "0x23b00909000914400709000923b00900716c00700723b00900712e00708f", + "0x900712e0070073020090070ee00709200923b0090910090a5007091009", + "0x9300911300709300923b00900716c00700723b00908f00911100700723b", + "0x9500923b00907700902e00709200923b0090940090a500709400923b009", + "0x723b00900712e0070073030090070ee00709600923b0090920090a5007", + "0x23b00909700914400709700923b00900716c00700723b009180009054007", + "0x14000709600923b0090980090a500709500923b00906400902e007098009", + "0x909900905400700723b00900712e0071a500930409900923b12e096009", + "0x11500700723b00909c0091550071a709c12e23b00909500915300700723b", + "0x23b00905b00915500709f05b12e23b00903700915300703700923b009007", + "0x12e14f0071b000923b00909f0091630071ac00923b0091a7009163007007", + "0x23b12e1b20091060071b200923b0091b200902e0071b200923b0091b01ac", + "0x900712e0070073060090070ee00700723b00900712e0070a3009305007", + "0x91db00915500700723b0090a300911100700723b0090070ea00700723b", + "0xe00923c00700723b00912500915200700723b00901100924200700723b", + "0x902e0070a500923b00900713b00704a00923b00900722900700723b009", + "0x923b0090072250071b500923b0090a504a12e0300070a500923b0090a5", + "0x1250071b800923b0090a90093070070a900923b0091b50a712e0310070a7", + "0x23b00903b00922100703a00923b00903a00900e00700700923b009007009", + "0x900712e0071b803b03a00700e0091b800923b0091b800930800703b009", + "0x90070ea00700723b00909500915500700723b0091a500905400700723b", + "0x12800700723b0090ac00923c0070ae0ac12e23b00900e00911c00700723b", + "0x23b00903a00900e00700700923b0090070091250071bc00923b0090ae009", + "0x3090071bc00923b0091bc00912300703b00923b00903b00922100703a009", + "0xb600923b12e0b400930a0070b41bd0b20b000e23b0091bc03b03a00700e", + "0x12e30d0071fd00923b0090b600930c00700723b00900712e0071bb00930b", + "0x90ba0092410070ba0b812e23b0091fd0091660071fd00923b0091fd011", + "0xb000923b0090b00091250070bc00923b0091ba1db12e30e0071ba00923b", + "0xbc00930f0071bd00923b0091bd0092210070b200923b0090b200900e007", + "0x70c20c01b90be00e23b0090bc1251bd0b20b01fd3100070bc00923b009", + "0x1b60092f300700723b00900712e0070c40093111b600923b12e0c20090c0", + "0x923b0090b80c612e31200700723b0091b30090540071b30c612e23b009", + "0x900e0070be00923b0090be0091250071b700923b0090c70093130070c7", + "0x923b0091b70093080070c000923b0090c00092210071b900923b0091b9", + "0x723b0090b800916800700723b00900712e0071b70c01b90be00e0091b7", + "0x1b900900e0070be00923b0090be0091250070c900923b0090c4009307007", + "0xc900923b0090c90093080070c000923b0090c00092210071b900923b009", + "0x700723b0091db00915500700723b00900712e0070c90c01b90be00e009", + "0x923b0091bb00930700700723b00901100924200700723b009125009152", + "0x92210070b200923b0090b200900e0070b000923b0090b00091250071ad", + "0x71ad1bd0b20b000e0091ad00923b0091ad0093080071bd00923b0091bd", + "0x700723b00901100924200700723b00900e00923c00700723b00900712e", + "0x923b00903e00930700700723b00922300907f00700723b009125009152", + "0x922100703a00923b00903a00900e00700700923b0090070091250070cb", + "0x70cb03b03a00700e0090cb00923b0090cb00930800703b00923b00903b", + "0x700723b00900e00923c00700723b00903800911100700723b00900712e", + "0x723b00922300907f00700723b00912500915200700723b009011009242", + "0x23b0091aa00902e0071aa00923b0090072f70070cd00923b009007229007", + "0x310071a800923b0090072250070cf00923b0091aa0cd12e0300071aa009", + "0x90070091250070d100923b0091a30093070071a300923b0090cf1a812e", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b00900712e0070d101b01800700e0090d100923b0090d1009308", + "0x723b00912500915200700723b00901100924200700723b00900e00923c", + "0x90070091250071a100923b00902000930700700723b00922300907f007", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b0090070ea0071a101b01800700e0091a100923b0091a1009308", + "0x1fd0090150071fd00923b00900e00924000700e12e12e23b00912e009314", + "0x22300923b0091db00902300700723b0090110090200071db01112e23b009", + "0x12512e03000701800923b00901800902e00701800923b0092230090df007", + "0x923b00900700912500701f00923b00912e00924100701b00923b009018", + "0x915700701f00923b00901f00931500700900923b00900900900e007007", + "0x6e00702502001512523b00901b01f00900700e31600701b00923b00901b", + "0x902300906f00700723b00900712e00702600931702300923b12e025009", + "0x31800722900923b00900716c00700723b00923c00905400723c22c12e23b", + "0x901500912500702e00923b00902c00931900702c00923b00922922c12e", + "0x902e00923b00902e00931a00702000923b00902000900e00701500923b", + "0x12500703000923b00902600931b00700723b00900712e00702e020015125", + "0x23b00903000931a00702000923b00902000900e00701500923b009015009", + "0x12e00900917500700900923b00900700901b007030020015125009030009", + "0x923b00912500917100700723b00900712e00700e00931c12512e12e23b", + "0x70ee0071db00923b0091fd0090ec00701100923b00912e0090b40071fd", + "0x2230090f000722300923b00900716c00700723b00900712e00700731d009", + "0x1db00923b0090180090ec00701100923b00900e0090b400701800923b009", + "0x1db00916900701b00923b00901b0091fd00701b00923b009011009058007", + "0x923b00901f00916500700723b00900712e00701500931e01f00923b12e", + "0x91fd00702300923b00902500931f00702500923b009020009163007020", + "0x712e00702301b12e00902300923b00902300932000701b00923b00901b", + "0x932100702600923b00900716c00700723b00901500905400700723b009", + "0x923b00922c00932000701b00923b00901b0091fd00722c00923b009026", + "0x712500923b00912e00901b00700723b0090070ea00722c01b12e00922c", + "0x917100700723b00900712e0070110093221fd00e12e23b12e125009175", + "0x923b0091db0090ec00722300923b00900e0090b40071db00923b0091fd", + "0x1b00923b00900716c00700723b00900712e0070073230090070ee007018", + "0x1f0090ec00722300923b0090110090b400701f00923b00901b0090f0007", + "0x1500923b0090150091fd00701500923b00922300905800701800923b009", + "0x916500700723b00900712e00702500932402000923b12e018009169007", + "0x22c00923b00902300916300702600923b00900722900702300923b009020", + "0x150091fd00700900923b00900900900e00700700923b009007009125007", + "0x22c00923b00922c00902e00702600923b00902600915700701500923b009", + "0x23b12e02c00907600702c22923c12523b00922c0260150090071fd325007", + "0x3122512e23b00902e00918000700723b00900712e00703000932602e009", + "0x912500703300923b00904500932800704500923b00903122512e327007", + "0x923b00903300932900722900923b00922900900e00723c00923b00923c", + "0x22100923b00903000932a00700723b00900712e00703322923c125009033", + "0x22100932900722900923b00922900900e00723c00923b00923c009125007", + "0x902500905400700723b00900712e00722122923c12500922100923b009", + "0x12e32700721900923b00903600923f00703600923b00900716c00700723b", + "0x23b00900700912500703a00923b00903800932800703800923b009219015", + "0x12500903a00923b00903a00932900700900923b00900900900e007007009", + "0x700723b0091db0090570072231db12e23b00901100915900703a009007", + "0x900900903300700700923b00900700912500701800923b009223009058", + "0x712500923b00912500922100712e00923b00912e00900e00700900923b", + "0x90071db32b00701800923b0090180091fd0071fd00923b0091fd00902e", + "0x923b12e0250091b000702502001501f01b1fd23b0090181fd00e12512e", + "0x14000722c00923b0090230091b200700723b00900712e00702600932c023", + "0x923c00905400700723b00900712e00722900932d23c00923b12e22c009", + "0x70ee00702e00923b00902c00902e00702c00923b00900714c00700723b", + "0x90072f400700723b00922900905400700723b00900712e00700732e009", + "0x722500923b00902e00932f00702e00923b00903000902e00703000923b", + "0x901f00903300701b00923b00901b00912500703100923b009225009330", + "0x702000923b00902000922100701500923b00901500900e00701f00923b", + "0x723b00900712e00703102001501f01b1fd00903100923b009031009331", + "0x1f00903300701b00923b00901b00912500704500923b009026009332007", + "0x2000923b00902000922100701500923b00901500900e00701f00923b009", + "0x23b00900733300704502001501f01b1fd00904500923b009045009331007", + "0x900733400722300923b00900707100701100923b00900733300700e009", + "0x900700912500700723b0090070ea00700723b00900716000701b00923b", + "0x1f12523b00912e00712e33500712e00923b00912e0091fd00700700923b", + "0x700723b00900712e00702500933701800923b12e020009336007020015", + "0x1b12e33800702602312e23b00901500916e00701500923b0090150091fd", + "0x900712e00722c0093391db00923b12e02600907200701800923b009018", + "0x22312e07400700723b00900710f00723c00923b00902300901b00700723b", + "0x712e00702e00933a02c22912e23b12e23c0091750071db00923b0091db", + "0x722500923b0092290090b400703000923b00902c00917100700723b009", + "0x700723b00900712e00700733b0090070ee00703100923b0090300090ec", + "0x23b00902e0090b400703300923b0090450090f000704500923b00900716c", + "0x1fd00722100923b00922500905800703100923b0090330090ec007225009", + "0x712e00721900933c03600923b12e03100916900722100923b009221009", + "0x703a00923b00903800916300703800923b00903600916500700723b009", + "0x3a01f12e33d00703a00923b00903a00902e00701f00923b00901f009125", + "0x900712e00703c00933f1fd00923b12e12600933e00712603b12e23b009", + "0x71fd00923b0091fd01112e34000703e00923b00922100901b00700723b", + "0x917100700723b00900712e00714500934104114112e23b12e03e009175", + "0x923b0090430090ec00714800923b0091410090b400704300923b009041", + "0x4900923b00900716c00700723b00900712e0070073420090070ee007047", + "0x1500090ec00714800923b0091450090b400715000923b0090490090f0007", + "0x4c00923b00904c0091fd00704c00923b00914800905800704700923b009", + "0x916500700723b00900712e00715300934315200923b12e047009169007", + "0x923b00903b00912500715700923b00915500916300715500923b009152", + "0x705405212e23b00915703b12e33d00715700923b00915700902e00703b", + "0x90070ea00700723b00900712e00715900934412500923b12e05400933e", + "0x1fd00700900923b00900900900e00705200923b00905200912500700723b", + "0x905212534500712500923b00912500e12e34000704c00923b00904c009", + "0x12e00705d00934715d00923b12e05a00934600705a05805712523b00904c", + "0x923b12e06000934800706015e12e23b00915d00923e00700723b009007", + "0x23b00915f1251fd1db0181fd34a00700723b00900712e00716000934915f", + "0x716200923b00916115e12e34c00716100923b00906400934b007064009", + "0x905800900e00705700923b00905700912500706700923b00916200934d", + "0x900712e00706705805712500906700923b00906700934e00705800923b", + "0x1fd00934f00700723b00912500934f00700723b00901800910100700723b", + "0x34c00716400923b00916000923d00700723b0091db00915500700723b009", + "0x905700912500716800923b00916600934d00716600923b00916415e12e", + "0x916800923b00916800934e00705800923b00905800900e00705700923b", + "0x910100700723b0091db00915500700723b00900712e007168058057125", + "0x35000700723b0091fd00934f00700723b00912500934f00700723b009018", + "0x23b00905800900e00705700923b00905700912500716b00923b00905d009", + "0x23b00900712e00716b05805712500916b00923b00916b00934e007058009", + "0x901800910100700723b0091db00915500700723b0091fd00934f007007", + "0x935200706d00923b00905200912500700723b00900e00935100700723b", + "0x905400700723b00900712e0070073530090070ee00706e00923b009159", + "0x15500700723b0091fd00934f00700723b00900e00935100700723b009153", + "0x706f00923b00900716c00700723b00901800910100700723b0091db009", + "0x23b0090070ea00706e00923b00906f00935200706d00923b00903b009125", + "0x34d00716e00923b00907104c12e34c00707100923b00906e00923d007007", + "0x23b00907200934e00700900923b00900900900e00707200923b00916e009", + "0x723b00900e00935100700723b00900712e00707200906d125009072009", + "0x23b00901100935100700723b00901800910100700723b0091db009155007", + "0x70ee00717400923b00903c00935200707400923b00903b009125007007", + "0xe00935100700723b00921900905400700723b00900712e007007354009", + "0x935100700723b00901800910100700723b0091db00915500700723b009", + "0x707400923b00901f00912500707600923b00900716c00700723b009011", + "0x923b00917400923d00700723b0090070ea00717400923b009076009352", + "0xe00707800923b00907700934d00707700923b00918022112e34c007180", + "0x707800907412500907800923b00907800934e00700900923b009009009", + "0x700723b00901800910100700723b00900e00935100700723b00900712e", + "0x923b00922c00923d00700723b00922300907f00700723b009011009351", + "0x12500718700923b00907b00934d00707b00923b00918602312e34c007186", + "0x23b00918700934e00700900923b00900900900e00701f00923b00901f009", + "0x723b00900e00935100700723b00900712e00718700901f125009187009", + "0x23b00901b00935500700723b00901100935100700723b00922300907f007", + "0x34d00707f00923b00908d01512e34c00708d00923b00902500923d007007", + "0x23b00900900900e00701f00923b00901f00912500708e00923b00907f009", + "0x23b0090072f800708e00901f12500908e00923b00908e00934e007009009", + "0x900707100702000923b00900708e00701f00923b00900708f007018009", + "0x715f00722900923b00900709000722c00923b00900708e00702300923b", + "0x70ea00700723b00900716000722500923b00900707100702e00923b009", + "0x90310093570070362210330450311fd23b00901100935600700723b009", + "0x3a12e23b00903800915300703800923b00921900910400721903112e23b", + "0x912600915300712600923b00900735800700723b00903a00915500703b", + "0x714100923b00903b00916300700723b00903c00915500703e03c12e23b", + "0x903e00916300700723b00904100915500714504112e23b009141009153", + "0x700723b00914800915500704714812e23b00904300915300704300923b", + "0x15004912e14f00715000923b00904700916300704900923b009145009163", + "0x35900723b12e04c00910600704c00923b00904c00902e00704c00923b009", + "0xe00922100715300923b00912e00900e00700723b00900712e007152009", + "0x12e00700735b0090070ee00715700923b00903100935a00715500923b009", + "0x712e00923b00912e00900e00700723b00915200911100700723b009007", + "0xfd00715905405212523b00900e12e12e15800700e00923b00900e009221", + "0x903100910700700723b00900712e00705800935c05700923b12e159009", + "0x15e12e23b00905d00910700705d00923b00905700915100715d05a12e23b", + "0x15f00910400715f00923b00906000910200700723b00915e009101007060", + "0x16100923b00906400910400706400923b00915d00910200716000923b009", + "0x16100915300700723b00916200915500706716212e23b009160009153007", + "0x16800923b00906700916300700723b00916400915500716616412e23b009", + "0x902e00706d00923b00916b16812e14f00716b00923b009166009163007", + "0x23b00900712e00706e00935d00723b12e06d00910600706d00923b00906d", + "0x935a00715500923b00905400922100715300923b00905200900e007007", + "0x923b00915500922100715300923b00915300900e00715700923b00905a", + "0x7200923b12e16e00935f00716e07106f12523b00915515312e35e007155", + "0x710f00717400923b00907200936100700723b00900712e007074009360", + "0x17412e23b00917400936200707603312e23b00903300936200700723b009", + "0x900712e00707b18612e36407807712e23b12e180076007125363007180", + "0x22100934f00700723b00903600936500700723b00907800934f00700723b", + "0x924200700723b00915700910100700723b00903300934f00700723b009", + "0x15500700723b00902000909700700723b0091db00905700700723b009018", + "0x700723b00901f00909600700723b00902300907f00700723b009045009", + "0x723b00902e00906400700723b00922c00909700700723b00922500907f", + "0x23b00917400934f00700723b00922900905b00700723b0091fd009152007", + "0x23b00900712e0070073660090070ee00718700923b009077009125007007", + "0x12536300708d22112e23b00922100936200700723b00907b00934f007007", + "0x34f00700723b00900712e00709008f12e36708e07f12e23b12e08d174186", + "0x700723b00922100934f00700723b00903600936500700723b00908e009", + "0x723b00901800924200700723b00915700910100700723b00903300934f", + "0x23b00904500915500700723b00902000909700700723b0091db009057007", + "0x922500907f00700723b00901f00909600700723b00902300907f007007", + "0x1fd00915200700723b00902e00906400700723b00922c00909700700723b", + "0xea00718700923b00907f00912500700723b00922900905b00700723b009", + "0x2e00709200923b00900736800709100923b00900722900700723b009007", + "0x23b00900722500709300923b00909209112e03000709200923b009092009", + "0x709600923b00909500930700709500923b00909309412e031007094009", + "0x906f00900e00700900923b00900900903300718700923b009187009125", + "0x707100923b00907100922100712500923b00912500909900706f00923b", + "0x23b00900712e00709607112506f00918701100909600923b009096009308", + "0x23b0091fd00936900700723b00909000934f00700723b0090070ea007007", + "0x1250071ac09f12e23b0091a700936a00705b0371a709c1a5099098097223", + "0x23b00912500909900706f00923b00906f00900e00708f00923b00908f009", + "0x71b004512e23b00904500936b00707100923b009071009221007125009", + "0x1b21fd23b0091b01ac07112506f08f01136c0071b000923b0091b000902e", + "0x23b00900712e0070a900936d0a700923b12e1b50091b00071b50a504a0a3", + "0x90a50070ac00923b0091b800936e0071b800923b0090a70091b2007007", + "0x900712e0071bc00936f0ae00923b12e0ac0091400070ac00923b0090ac", + "0x1db00905700700723b00901800924200700723b0090ae00905400700723b", + "0x907f00700723b00904500915500700723b00902000909700700723b009", + "0x37100700723b00909700937000700723b00901f00909600700723b009023", + "0x700723b00902e00906400700723b00922c00909700700723b009098009", + "0x723b00909f00937400700723b00903700937300700723b00905b009372", + "0x23b00909900937700700723b0091a500937600700723b00909c009375007", + "0x903600936500700723b00922900905b00700723b00922500907f007007", + "0x15700910100700723b00903300934f00700723b00922100934f00700723b", + "0x902e0070b200923b0090073780070b000923b00900722900700723b009", + "0x923b0090072250071bd00923b0090b20b012e0300070b200923b0090b2", + "0x1250071bb00923b0090b60093070070b600923b0091bd0b412e0310070b4", + "0x23b0090a300900e00700900923b0090090090330071b200923b0091b2009", + "0x3080070a500923b0090a500922100704a00923b00904a0090990070a3009", + "0x723b00900712e0071bb0a504a0a30091b20110091bb00923b0091bb009", + "0x1571fd34a0070b804512e23b00904500936b00700723b0091bc009054007", + "0x937900723c00923b00923c22912e09500723c00923b0090362210330b8", + "0x23b0090a50092210070a300923b0090a300900e0071ba0ba12e23b00923c", + "0x923b12e1b900914e0071b90be0bc12523b0090a50a312e14d0070a5009", + "0x10a0071b600923b0090c000914900700723b00900712e0070c200937a0c0", + "0x923b0090c600937b0070c600923b00900714c0070c400923b0091b6009", + "0x1b700902e0071b700923b0091b300937d0070c700923b00900737c0071b3", + "0x23b0090c71b704a12537e0070c700923b0090c700902e0071b700923b009", + "0x37f0070cd00923b0090cb00937b0070cb00923b00900714c0071ad0c912e", + "0x923b0090cf00902e0070cf00923b0090cd00937d0071aa00923b009007", + "0x1a31a812e23b0091aa0cf0c912537e0071aa00923b0091aa00902e0070cf", + "0x23b0090c400910c0071a100923b0090071430070d100923b009007380007", + "0x23b0091a000915500718a0e10df18e0dd1971980da0d819b19f0d51a0020", + "0x919b00915e00700723b00919f00914700700723b0090d5009101007007", + "0x19700914600700723b00919800915500700723b0090d800915500700723b", + "0x902000700723b00918e00915e00700723b0090dd00914700700723b009", + "0x38100700723b00918a00915e00700723b0090e100902000700723b0090df", + "0x938300718c18812e23b00918900938200718900923b0090da1a10d1125", + "0xe512523b00918b00938500718b00923b00918c00938400700723b009188", + "0x2e0070e800923b0090a000937d0070a000923b0091a300937b007183184", + "0xe50e81a812537e0070e500923b0090e500902e0070e800923b0090e8009", + "0x923b0090ea00937d0070ea00923b00917b00937b00717b17912e23b009", + "0x12537e00718400923b00918400902e00717500923b00917500902e007175", + "0xee00937d0070ee00923b0090ec00937b0070ec17112e23b009184175179", + "0x18300923b00918300902e00716c00923b00916c00902e00716c00923b009", + "0x716500923b00916900937b0071690f012e23b00918316c17112537e007", + "0x23b00916300902e00716300923b00916500937d0070f300923b009007386", + "0xf612e23b0090f31630f012537e0070f300923b0090f300902e007163009", + "0x937d0070fa00923b0090f800937b00715c00923b0091ad00937b0070f8", + "0x923b00915400902e00715400923b00915c00937d00715600923b0090fa", + "0xfd15812e23b0091561540f612537e00715600923b00915600902e007154", + "0xbc12e3870070be00923b0090be0092210070bc00923b0090bc00900e007", + "0x90fd00902e00715800923b00915800909900710702c15112523b0090be", + "0x10100923b12e1070090fd00702c00923b00902c02e12e1620070fd00923b", + "0x910400710400923b00910100915100700723b00900712e007102009388", + "0x923b00914f00937d00714f00923b0090fd00937b00714c00923b009104", + "0x3014d12e23b00914c10615812537e00710600923b00910600902e007106", + "0x14d00909900715100923b00915100900e0071b200923b0091b2009125007", + "0x923b00903022512e0740071ba00923b0091ba0091a500714d00923b009", + "0x12e10c00907b00710c10a14914e00e23b0091ba14d1511b200e389007030", + "0x14b00923b00903000937b00700723b00900712e00714600938a14700923b", + "0x14400902e00714400923b00914b00937d00710f00923b009147009187007", + "0x914300937b00714311112e23b00910f14410a12537e00714400923b009", + "0x2e00711800923b00911300937d00714000923b00900738600711300923b", + "0x14011811112537e00714000923b00914000902e00711800923b009118009", + "0x923b00913b00937d00713b00923b00911500937b00711502612e23b009", + "0x723b00913900910100712811c11a1371391fd23b0090ba009356007025", + "0x23b00911c00934f00700723b00911a00934f00700723b009137009155007", + "0x905800700723b00912300905700700012312e23b0091db009159007007", + "0x2f500923b0092f40091440072f400923b00900716c0072f300923b009000", + "0x914e0091250072f600923b00905b03709f09c1a5099098097223148007", + "0x714900923b00914900900e00700900923b00900900903300714e00923b", + "0x2f70091230072f712812e23b00912800938b00702c00923b00902c009221", + "0x12e23b00902500936b00702500923b00902502312e0740072f700923b009", + "0xa50072f300923b0092f30091fd0072f800923b0092f800902e0072f8025", + "0x914e01800000702600923b00902622c12e0370072f500923b0092f5009", + "0x1b01f12e1a700730930830701b2421fd23b0092f52f32f82f72f602c149", + "0x23b00900712e00730c00938c30a00923b12e3090090c000701b00923b009", + "0x936900700723b00924100905400724130d12e23b00930a0092f3007007", + "0x731600923b00900716c00731524031431331231030f30e22323b00930d", + "0x930700900e00724200923b00924200912500731800923b009316009144", + "0x730800923b00930800922100702600923b00902600909900730700923b", + "0x3072421db38d00731800923b0093180090a500704500923b00904500902e", + "0x23b00901502012e03700731f31b01531a3191fd23b009318045314308026", + "0x700723b00900712e00732100938f32000923b12e31f00938e007015009", + "0x931b00922100731a00923b00931a00900e00731900923b009319009125", + "0x23b00912831b31a31900e30900712800923b00912800912300731b00923b", + "0x900712e00723f00939032a00923b12e32900930a00732932832732500e", + "0x722300923b00922301812e30d00722300923b00932a00930c00700723b", + "0x905400733133012e23b00932000939100732f32b12e23b009223009166", + "0x923b00933202512e30e00733200923b00932f00924100700723b009331", + "0x32500912500733400923b00931524033031331231030f30e223148007333", + "0x32800923b00932800922100732700923b00932700900e00732500923b009", + "0x33500e23b0093333343283273251fd31000733300923b00933300930f007", + "0x723b00900712e00734000939233e00923b12e33d0090c000733d338336", + "0x34512e31200700723b00934600905400734634512e23b00933e0092f3007", + "0x923b00933500912500734800923b00923e00931300723e00923b00932b", + "0x909900733600923b00933600900e00701b00923b00901b009033007335", + "0x923b00934800930800733800923b00933800922100701500923b009015", + "0x932b00916800700723b00900712e00734833801533601b335011009348", + "0x3300733500923b00933500912500734a00923b00934000930700700723b", + "0x23b00901500909900733600923b00933600900e00701b00923b00901b009", + "0x1100934a00923b00934a00930800733800923b009338009221007015009", + "0x700723b00932000939300700723b00900712e00734a33801533601b335", + "0x723b00924000937300700723b00931500937200700723b00930e009370", + "0x23b00931200937600700723b00931300937500700723b009025009155007", + "0x901800924200700723b00930f00937100700723b009310009377007007", + "0x3300732500923b00932500912500734b00923b00923f00930700700723b", + "0x23b00901500909900732700923b00932700900e00701b00923b00901b009", + "0x1100934b00923b00934b00930800732800923b009328009221007015009", + "0x700723b00930e00937000700723b00900712e00734b32801532701b325", + "0x723b00901800924200700723b00930f00937100700723b009310009377", + "0x23b00902500915500700723b00924000937300700723b009315009372007", + "0x912800936500700723b00931200937600700723b009313009375007007", + "0x3300731900923b00931900912500734c00923b00932100930700700723b", + "0x23b00901500909900731a00923b00931a00900e00701b00923b00901b009", + "0x1100934c00923b00934c00930800731b00923b00931b009221007015009", + "0x700723b00912800936500700723b00900712e00734c31b01531a01b319", + "0x723b00902000909700700723b00904500915500700723b009018009242", + "0x924200912500734d00923b00930c00930700700723b009025009155007", + "0x730700923b00930700900e00701b00923b00901b00903300724200923b", + "0x934d00930800730800923b00930800922100702600923b009026009099", + "0x924200700723b00900712e00734d30802630701b24201100934d00923b", + "0x9700700723b0091db00905700700723b0090ba00909800700723b009018", + "0x700723b00902300907f00700723b00904500915500700723b009020009", + "0x723b00909800937100700723b00909700937000700723b00901f009096", + "0x23b00909f00937400700723b00903700937300700723b00905b009372007", + "0x909900937700700723b0091a500937600700723b00909c009375007007", + "0x14600930700700723b00903000915500700723b00922c00909700700723b", + "0x900923b00900900903300714e00923b00914e00912500734e00923b009", + "0x2c00922100710a00923b00910a00909900714900923b00914900900e007", + "0x34e02c10a14900914e01100934e00923b00934e00930800702c00923b009", + "0x723b0090ba00909800700723b00901800924200700723b00900712e007", + "0x23b00904500915500700723b00902000909700700723b0091db009057007", + "0x909700937000700723b00901f00909600700723b00902300907f007007", + "0x5b00937200700723b00922c00909700700723b00909800937100700723b", + "0x937500700723b00909f00937400700723b00903700937300700723b009", + "0x9800700723b00909900937700700723b0091a500937600700723b00909c", + "0x700723b0090fd00915500700723b00922500907f00700723b0091ba009", + "0x90090090330071b200923b0091b200912500734f00923b009102009307", + "0x715800923b00915800909900715100923b00915100900e00700900923b", + "0x1510091b201100934f00923b00934f00930800702c00923b00902c009221", + "0xba00909800700723b00901800924200700723b00900712e00734f02c158", + "0x915500700723b00902000909700700723b0091db00905700700723b009", + "0x37000700723b00901f00909600700723b00902300907f00700723b009045", + "0x700723b00922c00909700700723b00909800937100700723b009097009", + "0x723b00909f00937400700723b00903700937300700723b00905b009372", + "0x23b00909900937700700723b0091a500937600700723b00909c009375007", + "0x902e00906400700723b00922500907f00700723b0091ba009098007007", + "0x330071b200923b0091b200912500723d00923b0090c200930700700723b", + "0x23b00904a0090990070bc00923b0090bc00900e00700900923b009009009", + "0x1100923d00923b00923d0093080070be00923b0090be00922100704a009", + "0x700723b00901800924200700723b00900712e00723d0be04a0bc0091b2", + "0x723b00904500915500700723b00902000909700700723b0091db009057", + "0x23b00909700937000700723b00901f00909600700723b00902300907f007", + "0x902e00906400700723b00922c00909700700723b009098009371007007", + "0x9f00937400700723b00903700937300700723b00905b00937200700723b", + "0x937700700723b0091a500937600700723b00909c00937500700723b009", + "0x36500700723b00922900905b00700723b00922500907f00700723b009099", + "0x700723b00903300934f00700723b00922100934f00700723b009036009", + "0x23b0091b200912500735000923b0090a900930700700723b009157009101", + "0x990070a300923b0090a300900e00700900923b0090090090330071b2009", + "0x23b0093500093080070a500923b0090a500922100704a00923b00904a009", + "0x3600936500700723b00900712e0073500a504a0a30091b2011009350009", + "0x910100700723b00903300934f00700723b00922100934f00700723b009", + "0x9700700723b0091db00905700700723b00901800924200700723b009157", + "0x700723b00902300907f00700723b00904500915500700723b009020009", + "0x723b00922c00909700700723b00922500907f00700723b00901f009096", + "0x23b00922900905b00700723b0091fd00915200700723b00902e009064007", + "0x903300700700923b00900700912500735100923b009074009307007007", + "0x923b00912500909900706f00923b00906f00900e00700900923b009009", + "0x701100935100923b00935100930800707100923b009071009221007125", + "0x5b00700723b00906e00911100700723b00900712e00735107112506f009", + "0x700723b00922100934f00700723b00903600936500700723b009229009", + "0x723b0091db00905700700723b00901800924200700723b00903300934f", + "0x23b00902300907f00700723b00904500915500700723b009020009097007", + "0x922c00909700700723b00922500907f00700723b00901f009096007007", + "0x5a00910100700723b0091fd00915200700723b00902e00906400700723b", + "0x902e00735500923b00900739400735200923b00900722900700723b009", + "0x923b00900722500735600923b00935535212e03000735500923b009355", + "0x12500735a00923b00935800930700735800923b00935635712e031007357", + "0x23b00905200900e00700900923b00900900903300700700923b009007009", + "0x30800705400923b00905400922100712500923b009125009099007052009", + "0x723b00900712e00735a05412505200900701100935a00923b00935a009", + "0x23b00922100934f00700723b00903600936500700723b00922900905b007", + "0x91db00905700700723b00901800924200700723b00903300934f007007", + "0x2300907f00700723b00904500915500700723b00902000909700700723b", + "0x909700700723b00922500907f00700723b00901f00909600700723b009", + "0x10100700723b0091fd00915200700723b00902e00906400700723b00922c", + "0x923b00900700912500735e00923b00905800930700700723b009031009", + "0x909900705200923b00905200900e00700900923b009009009033007007", + "0x923b00935e00930800705400923b00905400922100712500923b009125", + "0x900715f0071db00923b00900707100735e05412505200900701100935e", + "0x900e00915200700723b0090070ea00700723b00900716000701800923b", + "0x14d00712500923b00912500922100700900923b00900900900e00700723b", + "0x2500939502000923b12e01500914e00701501f01b12523b00912500912e", + "0x23b00902300910a00702300923b00902000914900700723b00900712e007", + "0x737c00723c00923b00922c00937b00722c00923b00900714c007026009", + "0x2c00923b00902c00902e00702c00923b00923c00937d00722900923b009", + "0x703002e12e23b00922902c12e12537e00722900923b00922900902e007", + "0x923b00900737f00703100923b00922500937b00722500923b00900714c", + "0x902e00703300923b00903300902e00703300923b00903100937d007045", + "0x900738000703622112e23b00904503302e12537e00704500923b009045", + "0x12603b03a02023b00902600910c00703800923b00900714300721900923b", + "0x910100700723b00903a00915500715004904714804314504114103e03c", + "0x15500700723b00903c00915e00700723b00912600914700700723b00903b", + "0x700723b00914500914600700723b00904100915500700723b00903e009", + "0x723b00904700902000700723b00914800915e00700723b009043009147", + "0x14103821912538100700723b00915000915e00700723b009049009020007", + "0x723b00915200938300715315212e23b00904c00938200704c00923b009", + "0x37b00705405215712523b00915500938500715500923b009153009384007", + "0x23b00905700902e00705700923b00915900937d00715900923b009036009", + "0x5812e23b00915705722112537e00715700923b00915700902e007057009", + "0x902e00705d00923b00915d00937d00715d00923b00905a00937b00705a", + "0x905205d05812537e00705200923b00905200902e00705d00923b00905d", + "0x16000923b00915f00937d00715f00923b00906000937b00706015e12e23b", + "0x15e12537e00705400923b00905400902e00716000923b00916000902e007", + "0x23b00900738600716200923b00916100937b00716106412e23b009054160", + "0x2e00716400923b00916400902e00716400923b00916200937d007067009", + "0x937b00716816612e23b00906716406412537e00706700923b009067009", + "0x923b00906d00937d00706d00923b00916800937b00716b00923b009030", + "0x902e00706f00923b00906f00902e00706f00923b00916b00937d00706e", + "0x1b00900e00716e07112e23b00906e06f16612537e00706e00923b00906e", + "0x12523b00901f01b12e38700701f00923b00901f00922100701b00923b009", + "0x716e00923b00916e00902e00707100923b009071009099007074223072", + "0x707600939617400923b12e0740090fd00722300923b00922301812e162", + "0x923b00918000910400718000923b00917400915100700723b00900712e", + "0x902e00718600923b00907800937d00707800923b00916e00937b007077", + "0x1fd00937900701107b12e23b00907718607112537e00718600923b009186", + "0x700923b00900700912500700723b00918700909800708d18712e23b009", + "0x8d0091a500707b00923b00907b00909900707200923b00907200900e007", + "0x8d07b07200700e38900701100923b0090111db12e07400708d00923b009", + "0x12e00709200939709100923b12e09000907b00709008f08e07f00e23b009", + "0x9400923b00909100918700709300923b00901100937b00700723b009007", + "0x8f12537e00709500923b00909500902e00709500923b00909300937d007", + "0x23b00900738600709800923b00909700937b00709709612e23b009094095", + "0x2e0071a500923b0091a500902e0071a500923b00909800937d007099009", + "0x937b0071a709c12e23b0090991a509612537e00709900923b009099009", + "0x923b00905b00932f00705b00923b00903700937d00703700923b0091a7", + "0x900e00707f00923b00907f0091250071ac00923b00909f00933000709f", + "0x923b00922300922100709c00923b00909c00909900708e00923b00908e", + "0x900712e0071ac22309c08e07f1fd0091ac00923b0091ac009331007223", + "0x91250071b000923b00909200933200700723b00901100915500700723b", + "0x923b00908f00909900708e00923b00908e00900e00707f00923b00907f", + "0x7f1fd0091b000923b0091b000933100722300923b00922300922100708f", + "0x907f00700723b0091fd00909800700723b00900712e0071b022308f08e", + "0x71b200923b00907600933200700723b00916e00915500700723b0091db", + "0x907100909900707200923b00907200900e00700700923b009007009125", + "0x91b200923b0091b200933100722300923b00922300922100707100923b", + "0x700723b0091fd00909800700723b00900712e0071b22230710720071fd", + "0x923b00902500933200700723b00901800906400700723b0091db00907f", + "0x909900701b00923b00901b00900e00700700923b0090070091250070a3", + "0x923b0090a300933100701f00923b00901f00922100712e00923b00912e", + "0x1b0182231db01122323b00900e0093690070a301f12e01b0071fd0090a3", + "0x937700700723b0091db00937100700723b00901100937000702001501f", + "0x37300700723b00901b00937500700723b00901800937600700723b009223", + "0x700923b00900700912500700723b00902000937200700723b009015009", + "0x12500922100712e00923b00912e00909900700900923b00900900900e007", + "0x1f12512e00900701136c0071fd00923b0091fd00902e00712500923b009", + "0x2c00939822900923b12e23c0091b000723c22c0260230251fd23b0091fd", + "0x23b00902e00936e00702e00923b0092290091b200700723b00900712e007", + "0x12500703100923b00922500939a00722500923b009030009399007030009", + "0x23b00902600909900702300923b00902300900e00702500923b009025009", + "0x1fd00903100923b00903100939b00722c00923b00922c009221007026009", + "0x704500923b00902c00939c00700723b00900712e00703122c026023025", + "0x902600909900702300923b00902300900e00702500923b009025009125", + "0x904500923b00904500939b00722c00923b00922c00922100702600923b", + "0x23b12e12e00914000712e00923b00900700939d00704522c0260230251fd", + "0x14c00700723b00912500905400700723b00900712e00700e00939e125009", + "0x700739f0090070ee00701100923b0091fd00902e0071fd00923b009007", + "0x71db00923b00900714300700723b00900e00905400700723b00900712e", + "0x22300915500701822312e23b00901100915300701100923b0091db00902e", + "0x1b12e23b00900901812e05200700900923b00900900915700700723b009", + "0x701501b12e00901500923b00900716c00700723b00901f00905400701f", + "0x12500907200712512e12e23b00900900916e00700900923b0090090091fd", + "0x23b12e00e00712e3a100700723b00900712e0071fd0093a000e00923b12e", + "0x1800923b0091db0093a300700723b00900712e0072230093a21db01112e", + "0x180093a400712e00923b00912e0091fd00701100923b009011009125007", + "0x23b00900716c00700723b00900712e00701812e01112500901800923b009", + "0x1fd00722300923b00922300912500701f00923b00901b0093a500701b009", + "0x701f12e22312500901f00923b00901f0093a400712e00923b00912e009", + "0x923b00900700912500701500923b0091fd0093a500700723b00900712e", + "0x712500901500923b0090150093a400712e00923b00912e0091fd007007", + "0x12e00922100700900923b00900900900e00700723b0090070ea00701512e", + "0x12e2230090fd0072231db01112523b00912e00912e38700712e00923b009", + "0x1100923b00901100900e00700723b00900712e00701b0093a601800923b", + "0x702001501f12523b0091db01112e1580071db00923b0091db009221007", + "0x1800915100700723b00900712e0070230093a702500923b12e0200090fd", + "0x723b00922c00910100723c22c12e23b00902600910700702600923b009", + "0x2500915100702c00923b00922900910400722900923b00923c009102007", + "0x723b00903000910100722503012e23b00902e00910700702e00923b009", + "0x2c00915300704500923b00903100910400703100923b009225009102007", + "0x3612e23b00904500915300700723b00903300915500722103312e23b009", + "0x21900916300703800923b00922100916300700723b009036009155007219", + "0x923b00903b00902e00703b00923b00903a03812e14f00703a00923b009", + "0x93a900700723b00900712e0071260093a800723b12e03b00910600703b", + "0x923b00900724700703e00923b00903c0093aa00703c00e12e23b00900e", + "0x93ab00701500923b00901500922100701f00923b00901f00900e007141", + "0x14103e01501f00e3ac00714100923b00914100902e00703e00923b00903e", + "0x712e0070470093ad14800923b12e0430091b000704314504112523b009", + "0x3ae15000923b12e04900914000704900923b0091480091b200700723b009", + "0x900e0090ae00700723b00915000905400700723b00900712e00704c009", + "0x900722900700723b00912500915200700723b0091fd00905700700723b", + "0x3000715300923b00915300902e00715300923b0090073af00715200923b", + "0x915515712e03100715700923b00900722500715500923b00915315212e", + "0x700700923b00900700912500705400923b0090520093b000705200923b", + "0x90540093b100714500923b00914500922100704100923b00904100900e", + "0x904c00905400700723b00900712e00705414504100700e00905400923b", + "0x12e23b12e1591450411253b200715900e12e23b00900e0093a900700723b", + "0x15e00923b00900716c00700723b00900712e00705d15d05a1253b3058057", + "0x5800922100715f00923b00905700900e00706000923b00915e0093b4007", + "0x12e0070073b60090070ee00706400923b0090600093b500716000923b009", + "0x15f00923b00905a00900e00716100923b00905d0093b700700723b009007", + "0x640093b800706400923b0091610093b500716000923b00915d009221007", + "0x23b00900712e0071640093ba06700923b12e1620093b900716200923b009", + "0x93bc00716600e12e23b00900e0093a900700723b0090670093bb007007", + "0x923b00915f00900e00700700923b00900700912500716800923b009166", + "0x1fd3be00716800923b0091680093bd00716000923b00916000922100715f", + "0x7100923b12e06f0090c000706f06e06d16b00e23b00916812516015f007", + "0x912500707200923b00900e0093c000700723b00900712e00716e0093bf", + "0x923b00906e00922100706d00923b00906d00900e00716b00923b00916b", + "0x1fd3c20071fd00923b0091fd00915700707200923b0090720093c100706e", + "0x7700923b12e1800093c300718007617407400e23b0091fd07206e06d16b", + "0x5400707b18612e23b0090710092f300700723b00900712e0070780093c4", + "0x23b00918718612e3c600718700923b0090770093c500700723b00907b009", + "0xe00707400923b00907400912500707f00923b00908d0093c700708d009", + "0x23b00907f0093b100707600923b00907600922100717400923b009174009", + "0x23b0090710090c200700723b00900712e00707f07617407400e00907f009", + "0x900e00707400923b00907400912500708e00923b0090780093b0007007", + "0x923b00908e0093b100707600923b00907600922100717400923b009174", + "0x723b00900e0090ae00700723b00900712e00708e07617407400e00908e", + "0x916b00912500708f00923b00916e0093b000700723b0091fd009057007", + "0x706e00923b00906e00922100706d00923b00906d00900e00716b00923b", + "0x700723b00900712e00708f06e06d16b00e00908f00923b00908f0093b1", + "0x723b00912500915200700723b0091fd00905700700723b00900e0090ae", + "0x15f00900e00700700923b00900700912500709000923b0091640093b0007", + "0x9000923b0090900093b100716000923b00916000922100715f00923b009", + "0x700723b00900e0090ae00700723b00900712e00709016015f00700e009", + "0x923b0090470093b000700723b00912500915200700723b0091fd009057", + "0x922100704100923b00904100900e00700700923b009007009125007091", + "0x709114504100700e00909100923b0090910093b100714500923b009145", + "0x700723b00912500915200700723b00912600911100700723b00900712e", + "0x9200923b00900722900700723b00900e0090ae00700723b0091fd009057", + "0x9309212e03000709300923b00909300902e00709300923b0090073c8007", + "0x9600923b00909409512e03100709500923b00900722500709400923b009", + "0x1f00900e00700700923b00900700912500709700923b0090960093b0007", + "0x9700923b0090970093b100701500923b00901500922100701f00923b009", + "0x700723b00912500915200700723b00900712e00709701501f00700e009", + "0x723b0090180093c900700723b00900e0090ae00700723b0091fd009057", + "0x1f00900e00700700923b00900700912500709800923b0090230093b0007", + "0x9800923b0090980093b100701500923b00901500922100701f00923b009", + "0x700723b00912500915200700723b00900712e00709801501f00700e009", + "0x923b00901b0093b000700723b00900e0090ae00700723b0091fd009057", + "0x922100701100923b00901100900e00700700923b009007009125007099", + "0x70991db01100700e00909900923b0090990093b10071db00923b0091db", + "0x23b00900e00901f00700e12e12e23b00912e0093ca00700723b0090070ea", + "0x2300700723b0090110090200071db01112e23b0091fd0090150071fd009", + "0x23b00901800902e00701800923b0092230090df00722300923b0091db009", + "0x701f00923b00912e00905800701b00923b00901812512e030007018009", + "0x901f0091fd00700900923b00900900900e00700700923b009007009125", + "0x23b00901b01f00900700e3cb00701b00923b00901b00915700701f00923b", + "0x23b00900712e0070260093cc02300923b12e02500906e007025020015125", + "0x716c00700723b00923c00905400723c22c12e23b00902300906f007007", + "0x923b00902c00931900702c00923b00922922c12e31800722900923b009", + "0x931a00702000923b00902000900e00701500923b00901500912500702e", + "0x2600931b00700723b00900712e00702e02001512500902e00923b00902e", + "0x2000923b00902000900e00701500923b00901500912500703000923b009", + "0x1100923b00900715f00703002001512500903000923b00903000931a007", + "0x923b00900715f00701b00923b00900715f00722300923b0090073cd007", + "0x923b00900900900e00700723b0090070ea00700723b009007160007015", + "0x2302502012523b00912e00912e38700712e00923b00912e009221007009", + "0x900e00700723b00900712e00722c0093ce02600923b12e0230090fd007", + "0x23b00902502012e15800702500923b00902500922100702000923b009020", + "0x23b00900712e0070300093cf02e00923b12e02c0090fd00702c22923c125", + "0x10100704503112e23b00922500910700722500923b009026009151007007", + "0x923b00903300910400703300923b00904500910200700723b009031009", + "0x10100703821912e23b00903600910700703600923b00902e009151007221", + "0x923b00903a00910400703a00923b00903800910200700723b009219009", + "0x915300700723b00912600915500703c12612e23b00922100915300703b", + "0x923b00903c00916300700723b00903e00915500714103e12e23b00903b", + "0x2e00704300923b00914504112e14f00714500923b009141009163007041", + "0x900712e0071480093d000723b12e04300910600704300923b009043009", + "0x93d100715715515315204c15004904722323b00912500936900700723b", + "0x23b00922900922100723c00923b00923c00900e00705405212e23b009049", + "0x23b12e05800907b00705805715912523b00905422923c1253d2007229009", + "0x705d00923b00905a00918700700723b00900712e00715d0093d305a009", + "0x23b00900714c00700723b00915e00915500706015e12e23b00905d009153", + "0x16300700723b00916000915500706416012e23b00915f00915300715f009", + "0x916200915500706716212e23b00916100915300716100923b009060009", + "0x716816612e23b00916400915300716400923b00906400916300700723b", + "0x23b00916800916300716b00923b00906700916300700723b009166009155", + "0x902e00700723b00900710f00706e00923b00906d16b12e14f00706d009", + "0x23b00900712e00706f0093d400723b12e06e00910600706e00923b00906e", + "0x16e0090a500716e00923b00907100914400707100923b00900716c007007", + "0x6f00911100700723b00900712e0070073d50090070ee00707200923b009", + "0xa500717400923b00907400911300707400923b00900716c00700723b009", + "0x23b0090760090a500707600923b00907200936e00707200923b009174009", + "0x700723b00900712e0070770093d618000923b12e076009140007076009", + "0x700723b00901b00906400700723b00918000905400700723b0090070ea", + "0x723b00900e00905700700723b0092230093d700700723b009015009064", + "0x23b00904700937000700723b00905200937100700723b009011009064007", + "0x915300937400700723b00915500937300700723b009157009372007007", + "0x15000937700700723b00904c00937600700723b00915200937500700723b", + "0x902e00718600923b0090073d800707800923b00900722900700723b009", + "0x923b00900722500707b00923b00918607812e03000718600923b009186", + "0x12500707f00923b00908d0093b000708d00923b00907b18712e031007187", + "0x23b00905700922100715900923b00915900900e00700700923b009007009", + "0x900712e00707f05715900700e00907f00923b00907f0093b1007057009", + "0x91500093d900700723b00907700905400700723b0090070ea00700723b", + "0x5700923b00905700922100715900923b00915900900e00708f08e12e23b", + "0x9300923b12e09200907b00709209109012523b00908f0571591253da007", + "0x910600709500923b00909300918700700723b00900712e0070940093db", + "0x12e23b00904c0093dd00700723b00900712e0070960093dc00723b12e095", + "0x3de00709100923b00909100922100709000923b00909000900e007098097", + "0x93df1a700923b12e09c00907b00709c1a509912523b009098091090125", + "0x905b00915300705b00923b0091a700918700700723b00900712e007037", + "0x1530071b000923b00900714c00700723b00909f0091550071ac09f12e23b", + "0x23b0091ac00916300700723b0091b20091550070a31b212e23b0091b0009", + "0x71b500923b0090a504a12e14f0070a500923b0090a300916300704a009", + "0x712e0070a70093e000723b12e1b50091060071b500923b0091b500902e", + "0x71b800923b0091a50092210070a900923b00909900900e00700723b009", + "0x700723b00900712e0070073e20090070ee0070ac00923b0090970093e1", + "0x723b00901500906400700723b00901b00906400700723b0090a7009111", + "0x23b00901100906400700723b00900e00905700700723b0092230093d7007", + "0x908e00937700700723b00904700937000700723b009052009371007007", + "0x15300937400700723b00915500937300700723b00915700937200700723b", + "0x722900700723b00909700937600700723b00915200937500700723b009", + "0x71bc00923b0091bc00902e0071bc00923b0090073e30070ae00923b009", + "0xb00b212e0310070b200923b0090072250070b000923b0091bc0ae12e030", + "0x700923b0090070091250070b400923b0091bd0093b00071bd00923b009", + "0xb40093b10071a500923b0091a500922100709900923b00909900900e007", + "0x1b00906400700723b00900712e0070b41a509900700e0090b400923b009", + "0x905700700723b0092230093d700700723b00901500906400700723b009", + "0x37000700723b00905200937100700723b00901100906400700723b00900e", + "0x700723b00915700937200700723b00908e00937700700723b009047009", + "0x723b00915200937500700723b00915300937400700723b009155009373", + "0x90070091250070b600923b0090370093b000700723b009097009376007", + "0x71a500923b0091a500922100709900923b00909900900e00700700923b", + "0x700723b00900712e0070b61a509900700e0090b600923b0090b60093b1", + "0x23b0090910092210070a900923b00909000900e00700723b009096009111", + "0x70b81bb12e23b0090470093e40070ac00923b00904c0093e10071b8009", + "0x91b80092210070a900923b0090a900900e00700700923b009007009125", + "0x93e60070be0bc1ba0ba00e23b0090b81b80a900700e3e50071b800923b", + "0x23b0091b90093e800700723b00900712e0070c00093e71b900923b12e0be", + "0x3e90070c600923b0090073ea0070c41b612e23b0090c20093e90070c2009", + "0x23b0090c40093e900700723b0091b30090ae0070c71b312e23b0090c6009", + "0x70cb1ad12e23b0090c70093e900700723b0091b70090ae0070c91b712e", + "0x23b0090cb0091bc0070c900923b0090c90091bc00700723b0091ad0090ae", + "0x3eb1aa00923b12e0cd0091400070cd00923b0090cb0c912e2490070cb009", + "0x23b00900710f00700723b0091aa00905400700723b00900712e0070cf009", + "0x712e0071a01a10d11253ec1a31a812e23b12e1b60bc1ba1253b2007007", + "0xe00719f00923b0090d50093b40070d500923b00900716c00700723b009", + "0x23b00919f0093b50070d800923b0091a300922100719b00923b0091a8009", + "0x23b0091a00093b700700723b00900712e0070073ed0090070ee0070da009", + "0x3b50070d800923b0091a100922100719b00923b0090d100900e007198009", + "0x23b12e1970093b900719700923b0090da0093b80070da00923b009198009", + "0x3ea00700723b0090dd0093bb00700723b00900712e00718e0093ee0dd009", + "0x923b0090d800922100719b00923b00919b00900e0070df00923b009007", + "0xe112523b0090df1bb0d819b00e3ef0070df00923b0090df0091bc0070d8", + "0x700723b00900712e00718c0093f118800923b12e1890093f000718918a", + "0x18a0092210070e100923b0090e100900e0070e518b12e23b0090520093d1", + "0xa000907b0070a018318412523b0090e518a0e11253d200718a00923b009", + "0x700723b0090070ea00700723b00900712e0071790093f20e800923b12e", + "0x90e800918700700723b0090ea0090540070ea17b12e23b0091880093f3", + "0x1531520ac08e18b17b22314800717100923b0091750093f400717500923b", + "0x23b00918400900e0070ba00923b0090ba0091250070ec00923b009157155", + "0x3f600717100923b0091710093f500718300923b009183009221007184009", + "0x923b12e1690090c00071690f016c0ee00e23b0091710ec1831840ba1fd", + "0x70f616312e23b0091650092f300700723b00900712e0070f30093f7165", + "0x23b00916c00900e0070f800923b0090ee00912500700723b0090f6009054", + "0xee0070fa00923b0091630093f800701f00923b0090f000922100715c009", + "0x906400700723b00901b00906400700723b00900712e0070073f9009007", + "0x6400700723b00900e00905700700723b0092230093d700700723b009015", + "0x923b0090ee00912500715600923b0090f30093b000700723b009011009", + "0x93b10070f000923b0090f000922100716c00923b00916c00900e0070ee", + "0x70ea00700723b00900712e0071560f016c0ee00e00915600923b009156", + "0x93d700700723b00901500906400700723b00901b00906400700723b009", + "0x24800700723b00901100906400700723b00900e00905700700723b009223", + "0x700723b00915500937300700723b00915700937200700723b009188009", + "0x723b0090ac00937600700723b00915200937500700723b009153009374", + "0x23b0091790093b000700723b00918b00937100700723b00908e009377007", + "0x22100718400923b00918400900e0070ba00923b0090ba009125007154009", + "0x1541831840ba00e00915400923b0091540093b100718300923b009183009", + "0x700723b00901b00906400700723b0090070ea00700723b00900712e007", + "0x723b00900e00905700700723b0092230093d700700723b009015009064", + "0x23b00908e00937700700723b00905200937100700723b009011009064007", + "0x915300937400700723b00915500937300700723b009157009372007007", + "0x18c0093b000700723b0090ac00937600700723b00915200937500700723b", + "0xe100923b0090e100900e0070ba00923b0090ba00912500715800923b009", + "0xe10ba00e00915800923b0091580093b100718a00923b00918a009221007", + "0x23b00901b00906400700723b0090070ea00700723b00900712e00715818a", + "0x900e00905700700723b0092230093d700700723b009015009064007007", + "0xac00937600700723b00905200937100700723b00901100906400700723b", + "0x937300700723b00915700937200700723b00908e00937700700723b009", + "0x37000700723b00915200937500700723b00915300937400700723b009155", + "0x923b0090ba0091250070fd00923b00918e0093b000700723b0091bb009", + "0x93b10070d800923b0090d800922100719b00923b00919b00900e0070ba", + "0x905400700723b00900712e0070fd0d819b0ba00e0090fd00923b0090fd", + "0x1531520ac08e0521bb22314800700723b0091b60090ae00700723b0090cf", + "0x23b0091ba00900e0070f800923b0090ba00912500715100923b009157155", + "0x1590070fa00923b0091510093f800701f00923b0090bc00922100715c009", + "0x910200901500710200923b00910100901f00710110712e23b00900e009", + "0x1500714f00923b00900702500700723b00910400902000714c10412e23b", + "0x23b00914c00902300700723b00910600902000714d10612e23b00914f009", + "0x16200714e00923b00914e00902600714900923b00914d00902300714e009", + "0x712e0070073fa00723b12e14914e12e22c00701f00923b00901f01512e", + "0x700723b00910a00905700710c10a12e23b00910700915900700723b009", + "0x915c00900e0070f800923b0090f800912500714700923b00910c009058", + "0x12523b00914715c0f812501100714700923b0091470091fd00715c00923b", + "0x723b00900712e0071110093fb14400923b12e10f0091db00710f14b146", + "0x1400093fc1db00923b12e11300901800711314312e23b009144009223007", + "0x23b00911800901f00711800923b00914300901b00700723b00900712e007", + "0x2500700723b00913b00902000713913b12e23b009115009015007115009", + "0x23b00911a00902000711c11a12e23b00913700901500713700923b009007", + "0x902600712300923b00911c00902300712800923b009139009023007007", + "0x12e12312812e22c0071db00923b0091db22312e3fd00712800923b009128", + "0x906400700723b0090fa00915200700723b00900712e0070073fe00723b", + "0x22900700723b0091db00923c00700723b00901b00906400700723b009011", + "0x2f300923b0092f300902e0072f300923b0090073ff00700000923b009007", + "0x2f512e0310072f500923b0090072250072f400923b0092f300012e030007", + "0x923b0091460091250072f700923b0092f60093b00072f600923b0092f4", + "0x93b100701f00923b00901f00922100714b00923b00914b00900e007146", + "0x911c00700723b00900712e0072f701f14b14600e0092f700923b0092f7", + "0x23b00901f00922100714b00923b00914b00900e0072422f812e23b0091db", + "0x23b00901801b12e16200730801830712523b00901f14b12e38700701f009", + "0x700723b00900712e00730a00940030900923b12e3080090fd007018009", + "0x914600912500730d00923b00930900915100730c00923b009242009128", + "0x730c00923b00930c00912300730700923b00930700900e00714600923b", + "0x30f30e24112523b00930d30c30714600e40100730d00923b00930d00935a", + "0x940400700723b00900712e00731200940331000923b12e30f009402007", + "0x723b00931300923c00731431312e23b0092f800911c00700723b009310", + "0x30e00900e00724100923b00924100912500724000923b009314009128007", + "0x24000923b00924000912300701800923b00901800922100730e00923b009", + "0x91fd01112e1620073181fd31631500e23b00924001830e24100e309007", + "0x723b00900712e00731a00940531900923b12e31800930a0071fd00923b", + "0x931f00916600731f00923b00931900930c00731b00923b009007229007", + "0x731500923b00931500912500700723b00932000916800732132012e23b", + "0x931b00915700732100923b00932100916b00731600923b00931600900e", + "0x32800906e00732832732512523b00931b32131631500e06d00731b00923b", + "0x12e23b00932900906f00700723b00900712e00732a00940632900923b12e", + "0x3c700732f00923b00923f0fa12e3c600700723b00932b00905400732b23f", + "0x23b00932700900e00732500923b00932500912500733000923b00932f009", + "0xe00933000923b0093300093b10071fd00923b0091fd009221007327009", + "0x93b000700723b0090fa00915200700723b00900712e0073301fd327325", + "0x923b00932700900e00732500923b00932500912500733100923b00932a", + "0x32500e00933100923b0093310093b10071fd00923b0091fd009221007327", + "0x31a0093b000700723b0090fa00915200700723b00900712e0073311fd327", + "0x31600923b00931600900e00731500923b00931500912500733200923b009", + "0x31631500e00933200923b0093320093b10071fd00923b0091fd009221007", + "0x901100906400700723b0090fa00915200700723b00900712e0073321fd", + "0x912500733300923b0093120093b000700723b0092f800923c00700723b", + "0x923b00901800922100730e00923b00930e00900e00724100923b009241", + "0x23b00900712e00733301830e24100e00933300923b0093330093b1007018", + "0x92f800923c00700723b00901100906400700723b0090fa009152007007", + "0x912500733400923b00930a0093b000700723b00924200940700700723b", + "0x923b00901800922100730700923b00930700900e00714600923b009146", + "0x23b00900712e00733401830714600e00933400923b0093340093b1007018", + "0x901100906400700723b0090fa00915200700723b009140009054007007", + "0x2230093d700700723b00914300915e00700723b00901b00906400700723b", + "0x902e00733600923b0090073ff00733500923b00900722900700723b009", + "0x923b00900722500733800923b00933633512e03000733600923b009336", + "0x12500734000923b00933e0093b000733e00923b00933833d12e03100733d", + "0x23b00901f00922100714b00923b00914b00900e00714600923b009146009", + "0x900712e00734001f14b14600e00934000923b0093400093b100701f009", + "0x1b00906400700723b00901100906400700723b0090fa00915200700723b", + "0x12500734500923b0091110093b000700723b0092230093d700700723b009", + "0x23b00901f00922100714b00923b00914b00900e00714600923b009146009", + "0x900712e00734501f14b14600e00934500923b0093450093b100701f009", + "0x1100906400700723b0092230093d700700723b00901b00906400700723b", + "0x12e3c600734600923b00900722900700723b00910700905700700723b009", + "0x23b0090f800912500734800923b00923e0093c700723e00923b0093460fa", + "0x3b100701f00923b00901f00922100715c00923b00915c00900e0070f8009", + "0x6400700723b00900712e00734801f15c0f800e00934800923b009348009", + "0x700723b0092230093d700700723b00901500906400700723b00901b009", + "0x723b00905200937100700723b00901100906400700723b00900e009057", + "0x23b00915700937200700723b00908e00937700700723b0090ac009376007", + "0x915200937500700723b00915300937400700723b009155009373007007", + "0x912500734a00923b0090c00093b000700723b0091bb00937000700723b", + "0x923b0090bc0092210071ba00923b0091ba00900e0070ba00923b0090ba", + "0x23b00900712e00734a0bc1ba0ba00e00934a00923b00934a0093b10070bc", + "0x92230093d700700723b00901500906400700723b00901b009064007007", + "0x5200937100700723b00901100906400700723b00900e00905700700723b", + "0x937200700723b00908e00937700700723b00904700937000700723b009", + "0x37500700723b00915300937400700723b00915500937300700723b009157", + "0x34b00923b0090940093b000700723b00904c00937600700723b009152009", + "0x9100922100709000923b00909000900e00700700923b009007009125007", + "0x12e00734b09109000700e00934b00923b00934b0093b100709100923b009", + "0x3d700700723b00901500906400700723b00901b00906400700723b009007", + "0x700723b00901100906400700723b00900e00905700700723b009223009", + "0x723b00915700937200700723b00904700937000700723b009052009371", + "0x23b00915200937500700723b00915300937400700723b009155009373007", + "0x915d0093b000700723b00915000937700700723b00904c009376007007", + "0x715900923b00915900900e00700700923b00900700912500734c00923b", + "0x5715900700e00934c00923b00934c0093b100705700923b009057009221", + "0x23b00901b00906400700723b00914800911100700723b00900712e00734c", + "0x900e00905700700723b0092230093d700700723b009015009064007007", + "0x900722900700723b00912500915200700723b00901100906400700723b", + "0x3000734e00923b00934e00902e00734e00923b0090073c800734d00923b", + "0x934f23d12e03100723d00923b00900722500734f00923b00934e34d12e", + "0x700700923b00900700912500735100923b0093500093b000735000923b", + "0x93510093b100722900923b00922900922100723c00923b00923c00900e", + "0x901b00906400700723b00900712e00735122923c00700e00935100923b", + "0xe00905700700723b0092230093d700700723b00901500906400700723b", + "0x93c900700723b00912500915200700723b00901100906400700723b009", + "0x700923b00900700912500735200923b0090300093b000700723b009026", + "0x3520093b100722900923b00922900922100723c00923b00923c00900e007", + "0x12500915200700723b00900712e00735222923c00700e00935200923b009", + "0x93d700700723b00901500906400700723b00901b00906400700723b009", + "0x3b000700723b00901100906400700723b00900e00905700700723b009223", + "0x23b00902000900e00700700923b00900700912500735500923b00922c009", + "0xe00935500923b0093550093b100702500923b009025009221007020009", + "0x712e00923b00912e00900e00700723b0091fd009155007355025020007", + "0x14e0072231db01112523b00912512e12e14d00712500923b009125009221", + "0x901800914900700723b00900712e00701b00940801800923b12e223009", + "0x2502002023b00901500910c00701500923b00901f00910a00701f00923b", + "0x14700700723b00902500910100704503122503002e02c22923c22c026023", + "0x700723b00922900915500700723b00923c00915500700723b009023009", + "0x723b00903000915e00700723b00902e00914700700723b00902c009146", + "0x23b00904500915e00700723b00903100902000700723b009225009020007", + "0x915300703600923b00900714b00722103312e23b009020009153007007", + "0x923b00922100916300700723b00921900915500703821912e23b009036", + "0x12e14f00703a00923b00903a00902e00703b00923b00903800916300703a", + "0x23b0090260091fd00712600923b00912600902e00712600923b00903b03a", + "0x10600703300923b00903300902e00722c00923b00922c00902e007026009", + "0x923b00900716c00700723b00900712e00703c00940900723b12e126009", + "0x90a500704100923b00903300902e00714100923b00903e00914400703e", + "0x911100700723b00900712e00700740a0090070ee00714500923b009141", + "0x4700923b00900740b00714804312e23b00903300915300700723b00903c", + "0x14800916300700723b00904900915500715004912e23b009047009153007", + "0x923b00915204c12e14f00715200923b00915000916300704c00923b009", + "0x715500940c00723b12e15300910600715300923b00915300902e007153", + "0x5200923b00915700914400715700923b00900716c00700723b00900712e", + "0x723b00900712e00700740d0090070ee00705400923b0090520090a5007", + "0x23b00915900911300715900923b00900716c00700723b009155009111007", + "0xa500704100923b00904300902e00705400923b0090570090a5007057009", + "0x712e00705a00940e05800923b12e14500914000714500923b009054009", + "0x705d15d12e23b00904100915300700723b00905800905400700723b009", + "0x906000915500715f06012e23b00915e00915300715e00923b009007118", + "0x14f00706400923b00915f00916300716000923b00905d00916300700723b", + "0x12e16100910600716100923b00916100902e00716100923b00906416012e", + "0x14400706700923b00900716c00700723b00900712e00716200940f00723b", + "0x74100090070ee00716600923b0091640090a500716400923b009067009", + "0x16800923b00900716c00700723b00916200911100700723b00900712e007", + "0x15d00902e00716600923b00916b0090a500716b00923b009168009113007", + "0x12e0070074110090070ee00706e00923b0091660090a500706d00923b009", + "0x14400706f00923b00900716c00700723b00905a00905400700723b009007", + "0x23b0090710090a500706d00923b00904100902e00707100923b00906f009", + "0x700723b00900712e00707200941216e00923b12e06e00914000706e009", + "0x907400915500717407412e23b00906d00915300700723b00916e009054", + "0x15500707718012e23b00907600915300707600923b00900741300700723b", + "0x923b00907700916300707800923b00917400916300700723b009180009", + "0x10600707b00923b00907b00902e00707b00923b00918607812e14f007186", + "0x74150090070ee00700723b00900712e00718700941400723b12e07b009", + "0x723b00900e00915200700723b00918700911100700723b00900712e007", + "0x923b00900722900700723b00902600915e00700723b00922c009155007", + "0x8d12e03000707f00923b00907f00902e00707f00923b00900741600708d", + "0x923b00908e08f12e03100708f00923b00900722500708e00923b00907f", + "0x903300700700923b00900700912500709100923b009090009332007090", + "0x923b0091db00922100701100923b00901100900e00700900923b009009", + "0x900712e0070911db0110090071fd00909100923b0090910093310071db", + "0x1100900e00700723b00906d00915500700723b00907200905400700723b", + "0x12523b0091db01112e14d0071db00923b0091db00922100701100923b009", + "0x723b00900712e00709600941709500923b12e09400914e007094093092", + "0x9800910c00709800923b00909700910a00709700923b009095009149007", + "0x990091550070a504a0a31b21b01ac09f05b0371a709c1a509902023b009", + "0x915e00700723b00909c00914700700723b0091a500910100700723b009", + "0x15500700723b00905b00915500700723b00903700915500700723b0091a7", + "0x700723b0091b000914700700723b0091ac00914600700723b00909f009", + "0x723b0090a500915e00700723b00904a00902000700723b0090a3009020", + "0x1b500901f0071b500923b0091b50090b40071b500923b0091b200901b007", + "0x723b0090a90090200071b80a912e23b0090a70090150070a700923b009", + "0xae0090200071bc0ae12e23b0090ac0090150070ac00923b009007025007", + "0x70b200923b0091bc0090230070b000923b0091b800902300700723b009", + "0x712e00700741800723b12e0b20b012e22c0070b000923b0090b0009026", + "0x915200700723b00922c00915500700723b00902600915e00700723b009", + "0x2e0070b400923b00900711a0071bd00923b00900722900700723b00900e", + "0x23b0090072250070b600923b0090b41bd12e0300070b400923b0090b4009", + "0x70ba00923b0090b80093320070b800923b0090b61bb12e0310071bb009", + "0x909200900e00700900923b00900900903300700700923b009007009125", + "0x90ba00923b0090ba00933100709300923b00909300922100709200923b", + "0x700923b00900700912500700723b00900712e0070ba0930920090071fd", + "0x9300922100709200923b00909200900e00700900923b009009009033007", + "0x2600923b0090260091fd00722c00923b00922c00902e00709300923b009", + "0x3b90070c01b90be0bc1ba1fd23b00902622c00e0930920090071db419007", + "0x90c20093bb00700723b00900712e0071b600941a0c200923b12e0c0009", + "0x93300070c600923b0090c400932f0070c400923b0090072f400700723b", + "0x923b0090bc0090330071ba00923b0091ba0091250071b300923b0090c6", + "0x93310071b900923b0091b90092210070be00923b0090be00900e0070bc", + "0x33200700723b00900712e0071b31b90be0bc1ba1fd0091b300923b0091b3", + "0x23b0090bc0090330071ba00923b0091ba0091250070c700923b0091b6009", + "0x3310071b900923b0091b90092210070be00923b0090be00900e0070bc009", + "0x700723b00900712e0070c71b90be0bc1ba1fd0090c700923b0090c7009", + "0x723b00900e00915200700723b00922c00915500700723b00902600915e", + "0x900903300700700923b0090070091250071b700923b009096009332007", + "0x9300923b00909300922100709200923b00909200900e00700900923b009", + "0x23b00900712e0071b70930920090071fd0091b700923b0091b7009331007", + "0x70091250070c900923b00901b00933200700723b00900e009152007007", + "0x1100923b00901100900e00700900923b00900900903300700700923b009", + "0x90071fd0090c900923b0090c90093310071db00923b0091db009221007", + "0x915500700723b00901100915500700723b0091fd0091550070c91db011", + "0x712e00923b00912e00900e00700723b00922300915500700723b0091db", + "0x14e00701f01b01812523b00912512e12e14d00712500923b009125009221", + "0x901500914900700723b00900712e00702000941b01500923b12e01f009", + "0x22c02602023b00902300910c00702300923b00902500910a00702500923b", + "0x14700700723b00922c00910100703622103304503122503002e02c22923c", + "0x700723b00903000915500700723b00902e00915500700723b00923c009", + "0x723b00904500915e00700723b00903100914700700723b009225009146", + "0x23b00903600915e00700723b00922100902000700723b009033009020007", + "0x915300703a00923b00900714b00703821912e23b009026009153007007", + "0x923b00903800916300700723b00903b00915500712603b12e23b00903a", + "0x12e14f00703c00923b00903c00902e00703e00923b00912600916300703c", + "0x23b0092290091fd00714100923b00914100902e00714100923b00903e03c", + "0x10600721900923b00921900902e00702c00923b00902c00902e007229009", + "0x923b00900716c00700723b00900712e00704100941c00723b12e141009", + "0x90a500714800923b00921900902e00704300923b009145009144007145", + "0x911100700723b00900712e00700741d0090070ee00704700923b009043", + "0x4c00923b00900714300715004912e23b00921900915300700723b009041", + "0x15000916300700723b00915200915500715315212e23b00904c009153007", + "0x923b00915715512e14f00715700923b00915300916300715500923b009", + "0x705400941e00723b12e05200910600705200923b00905200902e007052", + "0x5700923b00915900914400715900923b00900716c00700723b00900712e", + "0x723b00900712e00700741f0090070ee00705800923b0090570090a5007", + "0x23b00905a00911300705a00923b00900716c00700723b009054009111007", + "0xa500714800923b00904900902e00705800923b00915d0090a500715d009", + "0x712e00715e00942005d00923b12e04700914000704700923b009058009", + "0x715f06012e23b00914800915300700723b00905d00905400700723b009", + "0x906400915500716106412e23b00916000915300716000923b009007118", + "0x14f00706700923b00916100916300716200923b00915f00916300700723b", + "0x12e16400910600716400923b00916400902e00716400923b00906716212e", + "0x14400716800923b00900716c00700723b00900712e00716600942100723b", + "0x74220090070ee00706d00923b00916b0090a500716b00923b009168009", + "0x6e00923b00900716c00700723b00916600911100700723b00900712e007", + "0x6000902e00706d00923b00906f0090a500706f00923b00906e009113007", + "0x12e0070074230090070ee00716e00923b00906d0090a500707100923b009", + "0x14400707200923b00900716c00700723b00915e00905400700723b009007", + "0x23b0090740090a500707100923b00914800902e00707400923b009072009", + "0x700723b00900712e00707600942417400923b12e16e00914000716e009", + "0x918000915500707718012e23b00907100915300700723b009174009054", + "0x15500707b18612e23b00907800915300707800923b00900711500700723b", + "0x923b00907b00916300718700923b00907700916300700723b009186009", + "0x10600707f00923b00907f00902e00707f00923b00908d18712e14f00708d", + "0x74260090070ee00700723b00900712e00708e00942500723b12e07f009", + "0x723b00900e00915200700723b00908e00911100700723b00900712e007", + "0x923b00900722900700723b00922900915e00700723b00902c009155007", + "0x8f12e03000709000923b00909000902e00709000923b00900742700708f", + "0x923b00909109212e03100709200923b00900722500709100923b009090", + "0x903300700700923b00900700912500709400923b009093009332007093", + "0x923b00901b00922100701800923b00901800900e00700900923b009009", + "0x900712e00709401b0180090071fd00909400923b00909400933100701b", + "0x1800900e00700723b00907100915500700723b00907600905400700723b", + "0x12523b00901b01812e14d00701b00923b00901b00922100701800923b009", + "0x723b00900712e00709900942809800923b12e09700914e007097096095", + "0x9c00910c00709c00923b0091a500910a0071a500923b009098009149007", + "0x1a70091550070a90a71b50a504a0a31b21b01ac09f05b0371a702023b009", + "0x915e00700723b00905b00914700700723b00903700910100700723b009", + "0x15500700723b0091b000915500700723b0091ac00915500700723b00909f", + "0x700723b00904a00914700700723b0090a300914600700723b0091b2009", + "0x723b0090a900915e00700723b0090a700902000700723b0091b5009020", + "0x1b800901f0071b800923b0091b80090b40071b800923b0090a500901b007", + "0x723b0090ae0090200071bc0ae12e23b0090ac0090150070ac00923b009", + "0xb20090200071bd0b212e23b0090b00090150070b000923b009007025007", + "0x70b600923b0091bd0090230070b400923b0091bc00902300700723b009", + "0x712e00700742900723b12e0b60b412e22c0070b400923b0090b4009026", + "0x915200700723b00902c00915500700723b00922900915e00700723b009", + "0x2e0070b800923b00900711a0071bb00923b00900722900700723b00900e", + "0x23b0090072250070ba00923b0090b81bb12e0300070b800923b0090b8009", + "0x70be00923b0090bc0093320070bc00923b0090ba1ba12e0310071ba009", + "0x909500900e00700900923b00900900903300700700923b009007009125", + "0x90be00923b0090be00933100709600923b00909600922100709500923b", + "0x700923b00900700912500700723b00900712e0070be0960950090071fd", + "0x9600922100709500923b00909500900e00700900923b009009009033007", + "0x22900923b0092290091fd00702c00923b00902c00902e00709600923b009", + "0x3b90070c41b60c20c01b91fd23b00922902c00e0960950090071db419007", + "0x90c60093bb00700723b00900712e0071b300942a0c600923b12e0c4009", + "0x93300071b700923b0090c700932f0070c700923b0090072f400700723b", + "0x923b0090c00090330071b900923b0091b90091250070c900923b0091b7", + "0x93310071b600923b0091b60092210070c200923b0090c200900e0070c0", + "0x33200700723b00900712e0070c91b60c20c01b91fd0090c900923b0090c9", + "0x23b0090c00090330071b900923b0091b90091250071ad00923b0091b3009", + "0x3310071b600923b0091b60092210070c200923b0090c200900e0070c0009", + "0x700723b00900712e0071ad1b60c20c01b91fd0091ad00923b0091ad009", + "0x723b00900e00915200700723b00902c00915500700723b00922900915e", + "0x900903300700700923b0090070091250070cb00923b009099009332007", + "0x9600923b00909600922100709500923b00909500900e00700900923b009", + "0x23b00900712e0070cb0960950090071fd0090cb00923b0090cb009331007", + "0x70091250070cd00923b00902000933200700723b00900e009152007007", + "0x1800923b00901800900e00700900923b00900900903300700700923b009", + "0x90071fd0090cd00923b0090cd00933100701b00923b00901b009221007", + "0x742b00701500923b00900708f00701b00923b00900708e0070cd01b018", + "0x12e00900e00700723b0090070ea00700723b00900716000702500923b009", + "0x12523b00900e12e12e38700700e00923b00900e00922100712e00923b009", + "0x723b00900712e00722900942c23c00923b12e22c0090fd00722c026023", + "0x2312e15800702600923b00902600922100702300923b00902300900e007", + "0x12e00703100942d22500923b12e0300090fd00703002e02c12523b009026", + "0x3312e23b00904500910700704500923b00923c00915100700723b009007", + "0x3600910400703600923b00922100910200700723b009033009101007221", + "0x3a12e23b00903800910700703800923b00922500915100721900923b009", + "0x12600910400712600923b00903b00910200700723b00903a00910100703b", + "0x723b00903e00915500714103e12e23b00921900915300703c00923b009", + "0x14100916300700723b00904100915500714504112e23b00903c009153007", + "0x923b00914804312e14f00714800923b00914500916300704300923b009", + "0x704900942e00723b12e04700910600704700923b00904700902e007047", + "0x23b00900700912500704c15012e23b0091fd00907800700723b00900712e", + "0x9900702c00923b00902c00900e00700900923b009009009033007007009", + "0x23b00901100936b00702e00923b00902e00922100712500923b009125009", + "0x71db00923b0091db00902e00715200923b00915200902e00715201112e", + "0x92231db15204c02e12502c00900701842f00722300923b00922300902e", + "0x12e03700701f00923b00901f01512e1a700705215701815501f15301123b", + "0x712e00715900943005400923b12e0520093b900701800923b00901801b", + "0x5a05805722323b00915000936900700723b0090540093bb00700723b009", + "0x23b00915300912500706416012e23b00905d00943100715f06015e05d15d", + "0x43200715700923b00915700922100715500923b00915500900e007153009", + "0x16600923b12e1640090cf00716406716216100e23b00906415715515300e", + "0x924600716b00923b0091660091a800700723b00900712e007168009433", + "0x23b00906f00915500700723b00906e00915500706f06e06d12523b00916b", + "0x922100716200923b00916200900e00716100923b009161009125007007", + "0x6d06716216100e43500706d00923b00906d00943400706700923b009067", + "0x12e00707600943717400923b12e07400943600707407216e07100e23b009", + "0x7712e23b00918000943900718000923b00917400943800700723b009007", + "0x7b00943900707b00923b00918600943a00718600923b00900716c007078", + "0x7800923b00907800943c00700723b00918700943b00708d18712e23b009", + "0x914000707f00923b00908d07812e43d00708d00923b00908d00943c007", + "0x23b00908e00905400700723b00900712e00708f00943e08e00923b12e07f", + "0x23b00900714c00709100923b00900714c00709000923b00900743f007007", + "0x7100923b00907100912500709300923b009092091090125440007092009", + "0x930091a100707200923b00907200922100716e00923b00916e00900e007", + "0x709709609509400e23b00909316007216e0711fd44100709300923b009", + "0x7700943900700723b00900712e00709900944309800923b12e097009442", + "0x71a700923b00900716c00700723b0091a500943b00709c1a512e23b009", + "0x5b00943b00709f05b12e23b00903700943900703700923b0091a7009444", + "0x700723b0091ac00943b0071b01ac12e23b00909c00943900700723b009", + "0x91b000943c00700723b0091b200943b0070a31b212e23b00909f009439", + "0x4a00923b0090a31b012e4450070a300923b0090a300943c0071b000923b", + "0x4a00914000700723b0091b50090540071b50a512e23b009098009446007", + "0x723b0090a700905400700723b00900712e0070a90094470a700923b12e", + "0x23b00915f06015e0a515d05a0580572231480071b800923b009007245007", + "0x22100709500923b00909500900e00709400923b0090940091250070ac009", + "0xb01bc0ae00e23b0091b80ac0960950941fd44800709600923b009096009", + "0x2f300700723b00900712e0070b40094491bd00923b12e0b20090c00070b2", + "0x23b0090ae00912500700723b0091bb0090540071bb0b612e23b0091bd009", + "0x3f80071ba00923b0090b00092210070ba00923b0091bc00900e0070b8009", + "0x15500700723b00900712e00700744a0090070ee0070bc00923b0090b6009", + "0xbe00923b0090b400944c00700723b00902500944b00700723b009011009", + "0x1bc00900e00701f00923b00901f0090330070ae00923b0090ae009125007", + "0xb000923b0090b000922100701800923b0090180090990071bc00923b009", + "0x900712e0070be0b00181bc01f0ae0110090be00923b0090be00944d007", + "0x15f06015e0a515d05a05805722314800700723b0090a900905400700723b", + "0xba00923b00909500900e0070b800923b0090940091250071b900923b009", + "0xb800944e0070bc00923b0091b90093f80071ba00923b009096009221007", + "0x1b600923b0091ba0094500070c200923b0090ba00944f0070c000923b009", + "0x723b00900712e0070074510090070ee0070c400923b0090bc0093f8007", + "0x23b00905700937000700723b00902500944b00700723b009011009155007", + "0x915e00937400700723b00906000937300700723b00915f009372007007", + "0x5a00937700700723b00915d00937600700723b00907700943b00700723b", + "0x1250070c600923b00909900944c00700723b00905800937100700723b009", + "0x23b00909500900e00701f00923b00901f00903300709400923b009094009", + "0x44d00709600923b00909600922100701800923b009018009099007095009", + "0x723b00900712e0070c609601809501f0940110090c600923b0090c6009", + "0x5a05805722314800700723b00907700943b00700723b00908f009054007", + "0x900e0070c000923b0090710091250071b300923b00915f06015e16015d", + "0x923b0091b30093f80071b600923b0090720092210070c200923b00916e", + "0x90070250070cf1aa0cd0cb1ad0c91b70c722323b0090c40093690070c4", + "0x23b0091a80cf1b60c200e4520071a800923b0091a80090260071a800923b", + "0x23b00900712e0070d50094531a000923b12e1a10092440071a10d11a3125", + "0xd10092210071a300923b0091a300900e00719f00923b009007025007007", + "0x919f1aa0d11a300e45400719f00923b00919f0090260070d100923b009", + "0x900712e00719700945619800923b12e0da0094550070da0d819b12523b", + "0x45800700723b00918e00905400718e0dd12e23b0091a000945700700723b", + "0xc91b70c722314800700723b0090e10090540070e10df12e23b009198009", + "0x18b18c18818922323b00918a00936900718a00923b0090dd0df0cd0cb1ad", + "0x923b00919b00900e0071790e812e23b0091880093d10070a01831840e5", + "0xea17b12523b0091790d819b1253d20070d800923b0090d800922100719b", + "0xe00700723b00900712e00717100945902000923b12e17500907b007175", + "0x23b00901100936b0070ea00923b0090ea00922100717b00923b00917b009", + "0x23b0090ec0e80ea17b00e45a0070ec00923b0090ec00902e0070ec01112e", + "0x923b12e0f000945c00702000923b00902002512e45b0070f016c0ee125", + "0x71630f312e23b00916900945e00700723b00900712e00716500945d169", + "0x90f600945f0070f601112e23b00901100936b00700723b009163009054", + "0x12500715c00923b0090a01831840e518b18c0f31892231480070f800923b", + "0x23b00916c0092210070ee00923b0090ee00900e0070c000923b0090c0009", + "0x23b0090f815c16c0ee0c01fd4610070f800923b0090f800946000716c009", + "0x900712e0071510094620fd00923b12e1580090c00071581541560fa00e", + "0x710210112e23b0090fd0092f300710700923b00902000918700700723b", + "0x23b0090fa00912500710400923b00910700946300700723b009102009054", + "0x46400715400923b00915400922100715600923b00915600900e0070fa009", + "0x10614f14c00e23b0091041011541560fa1fd46500710400923b009104009", + "0x2f300700723b00900712e00714900946614e00923b12e14d0090c000714d", + "0x23b0090110093f400700723b00910c00905400710c10a12e23b00914e009", + "0x22100714f00923b00914f00900e00714c00923b00914c009125007147009", + "0x10614f14c1fd3f600714700923b0091470093f500710600923b009106009", + "0x14300946711100923b12e1440090c000714410f14b14600e23b00914710a", + "0x914000905400714011312e23b0091110092f300700723b00900712e007", + "0x46900711500923b00911811312e46800711800923b00900716c00700723b", + "0x23b00901f00903300714600923b00914600912500713b00923b009115009", + "0x22100701800923b00901800909900714b00923b00914b00900e00701f009", + "0x1814b01f14601100913b00923b00913b00944d00710f00923b00910f009", + "0x14600912500713900923b00914300944c00700723b00900712e00713b10f", + "0x14b00923b00914b00900e00701f00923b00901f00903300714600923b009", + "0x13900944d00710f00923b00910f00922100701800923b009018009099007", + "0x15500700723b00900712e00713910f01814b01f14601100913900923b009", + "0x923b00914c00912500713700923b00914900944c00700723b009011009", + "0x909900714f00923b00914f00900e00701f00923b00901f00903300714c", + "0x923b00913700944d00710600923b00910600922100701800923b009018", + "0x901100915500700723b00900712e00713710601814f01f14c011009137", + "0x912500711a00923b00915100944c00700723b00902000924300700723b", + "0x923b00915600900e00701f00923b00901f0090330070fa00923b0090fa", + "0x944d00715400923b00915400922100701800923b009018009099007156", + "0x700723b00900712e00711a15401815601f0fa01100911a00923b00911a", + "0x723b00918900937000700723b00902000924300700723b009011009155", + "0x23b00918400937400700723b00918300937300700723b0090a0009372007", + "0x918c00937700700723b00918b00937600700723b0090e5009375007007", + "0x330070c000923b0090c000912500711c00923b00916500944c00700723b", + "0x23b0090180090990070ee00923b0090ee00900e00701f00923b00901f009", + "0x1100911c00923b00911c00944d00716c00923b00916c009221007018009", + "0x700723b00901100915500700723b00900712e00711c16c0180ee01f0c0", + "0x723b00918b00937600700723b00918c00937700700723b009189009370", + "0x23b00918400937400700723b00918300937300700723b0090a0009372007", + "0x902500944b00700723b0090e800937100700723b0090e5009375007007", + "0x330070c000923b0090c000912500712800923b00917100944c00700723b", + "0x23b00901800909900717b00923b00917b00900e00701f00923b00901f009", + "0x1100912800923b00912800944d0070ea00923b0090ea009221007018009", + "0x700723b00901100915500700723b00900712e0071280ea01817b01f0c0", + "0x723b0090c700937000700723b0091a000946a00700723b00902500944b", + "0x23b0091ad00937600700723b0090cb00937500700723b0090cd009374007", + "0x919700944c00700723b0091b700937100700723b0090c9009377007007", + "0x701f00923b00901f0090330070c000923b0090c000912500712300923b", + "0x90d800922100701800923b00901800909900719b00923b00919b00900e", + "0x71230d801819b01f0c001100912300923b00912300944d0070d800923b", + "0x700723b00902500944b00700723b00901100915500700723b00900712e", + "0x723b0090c700937000700723b0090c900937700700723b0091b7009371", + "0x23b0091ad00937600700723b0090cb00937500700723b0090cd009374007", + "0xc000912500700000923b0090d500944c00700723b0091aa009373007007", + "0x1a300923b0091a300900e00701f00923b00901f0090330070c000923b009", + "0x944d0070d100923b0090d100922100701800923b009018009099007", + "0x15500700723b00900712e0070000d10181a301f0c001100900000923b009", + "0x700723b00905700937000700723b00902500944b00700723b009011009", + "0x723b00905800937100700723b00905a00937700700723b00915d009376", + "0x23b00915e00937400700723b00906000937300700723b00915f009372007", + "0x710091250072f300923b00907600944c00700723b009160009375007007", + "0x16e00923b00916e00900e00701f00923b00901f00903300707100923b009", + "0x2f300944d00707200923b00907200922100701800923b009018009099007", + "0x15500700723b00900712e0072f307201816e01f0710110092f300923b009", + "0x700723b00905700937000700723b00902500944b00700723b009011009", + "0x723b00905800937100700723b00905a00937700700723b00915d009376", + "0x23b00915e00937400700723b00906000937300700723b00915f009372007", + "0x1610091250072f400923b00916800944c00700723b009160009375007007", + "0x16200923b00916200900e00701f00923b00901f00903300716100923b009", + "0x2f400944d00706700923b00906700922100701800923b009018009099007", + "0x15500700723b00900712e0072f406701816201f1610110092f400923b009", + "0x700723b00915000915200700723b00902500944b00700723b009011009", + "0x901f00903300715300923b0091530091250072f500923b00915900944c", + "0x701800923b00901800909900715500923b00915500900e00701f00923b", + "0x15501f1530110092f500923b0092f500944d00715700923b009157009221", + "0x2500944b00700723b00904900911100700723b00900712e0072f5157018", + "0x909700700723b00901500909600700723b00901100915500700723b009", + "0x15200700723b0091db00915500700723b00922300915500700723b00901b", + "0x72f700923b0090073c80072f600923b00900722900700723b0091fd009", + "0x90072250072f800923b0092f72f612e0300072f700923b0092f700902e", + "0x30800923b00930700944c00730700923b0092f824212e03100724200923b", + "0x2c00900e00700900923b00900900903300700700923b009007009125007", + "0x2e00923b00902e00922100712500923b00912500909900702c00923b009", + "0x900712e00730802e12502c00900701100930800923b00930800944d007", + "0x1500909600700723b00901100915500700723b00902500944b00700723b", + "0x915500700723b00922300915500700723b00901b00909700700723b009", + "0x44c00700723b00923c0093c900700723b0091fd00915200700723b0091db", + "0x23b00900900903300700700923b00900700912500730900923b009031009", + "0x22100712500923b00912500909900702c00923b00902c00900e007009009", + "0x12502c00900701100930900923b00930900944d00702e00923b00902e009", + "0x901100915500700723b00902500944b00700723b00900712e00730902e", + "0x22300915500700723b00901b00909700700723b00901500909600700723b", + "0x944c00700723b0091fd00915200700723b0091db00915500700723b009", + "0x923b00900900903300700700923b00900700912500730a00923b009229", + "0x922100712500923b00912500909900702300923b00902300900e007009", + "0x2612502300900701100930a00923b00930a00944d00702600923b009026", + "0x912e00922100700900923b00900900900e00700723b0090070ea00730a", + "0x23b12e1db0090fd0071db0111fd12523b00912e00912e38700712e00923b", + "0x71fd00923b0091fd00900e00700723b00900712e00701800946b223009", + "0xfd00701501f01b12523b0090111fd12e15800701100923b009011009221", + "0x922300915100700723b00900712e00702500946c02000923b12e015009", + "0x700723b00902600910100722c02612e23b00902300910700702300923b", + "0x902000915100722900923b00923c00910400723c00923b00922c009102", + "0x700723b00902e00910100703002e12e23b00902c00910700702c00923b", + "0x922900915300703100923b00922500910400722500923b009030009102", + "0x3622112e23b00903100915300700723b00904500915500703304512e23b", + "0x903600916300721900923b00903300916300700723b009221009155007", + "0x3a00923b00903a00902e00703a00923b00903821912e14f00703800923b", + "0xe00936b00700723b00900712e00703b00946d00723b12e03a009106007", + "0x23b00900712e00703c00946e00723b12e12600910600712600e12e23b009", + "0x1450093dd00704904714804314504114103e22323b009125009369007007", + "0x923b00901f00922100701b00923b00901b00900e00704c15012e23b009", + "0x923b12e15500907b00715515315212523b00904c01f01b1253de00701f", + "0x15300705400923b00915700918700700723b00900712e00705200946f157", + "0x923b00900714c00700723b00915900915500705715912e23b009054009", + "0x916300700723b00905a00915500715d05a12e23b009058009153007058", + "0x23b00915e05d12e14f00715e00923b00915d00916300705d00923b009057", + "0x15f00947000723b12e06000910600706000923b00906000902e007060009", + "0x923b00904904714804315004114103e22314800700723b00900712e007", + "0x93f800716100923b00915300922100706400923b00915200900e007160", + "0x911100700723b00900712e0070074710090070ee00716200923b009160", + "0x37300700723b00904900937200700723b00900e00915500700723b00915f", + "0x700723b00904300937500700723b00914800937400700723b009047009", + "0x723b00914100937100700723b00904100937700700723b009150009376", + "0x923b0090073e300706700923b00900722900700723b00903e009370007", + "0x22500716600923b00916406712e03000716400923b00916400902e007164", + "0x23b00916b00944c00716b00923b00916616812e03100716800923b009007", + "0x22100715200923b00915200900e00700700923b00900700912500706d009", + "0x6d15315200700e00906d00923b00906d00944d00715300923b009153009", + "0x723b00904900937200700723b00900e00915500700723b00900712e007", + "0x23b00904300937500700723b00914800937400700723b009047009373007", + "0x914100937100700723b00904100937700700723b009150009376007007", + "0x912500706e00923b00905200944c00700723b00903e00937000700723b", + "0x923b00915300922100715200923b00915200900e00700700923b009007", + "0x23b00900712e00706e15315200700e00906e00923b00906e00944d007153", + "0x1f00922100706400923b00901b00900e00700723b00903c009111007007", + "0x6f22323b00916200936900716200923b0091250093f800716100923b009", + "0x700912500707807712e23b00907400943100718007617407407216e071", + "0x16100923b00916100922100706400923b00906400900e00700700923b009", + "0x23b12e08d0090cf00708d18707b18600e23b00907816106400700e432007", + "0x708f00923b00907f0091a800700723b00900712e00708e00947207f009", + "0x9200915500700723b00909100915500709209109012523b00908f009246", + "0x707b00923b00907b00900e00718600923b00918600912500700723b009", + "0x7b18600e43500709000923b00909000943400718700923b009187009221", + "0x9800947309700923b12e09600943600709609509409300e23b009090187", + "0x23b00909900943900709900923b00909700943800700723b00900712e007", + "0x43900703700923b0091a700943a0071a700923b00900716c00709c1a512e", + "0x23b00909c00943c00700723b00905b00943b00709f05b12e23b009037009", + "0x71ac00923b00909f09c12e43d00709f00923b00909f00943c00709c009", + "0x1b000905400700723b00900712e0071b20094741b000923b12e1ac009140", + "0x714c00704a00923b00900714c0070a300923b00900743f00700723b009", + "0x23b0090930091250071b500923b0090a504a0a31254400070a500923b009", + "0x1a100709500923b00909500922100709400923b00909400900e007093009", + "0x1b80a90a700e23b0091b50770950940931fd4410071b500923b0091b5009", + "0x43900700723b00900712e0071bc0094750ae00923b12e0ac0094420070ac", + "0x923b00900716c00700723b0090b000943b0070b20b012e23b0091a5009", + "0x43b0071bb0b612e23b0090b40094390070b400923b0091bd0094440071bd", + "0x23b0090b800943b0070ba0b812e23b0090b200943900700723b0090b6009", + "0x943c00700723b0091ba00943b0070bc1ba12e23b0091bb009439007007", + "0x23b0090bc0ba12e4450070bc00923b0090bc00943c0070ba00923b0090ba", + "0x14000700723b0090c00090540070c01b912e23b0090ae0094460070be009", + "0x90c200905400700723b00900712e0071b60094760c200923b12e0be009", + "0x1800761741b907216e07106f2231480070c400923b00900724500700723b", + "0xa900923b0090a900900e0070a700923b0090a70091250070c600923b009", + "0x1b300e23b0090c40c61b80a90a71fd4480071b800923b0091b8009221007", + "0x723b00900712e0070cb0094771ad00923b12e0c90090c00070c91b70c7", + "0x1b300912500700723b0091aa0090540071aa0cd12e23b0091ad0092f3007", + "0x1a300923b0091b70092210071a800923b0090c700900e0070cf00923b009", + "0x723b00900712e0070074780090070ee0070d100923b0090cd0093f8007", + "0x91b30091250071a100923b0090cb00944c00700723b00900e009155007", + "0x71b700923b0091b70092210070c700923b0090c700900e0071b300923b", + "0x700723b00900712e0071a11b70c71b300e0091a100923b0091a100944d", + "0x923b0091800761741b907216e07106f22314800700723b0091b6009054", + "0x92210071a800923b0090a900900e0070cf00923b0090a70091250071a0", + "0x923b0090cf00944e0070d100923b0091a00093f80071a300923b0091b8", + "0x93f800719b00923b0091a300945000719f00923b0091a800944f0070d5", + "0x915500700723b00900712e0070074790090070ee0070d800923b0090d1", + "0x37300700723b00918000937200700723b00906f00937000700723b00900e", + "0x700723b0091a500943b00700723b00917400937400700723b009076009", + "0x723b00907100937100700723b00916e00937700700723b009072009376", + "0xa900900e0070a700923b0090a70091250070da00923b0091bc00944c007", + "0xda00923b0090da00944d0071b800923b0091b80092210070a900923b009", + "0x700723b0091b200905400700723b00900712e0070da1b80a90a700e009", + "0x923b00918007617407707216e07106f22314800700723b0091a500943b", + "0x922100719f00923b00909400900e0070d500923b009093009125007198", + "0x22323b0090d80093690070d800923b0091980093f800719b00923b009095", + "0x918c00902600718c00923b00900702500718818918a0e10df18e0dd197", + "0x1840092440071840e518b12523b00918c18819b19f00e45200718c00923b", + "0xe800923b00900702500700723b00900712e0070a000947a18300923b12e", + "0xe80090260070e500923b0090e500922100718b00923b00918b00900e007", + "0x94550070ea17b17912523b0090e81890e518b00e4540070e800923b009", + "0x23b00918300945700700723b00900712e00717100947b17500923b12e0ea", + "0x70f016c12e23b00917500945800700723b0090ee0090540070ee0ec12e", + "0x923b0090ec16c18a0e10df18e0dd19722314800700723b0090f0009054", + "0x17900900e0071560fa15c0f80f61630f316522323b009169009369007169", + "0xe12e23b00900e00936b00717b00923b00917b00922100717900923b009", + "0x15812523b00915416317b17900e47c00715400923b00915400902e007154", + "0x700723b00900712e00710100947e10700923b12e15100947d0071510fd", + "0x900e00948000700723b00910400905400710410212e23b00910700947f", + "0x12500714f00923b0091560fa15c0f80f61020f316522314800714c00923b", + "0x23b0090fd00922100715800923b00915800900e0070d500923b0090d5009", + "0x23b00914c14f0fd1580d51fd48200714c00923b00914c0094810070fd009", + "0x900712e00710c00948310a00923b12e1490090c000714914e14d10600e", + "0x16c00700723b00914600905400714614712e23b00910a0092f300700723b", + "0x23b00910f00946900710f00923b00914b14712e46800714b00923b009007", + "0x22100714d00923b00914d00900e00710600923b009106009125007144009", + "0x14414e14d10600e00914400923b00914400944d00714e00923b00914e009", + "0x23b00910600912500711100923b00910c00944c00700723b00900712e007", + "0x44d00714e00923b00914e00922100714d00923b00914d00900e007106009", + "0x37000700723b00900712e00711114e14d10600e00911100923b009111009", + "0x700723b0090fa00937300700723b00915600937200700723b009165009", + "0x723b0090f600937600700723b0090f800937500700723b00915c009374", + "0x23b00910100944c00700723b0090f300937100700723b00900e009155007", + "0x22100715800923b00915800900e0070d500923b0090d5009125007143009", + "0x1430fd1580d500e00914300923b00914300944d0070fd00923b0090fd009", + "0x723b00918300946a00700723b00900e00915500700723b00900712e007", + "0x23b0090e100937500700723b00918a00937400700723b009197009370007", + "0x90dd00937100700723b00918e00937700700723b0090df009376007007", + "0xe0070d500923b0090d500912500711300923b00917100944c00700723b", + "0x23b00911300944d00717b00923b00917b00922100717900923b009179009", + "0x23b00918e00937700700723b00900712e00711317b1790d500e009113009", + "0x919700937000700723b00900e00915500700723b0090dd009371007007", + "0xdf00937600700723b0090e100937500700723b00918a00937400700723b", + "0x12500714000923b0090a000944c00700723b00918900937300700723b009", + "0x23b0090e500922100718b00923b00918b00900e0070d500923b0090d5009", + "0x900712e0071400e518b0d500e00914000923b00914000944d0070e5009", + "0x7200937600700723b00906f00937000700723b00900e00915500700723b", + "0x937200700723b00907100937100700723b00916e00937700700723b009", + "0x37500700723b00917400937400700723b00907600937300700723b009180", + "0x923b00909300912500711800923b00909800944c00700723b009077009", + "0x944d00709500923b00909500922100709400923b00909400900e007093", + "0x915500700723b00900712e00711809509409300e00911800923b009118", + "0x37700700723b00907200937600700723b00906f00937000700723b00900e", + "0x700723b00918000937200700723b00907100937100700723b00916e009", + "0x723b00907700937500700723b00917400937400700723b009076009373", + "0x7b00900e00718600923b00918600912500711500923b00908e00944c007", + "0x11500923b00911500944d00718700923b00918700922100707b00923b009", + "0x700723b00903b00911100700723b00900712e00711518707b18600e009", + "0x13b00923b00900722900700723b00912500915200700723b00900e009155", + "0x13913b12e03000713900923b00913900902e00713900923b0090073c8007", + "0x11c00923b00913711a12e03100711a00923b00900722500713700923b009", + "0x1b00900e00700700923b00900700912500712800923b00911c00944c007", + "0x12800923b00912800944d00701f00923b00901f00922100701b00923b009", + "0x700723b00900e00915500700723b00900712e00712801f01b00700e009", + "0x923b00902500944c00700723b0092230093c900700723b009125009152", + "0x922100701b00923b00901b00900e00700700923b009007009125007123", + "0x712301f01b00700e00912300923b00912300944d00701f00923b00901f", + "0x700723b00912500915200700723b00900e00915500700723b00900712e", + "0x91fd00900e00700700923b00900700912500700000923b00901800944c", + "0x900000923b00900000944d00701100923b0090110092210071fd00923b", + "0x700900923b00900900900e00700723b0090070ea0070000111fd00700e", + "0xfd0071db0111fd12523b00912e00912e38700712e00923b00912e009221", + "0x91fd00900e00700723b00900712e00701800948422300923b12e1db009", + "0x1b12523b0090111fd12e15800701100923b0090110092210071fd00923b", + "0x700723b00900712e00702500948502000923b12e0150090fd00701501f", + "0x2600910100722c02612e23b00902300910700702300923b009223009151", + "0x722900923b00923c00910400723c00923b00922c00910200700723b009", + "0x2e00910100703002e12e23b00902c00910700702c00923b009020009151", + "0x703100923b00922500910400722500923b00903000910200700723b009", + "0x903100915300700723b00904500915500703304512e23b009229009153", + "0x721900923b00903300916300700723b00922100915500703622112e23b", + "0x3a00902e00703a00923b00903821912e14f00703800923b009036009163", + "0x723b00900712e00703b00948600723b12e03a00910600703a00923b009", + "0x14504114103e22323b00903c00936900703c12612e23b009125009078007", + "0x37600700723b00914100937100700723b00903e009370007049047148043", + "0x700723b00914800937400700723b00904300937500700723b009145009", + "0x923b00901b00900e00700723b00904900937200700723b009047009373", + "0x4c15012523b00904101f01b1253da00701f00923b00901f00922100701b", + "0x18700700723b00900712e00715500948715300923b12e15200907b007152", + "0x905200915500705405212e23b00915700915300715700923b009153009", + "0x15500705805712e23b00915900915300715900923b00900714c00700723b", + "0x12e23b00905a00915300705a00923b00905400916300700723b009057009", + "0x915300715e00923b00905800916300700723b00915d00915500705d15d", + "0x923b00905d00916300700723b00906000915500715f06012e23b00915e", + "0x10f00716100923b00906416012e14f00706400923b00915f009163007160", + "0x48800723b12e16100910600716100923b00916100902e00700723b009007", + "0x906700914400706700923b00900716c00700723b00900712e007162009", + "0x712e0070074890090070ee00716600923b0091640090a500716400923b", + "0x911300716800923b00900716c00700723b00916200911100700723b009", + "0x923b00916600936e00716600923b00916b0090a500716b00923b009168", + "0x6f00948a06e00923b12e06d00914000706d00923b00906d0090a500706d", + "0x700723b00906e00905400700723b0090070ea00700723b00900712e007", + "0x7100923b00900722900700723b00912600915200700723b00900e009155", + "0x16e07112e03000716e00923b00916e00902e00716e00923b00900748b007", + "0x17400923b00907207412e03100707400923b00900722500707200923b009", + "0x15000900e00700700923b00900700912500707600923b00917400944c007", + "0x7600923b00907600944d00704c00923b00904c00922100715000923b009", + "0x5400700723b0090070ea00700723b00900712e00707604c15000700e009", + "0x7f08d18707b18607807718022323b00912600936900700723b00906f009", + "0x900e00700700923b00900700912500708f08e12e23b00907b009431007", + "0x8f04c15000700e43200704c00923b00904c00922100715000923b009150", + "0x12e00709500948c09400923b12e0930090cf00709309209109000e23b009", + "0x9712523b00909600924600709600923b0090940091a800700723b009007", + "0x9000912500700723b00909900915500700723b009098009155007099098", + "0x9200923b00909200922100709100923b00909100900e00709000923b009", + "0x9c1a500e23b00909709209109000e43500709700923b009097009434007", + "0x700723b00900712e00709f00948d05b00923b12e0370094360070371a7", + "0x900716c0071b21b012e23b0091ac0094390071ac00923b00905b009438", + "0x1b50a512e23b00904a00943900704a00923b0090a300943a0070a300923b", + "0x91b500943c0071b200923b0091b200943c00700723b0090a500943b007", + "0xa900923b12e0a70091400070a700923b0091b51b212e43d0071b500923b", + "0x900743f00700723b0090a900905400700723b00900712e0071b800948e", + "0x1254400071bc00923b00900714c0070ae00923b00900714c0070ac00923b", + "0x909c00900e0071a500923b0091a50091250070b000923b0091bc0ae0ac", + "0x70b000923b0090b00091a10071a700923b0091a700922100709c00923b", + "0x23b12e0b60094420070b60b41bd0b200e23b0090b008e1a709c1a51fd441", + "0x1ba0ba12e23b0091b000943900700723b00900712e0070b800948f1bb009", + "0x23b0090bc0094440070bc00923b00900716c00700723b0090ba00943b007", + "0x43900700723b0091b900943b0070c01b912e23b0090be0094390070be009", + "0x23b0090c000943900700723b0090c200943b0071b60c212e23b0091ba009", + "0x43c0071b600923b0091b600943c00700723b0090c400943b0070c60c412e", + "0x91bb0094460071b300923b0090c61b612e4450070c600923b0090c6009", + "0x4900c900923b12e1b300914000700723b0091b70090540071b70c712e23b", + "0x23b00900724500700723b0090c900905400700723b00900712e0071ad009", + "0x91250070cd00923b00907f08d1870c71860780771802231480070cb009", + "0x923b0090b40092210071bd00923b0091bd00900e0070b200923b0090b2", + "0x1a30090c00071a31a80cf1aa00e23b0090cb0cd0b41bd0b21fd4480070b4", + "0x12e23b0090d10092f300700723b00900712e0071a10094910d100923b12e", + "0x900e00719f00923b0091aa00912500700723b0090d50090540070d51a0", + "0x923b0091a00093f80070d800923b0091a800922100719b00923b0090cf", + "0x723b00900e00915500700723b00900712e0070074920090070ee0070da", + "0xcf00900e0071aa00923b0091aa00912500719800923b0091a100944c007", + "0x19800923b00919800944d0071a800923b0091a80092210070cf00923b009", + "0x700723b0091ad00905400700723b00900712e0071981a80cf1aa00e009", + "0x23b0090b200912500719700923b00907f08d1870c7186078077180223148", + "0x3f80070d800923b0090b400922100719b00923b0091bd00900e00719f009", + "0x23b00919b00944f0070dd00923b00919f00944e0070da00923b009197009", + "0xee0070e100923b0090da0093f80070df00923b0090d800945000718e009", + "0x937000700723b00900e00915500700723b00900712e007007493009007", + "0x37400700723b00908d00937300700723b00907f00937200700723b009180", + "0x700723b00918600937600700723b0091b000943b00700723b009187009", + "0x923b0090b800944c00700723b00907700937100700723b009078009377", + "0x92210071bd00923b0091bd00900e0070b200923b0090b200912500718a", + "0x718a0b41bd0b200e00918a00923b00918a00944d0070b400923b0090b4", + "0x700723b0091b000943b00700723b0091b800905400700723b00900712e", + "0x23b0091a500912500718900923b00907f08d18708e186078077180223148", + "0x3f80070df00923b0091a700922100718e00923b00909c00900e0070dd009", + "0xa01831840e518b18c18822323b0090e10093690070e100923b009189009", + "0x18e00e45200717900923b00917900902600717900923b0090070250070e8", + "0xec00949417100923b12e1750092440071750ea17b12523b0091790e80df", + "0x923b00917b00900e0070ee00923b00900702500700723b00900712e007", + "0xe4540070ee00923b0090ee0090260070ea00923b0090ea00922100717b", + "0x949516500923b12e1690094550071690f016c12523b0090ee0a00ea17b", + "0xf60090540070f616312e23b00917100945700700723b00900712e0070f3", + "0x700723b00915c00905400715c0f812e23b00916500945800700723b009", + "0x23b0090fa0093690070fa00923b0091630f81831840e518b18c188223148", + "0x922100716c00923b00916c00900e0071021011071510fd158154156223", + "0x23b00910400902e00710400e12e23b00900e00936b0070f000923b0090f0", + "0x12e10600949700710614f14c12523b0091040fd0f016c00e496007104009", + "0x14912e23b00914d00949900700723b00900712e00714e00949814d00923b", + "0x15622314800710c00923b00900e00949a00700723b00910a00905400710a", + "0x70dd00923b0090dd00912500714700923b009102101107151149158154", + "0x910c00949b00714f00923b00914f00922100714c00923b00914c00900e", + "0xc000714410f14b14600e23b00910c14714f14c0dd1fd49c00710c00923b", + "0x91110092f300700723b00900712e00714300949d11100923b12e144009", + "0x46800711800923b00900716c00700723b00914000905400714011312e23b", + "0x914600912500713b00923b00911500946900711500923b00911811312e", + "0x710f00923b00910f00922100714b00923b00914b00900e00714600923b", + "0x700723b00900712e00713b10f14b14600e00913b00923b00913b00944d", + "0x914b00900e00714600923b00914600912500713900923b00914300944c", + "0x913900923b00913900944d00710f00923b00910f00922100714b00923b", + "0x37200700723b00915600937000700723b00900712e00713910f14b14600e", + "0x700723b00910700937400700723b00910100937300700723b009102009", + "0x723b00915800937700700723b00900e00915500700723b009151009375", + "0x90dd00912500713700923b00914e00944c00700723b009154009371007", + "0x714f00923b00914f00922100714c00923b00914c00900e0070dd00923b", + "0x700723b00900712e00713714f14c0dd00e00913700923b00913700944d", + "0x723b00918800937000700723b00917100946a00700723b00900e009155", + "0x23b0090e500937600700723b00918400937500700723b009183009374007", + "0x90f300944c00700723b00918c00937100700723b00918b009377007007", + "0x716c00923b00916c00900e0070dd00923b0090dd00912500711a00923b", + "0xf016c0dd00e00911a00923b00911a00944d0070f000923b0090f0009221", + "0x23b00918c00937100700723b00918b00937700700723b00900712e00711a", + "0x918300937400700723b00918800937000700723b00900e009155007007", + "0xa000937300700723b0090e500937600700723b00918400937500700723b", + "0x70dd00923b0090dd00912500711c00923b0090ec00944c00700723b009", + "0x911c00944d0070ea00923b0090ea00922100717b00923b00917b00900e", + "0x900e00915500700723b00900712e00711c0ea17b0dd00e00911c00923b", + "0x7800937700700723b00918600937600700723b00918000937000700723b", + "0x937300700723b00907f00937200700723b00907700937100700723b009", + "0x44c00700723b00908e00937500700723b00918700937400700723b00908d", + "0x23b00909c00900e0071a500923b0091a500912500712800923b00909f009", + "0xe00912800923b00912800944d0071a700923b0091a700922100709c009", + "0x937000700723b00900e00915500700723b00900712e0071281a709c1a5", + "0x37100700723b00907800937700700723b00918600937600700723b009180", + "0x700723b00908d00937300700723b00907f00937200700723b009077009", + "0x923b00909500944c00700723b00908e00937500700723b009187009374", + "0x922100709100923b00909100900e00709000923b009090009125007123", + "0x712309209109000e00912300923b00912300944d00709200923b009092", + "0x700723b00912600915200700723b00900e00915500700723b00900712e", + "0x915000900e00700700923b00900700912500700000923b00915500944c", + "0x900000923b00900000944d00704c00923b00904c00922100715000923b", + "0x15500700723b00903b00911100700723b00900712e00700004c15000700e", + "0x72f300923b00900722900700723b00912500915200700723b00900e009", + "0x92f42f312e0300072f400923b0092f400902e0072f400923b0090073c8", + "0x72f700923b0092f52f612e0310072f600923b0090072250072f500923b", + "0x901b00900e00700700923b0090070091250072f800923b0092f700944c", + "0x92f800923b0092f800944d00701f00923b00901f00922100701b00923b", + "0x15200700723b00900e00915500700723b00900712e0072f801f01b00700e", + "0x24200923b00902500944c00700723b0092230093c900700723b009125009", + "0x1f00922100701b00923b00901b00900e00700700923b009007009125007", + "0x12e00724201f01b00700e00924200923b00924200944d00701f00923b009", + "0x44c00700723b00912500915200700723b00900e00915500700723b009007", + "0x23b0091fd00900e00700700923b00900700912500730700923b009018009", + "0xe00930700923b00930700944d00701100923b0090110092210071fd009", + "0x22100700900923b00900900900e00700723b0090070ea0073070111fd007", + "0x90fd0071db0111fd12523b00912e00912e38700712e00923b00912e009", + "0x23b0091fd00900e00700723b00900712e00701800949e22300923b12e1db", + "0x1f01b12523b0090111fd12e15800701100923b0090110092210071fd009", + "0x15100700723b00900712e00702500949f02000923b12e0150090fd007015", + "0x902600910100722c02612e23b00902300910700702300923b009223009", + "0x15100722900923b00923c00910400723c00923b00922c00910200700723b", + "0x902e00910100703002e12e23b00902c00910700702c00923b009020009", + "0x15300703100923b00922500910400722500923b00903000910200700723b", + "0x23b00903100915300700723b00904500915500703304512e23b009229009", + "0x16300721900923b00903300916300700723b00922100915500703622112e", + "0x903a00902e00703a00923b00903821912e14f00703800923b009036009", + "0x700723b00900712e00703b0094a000723b12e03a00910600703a00923b", + "0x23b00904100943100714804314504114103e03c12622323b009125009369", + "0x701b00923b00901b00900e00700700923b00900700912500704904712e", + "0x15204c15000e23b00904901f01b00700e43200701f00923b00901f009221", + "0x1a800700723b00900712e0071570094a115500923b12e1530090cf007153", + "0x5700915500705715905412523b00905200924600705200923b009155009", + "0x705a00923b00905815912e14f00705800923b00900714300700723b009", + "0x712e00715d0094a200723b12e05a00910600705a00923b00905a00902e", + "0x704c00923b00904c00900e00715000923b00915000912500700723b009", + "0x4c15000e43500705400923b00905400943400715200923b009152009221", + "0x640094a316000923b12e15f00943600715f06015e05d00e23b009054152", + "0x23b00916100943900716100923b00916000943800700723b00900712e007", + "0x944400716400923b00900716c00700723b00916200943b00706716212e", + "0x23b00916800943b00716b16812e23b00916600943900716600923b009164", + "0x12e43d00716b00923b00916b00943c00706700923b00906700943c007007", + "0x712e00706f0094a406e00923b12e06d00914000706d00923b00916b067", + "0x937000700723b00900e00915500700723b00906e00905400700723b009", + "0x37400700723b00904300937300700723b00914800937200700723b009126", + "0x700723b00914100937600700723b00904700937500700723b009145009", + "0x7100923b00900722900700723b00903c00937100700723b00903e009377", + "0x16e07112e03000716e00923b00916e00902e00716e00923b0090074a5007", + "0x17400923b00907207412e03100707400923b00900722500707200923b009", + "0x15e00900e00705d00923b00905d00912500707600923b00917400944c007", + "0x7600923b00907600944d00706000923b00906000922100715e00923b009", + "0x700723b00906f00905400700723b00900712e00707606015e05d00e009", + "0x906000922100707700923b00915e00900e00718000923b00905d009125", + "0x900e00915500700723b00900712e0070074a60090070ee00707800923b", + "0x4300937300700723b00914800937200700723b00912600937000700723b", + "0x937600700723b00904700937500700723b00914500937400700723b009", + "0x44c00700723b00903c00937100700723b00903e00937700700723b009141", + "0x23b00915e00900e00705d00923b00905d00912500718600923b009064009", + "0xe00918600923b00918600944d00706000923b00906000922100715e009", + "0x934f00700723b00915d00911100700723b00900712e00718606015e05d", + "0x7700923b00904c00900e00718000923b00915000912500700723b009054", + "0x914804314504714103e03c12622314800707800923b009152009221007", + "0x43100709209109008f08e07f08d18722323b00907b00936900707b00923b", + "0x9709609500e23b00909407807718000e43200709409312e23b00908f009", + "0x1a800700723b00900712e0071a50094a709900923b12e0980090cf007098", + "0x3700915500705b0371a712523b00909c00924600709c00923b009099009", + "0xe00709500923b00909500912500700723b00905b00915500700723b009", + "0x23b0091a700943400709700923b00909700922100709600923b009096009", + "0x1b20094360071b21b01ac09f00e23b0091a709709609500e4350071a7009", + "0x923b0090a300943800700723b00900712e00704a0094a80a300923b12e", + "0x943a0070a900923b00900716c0070a71b512e23b0090a50094390070a5", + "0x23b0090ac00943b0070ae0ac12e23b0091b80094390071b800923b0090a9", + "0x12e43d0070ae00923b0090ae00943c0070a700923b0090a700943c007007", + "0x712e0070b20094a90b000923b12e1bc0091400071bc00923b0090ae0a7", + "0x714c0071bd00923b00900743f00700723b0090b000905400700723b009", + "0x923b0090b60b41bd1254400070b600923b00900714c0070b400923b009", + "0x92210071ac00923b0091ac00900e00709f00923b00909f0091250071bb", + "0x931b01ac09f1fd4410071bb00923b0091bb0091a10071b000923b0091b0", + "0x71b90094aa0be00923b12e0bc0094420070bc1ba0ba0b800e23b0091bb", + "0x23b0090c000943b0070c20c012e23b0091b500943900700723b00900712e", + "0xc40094390070c400923b0091b60094440071b600923b00900716c007007", + "0xc712e23b0090c200943900700723b0090c600943b0071b30c612e23b009", + "0x943b0071ad0c912e23b0091b300943900700723b0090c700943b0071b7", + "0x1ad00923b0091ad00943c0071b700923b0091b700943c00700723b0090c9", + "0x540071aa0cd12e23b0090be0094460070cb00923b0091ad1b712e445007", + "0x900712e0071a80094ab0cf00923b12e0cb00914000700723b0091aa009", + "0x1872231480071a300923b00900724500700723b0090cf00905400700723b", + "0x70b800923b0090b80091250070d100923b0090920910900cd08e07f08d", + "0xba0b81fd4480071ba00923b0091ba0092210070ba00923b0090ba00900e", + "0x94ac19b00923b12e19f0090c000719f0d51a01a100e23b0091a30d11ba", + "0x1980090540071980da12e23b00919b0092f300700723b00900712e0070d8", + "0x70dd00923b0091a000900e00719700923b0091a100912500700723b009", + "0x4ad0090070ee0070df00923b0090da0093f800718e00923b0090d5009221", + "0x23b0090d800944c00700723b00900e00915500700723b00900712e007007", + "0x2210071a000923b0091a000900e0071a100923b0091a10091250070e1009", + "0xe10d51a01a100e0090e100923b0090e100944d0070d500923b0090d5009", + "0x8e07f08d18722314800700723b0091a800905400700723b00900712e007", + "0xba00900e00719700923b0090b800912500718a00923b0090920910900cd", + "0xdf00923b00918a0093f800718e00923b0091ba0092210070dd00923b009", + "0x18e00945000718800923b0090dd00944f00718900923b00919700944e007", + "0x12e0070074ae0090070ee00718b00923b0090df0093f800718c00923b009", + "0x37200700723b00918700937000700723b00900e00915500700723b009007", + "0x700723b00909000937400700723b00909100937300700723b009092009", + "0x723b00907f00937700700723b00908e00937600700723b0091b500943b", + "0x90b80091250070e500923b0091b900944c00700723b00908d009371007", + "0x71ba00923b0091ba0092210070ba00923b0090ba00900e0070b800923b", + "0x700723b00900712e0070e51ba0ba0b800e0090e500923b0090e500944d", + "0x8e07f08d18722314800700723b0091b500943b00700723b0090b2009054", + "0x1ac00900e00718900923b00909f00912500718400923b009092091090093", + "0x18b00923b0091840093f800718c00923b0091b000922100718800923b009", + "0x4af17900923b12e0e800935f0070e80a018312523b00918c18812e35e007", + "0x90074b00070ea00923b00917900936100700723b00900712e00717b009", + "0x70ea00923b0090ea00943400718900923b00918900912500717500923b", + "0x35f0070ec17112e23b0091750ea1891254b100717500923b009175009434", + "0x918b00936900700723b00900712e00716c0094b20ee00923b12e0ec009", + "0x40b0070fa00923b0090ee00936100715c0f80f61630f31651690f022323b", + "0x23b00900e00936b0071540fa12e23b0090fa00936200715600923b009007", + "0x923b0091710091250070fd00923b00915815615412544000715800e12e", + "0x91a10070a000923b0090a000922100718300923b00918300900e007171", + "0x10210110715100e23b0090fd1630a01831711fd4410070fd00923b0090fd", + "0x944600700723b00900712e00714c0094b310400923b12e102009442007", + "0x23b00900e0fa12e4b400700723b00910600905400710614f12e23b009104", + "0x912500714e00923b00915c0f80f614f0f31651690f022314800714d009", + "0x923b00910100922100710700923b00910700900e00715100923b009151", + "0xe23b00914d14e1011071511fd4b600714d00923b00914d0094b5007101", + "0x23b00900712e00714b0094b714600923b12e1470090c000714710c10a149", + "0x716c00700723b00914400905400714410f12e23b0091460092f3007007", + "0x923b00914300946900714300923b00911110f12e46800711100923b009", + "0x922100710a00923b00910a00900e00714900923b009149009125007113", + "0x711310c10a14900e00911300923b00911300944d00710c00923b00910c", + "0x923b00914900912500714000923b00914b00944c00700723b00900712e", + "0x944d00710c00923b00910c00922100710a00923b00910a00900e007149", + "0x937000700723b00900712e00714010c10a14900e00914000923b009140", + "0x37400700723b0090f800937300700723b00915c00937200700723b0090f0", + "0x700723b0090f300937600700723b0090fa00934f00700723b0090f6009", + "0x723b00900e00915500700723b00916900937100700723b009165009377", + "0x10700900e00715100923b00915100912500711800923b00914c00944c007", + "0x11800923b00911800944d00710100923b00910100922100710700923b009", + "0x700723b00918b00915200700723b00900712e00711810110715100e009", + "0x23b00917100912500711500923b00916c00944c00700723b00900e009155", + "0x44d0070a000923b0090a000922100718300923b00918300900e007171009", + "0x15200700723b00900712e0071150a018317100e00911500923b009115009", + "0x13b00923b00917b00944c00700723b00900e00915500700723b00918b009", + "0xa000922100718300923b00918300900e00718900923b009189009125007", + "0x12e00713b0a018318900e00913b00923b00913b00944d0070a000923b009", + "0x37600700723b00918700937000700723b00900e00915500700723b009007", + "0x700723b00908d00937100700723b00907f00937700700723b00908e009", + "0x723b00909000937400700723b00909100937300700723b009092009372", + "0x909f00912500713900923b00904a00944c00700723b009093009375007", + "0x71b000923b0091b00092210071ac00923b0091ac00900e00709f00923b", + "0x700723b00900712e0071391b01ac09f00e00913900923b00913900944d", + "0x723b00908e00937600700723b00918700937000700723b00900e009155", + "0x23b00909200937200700723b00908d00937100700723b00907f009377007", + "0x909300937500700723b00909000937400700723b009091009373007007", + "0xe00709500923b00909500912500713700923b0091a500944c00700723b", + "0x23b00913700944d00709700923b00909700922100709600923b009096009", + "0x23b00914100937600700723b00900712e00713709709609500e009137009", + "0x900e00915500700723b00903c00937100700723b00903e009377007007", + "0x4300937300700723b00914800937200700723b00912600937000700723b", + "0x944c00700723b00904700937500700723b00914500937400700723b009", + "0x923b00904c00900e00715000923b00915000912500711a00923b009157", + "0x15000e00911a00923b00911a00944d00715200923b00915200922100704c", + "0xe00915500700723b00903b00911100700723b00900712e00711a15204c", + "0x73c800711c00923b00900722900700723b00912500915200700723b009", + "0x923b00912811c12e03000712800923b00912800902e00712800923b009", + "0x944c0072f300923b00912300012e03100700000923b009007225007123", + "0x923b00901b00900e00700700923b0090070091250072f400923b0092f3", + "0x700e0092f400923b0092f400944d00701f00923b00901f00922100701b", + "0x12500915200700723b00900e00915500700723b00900712e0072f401f01b", + "0x1250072f500923b00902500944c00700723b0092230093c900700723b009", + "0x23b00901f00922100701b00923b00901b00900e00700700923b009007009", + "0x900712e0072f501f01b00700e0092f500923b0092f500944d00701f009", + "0x1800944c00700723b00900e00915500700723b00912500915200700723b", + "0x1fd00923b0091fd00900e00700700923b0090070091250072f600923b009", + "0x1fd00700e0092f600923b0092f600944d00701100923b009011009221007", + "0x12e00922100700900923b00900900900e00700723b0090070ea0072f6011", + "0x12e1db0090fd0071db0111fd12523b00912e00912e38700712e00923b009", + "0x1fd00923b0091fd00900e00700723b00900712e0070180094b822300923b", + "0x701501f01b12523b0090111fd12e15800701100923b009011009221007", + "0x22300915100700723b00900712e0070250094b902000923b12e0150090fd", + "0x723b00902600910100722c02612e23b00902300910700702300923b009", + "0x2000915100722900923b00923c00910400723c00923b00922c009102007", + "0x723b00902e00910100703002e12e23b00902c00910700702c00923b009", + "0x22900915300703100923b00922500910400722500923b009030009102007", + "0x22112e23b00903100915300700723b00904500915500703304512e23b009", + "0x3600916300721900923b00903300916300700723b009221009155007036", + "0x923b00903a00902e00703a00923b00903821912e14f00703800923b009", + "0x936900700723b00900712e00703b0094ba00723b12e03a00910600703a", + "0x4712e23b00904100943100714804314504114103e03c12622323b009125", + "0x922100701b00923b00901b00900e00700700923b009007009125007049", + "0x715315204c15000e23b00904901f01b00700e43200701f00923b00901f", + "0x1550091a800700723b00900712e0071570094bb15500923b12e1530090cf", + "0x23b00915900915500705715905412523b00905200924600705200923b009", + "0x4c00900e00715000923b00915000912500700723b009057009155007007", + "0x5400923b00905400943400715200923b00915200922100704c00923b009", + "0x23b12e05d00943600705d15d05a05800e23b00905415204c15000e435007", + "0x715f00923b00915e00943800700723b00900712e0070600094bc15e009", + "0x916100943a00716100923b00900716c00706416012e23b00915f009439", + "0x700723b00906700943b00716406712e23b00916200943900716200923b", + "0x16406412e43d00716400923b00916400943c00706400923b00906400943c", + "0x23b00900712e00716b0094bd16800923b12e16600914000716600923b009", + "0x23b00900714c00706d00923b00900743f00700723b009168009054007007", + "0x707100923b00906f06e06d12544000706f00923b00900714c00706e009", + "0x915d00922100705a00923b00905a00900e00705800923b009058009125", + "0x907104715d05a0581fd44100707100923b0090710091a100715d00923b", + "0x712e0071800094be07600923b12e17400944200717407407216e00e23b", + "0x700723b00907700943b00707807712e23b00916000943900700723b009", + "0x23b00907b00943900707b00923b00918600944400718600923b00900716c", + "0x708e07f12e23b00907800943900700723b00918700943b00708d18712e", + "0x908f00943b00709008f12e23b00908d00943900700723b00907f00943b", + "0x44500709000923b00909000943c00708e00923b00908e00943c00700723b", + "0x9300905400709309212e23b00907600944600709100923b00909008e12e", + "0x723b00900712e0070950094bf09400923b12e09100914000700723b009", + "0x3e03c12622314800709600923b00900724500700723b009094009054007", + "0x900e00716e00923b00916e00912500709700923b009148043145092141", + "0x9707407216e1fd44800707400923b00907400922100707200923b009072", + "0x70370094c01a700923b12e09c0090c000709c1a509909800e23b009096", + "0x23b00909f00905400709f05b12e23b0091a70092f300700723b00900712e", + "0x92210071b000923b00909900900e0071ac00923b009098009125007007", + "0x70074c10090070ee0070a300923b00905b0093f80071b200923b0091a5", + "0x4a00923b00903700944c00700723b00900e00915500700723b00900712e", + "0x1a500922100709900923b00909900900e00709800923b009098009125007", + "0x12e00704a1a509909800e00904a00923b00904a00944d0071a500923b009", + "0x14509214103e03c12622314800700723b00909500905400700723b009007", + "0x23b00907200900e0071ac00923b00916e0091250070a500923b009148043", + "0x44e0070a300923b0090a50093f80071b200923b0090740092210071b0009", + "0x23b0091b20094500070a700923b0091b000944f0071b500923b0091ac009", + "0x900712e0070074c20090070ee0071b800923b0090a30093f80070a9009", + "0x14800937200700723b00912600937000700723b00900e00915500700723b", + "0x943b00700723b00914500937400700723b00904300937300700723b009", + "0x37100700723b00903e00937700700723b00914100937600700723b009160", + "0x923b00916e0091250070ac00923b00918000944c00700723b00903c009", + "0x944d00707400923b00907400922100707200923b00907200900e00716e", + "0x905400700723b00900712e0070ac07407216e00e0090ac00923b0090ac", + "0x14504714103e03c12622314800700723b00916000943b00700723b00916b", + "0x23b00905a00900e0071b500923b0090580091250070ae00923b009148043", + "0x35e0071b800923b0090ae0093f80070a900923b00915d0092210070a7009", + "0xb40094c31bd00923b12e0b200935f0070b20b01bc12523b0090a90a712e", + "0x923b0090074b00070b600923b0091bd00936100700723b00900712e007", + "0x94340070b600923b0090b60094340071b500923b0091b50091250071bb", + "0xba00935f0070ba0b812e23b0091bb0b61b51254b10071bb00923b0091bb", + "0x22323b0091b800936900700723b00900712e0070bc0094c41ba00923b12e", + "0x90071430070c700923b0091ba0093610071b30c60c41b60c20c01b90be", + "0xe12e23b00900e00936b0070c90c712e23b0090c70093620071b700923b", + "0x70b800923b0090b80091250070cb00923b0091ad1b70c91254400071ad", + "0x90cb0091a10070b000923b0090b00092210071bc00923b0091bc00900e", + "0x4420071a80cf1aa0cd00e23b0090cb1b60b01bc0b81fd4410070cb00923b", + "0x91a300944600700723b00900712e0070d10094c51a300923b12e1a8009", + "0xd500923b00900e0c712e4c600700723b0091a00090540071a01a112e23b", + "0x90cd00912500719f00923b0091b30c60c41a10c20c01b90be223148007", + "0x70cf00923b0090cf0092210071aa00923b0091aa00900e0070cd00923b", + "0xd819b00e23b0090d519f0cf1aa0cd1fd4c80070d500923b0090d50094c7", + "0x700723b00900712e0070dd0094c919700923b12e1980090c00071980da", + "0x23b00900716c00700723b0090df0090540070df18e12e23b0091970092f3", + "0x718900923b00918a00946900718a00923b0090e118e12e4680070e1009", + "0x90da0092210070d800923b0090d800900e00719b00923b00919b009125", + "0x712e0071890da0d819b00e00918900923b00918900944d0070da00923b", + "0x719b00923b00919b00912500718800923b0090dd00944c00700723b009", + "0x918800944d0070da00923b0090da0092210070d800923b0090d800900e", + "0x90be00937000700723b00900712e0071880da0d819b00e00918800923b", + "0xc400937400700723b0090c600937300700723b0091b300937200700723b", + "0x937700700723b0090c200937600700723b0090c700934f00700723b009", + "0x44c00700723b00900e00915500700723b0091b900937100700723b0090c0", + "0x23b0091aa00900e0070cd00923b0090cd00912500718c00923b0090d1009", + "0xe00918c00923b00918c00944d0070cf00923b0090cf0092210071aa009", + "0x915500700723b0091b800915200700723b00900712e00718c0cf1aa0cd", + "0xb800923b0090b800912500718b00923b0090bc00944c00700723b00900e", + "0x18b00944d0070b000923b0090b00092210071bc00923b0091bc00900e007", + "0x1b800915200700723b00900712e00718b0b01bc0b800e00918b00923b009", + "0x1250070e500923b0090b400944c00700723b00900e00915500700723b009", + "0x23b0090b00092210071bc00923b0091bc00900e0071b500923b0091b5009", + "0x900712e0070e50b01bc1b500e0090e500923b0090e500944d0070b0009", + "0x14100937600700723b00912600937000700723b00900e00915500700723b", + "0x937200700723b00903c00937100700723b00903e00937700700723b009", + "0x37500700723b00914500937400700723b00904300937300700723b009148", + "0x923b00905800912500718400923b00906000944c00700723b009047009", + "0x944d00715d00923b00915d00922100705a00923b00905a00900e007058", + "0x915500700723b00900712e00718415d05a05800e00918400923b009184", + "0x37700700723b00914100937600700723b00912600937000700723b00900e", + "0x700723b00914800937200700723b00903c00937100700723b00903e009", + "0x723b00904700937500700723b00914500937400700723b009043009373", + "0x4c00900e00715000923b00915000912500718300923b00915700944c007", + "0x18300923b00918300944d00715200923b00915200922100704c00923b009", + "0x700723b00903b00911100700723b00900712e00718315204c15000e009", + "0xa000923b00900722900700723b00912500915200700723b00900e009155", + "0xe80a012e0300070e800923b0090e800902e0070e800923b0090073c8007", + "0xea00923b00917917b12e03100717b00923b00900722500717900923b009", + "0x1b00900e00700700923b00900700912500717500923b0090ea00944c007", + "0x17500923b00917500944d00701f00923b00901f00922100701b00923b009", + "0x700723b00900e00915500700723b00900712e00717501f01b00700e009", + "0x923b00902500944c00700723b0092230093c900700723b009125009152", + "0x922100701b00923b00901b00900e00700700923b009007009125007171", + "0x717101f01b00700e00917100923b00917100944d00701f00923b00901f", + "0x700723b00912500915200700723b00900e00915500700723b00900712e", + "0x91fd00900e00700700923b0090070091250070ec00923b00901800944c", + "0x90ec00923b0090ec00944d00701100923b0090110092210071fd00923b", + "0x71db00923b00900742b0071fd00923b0090070710070ec0111fd00700e", + "0x700900923b00900900900e00700723b0090070ea00700723b009007160", + "0xfd00701b01822312523b00912e00912e38700712e00923b00912e009221", + "0x922300900e00700723b00900712e0070150094ca01f00923b12e01b009", + "0x2012523b00901822312e15800701800923b00901800922100722300923b", + "0x700723b00900712e00722c0094cb02600923b12e0230090fd007023025", + "0x22900910100702c22912e23b00923c00910700723c00923b00901f009151", + "0x703000923b00902e00910400702e00923b00902c00910200700723b009", + "0x3100910100704503112e23b00922500910700722500923b009026009151", + "0x722100923b00903300910400703300923b00904500910200700723b009", + "0x922100915300700723b00903600915500721903612e23b009030009153", + "0x703b00923b00921900916300700723b00903800915500703a03812e23b", + "0x3c00902e00703c00923b00912603b12e14f00712600923b00903a009163", + "0x723b00900712e00703e0094cc00723b12e03c00910600703c00923b009", + "0x914800943100715004904714804314504114122323b009125009369007", + "0x2000923b00902000900e00700700923b00900700912500715204c12e23b", + "0x15515300e23b00915202502000700e43200702500923b009025009221007", + "0x700723b00900712e0071590094cd05400923b12e0520090cf007052157", + "0x915500700e05a05812523b00905700924600705700923b0090540091a8", + "0x15500923b00915500900e00715300923b00915300912500700723b00905a", + "0x15300e43500705800923b00905800943400715700923b009157009221007", + "0x700e00923b00900e1fd12e07400706015e05d15d00e23b009058157155", + "0x15f00943800700723b00900712e0071600094ce15f00923b12e060009436", + "0x723b00916100943b00716216112e23b00906400943900706400923b009", + "0x916400943900716400923b0090670094cf00706700923b00900716c007", + "0x716200923b00916200943c00700723b00916600943b00716816612e23b", + "0x16b00914000716b00923b00916816212e43d00716800923b00916800943c", + "0x723b00906d00905400700723b00900712e00706e0094d006d00923b12e", + "0x23b00915000937200700723b0091db00944b00700723b00900e009155007", + "0x904c00937500700723b00904700937400700723b009049009373007007", + "0x4100937100700723b00914500937700700723b00904300937600700723b", + "0x74d100706f00923b00900722900700723b00914100937000700723b009", + "0x923b00907106f12e03000707100923b00907100902e00707100923b009", + "0x944c00707400923b00916e07212e03100707200923b00900722500716e", + "0x923b00905d00900e00715d00923b00915d00912500717400923b009074", + "0x15d00e00917400923b00917400944d00715e00923b00915e00922100705d", + "0x14122314800700723b00906e00905400700723b00900712e00717415e05d", + "0x7718022323b00907600936900707600923b00915004904704c043145041", + "0x923b00905d00900e00708e00923b00900702500707f08d18707b186078", + "0xe45200708e00923b00908e00902600715e00923b00915e00922100705d", + "0x94d209200923b12e09100924400709109008f12523b00908e07f15e05d", + "0x23b00908f00900e00709400923b00900702500700723b00900712e007093", + "0x45400709400923b00909400902600709000923b00909000922100708f009", + "0x4d309800923b12e09700945500709709609512523b00909408d09008f00e", + "0x905400709c1a512e23b00909200945700700723b00900712e007099009", + "0x723b0090370090540070371a712e23b00909800945800700723b00909c", + "0x905b00936900705b00923b0091a51a718707b186078077180223148007", + "0x70a90a712e23b0091ac0093d10071b50a504a0a31b21b01ac09f22323b", + "0x960951253d200709600923b00909600922100709500923b00909500900e", + "0x12e0071bc0094d401100923b12e0ae00907b0070ae0ac1b812523b0090a9", + "0xac00923b0090ac0092210071b800923b0091b800900e00700723b009007", + "0xe45a0070b000923b0090b000902e0070b000e12e23b00900e00936b007", + "0x701100923b0090111db12e45b0070b41bd0b212523b0090b00a70ac1b8", + "0xb600945e00700723b00900712e0071bb0094d50b600923b12e0b400945c", + "0xe12e23b00900e00936b00700723b0090ba0090540070ba0b812e23b009", + "0x1b50a504a0a31b21b00b809f2231480070bc00923b0091ba0094d60071ba", + "0xb200923b0090b200900e00715d00923b00915d0091250070be00923b009", + "0x15d1fd4d80070bc00923b0090bc0094d70071bd00923b0091bd009221007", + "0x4d90c400923b12e1b60090c00071b60c20c01b900e23b0090bc0be1bd0b2", + "0xc40092f30071b300923b00901100918700700723b00900712e0070c6009", + "0xc900923b0091b300946300700723b0091b70090540071b70c712e23b009", + "0xc20092210070c000923b0090c000900e0071b900923b0091b9009125007", + "0xc90c70c20c01b91fd4650070c900923b0090c90094640070c200923b009", + "0x12e0071a80094da0cf00923b12e1aa0090c00071aa0cd0cb1ad00e23b009", + "0x723b0090d10090540070d11a312e23b0090cf0092f300700723b009007", + "0xcb00900e0071ad00923b0091ad0091250071a100923b00900e0093f4007", + "0x1a100923b0091a10093f50070cd00923b0090cd0092210070cb00923b009", + "0x12e19b0090c000719b19f0d51a000e23b0091a11a30cd0cb1ad1fd3f6007", + "0x19812e23b0090d80092f300700723b00900712e0070da0094db0d800923b", + "0x18a0e10df18e0dd22323b00919800936900700723b009197009054007197", + "0x714c0070e500923b00900714c00718b00923b00900743f00718c188189", + "0x23b0091a000912500718300923b0091840e518b12544000718400923b009", + "0x1a100719f00923b00919f0092210070d500923b0090d500900e0071a0009", + "0x1790e80a000e23b00918318a19f0d51a01fd44100718300923b009183009", + "0x44600700723b00900712e0071750094dc0ea00923b12e17b00944200717b", + "0x923b00900716c00700723b0090ec0090540070ec17112e23b0090ea009", + "0x16c12e46800716c00923b00918c1881891710e10df18e0dd2231480070ee", + "0x923b0090a000912500716900923b0090f00094690070f000923b0090ee", + "0x944d00717900923b0091790092210070e800923b0090e800900e0070a0", + "0x937000700723b00900712e0071691790e80a000e00916900923b009169", + "0x37400700723b00918800937300700723b00918c00937200700723b0090dd", + "0x700723b0090e100937600700723b00918e00937100700723b009189009", + "0x23b0090a000912500716500923b00917500944c00700723b0090df009377", + "0x44d00717900923b0091790092210070e800923b0090e800900e0070a0009", + "0x44c00700723b00900712e0071651790e80a000e00916500923b009165009", + "0x23b0090d500900e0071a000923b0091a00091250070f300923b0090da009", + "0xe0090f300923b0090f300944d00719f00923b00919f0092210070d5009", + "0x944c00700723b00900e00915500700723b00900712e0070f319f0d51a0", + "0x923b0090cb00900e0071ad00923b0091ad00912500716300923b0091a8", + "0x1ad00e00916300923b00916300944d0070cd00923b0090cd0092210070cb", + "0x1100924300700723b00900e00915500700723b00900712e0071630cd0cb", + "0x71b900923b0091b90091250070f600923b0090c600944c00700723b009", + "0x90f600944d0070c200923b0090c20092210070c000923b0090c000900e", + "0x900e00915500700723b00900712e0070f60c20c01b900e0090f600923b", + "0x1b500937200700723b00909f00937000700723b00901100924300700723b", + "0x937500700723b00904a00937400700723b0090a500937300700723b009", + "0x44c00700723b0091b000937700700723b0091b200937600700723b0090a3", + "0x23b0090b200900e00715d00923b00915d0091250070f800923b0091bb009", + "0xe0090f800923b0090f800944d0071bd00923b0091bd0092210070b2009", + "0x937000700723b00900e00915500700723b00900712e0070f81bd0b215d", + "0x37200700723b0091b200937600700723b0091b000937700700723b00909f", + "0x700723b00904a00937400700723b0090a500937300700723b0091b5009", + "0x723b0091db00944b00700723b0090a700937100700723b0090a3009375", + "0x1b800900e00715d00923b00915d00912500715c00923b0091bc00944c007", + "0x15c00923b00915c00944d0070ac00923b0090ac0092210071b800923b009", + "0x700723b00900e00915500700723b00900712e00715c0ac1b815d00e009", + "0x723b00918000937000700723b00909200946a00700723b0091db00944b", + "0x23b00918600937600700723b00907b00937500700723b009187009374007", + "0x909900944c00700723b00907700937100700723b009078009377007007", + "0x709500923b00909500900e00715d00923b00915d0091250070fa00923b", + "0x9609515d00e0090fa00923b0090fa00944d00709600923b009096009221", + "0x23b0091db00944b00700723b00900e00915500700723b00900712e0070fa", + "0x918000937000700723b00907800937700700723b009077009371007007", + "0x18600937600700723b00907b00937500700723b00918700937400700723b", + "0x12500715600923b00909300944c00700723b00908d00937300700723b009", + "0x23b00909000922100708f00923b00908f00900e00715d00923b00915d009", + "0x900712e00715609008f15d00e00915600923b00915600944d007090009", + "0x15000937200700723b0091db00944b00700723b00900e00915500700723b", + "0x937500700723b00904700937400700723b00904900937300700723b009", + "0x37100700723b00914500937700700723b00904300937600700723b00904c", + "0x15400923b00916000944c00700723b00914100937000700723b009041009", + "0x15e00922100705d00923b00905d00900e00715d00923b00915d009125007", + "0x12e00715415e05d15d00e00915400923b00915400944d00715e00923b009", + "0x37000700723b00904100937100700723b00914500937700700723b009007", + "0x700723b00915000937200700723b0091db00944b00700723b009141009", + "0x723b00904c00937500700723b00904700937400700723b009049009373", + "0x23b00915900944c00700723b0091fd00907f00700723b009043009376007", + "0x22100715500923b00915500900e00715300923b009153009125007158009", + "0x15815715515300e00915800923b00915800944d00715700923b009157009", + "0x723b0091fd00907f00700723b00903e00911100700723b00900712e007", + "0x923b00900722900700723b00912500915200700723b0091db00944b007", + "0xfd12e03000715100923b00915100902e00715100923b0090073c80070fd", + "0x923b00910710112e03100710100923b00900722500710700923b009151", + "0x900e00700700923b00900700912500710400923b00910200944c007102", + "0x923b00910400944d00702500923b00902500922100702000923b009020", + "0x723b0091fd00907f00700723b00900712e00710402502000700e009104", + "0x23b00901f0093c900700723b00912500915200700723b0091db00944b007", + "0x900e00700700923b00900700912500714c00923b00922c00944c007007", + "0x923b00914c00944d00702500923b00902500922100702000923b009020", + "0x723b00912500915200700723b00900712e00714c02502000700e00914c", + "0x23b00901500944c00700723b0091db00944b00700723b0091fd00907f007", + "0x22100722300923b00922300900e00700700923b00900700912500714f009", + "0x14f01822300700e00914f00923b00914f00944d00701800923b009018009", + "0x23b00912e00922100700900923b00900900900e00700723b0090070ea007", + "0x923b12e0110090fd0070111fd00e12523b00912e00912e38700712e009", + "0x22100700e00923b00900e00900e00700723b00900712e0072230094dd1db", + "0x90fd00701f01b01812523b0091fd00e12e1580071fd00923b0091fd009", + "0x23b0091db00915100700723b00900712e0070200094de01500923b12e01f", + "0x10200700723b00902300910100702602312e23b009025009107007025009", + "0x23b00901500915100723c00923b00922c00910400722c00923b009026009", + "0x10200700723b00902c00910100702e02c12e23b009229009107007229009", + "0x23b00923c00915300722500923b00903000910400703000923b00902e009", + "0x722103312e23b00922500915300700723b00903100915500704503112e", + "0x23b00922100916300703600923b00904500916300700723b009033009155", + "0x703800923b00903800902e00703800923b00921903612e14f007219009", + "0x912500936900700723b00900712e00703a0094df00723b12e038009106", + "0x704714812e23b00914100943100704314504114103e03c12603b22323b", + "0x901b00922100701800923b00901800900e00700700923b009007009125", + "0x90cf00715204c15004900e23b00904701b01800700e43200701b00923b", + "0x23b0091530091a800700723b00900712e0071550094e015300923b12e152", + "0x700723b00905400915500715905405212523b009157009246007157009", + "0x904c00922100715000923b00915000900e00704900923b009049009125", + "0x23b00905204c15004900e43500705200923b00905200943400704c00923b", + "0x900712e00715e0094e105d00923b12e15d00943600715d05a05805700e", + "0x716015f12e23b00906000943900706000923b00905d00943800700723b", + "0x923b0090640094cf00706400923b00900716c00700723b00915f00943b", + "0x943c00700723b00916200943b00706716212e23b009161009439007161", + "0x23b00906716012e43d00706700923b00906700943c00716000923b009160", + "0x700723b00900712e0071680094e216600923b12e164009140007164009", + "0x723b00904300937200700723b00915900915500700723b009166009054", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x912600937100700723b00903c00937700700723b00903e009376007007", + "0x90074d100716b00923b00900722900700723b00903b00937000700723b", + "0x6e00923b00906d16b12e03000706d00923b00906d00902e00706d00923b", + "0x7100944c00707100923b00906e06f12e03100706f00923b009007225007", + "0x5800923b00905800900e00705700923b00905700912500716e00923b009", + "0x5805700e00916e00923b00916e00944d00705a00923b00905a009221007", + "0x12603b22314800700723b00916800905400700723b00900712e00716e05a", + "0x7617407422323b00907200936900707200923b00904314504114803e03c", + "0x5800923b00905800900e00718700923b00900702500707b186078077180", + "0x5800e45200718700923b00918700902600705a00923b00905a009221007", + "0x900094e308f00923b12e08e00924400708e07f08d12523b00918707b05a", + "0x923b00908d00900e00709100923b00900702500700723b00900712e007", + "0xe45400709100923b00909100902600707f00923b00907f00922100708d", + "0x94e409500923b12e09400945500709409309212523b00909118607f08d", + "0x9800905400709809712e23b00908f00945700700723b00900712e007096", + "0x700723b0091a50090540071a509912e23b00909500945800700723b009", + "0x23b00909c00936900709c00923b009097099078077180076174074223148", + "0x922100709200923b00909200900e0070a31b21b01ac09f05b0371a7223", + "0x23b00904a00902e00704a15912e23b00915900936b00709300923b009093", + "0x12e0a700947d0070a71b50a512523b00904a05b09309200e47c00704a009", + "0xac12e23b0090a900947f00700723b00900712e0071b80094e50a900923b", + "0x1a72231480071bc00923b0091590094e600700723b0090ae0090540070ae", + "0x705700923b0090570091250070b000923b0090a31b21b01ac09f0ac037", + "0x91bc0094e70071b500923b0091b50092210070a500923b0090a500900e", + "0xc00070b60b41bd0b200e23b0091bc0b01b50a50571fd4e80071bc00923b", + "0x91bb0092f300700723b00900712e0070b80094e91bb00923b12e0b6009", + "0xbe0bc22323b0090ba00936900700723b0091ba0090540071ba0ba12e23b", + "0xc700923b00900714c0071b300923b00900743f0070c60c41b60c20c01b9", + "0x91250070c900923b0091b70c71b31254400071b700923b00900714c007", + "0x923b0090b40092210071bd00923b0091bd00900e0070b200923b0090b2", + "0xe23b0090c90c20b41bd0b21fd4410070c900923b0090c90091a10070b4", + "0x23b00900712e0071a80094ea0cf00923b12e1aa0094420071aa0cd0cb1ad", + "0x716c00700723b0090d10090540070d11a312e23b0090cf009446007007", + "0x71a000923b0090c60c41b61a30c01b90be0bc2231480071a100923b009", + "0x1ad00912500719f00923b0090d50094690070d500923b0091a11a012e468", + "0xcd00923b0090cd0092210070cb00923b0090cb00900e0071ad00923b009", + "0x723b00900712e00719f0cd0cb1ad00e00919f00923b00919f00944d007", + "0x23b0090c400937300700723b0090c600937200700723b0090bc009370007", + "0x90c000937600700723b0090be00937100700723b0091b6009374007007", + "0x912500719b00923b0091a800944c00700723b0091b900937700700723b", + "0x923b0090cd0092210070cb00923b0090cb00900e0071ad00923b0091ad", + "0x23b00900712e00719b0cd0cb1ad00e00919b00923b00919b00944d0070cd", + "0x900e0070b200923b0090b20091250070d800923b0090b800944c007007", + "0x923b0090d800944d0070b400923b0090b40092210071bd00923b0091bd", + "0x723b0091a700937000700723b00900712e0070d80b41bd0b200e0090d8", + "0x23b0091b000937400700723b0091b200937300700723b0090a3009372007", + "0x915900915500700723b00909f00937600700723b0091ac009375007007", + "0x91250070da00923b0091b800944c00700723b00903700937100700723b", + "0x923b0091b50092210070a500923b0090a500900e00705700923b009057", + "0x23b00900712e0070da1b50a505700e0090da00923b0090da00944d0071b5", + "0x907400937000700723b00908f00946a00700723b009159009155007007", + "0x18000937600700723b00907700937500700723b00907800937400700723b", + "0x944c00700723b00917400937100700723b00907600937700700723b009", + "0x923b00909200900e00705700923b00905700912500719800923b009096", + "0x5700e00919800923b00919800944d00709300923b009093009221007092", + "0x17400937100700723b00907600937700700723b00900712e007198093092", + "0x937400700723b00907400937000700723b00915900915500700723b009", + "0x37300700723b00918000937600700723b00907700937500700723b009078", + "0x923b00905700912500719700923b00909000944c00700723b009186009", + "0x944d00707f00923b00907f00922100708d00923b00908d00900e007057", + "0x915500700723b00900712e00719707f08d05700e00919700923b009197", + "0x37400700723b00914500937300700723b00904300937200700723b009159", + "0x700723b00903e00937600700723b00914800937500700723b009041009", + "0x723b00903b00937000700723b00912600937100700723b00903c009377", + "0x5800900e00705700923b0090570091250070dd00923b00915e00944c007", + "0xdd00923b0090dd00944d00705a00923b00905a00922100705800923b009", + "0x700723b00903c00937700700723b00900712e0070dd05a05805700e009", + "0x723b00904300937200700723b00903b00937000700723b009126009371", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x4900912500718e00923b00915500944c00700723b00903e009376007007", + "0x4c00923b00904c00922100715000923b00915000900e00704900923b009", + "0x723b00900712e00718e04c15004900e00918e00923b00918e00944d007", + "0x923b00900722900700723b00912500915200700723b00903a009111007", + "0xdf12e0300070e100923b0090e100902e0070e100923b0090073c80070df", + "0x923b00918a18912e03100718900923b00900722500718a00923b0090e1", + "0x900e00700700923b00900700912500718c00923b00918800944c007188", + "0x923b00918c00944d00701b00923b00901b00922100701800923b009018", + "0x723b00912500915200700723b00900712e00718c01b01800700e00918c", + "0x900700912500718b00923b00902000944c00700723b0091db0093c9007", + "0x701b00923b00901b00922100701800923b00901800900e00700700923b", + "0x700723b00900712e00718b01b01800700e00918b00923b00918b00944d", + "0x23b0090070091250070e500923b00922300944c00700723b009125009152", + "0x44d0071fd00923b0091fd00922100700e00923b00900e00900e007007009", + "0xe00700723b0090070ea0070e51fd00e00700e0090e500923b0090e5009", + "0x912e00912e38700712e00923b00912e00922100700900923b009009009", + "0x900712e0072230094eb1db00923b12e0110090fd0070111fd00e12523b", + "0x1580071fd00923b0091fd00922100700e00923b00900e00900e00700723b", + "0x200094ec01500923b12e01f0090fd00701f01b01812523b0091fd00e12e", + "0x23b00902500910700702500923b0091db00915100700723b00900712e007", + "0x10400722c00923b00902600910200700723b00902300910100702602312e", + "0x23b00922900910700722900923b00901500915100723c00923b00922c009", + "0x10400703000923b00902e00910200700723b00902c00910100702e02c12e", + "0x903100915500704503112e23b00923c00915300722500923b009030009", + "0x16300700723b00903300915500722103312e23b00922500915300700723b", + "0x921903612e14f00721900923b00922100916300703600923b009045009", + "0x94ed00723b12e03800910600703800923b00903800902e00703800923b", + "0x4114103e03c12603b22323b00912500936900700723b00900712e00703a", + "0x700700923b00900700912500704714812e23b009141009431007043145", + "0x1800700e43200701b00923b00901b00922100701800923b00901800900e", + "0x1550094ee15300923b12e1520090cf00715204c15004900e23b00904701b", + "0x23b00915700924600715700923b0091530091a800700723b00900712e007", + "0x12500700723b00915900915500700723b009054009155007159054052125", + "0x23b00904c00922100715000923b00915000900e00704900923b009049009", + "0xe23b00905204c15004900e43500705200923b00905200943400704c009", + "0x23b00900712e00715e0094ef05d00923b12e15d00943600715d05a058057", + "0x43b00716015f12e23b00906000943900706000923b00905d009438007007", + "0x16100923b00906400943a00706400923b00900716c00700723b00915f009", + "0x16000943900700723b00916200943b00706716212e23b009161009439007", + "0x16812e23b00906700943900700723b00916400943b00716616412e23b009", + "0x16b00943c00716600923b00916600943c00700723b00916800943b00716b", + "0x923b00906d00936e00706d00923b00916b16612e44500716b00923b009", + "0x710094f006f00923b12e06e00914000706e00923b00906e0090a500706e", + "0x723b00904300937200700723b00906f00905400700723b00900712e007", + "0x23b00914800937500700723b00904100937400700723b009145009373007", + "0x912600937100700723b00903c00937700700723b00903e009376007007", + "0x90074d100716e00923b00900722900700723b00903b00937000700723b", + "0x7400923b00907216e12e03000707200923b00907200902e00707200923b", + "0x7600944c00707600923b00907417412e03100717400923b009007225007", + "0x5800923b00905800900e00705700923b00905700912500718000923b009", + "0x5805700e00918000923b00918000944d00705a00923b00905a009221007", + "0x12603b22314800700723b00907100905400700723b00900712e00718005a", + "0x7b18607822323b00907700936900707700923b00904314504114803e03c", + "0x23b00905700912500709109012e23b00908d00943100708f08e07f08d187", + "0x43200705a00923b00905a00922100705800923b00905800900e007057009", + "0x9600923b12e0950090cf00709509409309200e23b00909105a05805700e", + "0x924600709800923b0090960091a800700723b00900712e0070970094f1", + "0x23b00909c00915500700723b0091a500915500709c1a509912523b009098", + "0x922100709300923b00909300900e00709200923b009092009125007007", + "0x9909409309200e43500709900923b00909900943400709400923b009094", + "0x12e0071b00094f21ac00923b12e09f00943600709f05b0371a700e23b009", + "0xa312e23b0091b20094390071b200923b0091ac00943800700723b009007", + "0x1b50094390071b500923b0090a500943a0070a500923b00900716c00704a", + "0x4a00923b00904a00943c00700723b0090a700943b0070a90a712e23b009", + "0x91400071b800923b0090a904a12e43d0070a900923b0090a900943c007", + "0x23b0090ac00905400700723b00900712e0070ae0094f30ac00923b12e1b8", + "0x23b00900714c0070b000923b00900714c0071bc00923b00900743f007007", + "0x1a700923b0091a70091250071bd00923b0090b20b01bc1254400070b2009", + "0x1bd0091a100705b00923b00905b00922100703700923b00903700900e007", + "0x70b81bb0b60b400e23b0091bd09005b0371a71fd4410071bd00923b009", + "0xa300943900700723b00900712e0071ba0094f40ba00923b12e0b8009442", + "0x71b900923b00900716c00700723b0090bc00943b0070be0bc12e23b009", + "0xc200943b0071b60c212e23b0090c00094390070c000923b0091b9009444", + "0x700723b0090c400943b0070c60c412e23b0090be00943900700723b009", + "0x90c600943c00700723b0091b300943b0070c71b312e23b0091b6009439", + "0x1b700923b0090c70c612e4450070c700923b0090c700943c0070c600923b", + "0x1b700914000700723b0091ad0090540071ad0c912e23b0090ba009446007", + "0x723b0090cb00905400700723b00900712e0070cd0094f50cb00923b12e", + "0x23b00908f08e07f0c918707b1860782231480071aa00923b009007245007", + "0x2210070b600923b0090b600900e0070b400923b0090b40091250070cf009", + "0xd11a31a800e23b0091aa0cf1bb0b60b41fd4480071bb00923b0091bb009", + "0x2f300700723b00900712e0070d50094f61a000923b12e1a10090c00071a1", + "0x23b0091a800912500700723b00919b00905400719b19f12e23b0091a0009", + "0x3f800719800923b0090d10092210070da00923b0091a300900e0070d8009", + "0x44c00700723b00900712e0070074f70090070ee00719700923b00919f009", + "0x23b0091a300900e0071a800923b0091a80091250070dd00923b0090d5009", + "0xe0090dd00923b0090dd00944d0070d100923b0090d10092210071a3009", + "0x22314800700723b0090cd00905400700723b00900712e0070dd0d11a31a8", + "0xd800923b0090b400912500718e00923b00908f08e07f0c918707b186078", + "0x18e0093f800719800923b0091bb0092210070da00923b0090b600900e007", + "0xe100923b0090da00944f0070df00923b0090d800944e00719700923b009", + "0x90070ee00718900923b0091970093f800718a00923b009198009450007", + "0x908f00937200700723b00907800937000700723b00900712e0070074f8", + "0xa300943b00700723b00907f00937400700723b00908e00937300700723b", + "0x937100700723b00907b00937700700723b00918700937600700723b009", + "0xb400923b0090b400912500718800923b0091ba00944c00700723b009186", + "0x18800944d0071bb00923b0091bb0092210070b600923b0090b600900e007", + "0xae00905400700723b00900712e0071881bb0b60b400e00918800923b009", + "0x8e07f09018707b18607822314800700723b0090a300943b00700723b009", + "0x923b00903700900e0070df00923b0091a700912500718c00923b00908f", + "0x936900718900923b00918c0093f800718a00923b00905b0092210070e1", + "0x70ea00923b00900702500717b1790e80a01831840e518b22323b009189", + "0xec17117512523b0090ea17b18a0e100e4520070ea00923b0090ea009026", + "0x702500700723b00900712e00716c0094f90ee00923b12e0ec009244007", + "0x17100923b00917100922100717500923b00917500900e0070f000923b009", + "0x16516912523b0090f017917117500e4540070f000923b0090f0009026007", + "0x45700700723b00900712e0070f60094fa16300923b12e0f30094550070f3", + "0x23b00916300945800700723b00915c00905400715c0f812e23b0090ee009", + "0xfa0e80a01831840e518b22314800700723b0091560090540071560fa12e", + "0x923b00915815412e46800715800923b00900716c00715400923b0090f8", + "0x900e0070df00923b0090df00912500715100923b0090fd0094690070fd", + "0x923b00915100944d00716500923b00916500922100716900923b009169", + "0x723b0090ee00946a00700723b00900712e0071511651690df00e009151", + "0x23b0090a000937500700723b0090e800937400700723b00918b009370007", + "0x90e500937100700723b00918400937700700723b009183009376007007", + "0xe0070df00923b0090df00912500710700923b0090f600944c00700723b", + "0x23b00910700944d00716500923b00916500922100716900923b009169009", + "0x23b0090e500937100700723b00900712e0071071651690df00e009107009", + "0x90e800937400700723b00918b00937000700723b009184009377007007", + "0x17900937300700723b00918300937600700723b0090a000937500700723b", + "0x70df00923b0090df00912500710100923b00916c00944c00700723b009", + "0x910100944d00717100923b00917100922100717500923b00917500900e", + "0x907800937000700723b00900712e0071011711750df00e00910100923b", + "0x18600937100700723b00907b00937700700723b00918700937600700723b", + "0x937400700723b00908e00937300700723b00908f00937200700723b009", + "0x710200923b0091b000944c00700723b00909000937500700723b00907f", + "0x905b00922100703700923b00903700900e0071a700923b0091a7009125", + "0x712e00710205b0371a700e00910200923b00910200944d00705b00923b", + "0x937700700723b00918700937600700723b00907800937000700723b009", + "0x37300700723b00908f00937200700723b00918600937100700723b00907b", + "0x700723b00909000937500700723b00907f00937400700723b00908e009", + "0x909300900e00709200923b00909200912500710400923b00909700944c", + "0x910400923b00910400944d00709400923b00909400922100709300923b", + "0x37300700723b00904300937200700723b00900712e00710409409309200e", + "0x700723b00914800937500700723b00904100937400700723b009145009", + "0x723b00912600937100700723b00903c00937700700723b00903e009376", + "0x905700912500714c00923b00915e00944c00700723b00903b009370007", + "0x705a00923b00905a00922100705800923b00905800900e00705700923b", + "0x700723b00900712e00714c05a05805700e00914c00923b00914c00944d", + "0x723b00903b00937000700723b00912600937100700723b00903c009377", + "0x23b00904100937400700723b00914500937300700723b009043009372007", + "0x915500944c00700723b00903e00937600700723b009148009375007007", + "0x715000923b00915000900e00704900923b00904900912500714f00923b", + "0x4c15004900e00914f00923b00914f00944d00704c00923b00904c009221", + "0x23b00912500915200700723b00903a00911100700723b00900712e00714f", + "0x914d00902e00714d00923b0090073c800710600923b009007229007007", + "0x714900923b00900722500714e00923b00914d10612e03000714d00923b", + "0x700912500710c00923b00910a00944c00710a00923b00914e14912e031", + "0x1b00923b00901b00922100701800923b00901800900e00700700923b009", + "0x723b00900712e00710c01b01800700e00910c00923b00910c00944d007", + "0x23b00902000944c00700723b0091db0093c900700723b009125009152007", + "0x22100701800923b00901800900e00700700923b009007009125007147009", + "0x14701b01800700e00914700923b00914700944d00701b00923b00901b009", + "0x923b00922300944c00700723b00912500915200700723b00900712e007", + "0x922100700e00923b00900e00900e00700700923b009007009125007146", + "0x71461fd00e00700e00914600923b00914600944d0071fd00923b0091fd", + "0x23b00912500937000701b0182231db0111fd00e12522323b00912e009369", + "0x91db00937500700723b00901100937600700723b0091fd009377007007", + "0x1b00937200700723b00901800937300700723b00922300937400700723b", + "0x700900923b00900900922100700700923b00900700900e00700723b009", + "0x4fb02500923b12e02000907b00702001501f12523b00900e0090071253d2", + "0x2600932f00702600923b00902500918700700723b00900712e007023009", + "0x1f00923b00901f00900e00723c00923b00922c00933000722c00923b009", + "0x1501f12500923c00923b00923c00933100701500923b009015009221007", + "0x901f00900e00722900923b00902300933200700723b00900712e00723c", + "0x922900923b00922900933100701500923b00901500922100701f00923b", + "0x701b0182231db0111fd00e12522323b00912e00936900722901501f125", + "0x723b00901100937600700723b00900e00937100700723b009125009370", + "0x23b00901800937300700723b00922300937400700723b0091db009375007", + "0x900922100700700923b00900700900e00700723b00901b009372007007", + "0x2000907b00702001501f12523b0091fd0090071253da00700900923b009", + "0x923b00902500918700700723b00900712e0070230094fc02500923b12e", + "0x900e00723c00923b00922c00933000722c00923b00902600932f007026", + "0x923b00923c00933100701500923b00901500922100701f00923b00901f", + "0x22900923b00902300933200700723b00900712e00723c01501f12500923c", + "0x22900933100701500923b00901500922100701f00923b00901f00900e007", + "0x111fd00e12522323b00912e00936900722901501f12500922900923b009", + "0x37700700723b00900e00937100700723b00912500937000701b0182231db", + "0x700723b00922300937400700723b0091db00937500700723b0091fd009", + "0x923b00900700900e00700723b00901b00937200700723b009018009373", + "0x1501f12523b0090110090071253de00700900923b009009009221007007", + "0x18700700723b00900712e0070230094fd02500923b12e02000907b007020", + "0x23b00922c00933000722c00923b00902600932f00702600923b009025009", + "0x33100701500923b00901500922100701f00923b00901f00900e00723c009", + "0x933200700723b00900712e00723c01501f12500923c00923b00923c009", + "0x923b00901500922100701f00923b00901f00900e00722900923b009023", + "0x23b00912500936900722901501f12500922900923b009229009331007015", + "0x1fd00937100700723b00900e00937000701f01b0182231db0111fd00e223", + "0x937400700723b0091db00937600700723b00901100937700700723b009", + "0x12500700723b00901f00937200700723b00901b00937300700723b009018", + "0x23b00912e00922100700900923b00900900900e00700700923b009007009", + "0x230090cf00702302502001500e23b00922312e00900700e43200712e009", + "0x923b0090260091a800700723b00900712e00722c0094fe02600923b12e", + "0x912500702c00923b00922900950000722900923b00923c0094ff00723c", + "0x923b00902500922100702000923b00902000900e00701500923b009015", + "0x23b00900712e00702c02502001500e00902c00923b00902c009501007025", + "0x900e00701500923b00901500912500702e00923b00922c009502007007", + "0x923b00902e00950100702500923b00902500922100702000923b009020", + "0x12e00924600712e00712e23b00900700950300702e02502001500e00902e", + "0x723b0091fd00915500700723b00900e0091550071fd00e12512523b009", + "0x912e0300071db00923b00901100950500701100923b009125009504007", + "0x23b00901800924600701800712e23b00900700950300722300923b0091db", + "0x2e00700723b00901500915500700723b00901b00934f00701501f01b125", + "0x922301f12e05200722300923b00922300915700701f00923b00901f009", + "0x2602312523b00900700924600700723b00902500905400702502012e23b", + "0x922c00902e00700723b00902600915500700723b00902300934f00722c", + "0x23c12e23b00902022c12e05200702000923b00902000915700722c00923b", + "0x700900923b00900750600700723b00900700915200722923c12e009229", + "0x912512e00912550900712500923b00900750800712e00923b009007507", + "0x23b00900700950a00700e00900900e00923b00900e0090d800700e00923b", + "0x723b00900e00950c0071fd00e12512523b00912e00950b00712e00712e", + "0x901100950e00701100923b00912500950d00700723b0091fd00950c007", + "0x712e23b00900700950a00722300923b0091db00912e0300071db00923b", + "0x50c00700723b00901b00950c00701501f01b12523b00901800950b007018", + "0x923b00902000950e00702000923b00901f00950d00700723b009015009", + "0x23c22c02612523b00900700950b00702300923b00902522312e030007025", + "0x23b00923c00950d00700723b00922c00950c00700723b00902600950c007", + "0x702e00923b00902c02312e03000702c00923b00922900950e007229009", + "0x36900703002e12e00902e00923b00902e00915700703000923b00900716c", + "0x723b00900e00937000701f01b0182231db0111fd00e22323b009125009", + "0x23b0091db00937600700723b00901100937700700723b0091fd009371007", + "0x901f00937200700723b00901800937400700723b009223009375007007", + "0x22100700900923b00900900900e00700700923b00900700912500700723b", + "0x2302502001500e23b00901b12e00900700e50f00712e00923b00912e009", + "0x918e00700723b00900712e00722c00951002600923b12e0230090dd007", + "0x923b00922900951200722900923b00923c00951100723c00923b009026", + "0x922100702000923b00902000900e00701500923b00901500912500702c", + "0x702c02502001500e00902c00923b00902c00951300702500923b009025", + "0x923b00901500912500702e00923b00922c00951400700723b00900712e", + "0x951300702500923b00902500922100702000923b00902000900e007015", + "0x1fd00e22323b00912500936900702e02502001500e00902e00923b00902e", + "0x723b0091fd00937100700723b00900e00937000701f01b0182231db011", + "0x23b00922300937500700723b0091db00937600700723b009011009377007", + "0x900700912500700723b00901b00937300700723b009018009374007007", + "0x712e00923b00912e00922100700900923b00900900900e00700700923b", + "0x923b12e0230090dd00702302502001500e23b00901f12e00900700e515", + "0x51100723c00923b00902600918e00700723b00900712e00722c009516026", + "0x23b00901500912500702c00923b00922900951200722900923b00923c009", + "0x51300702500923b00902500922100702000923b00902000900e007015009", + "0x51400700723b00900712e00702c02502001500e00902c00923b00902c009", + "0x23b00902000900e00701500923b00901500912500702e00923b00922c009", + "0xe00902e00923b00902e00951300702500923b009025009221007020009", + "0x701f01b0182231db0111fd00e22323b00912500936900702e025020015", + "0x723b00901100937700700723b0091fd00937100700723b00900e009370", + "0x23b00901b00937300700723b00901800937400700723b0091db009376007", + "0x900900e00700700923b00900700912500700723b00901f009372007007", + "0x922312e00900700e43200712e00923b00912e00922100700900923b009", + "0x712e00722c00951702600923b12e0230090cf00702302502001500e23b", + "0x2c22912523b00923c00924600723c00923b0090260091a800700723b009", + "0x922100702000923b00902000900e00701500923b00901500912500702e", + "0x23b00903000943400703022912e23b00922900936200702500923b009025", + "0x3300943600703304503122500e23b00903002502001500e435007030009", + "0x923b00922100943800700723b00900712e00703600951822100923b12e", + "0x3a00923b00921903812e51900703800923b00902e02c229125440007219", + "0x22500912500712600923b00903b00951b00703b00923b00903a00951a007", + "0x4500923b00904500922100703100923b00903100900e00722500923b009", + "0x723b00900712e00712604503122500e00912600923b00912600951c007", + "0x23b00902c00915500700723b00902e00915500700723b00922900934f007", + "0x900e00722500923b00922500912500703c00923b00903600951d007007", + "0x923b00903c00951c00704500923b00904500922100703100923b009031", + "0x923b00922c00951d00700723b00900712e00703c04503122500e00903c", + "0x922100702000923b00902000900e00701500923b00901500912500703e", + "0x703e02502001500e00903e00923b00903e00951c00702500923b009025", + "0x900915700712e00923b00912e0091a100712512e12e23b00900700951e", + "0x23b0091fd0090540071fd00e12e23b00900912e12e1a000700900923b009", + "0x12e51f00700e00923b00900e00915700712500923b00912500943c007007", + "0x52000700723b0090070091520071db01112e0091db01112e23b00900e125", + "0x912e12512e14f00712500912e23b00900900936b00712e00923b009007", + "0x952100723b12e00e00910600700e00923b00900e00902e00700e00923b", + "0x923b00900716c00700723b00900900915500700723b00900712e0071fd", + "0x70ee00722300923b0091db0090a50071db00923b009011009144007011", + "0x900724700700723b0091fd00911100700723b00900712e007007522009", + "0x923b00901801b12e14f00701b00912e23b00900900936b00701800923b", + "0x701500952300723b12e01f00910600701f00923b00901f00902e00701f", + "0x702000923b00900716c00700723b00900900915500700723b00900712e", + "0x5240090070ee00702300923b0090250090a500702500923b009020009144", + "0x923b00900752500700723b00901500911100700723b00900712e007007", + "0x723c00923b00902622c12e14f00722c00912e23b00900900936b007026", + "0x712e00722900952600723b12e23c00910600723c00923b00923c00902e", + "0x914400702c00923b00900716c00700723b00900900915500700723b009", + "0x70075270090070ee00703000923b00902e0090a500702e00923b00902c", + "0x722500923b00900752800700723b00922900911100700723b00900712e", + "0x902e00704500923b00922503112e14f00703100912e23b00900900936b", + "0x23b00900712e00703300952900723b12e04500910600704500923b009045", + "0x922100914400722100923b00900716c00700723b009009009155007007", + "0x712e00700752a0090070ee00721900923b0090360090a500703600923b", + "0x936b00703800923b00900752b00700723b00903300911100700723b009", + "0x903b00902e00703b00923b00903803a12e14f00703a00912e23b009009", + "0x700723b00900712e00712600952c00723b12e03b00910600703b00923b", + "0x923b00903c00914400703c00923b00900716c00700723b009009009155", + "0x23b00900712e00700752d0090070ee00714100923b00903e0090a500703e", + "0x4100912e14f00704100923b00900752e00700723b009126009111007007", + "0x52f00723b12e14500910600714500923b00914500902e00714500923b009", + "0x914800914400714800923b00900716c00700723b00900712e007043009", + "0x712e0070075300090070ee00704900923b0090470090a500704700923b", + "0x911300715000923b00900716c00700723b00904300911100700723b009", + "0x923b00904900939d00704900923b00904c0090a500704c00923b009150", + "0x939d00703000923b00921900939d00721900923b00914100939d007141", + "0x900902e00722300900922300923b00902300939d00702300923b009030", + "0x923b12e12e00914000712e00923b00900900712e18300700900923b009", + "0x714c00700723b00912500905400700723b00900712e00700e009531125", + "0x12e0070075320090070ee00701100923b0091fd00902e0071fd00923b009", + "0x2e0071db00923b00900714300700723b00900e00905400700723b009007", + "0x903300700700923b00900700912500701100900901100923b0091db009", + "0x923b00912500922100712e00923b00912e00900e00700900923b009009", + "0x1db18600701100923b0090110091570071fd00923b0091fd00902e007125", + "0x12e01f00907b00701f01b0182231db1fd23b0090111fd00e12512e009007", + "0x2500923b00901500918700700723b00900712e00702000953301500923b", + "0x90072f400700723b00902300915500702602312e23b009025009153007", + "0x700723b00923c00915500722923c12e23b00922c00915300722c00923b", + "0x2e02c12e14f00702e00923b00922900916300702c00923b009026009163", + "0x53400723b12e03000910600703000923b00903000902e00703000923b009", + "0x903100932f00703100923b00900714300700723b00900712e007225009", + "0x71db00923b0091db00912500703300923b00904500933000704500923b", + "0x901b00922100701800923b00901800900e00722300923b009223009033", + "0x12e00703301b0182231db1fd00903300923b00903300933100701b00923b", + "0x53500722100923b00900722900700723b00922500911100700723b009007", + "0x23b00903622112e03000703600923b00903600902e00703600923b009007", + "0x33200703a00923b00921903812e03100703800923b009007225007219009", + "0x23b0092230090330071db00923b0091db00912500703b00923b00903a009", + "0x33100701b00923b00901b00922100701800923b00901800900e007223009", + "0x700723b00900712e00703b01b0182231db1fd00903b00923b00903b009", + "0x92230090330071db00923b0091db00912500712600923b009020009332", + "0x701b00923b00901b00922100701800923b00901800900e00722300923b", + "0x723b0090070ea00712601b0182231db1fd00912600923b009126009331", + "0x22300915300722300923b00900714c0071db01112e23b00900e009153007", + "0x1f00923b0091db00916300700723b00901800915500701b01812e23b009", + "0x1b00916300700723b00901500915500702001512e23b00901f009153007", + "0x723b00902300915500702602312e23b00902500915300702500923b009", + "0x22c12e14f00723c00923b00902600916300722c00923b009020009163007", + "0x723b12e22900910600722900923b00922900902e00722900923b00923c", + "0x2e00914400702e00923b00900716c00700723b00900712e00702c009536", + "0x12e0070075370090070ee00722500923b0090300090a500703000923b009", + "0x11300703100923b00900716c00700723b00902c00911100700723b009007", + "0x23b00922500936e00722500923b0090450090a500704500923b009031009", + "0x953822100923b12e03300914000703300923b0090330090a5007033009", + "0x23b00901100915500700723b00922100905400700723b00900712e007036", + "0x23b00900722900700723b00912500915200700723b0091fd009155007007", + "0x12e03000703800923b00903800902e00703800923b0090073d8007219009", + "0x23b00903a03b12e03100703b00923b00900722500703a00923b009038219", + "0xe00700700923b00900700912500703c00923b00912600944c007126009", + "0x23b00903c00944d00712e00923b00912e00922100700900923b009009009", + "0x23b00903600905400700723b00900712e00703c12e00900700e00903c009", + "0x900900e00704904714804314504114103e22323b009125009369007007", + "0x1112e23b00901100936b00712e00923b00912e00922100700900923b009", + "0x4c12523b00915014112e00900e45a00715000923b00915000902e007150", + "0x700723b00900712e00715700953915500923b12e15300945c007153152", + "0x91fd00936b00715200923b00915200922100704c00923b00904c00900e", + "0x905204115204c00e47c00705200923b00905200902e0070521fd12e23b", + "0x900712e00705a00953a05800923b12e05700947d00705715905412523b", + "0x922100705400923b00905400900e00715d00923b00900714c00700723b", + "0x15d14515905400e49600715d00923b00915d00902e00715900923b009159", + "0x712e00716000953b15f00923b12e06000949700706015e05d12523b009", + "0x700723b00916100905400716106412e23b00915500945e00700723b009", + "0x915f00949900700723b00906700905400706716212e23b00905800947f", + "0x16801112e23b00901100936b00700723b00916600905400716616412e23b", + "0x4904714804316416206403e22314800716b00923b0091fd16812e53c007", + "0x5d00923b00905d00900e00700700923b00900700912500706d00923b009", + "0x71fd53e00716b00923b00916b00953d00715e00923b00915e009221007", + "0x53f07200923b12e16e0090c000716e07106f06e00e23b00916b06d15e05d", + "0x905400707617412e23b0090720092f300700723b00900712e007074009", + "0x6e00923b00906e00912500718000923b0090110093f400700723b009076", + "0x1800093f500707100923b00907100922100706f00923b00906f00900e007", + "0x707b18607807700e23b00918017407106f06e1fd3f600718000923b009", + "0x1870092f300700723b00900712e00708d00954018700923b12e07b0090c0", + "0x708f00923b00900716c00700723b00908e00905400708e07f12e23b009", + "0x7700912500709100923b00909000946900709000923b00908f07f12e468", + "0x18600923b00918600922100707800923b00907800900e00707700923b009", + "0x723b00900712e00709118607807700e00909100923b00909100944d007", + "0x7800900e00707700923b00907700912500709200923b00908d00944c007", + "0x9200923b00909200944d00718600923b00918600922100707800923b009", + "0x700723b00901100915500700723b00900712e00709218607807700e009", + "0x906f00900e00706e00923b00906e00912500709300923b00907400944c", + "0x909300923b00909300944d00707100923b00907100922100706f00923b", + "0x37000700723b00901100915500700723b00900712e00709307106f06e00e", + "0x700723b00904700937300700723b00904900937200700723b00903e009", + "0x723b0091fd00915500700723b00904300937500700723b009148009374", + "0x23b00916000944c00700723b00905800954200700723b009155009541007", + "0x22100705d00923b00905d00900e00700700923b009007009125007094009", + "0x9415e05d00700e00909400923b00909400944d00715e00923b00915e009", + "0x723b00903e00937000700723b00901100915500700723b00900712e007", + "0x23b00904700937300700723b00904900937200700723b009155009541007", + "0x91fd00915500700723b00904300937500700723b009148009374007007", + "0x912500709500923b00905a00944c00700723b00914500937600700723b", + "0x923b00915900922100705400923b00905400900e00700700923b009007", + "0x23b00900712e00709515905400700e00909500923b00909500944d007159", + "0x914500937600700723b00903e00937000700723b009011009155007007", + "0x14800937400700723b00904700937300700723b00904900937200700723b", + "0x937700700723b0091fd00915500700723b00904300937500700723b009", + "0x700923b00900700912500709600923b00915700944c00700723b009041", + "0x9600944d00715200923b00915200922100704c00923b00904c00900e007", + "0x900721900700723b0090070ea00709615204c00700e00909600923b009", + "0x12e23b12e1fd00900712503a0071fd00923b0091fd0090380071fd00923b", + "0xe12e23b00900e00936b00700723b00900712e00701822312e5431db011", + "0x701f00954400723b12e01b00910600701100923b00901100912500701b", + "0x1500923b00912500954500700723b00900e00915500700723b00900712e", + "0x912500702500923b00902000915c00702000923b00901512e12e0f8007", + "0x923b0090250090fa0071db00923b0091db00900e00701100923b009011", + "0x700723b00901f00911100700723b00900712e0070251db011125009025", + "0x912e0091fd0071db00923b0091db00900e00701100923b009011009125", + "0x12e22c00924f00722c02602312523b00912e1db01112554600712e00923b", + "0x2c12e23b00923c00954800700723b00900712e00722900954723c00923b", + "0x54b00700723b00900712e00722500954a03000923b12e02e00954900702e", + "0x904500e12e14f00704500923b00900714300703100923b00903012512e", + "0x702600923b00902600900e00702300923b00902300912500703300923b", + "0x903300902e00703100923b00903100904700702c00923b00902c0091fd", + "0x91db00721903622112523b00903303102c0260231fd0f600703300923b", + "0x23b00903800922300700723b00900712e00703a00954c03800923b12e219", + "0x3e00923b00903c00915c00703c00923b00912603b12e0f800712603b12e", + "0x3e0090fa00703600923b00903600900e00722100923b009221009125007", + "0x903a00915600700723b00900712e00703e03622112500903e00923b009", + "0x703600923b00903600900e00722100923b00922100912500714100923b", + "0x15500700723b00900712e00714103622112500914100923b0091410090fa", + "0x4100923b00922500915400700723b00912500923c00700723b00900e009", + "0x912500704300923b00914500915c00714500923b00904102c12e0f8007", + "0x923b0090430090fa00702600923b00902600900e00702300923b009023", + "0x700723b00900e00915500700723b00900712e007043026023125009043", + "0x23b00902300912500714800923b00922900915600700723b00912500923c", + "0x12500914800923b0091480090fa00702600923b00902600900e007023009", + "0x12500923c00700723b00900e00915500700723b00900712e007148026023", + "0x705d00704700923b00900722900700723b00912e00915e00700723b009", + "0x923b00904904712e03000704900923b00904900902e00704900923b009", + "0x915600715200923b00915004c12e03100704c00923b009007225007150", + "0x923b00901800900e00722300923b00922300912500715300923b009152", + "0x23b00900700900e00715301822312500915300923b0091530090fa007018", + "0x12512e12523b00900900712e54d00700900923b009009009221007007009", + "0x55000700723b00900712e00701100954f1fd00923b12e00e00954e00700e", + "0x23b00922300955200722300923b0091db0095510071db00923b0091fd009", + "0x723b00901b00955400700723b00901800955300702001501f01b0181fd", + "0x23b00901f00955500700723b00902000915500700723b009015009101007", + "0x22100712e00923b00912e00900e00702300923b009025009556007025009", + "0x702312512e12500902300923b00902300955700712500923b009125009", + "0x923b00912e00900e00702600923b00901100955800700723b00900712e", + "0x12e12500902600923b00902600955700712500923b00912500922100712e", + "0x54d00700900923b00900900922100700700923b00900700900e007026125", + "0x110095591fd00923b12e00e00954e00700e12512e12523b00900900712e", + "0x23b0091db0095510071db00923b0091fd00955000700723b00900712e007", + "0x23b00901800955300702001501f01b0181fd23b009223009552007223009", + "0x902000915500700723b00901500910100700723b00901f009101007007", + "0xe00702300923b00902500955b00702500923b00901b00955a00700723b", + "0x23b00902300955c00712500923b00912500922100712e00923b00912e009", + "0x923b00901100955d00700723b00900712e00702312512e125009023009", + "0x955c00712500923b00912500922100712e00923b00912e00900e007026", + "0x755f00701b00923b00900755e00702612512e12500902600923b009026", + "0x55f00702600923b00900755f00702500923b00900755f00701500923b009", + "0xea00700723b00900716000702c00923b00900715f00723c00923b009007", + "0x12500923b00912500922100712e00923b00912e00900e00700723b009007", + "0x22900923b00922902c12e16200703022902e12523b00912512e12e54d007", + "0x955000700723b00900712e00703100956022500923b12e03000954e007", + "0x12e23b0091fd00938b00703300923b00904500955100704500923b009225", + "0x55200721900923b00903600956200703600923b0092210095610072211fd", + "0x955400700723b00903800955300703c12603b03a0381fd23b009033009", + "0x1500700723b00903c00915500700723b00903b00910100700723b00903a", + "0x923b00900756300700723b00903e00902000714103e12e23b009219009", + "0x902300700723b00914500902000704314512e23b009041009015007041", + "0x923b00914800902600704700923b00904300902300714800923b009141", + "0x700756400723b12e04714812e22c00712600923b00912600935a007148", + "0x700723b00923c00956600700723b00901b00956500700723b00900712e", + "0x723b00902500956600700723b00902600956600700723b00922300904a", + "0x902e00900e00700700923b00900700912500700723b009015009566007", + "0x712600923b00912600935a0071fd00923b0091fd00912300702e00923b", + "0x15200923b12e04c00940200704c15004912523b0091261fd02e00700e401", + "0x4900912500700723b00915200940400700723b00900712e007153009567", + "0x12e0070075680090070ee00715700923b00915000900e00715500923b009", + "0x15200700723b00901100915500700723b0091db00915e00700723b009007", + "0x923b00904900912500705200923b00915300944c00700723b00900e009", + "0x922100715000923b00915000900e00700900923b009009009033007049", + "0x522291500090491fd00905200923b00905200944d00722900923b009229", + "0x923b0091fd00956100705400923b00900702500700723b00900712e007", + "0x902600715900923b00915900956900700700923b009007009125007159", + "0x5800956b00705805712e23b00905415900712556a00705400923b009054", + "0x923b00905a00956d00700723b00900712e00715d00956c05a00923b12e", + "0x57000701800923b00901801b12e56f00701800923b00905d00956e00705d", + "0x915500716015f06012523b00915e00957100715e01812e23b009018009", + "0x706400923b00906000910200700723b00916000957200700723b00915f", + "0x916200910200700723b00916100910100716216112e23b009064009107", + "0x16816612e23b00912600910700716400923b00906700910400706700923b", + "0x916b00910400716b00923b00916800910200700723b009166009101007", + "0x700723b00906e00915500706f06e12e23b00916400915300706d00923b", + "0x906f00916300700723b00907100915500716e07112e23b00906d009153", + "0x17400923b00907407212e14f00707400923b00916e00916300707200923b", + "0x23b12e17400910600717400923b00917400902e00700723b00900710f007", + "0x718001812e23b00901800957000700723b00900712e007076009573007", + "0x18600957200700723b00907700910100718607807712523b009180009571", + "0x36b00718700923b00900757400707b00923b00907800916300700723b009", + "0x7f00902e00707f00923b00918708d12e14f00708d07b12e23b00907b009", + "0x723b00900712e00708e00957500723b12e07f00910600707f00923b009", + "0x23b00901500956600700723b00902500956600700723b009026009566007", + "0x709000957608f00923b12e22300914000700723b00907b009155007007", + "0x36900700723b00908f00905400700723b0090070ea00700723b00900712e", + "0x12e23b00909700957700709809709609509409309209122323b00900e009", + "0x22100702e00923b00902e00900e00705700923b0090570091250071a5099", + "0x5b0371a709c00e23b0091a522902e05700e50f00722900923b009229009", + "0x918e00700723b00900712e0071ac00957809f00923b12e05b0090dd007", + "0x923b0091a700900e00709c00923b00909c00912500722c00923b00909f", + "0x260071b022c12e23b00922c00957900703700923b0090370092210071a7", + "0x1a709c00e57b00722c00923b00922c23c12e57a0071b000923b0091b0009", + "0xa700957c1b500923b12e0a50093b90070a504a0a31b200e23b0091b0037", + "0xa900923b00900756300700723b0091b50093bb00700723b00900712e007", + "0xa900902600722c00923b00922c0090260071b200923b0091b2009125007", + "0x12e0ac0090dd0070ac1b812e23b0090a922c1b212557d0070a900923b009", + "0xb000923b0090ae00918e00700723b00900712e0071bc00957e0ae00923b", + "0xb000902600704a00923b00904a0092210070a300923b0090a300900e007", + "0x94550070b41bd0b212523b0090b009904a0a300e4540070b000923b009", + "0x23b0090b600945800700723b00900712e0071bb00957f0b600923b12e0b4", + "0xb809609509409309209122314800700723b0090ba0090540070ba0b812e", + "0x923b0090b200900e0070bc00923b0091b80091250071ba00923b009098", + "0x70ee0070c000923b0091ba0093f80071b900923b0091bd0092210070be", + "0x1db00915e00700723b00901100915500700723b00900712e007007580009", + "0x937000700723b00909800937200700723b00901800958100700723b009", + "0x37600700723b00909500937500700723b00909600937400700723b009091", + "0x700723b00909200937100700723b00909300937700700723b009094009", + "0x90090090330071b800923b0091b80091250070c200923b0091bb00944c", + "0x71bd00923b0091bd0092210070b200923b0090b200900e00700900923b", + "0x723b00900712e0070c21bd0b20091b81fd0090c200923b0090c200944d", + "0x23b00901100915500700723b00909200937100700723b009093009377007", + "0x909800937200700723b00901800958100700723b0091db00915e007007", + "0x9500937500700723b00909600937400700723b00909100937000700723b", + "0x944c00700723b00909900937300700723b00909400937600700723b009", + "0x923b0090090090330071b800923b0091b80091250071b600923b0091bc", + "0x944d00704a00923b00904a0092210070a300923b0090a300900e007009", + "0x37700700723b00900712e0071b604a0a30091b81fd0091b600923b0091b6", + "0x700723b00901100915500700723b00909200937100700723b009093009", + "0x723b00909800937200700723b00901800958100700723b0091db00915e", + "0x23b00909500937500700723b00909600937400700723b009091009370007", + "0x922c00902000700723b00909900937300700723b009094009376007007", + "0x330071b200923b0091b20091250070c400923b0090a700944c00700723b", + "0x23b00904a0092210070a300923b0090a300900e00700900923b009009009", + "0x712e0070c404a0a30091b21fd0090c400923b0090c400944d00704a009", + "0x937100700723b00909900937300700723b00909300937700700723b009", + "0x58100700723b0091db00915e00700723b00901100915500700723b009092", + "0x700723b00909100937000700723b00909800937200700723b009018009", + "0x723b00909400937600700723b00909500937500700723b009096009374", + "0x909c0091250070c600923b0091ac00944c00700723b00923c009566007", + "0x71a700923b0091a700900e00700900923b00900900903300709c00923b", + "0x1a700909c1fd0090c600923b0090c600944d00703700923b009037009221", + "0x23b00909000905400700723b0090070ea00700723b00900712e0070c6037", + "0x2e00900e0070bc00923b00905700912500700723b00923c009566007007", + "0xc000923b00900e0093f80071b900923b0092290092210070be00923b009", + "0x915500700723b0091b30091010071b70c71b312523b009018009571007", + "0xc900923b0090c90091fd0070c900923b0091b700905800700723b0090c7", + "0x1aa0095820cd00923b12e0cb0090720070cb1ad12e23b0090c900916e007", + "0x23b0090cf00901f0070cf00923b0091ad00901b00700723b00900712e007", + "0x2500700723b0091a30090200070d11a312e23b0091a80090150071a8009", + "0x23b0091a00090200070d51a012e23b0091a10090150071a100923b009007", + "0x902600719b00923b0090d500902300719f00923b0090d1009023007007", + "0x23b00900712e00700758300723b12e19b19f12e22c00719f00923b00919f", + "0x90c000915200700723b0091db00915e00700723b009011009155007007", + "0x90075840070d800923b00900722900700723b0090cd00915500700723b", + "0x19800923b0090da0d812e0300070da00923b0090da00902e0070da00923b", + "0xdd00944c0070dd00923b00919819712e03100719700923b009007225007", + "0x900923b0090090090330070bc00923b0090bc00912500718e00923b009", + "0x18e00944d0071b900923b0091b90092210070be00923b0090be00900e007", + "0x915300700723b00900712e00718e1b90be0090bc1fd00918e00923b009", + "0x18a00923b00900714c00700723b0090df0091550070e10df12e23b0090cd", + "0xe100916300700723b00918900915500718818912e23b00918a009153007", + "0x723b00918b0091550070e518b12e23b00918c00915300718c00923b009", + "0x91550070a018312e23b00918400915300718400923b009188009163007", + "0x17900923b0090a00091630070e800923b0090e500916300700723b009183", + "0x917b00902e00700723b00900710f00717b00923b0091790e812e14f007", + "0x700723b00900712e0070ea00958500723b12e17b00910600717b00923b", + "0x23b0091710090a500717100923b00917500914400717500923b00900716c", + "0x23b0090ea00911100700723b00900712e0070075860090070ee0070ec009", + "0x16c0090a500716c00923b0090ee0091130070ee00923b00900716c007007", + "0xf000923b0090f00090a50070f000923b0090ec00936e0070ec00923b009", + "0x70ea00700723b00900712e00716500958716900923b12e0f0009140007", + "0x915e00700723b00901100915500700723b00916900905400700723b009", + "0x3d80070f300923b00900722900700723b0090c000915200700723b0091db", + "0x23b0091630f312e03000716300923b00916300902e00716300923b009007", + "0x44c00715c00923b0090f60f812e0310070f800923b0090072250070f6009", + "0x23b0090090090330070bc00923b0090bc0091250070fa00923b00915c009", + "0x44d0071b900923b0091b90092210070be00923b0090be00900e007009009", + "0x700723b00900712e0070fa1b90be0090bc1fd0090fa00923b0090fa009", + "0x915400936900715415612e23b0090c000907800700723b009165009054", + "0x937100700723b00915800937000714c1041021011071510fd15822323b", + "0x37400700723b00910100937500700723b00910700937600700723b0090fd", + "0x700723b00914c00937200700723b00910400937300700723b009102009", + "0x1b90be1253da0071b900923b0091b90092210070be00923b0090be00900e", + "0x12e00714900958814e00923b12e14d00907b00714d10614f12523b009151", + "0x10c12e23b00910a00915300710a00923b00914e00918700700723b009007", + "0x914600915300714600923b00900714c00700723b00910c009155007147", + "0x714400923b00914700916300700723b00914b00915500710f14b12e23b", + "0x910f00916300700723b00911100915500714311112e23b009144009153", + "0x700723b00914000915500711814012e23b00911300915300711300923b", + "0x13b11512e14f00713b00923b00911800916300711500923b009143009163", + "0x58900723b12e13900910600713900923b00913900902e00713900923b009", + "0x911a00914400711a00923b00900716c00700723b00900712e007137009", + "0x712e00700758a0090070ee00712800923b00911c0090a500711c00923b", + "0x911300712300923b00900716c00700723b00913700911100700723b009", + "0x923b00912800936e00712800923b0090000090a500700000923b009123", + "0x2f500958b2f400923b12e2f30091400072f300923b0092f30090a50072f3", + "0x700723b0092f400905400700723b0090070ea00700723b00900712e007", + "0x723b00915600915200700723b00901100915500700723b0091db00915e", + "0x23b0092f700902e0072f700923b00900748b0072f600923b009007229007", + "0x3100724200923b0090072250072f800923b0092f72f612e0300072f7009", + "0x90bc00912500730800923b00930700944c00730700923b0092f824212e", + "0x714f00923b00914f00900e00700900923b0090090090330070bc00923b", + "0x14f0090bc1fd00930800923b00930800944d00710600923b009106009221", + "0x23b0092f500905400700723b0090070ea00700723b00900712e007308106", + "0x330070bc00923b0090bc00912500730a30912e23b009156009078007007", + "0x23b00910600922100714f00923b00914f00900e00700900923b009009009", + "0x58c0071db00923b0091db0091fd00701100923b00901100902e007106009", + "0x30f0091b000730f30e24130d30c1fd23b0091db01130a10614f0090bc1db", + "0x923b0093100091b200700723b00900712e00731200958d31000923b12e", + "0x5400700723b00900712e00724000958e31400923b12e313009140007313", + "0x731500923b00900722900700723b00930900915200700723b009314009", + "0x931631512e03000731600923b00931600902e00731600923b00900758f", + "0x731a00923b00931831912e03100731900923b00900722500731800923b", + "0x930d00903300730c00923b00930c00912500731b00923b00931a00944c", + "0x730e00923b00930e00922100724100923b00924100900e00730d00923b", + "0x723b00900712e00731b30e24130d30c1fd00931b00923b00931b00944d", + "0x931f30912e46800731f00923b00900716c00700723b009240009054007", + "0x730c00923b00930c00912500732100923b00932000946900732000923b", + "0x930e00922100724100923b00924100900e00730d00923b00930d009033", + "0x12e00732130e24130d30c1fd00932100923b00932100944d00730e00923b", + "0x732500923b00931200944c00700723b00930900915200700723b009007", + "0x924100900e00730d00923b00930d00903300730c00923b00930c009125", + "0x932500923b00932500944d00730e00923b00930e00922100724100923b", + "0x15e00700723b0090070ea00700723b00900712e00732530e24130d30c1fd", + "0x700723b00915600915200700723b00901100915500700723b0091db009", + "0x90090090330070bc00923b0090bc00912500732700923b00914900944c", + "0x710600923b00910600922100714f00923b00914f00900e00700900923b", + "0x723b00900712e00732710614f0090bc1fd00932700923b00932700944d", + "0x23b0091db00915e00700723b00901100915500700723b0091aa009054007", + "0x23b00900722900700723b0091ad00915e00700723b0090c0009152007007", + "0x12e03000732900923b00932900902e00732900923b009007584007328009", + "0x23b00932a23f12e03100723f00923b00900722500732a00923b009329328", + "0x330070bc00923b0090bc00912500732f00923b00932b00944c00732b009", + "0x23b0091b90092210070be00923b0090be00900e00700900923b009009009", + "0x712e00732f1b90be0090bc1fd00932f00923b00932f00944d0071b9009", + "0x759000700723b00923c00956600700723b00908e00911100700723b009", + "0x23b00933033112e14f00733107b12e23b00907b00936b00733000923b009", + "0x33300959100723b12e33200910600733200923b00933200902e007332009", + "0x723b00901500956600700723b00902500956600700723b00900712e007", + "0x12e00733500959233400923b12e22300914000700723b00907b009155007", + "0x936900700723b00933400905400700723b0090070ea00700723b009007", + "0x34812e23b00934600957700723e34634534033e33d33833622323b00900e", + "0x922100702e00923b00902e00900e00705700923b00905700912500734a", + "0x734e34d34c34b00e23b00934a22902e05700e50f00722900923b009229", + "0x34f00918e00700723b00900712e00723d00959334f00923b12e34e0090dd", + "0x34c00923b00934c00900e00734b00923b00934b00912500702300923b009", + "0x902600735002312e23b00902300957900734d00923b00934d009221007", + "0x34d34c34b00e57b00702300923b00902302612e57a00735000923b009350", + "0x735800959435700923b12e3560093b900735635535235100e23b009350", + "0x735a00923b00900756300700723b0093570093bb00700723b00900712e", + "0x935a00902600702300923b00902300902600735100923b009351009125", + "0x23b12e35f0090dd00735f35e12e23b00935a02335112557d00735a00923b", + "0x736300923b00936100918e00700723b00900712e007362009595361009", + "0x936300902600735500923b00935500922100735200923b00935200900e", + "0x36900945500736936836512523b00936334835535200e45400736300923b", + "0x12e23b00936a00945800700723b00900712e00736b00959636a00923b12e", + "0x23e36c34534033e33d33833622314800700723b00936e00905400736e36c", + "0x37200923b00936500900e00737100923b00935e00912500737000923b009", + "0x90070ee00737400923b0093700093f800737300923b009368009221007", + "0x91db00915e00700723b00901100915500700723b00900712e007007597", + "0x33600937000700723b00923e00937200700723b00901800958100700723b", + "0x937600700723b00934000937500700723b00934500937400700723b009", + "0x44c00700723b00933800937100700723b00933d00937700700723b00933e", + "0x23b00900900903300735e00923b00935e00912500737500923b00936b009", + "0x44d00736800923b00936800922100736500923b00936500900e007009009", + "0x700723b00900712e00737536836500935e1fd00937500923b009375009", + "0x723b00901100915500700723b00933800937100700723b00933d009377", + "0x23b00923e00937200700723b00901800958100700723b0091db00915e007", + "0x934000937500700723b00934500937400700723b009336009370007007", + "0x36200944c00700723b00934800937300700723b00933e00937600700723b", + "0x900923b00900900903300735e00923b00935e00912500737600923b009", + "0x37600944d00735500923b00935500922100735200923b00935200900e007", + "0x937700700723b00900712e00737635535200935e1fd00937600923b009", + "0x15e00700723b00901100915500700723b00933800937100700723b00933d", + "0x700723b00923e00937200700723b00901800958100700723b0091db009", + "0x723b00934000937500700723b00934500937400700723b009336009370", + "0x23b00902300902000700723b00934800937300700723b00933e009376007", + "0x903300735100923b00935100912500737700923b00935800944c007007", + "0x923b00935500922100735200923b00935200900e00700900923b009009", + "0x900712e0073773553520093511fd00937700923b00937700944d007355", + "0x33800937100700723b00934800937300700723b00933d00937700700723b", + "0x958100700723b0091db00915e00700723b00901100915500700723b009", + "0x37400700723b00933600937000700723b00923e00937200700723b009018", + "0x700723b00933e00937600700723b00934000937500700723b009345009", + "0x23b00934b00912500737800923b00923d00944c00700723b009026009566", + "0x22100734c00923b00934c00900e00700900923b00900900903300734b009", + "0x34d34c00934b1fd00937800923b00937800944d00734d00923b00934d009", + "0x723b00933500905400700723b0090070ea00700723b00900712e007378", + "0x902e00900e00737100923b00905700912500700723b009026009566007", + "0x737400923b00900e0093f800737300923b00922900922100737200923b", + "0x37b00915500700723b00937900910100737c37b37912523b009018009571", + "0x37f37e12e23b00937d00901500737d00923b00937c00901f00700723b009", + "0x23b00938000901500738000923b00900702500700723b00937e009020007", + "0x2300738300923b00937f00902300700723b00938100902000738238112e", + "0x12e38438312e22c00738300923b00938300902600738400923b009382009", + "0x915e00700723b00901100915500700723b00900712e00700759800723b", + "0x58400738500923b00900722900700723b00937400915200700723b0091db", + "0x23b00938638512e03000738600923b00938600902e00738600923b009007", + "0x44c00738b00923b00938738912e03100738900923b009007225007387009", + "0x23b00900900903300737100923b00937100912500738d00923b00938b009", + "0x44d00737300923b00937300922100737200923b00937200900e007009009", + "0x700723b00900712e00738d3733720093711fd00938d00923b00938d009", + "0x39b39a39939439322323b00939100936900739138e12e23b009374009078", + "0x937600700723b00939400937100700723b0093930093700073a139d39c", + "0x37300700723b00939c00937400700723b00939b00937500700723b00939a", + "0x37200923b00937200900e00700723b0093a100937200700723b00939d009", + "0x3a53a43a312523b0093993733721253da00737300923b009373009221007", + "0x918700700723b00900712e0073aa0095993a900923b12e3a500907b007", + "0x23b0093ab0091550073ac3ab12e23b00924700915300724700923b0093a9", + "0x91550073b13b012e23b0093af0091530073af00923b00900714c007007", + "0x3b412e23b0093b20091530073b200923b0093ac00916300700723b0093b0", + "0x3b70091530073b700923b0093b100916300700723b0093b40091550073b5", + "0x3bb00923b0093b500916300700723b0093b80091550073b93b812e23b009", + "0x710f0073bd00923b0093bc3bb12e14f0073bc00923b0093b9009163007", + "0x959a00723b12e3bd0091060073bd00923b0093bd00902e00700723b009", + "0x23b0093c00091440073c000923b00900716c00700723b00900712e0073be", + "0x900712e00700759b0090070ee0073c200923b0093c10090a50073c1009", + "0x3c30091130073c300923b00900716c00700723b0093be00911100700723b", + "0x3c600923b0093c200936e0073c200923b0093c50090a50073c500923b009", + "0x73c800959c3c700923b12e3c60091400073c600923b0093c60090a5007", + "0x15e00700723b0093c700905400700723b0090070ea00700723b00900712e", + "0x700723b00938e00915200700723b00901100915500700723b0091db009", + "0x923b0093ca00902e0073ca00923b00900748b0073c900923b009007229", + "0x12e0310073cd00923b0090072250073cb00923b0093ca3c912e0300073ca", + "0x23b0093710091250073d200923b0093d100944c0073d100923b0093cb3cd", + "0x2210073a300923b0093a300900e00700900923b009009009033007371009", + "0x3a43a30093711fd0093d200923b0093d200944d0073a400923b0093a4009", + "0x23b00938e00936900700723b0093c800905400700723b00900712e0073d2", + "0x1250073e53e412e23b0093dd0094310073e33e13de3dd3da3d93d83d7223", + "0x23b0093a40092210073a300923b0093a300900e00737100923b009371009", + "0x3ea0090cf0073ea3e93e83e600e23b0093e53a43a337100e4320073a4009", + "0x923b0092490091a800700723b00900712e0073ef00959d24900923b12e", + "0x15300700723b0093f300934f0073f53f43f312523b0093f00092460073f0", + "0x923b00900740b00700723b0093f60091550073f83f612e23b0093f4009", + "0x916300700723b0093fd0091550073ff3fd12e23b009248009153007248", + "0x23b00940240112e14f00740200923b0093ff00916300740100923b0093f8", + "0x40700959e00723b12e40400910600740400923b00940400902e007404009", + "0x940b00915500741340b12e23b0093f500915300700723b00900712e007", + "0x15500742741912e23b00941600915300741600923b00900714c00700723b", + "0x12e23b00942b00915300742b00923b00941300916300700723b009419009", + "0x915300743200923b00942700916300700723b00942f00915500743142f", + "0x923b00943100916300700723b00924600915500743424612e23b009432", + "0x2e00743800923b00943643512e14f00743600923b009434009163007435", + "0x900712e00743900959f00723b12e43800910600743800923b009438009", + "0x90a500743b00923b00943a00914400743a00923b00900716c00700723b", + "0x911100700723b00900712e0070075a00090070ee00743c00923b00943b", + "0x743f00923b00943d00911300743d00923b00900716c00700723b009439", + "0x94400090a500744000923b00943c00936e00743c00923b00943f0090a5", + "0x723b00900712e0074420095a144100923b12e44000914000744000923b", + "0x723b0091db00915e00700723b00944100905400700723b0090070ea007", + "0x23b0093e100937300700723b0093e300937200700723b009011009155007", + "0x93da00937600700723b0093e400937500700723b0093de009374007007", + "0x3d700937000700723b0093d800937100700723b0093d900937700700723b", + "0x902e00744500923b0090073d800744400923b00900722900700723b009", + "0x923b00900722500744600923b00944544412e03000744500923b009445", + "0x12500744b00923b00944800944c00744800923b00944624512e031007245", + "0x23b0093e800900e00700900923b0090090090330073e600923b0093e6009", + "0x1fd00944b00923b00944b00944d0073e900923b0093e90092210073e8009", + "0x905400700723b0090070ea00700723b00900712e00744b3e93e80093e6", + "0x744c00923b0093e33e13de3e43da3d93d83d722314800700723b009442", + "0x90090330073e600923b0093e600912500744e44d12e23b00944c009078", + "0x3e900923b0093e90092210073e800923b0093e800900e00700900923b009", + "0x3e61db58c0071db00923b0091db0091fd00701100923b00901100902e007", + "0x23b12e4540091b000745424445245044f1fd23b0091db01144e3e93e8009", + "0x745800923b0094550091b200700723b00900712e0074570095a2455009", + "0x45a00905400700723b00900712e00745b0095a345a00923b12e458009140", + "0x758f00745c00923b00900722900700723b00944d00915200700723b009", + "0x923b00945e45c12e03000745e00923b00945e00902e00745e00923b009", + "0x944c00746100923b00945f46012e03100746000923b00900722500745f", + "0x923b00945000903300744f00923b00944f00912500746300923b009461", + "0x944d00724400923b00924400922100745200923b00945200900e007450", + "0x5400700723b00900712e00746324445245044f1fd00946300923b009463", + "0x923b00946444d12e46800746400923b00900716c00700723b00945b009", + "0x903300744f00923b00944f00912500746800923b009465009469007465", + "0x923b00924400922100745200923b00945200900e00745000923b009450", + "0x900712e00746824445245044f1fd00946800923b00946800944d007244", + "0x912500746900923b00945700944c00700723b00944d00915200700723b", + "0x923b00945200900e00745000923b00945000903300744f00923b00944f", + "0x44f1fd00946900923b00946900944d00724400923b009244009221007452", + "0x40700911100700723b0090070ea00700723b00900712e007469244452450", + "0x937200700723b00901100915500700723b0091db00915e00700723b009", + "0x37500700723b0093de00937400700723b0093e100937300700723b0093e3", + "0x700723b0093d900937700700723b0093da00937600700723b0093e4009", + "0x723b0093f500915500700723b0093d700937000700723b0093d8009371", + "0x23b00946a00902e00746a00923b0090074d100724300923b009007229007", + "0x3100747d00923b00900722500747c00923b00946a24312e03000746a009", + "0x93e600912500748000923b00947f00944c00747f00923b00947c47d12e", + "0x73e800923b0093e800900e00700900923b0090090090330073e600923b", + "0x3e80093e61fd00948000923b00948000944d0073e900923b0093e9009221", + "0x23b0091db00915e00700723b0090070ea00700723b00900712e0074803e9", + "0x93e100937300700723b0093e300937200700723b009011009155007007", + "0x3da00937600700723b0093e400937500700723b0093de00937400700723b", + "0x937000700723b0093d800937100700723b0093d900937700700723b009", + "0x3e600923b0093e600912500748100923b0093ef00944c00700723b0093d7", + "0x3e90092210073e800923b0093e800900e00700900923b009009009033007", + "0x74813e93e80093e61fd00948100923b00948100944d0073e900923b009", + "0x700723b00901100915500700723b0091db00915e00700723b00900712e", + "0x23b00937100912500748200923b0093aa00944c00700723b00938e009152", + "0x2210073a300923b0093a300900e00700900923b009009009033007371009", + "0x3a43a30093711fd00948200923b00948200944d0073a400923b0093a4009", + "0x23b00902600956600700723b00933300911100700723b00900712e007482", + "0x12e14f00749607b12e23b00907b00936b00748b00923b0090075a4007007", + "0x23b12e49700910600749700923b00949700902e00749700923b00948b496", + "0x915500700723b00901500956600700723b00900712e0074990095a5007", + "0x23b00900712e00749b0095a649a00923b12e22300914000700723b00907b", + "0x23b00900e00936900700723b00949a00905400700723b0090070ea007007", + "0x1250074c84c712e23b0094c60095a70074c64b64b54b44b14b04a549c223", + "0x23b00922900922100702e00923b00902e00900e00705700923b009057009", + "0x4d70090dd0074d74d64d14cf00e23b0094c822902e05700e515007229009", + "0x923b0094d800918e00700723b00900712e0074e60095a84d800923b12e", + "0x92210074d100923b0094d100900e0074cf00923b0094cf009125007020", + "0x23b0094e70090260074e702012e23b0090200095790074d600923b0094d6", + "0x23b0094e74d64d14cf00e57b00702000923b00902002512e57a0074e7009", + "0x900712e0075030095a950200923b12e5010093b90075015004ff4e800e", + "0x4e800912500750400923b00900756300700723b0095020093bb00700723b", + "0x50400923b00950400902600702000923b0090200090260074e800923b009", + "0x5aa50700923b12e5060090dd00750650512e23b0095040204e812557d007", + "0x4ff00900e00750900923b00950700918e00700723b00900712e007508009", + "0x50900923b00950900902600750000923b0095000092210074ff00923b009", + "0x923b12e50c00924400750c50b50a12523b0095094c75004ff00e452007", + "0x751150f12e23b00950d00945700700723b00900712e00750e0095ab50d", + "0x923b00950f4b64b54b44b14b04a549c22314800700723b009511009054", + "0x922100751400923b00950a00900e00751300923b009505009125007512", + "0x70075ac0090070ee00751900923b0095120093f800751500923b00950b", + "0x700723b0091db00915e00700723b00901100915500700723b00900712e", + "0x723b0094b600937300700723b00949c00937000700723b009018009581", + "0x23b0094b100937600700723b0094b400937500700723b0094b5009374007", + "0x950e00944c00700723b0094a500937100700723b0094b0009377007007", + "0x700900923b00900900903300750500923b00950500912500751a00923b", + "0x951a00944d00750b00923b00950b00922100750a00923b00950a00900e", + "0x4b000937700700723b00900712e00751a50b50a0095051fd00951a00923b", + "0x915e00700723b00901100915500700723b0094a500937100700723b009", + "0x37300700723b00949c00937000700723b00901800958100700723b0091db", + "0x700723b0094b400937500700723b0094b500937400700723b0094b6009", + "0x923b00950800944c00700723b0094c700937200700723b0094b1009376", + "0x900e00700900923b00900900903300750500923b00950500912500751b", + "0x923b00951b00944d00750000923b0095000092210074ff00923b0094ff", + "0x23b0094b000937700700723b00900712e00751b5004ff0095051fd00951b", + "0x91db00915e00700723b00901100915500700723b0094a5009371007007", + "0x4b600937300700723b00949c00937000700723b00901800958100700723b", + "0x937600700723b0094b400937500700723b0094b500937400700723b009", + "0x44c00700723b00902000902000700723b0094c700937200700723b0094b1", + "0x23b0090090090330074e800923b0094e800912500751c00923b009503009", + "0x44d00750000923b0095000092210074ff00923b0094ff00900e007009009", + "0x700723b00900712e00751c5004ff0094e81fd00951c00923b00951c009", + "0x723b0094a500937100700723b0094c700937200700723b0094b0009377", + "0x23b00901800958100700723b0091db00915e00700723b009011009155007", + "0x94b500937400700723b0094b600937300700723b00949c009370007007", + "0x2500956600700723b0094b100937600700723b0094b400937500700723b", + "0x74cf00923b0094cf00912500751d00923b0094e600944c00700723b009", + "0x94d60092210074d100923b0094d100900e00700900923b009009009033", + "0x12e00751d4d64d10094cf1fd00951d00923b00951d00944d0074d600923b", + "0x956600700723b00949b00905400700723b0090070ea00700723b009007", + "0x51400923b00902e00900e00751300923b00905700912500700723b009025", + "0x1800957100751900923b00900e0093f800751500923b009229009221007", + "0x723b00951f00915500700723b00951e00910100752051f51e12523b009", + "0x52500916e00752500923b0095250091fd00752500923b009520009058007", + "0x900712e0075350095ad52e00923b12e52b00907200752b52812e23b009", + "0x1500753d00923b00953c00901f00753c00923b00952800901b00700723b", + "0x923b00900702500700723b00953e00902000754153e12e23b00953d009", + "0x902300700723b00954500902000754654512e23b009542009015007542", + "0x923b00924f00902600754800923b00954600902300724f00923b009541", + "0x915500700723b00900712e0070075ae00723b12e54824f12e22c00724f", + "0x15500700723b00951900915200700723b0091db00915e00700723b009011", + "0x754b00923b00900758400754900923b00900722900700723b00952e009", + "0x900722500754d00923b00954b54912e03000754b00923b00954b00902e", + "0x55100923b00955000944c00755000923b00954d54e12e03100754e00923b", + "0x51400900e00700900923b00900900903300751300923b009513009125007", + "0x55100923b00955100944d00751500923b00951500922100751400923b009", + "0x700723b00900710f00700723b00900712e0075515155140095131fd009", + "0x951900936900700723b00900712e0075520095af00723b12e52e009106", + "0x755d55c12e23b0095560093dd00755b55a55855755655555455322323b", + "0x5155141253de00751500923b00951500922100751400923b00951400900e", + "0x12e0075630095b056200923b12e56100907b00756155f55e12523b00955d", + "0x56612e23b00956500915300756500923b00956200918700700723b009007", + "0x956a00915300756a00923b00900714c00700723b009566009155007569", + "0x756e00923b00956900916300700723b00956b00915500756d56b12e23b", + "0x57000902e00757000923b00956f56e12e14f00756f00923b00956d009163", + "0x723b00900712e0075710095b100723b12e57000910600757000923b009", + "0x955e00900e00757200923b00955b55a55855755c555554553223148007", + "0x757900923b0095720093f800757700923b00955f00922100757400923b", + "0x911100700723b0090070ea00700723b00900712e0070075b20090070ee", + "0x37200700723b0091db00915e00700723b00901100915500700723b009571", + "0x700723b00955800937400700723b00955a00937300700723b00955b009", + "0x723b00955500937700700723b00955c00937600700723b009557009375", + "0x923b00900722900700723b00955300937000700723b009554009371007", + "0x57a12e03000757b00923b00957b00902e00757b00923b0090073e300757a", + "0x923b00957d58112e03100758100923b00900722500757d00923b00957b", + "0x903300751300923b00951300912500758c00923b00958400944c007584", + "0x923b00955f00922100755e00923b00955e00900e00700900923b009009", + "0x900712e00758c55f55e0095131fd00958c00923b00958c00944d00755f", + "0x91db00915e00700723b00901100915500700723b0090070ea00700723b", + "0x55800937400700723b00955a00937300700723b00955b00937200700723b", + "0x937700700723b00955c00937600700723b00955700937500700723b009", + "0x44c00700723b00955300937000700723b00955400937100700723b009555", + "0x23b00900900903300751300923b00951300912500758f00923b009563009", + "0x44d00755f00923b00955f00922100755e00923b00955e00900e007009009", + "0x700723b00900712e00758f55f55e0095131fd00958f00923b00958f009", + "0x23b00951500922100757400923b00951400900e00700723b009552009111", + "0x75a459012e23b00957900907800757900923b0095190093f8007577009", + "0x23b0095a70093700075b82525b75b65b55b45b35a722323b0095a4009369", + "0x95b600937500700723b0095b500937600700723b0095b3009371007007", + "0x5b800937200700723b00925200937300700723b0095b700937400700723b", + "0x12e5bb00907b0075bb5ba5b912523b0095b45775741253da00700723b009", + "0x5bf00923b0095bc00918700700723b00900712e0075be0095bd5bc00923b", + "0x900714c00700723b0095c00091550072515c012e23b0095bf009153007", + "0x700723b0095c20091550075c35c212e23b0095c10091530075c100923b", + "0x5c50091550075c65c512e23b0095c40091530075c400923b009251009163", + "0x2505c812e23b0095c70091530075c700923b0095c300916300700723b009", + "0x92500091630075c900923b0095c600916300700723b0095c8009155007", + "0x5cb00923b0095cb00902e0075cb00923b0095ca5c912e14f0075ca00923b", + "0x900716c00700723b00900712e0075cd0095cc00723b12e5cb009106007", + "0x75d000923b0095cf0090a50075cf00923b0095ce0091440075ce00923b", + "0x16c00700723b0095cd00911100700723b00900712e0070075d10090070ee", + "0x923b0095d30090a50075d300923b0095d20091130075d200923b009007", + "0x91400075d400923b0095d40090a50075d400923b0095d000936e0075d0", + "0x723b0090070ea00700723b00900712e0075d70095d65d500923b12e5d4", + "0x23b00901100915500700723b0091db00915e00700723b0095d5009054007", + "0x23b00900748b0075d800923b00900722900700723b009590009152007007", + "0x75da00923b0095d95d812e0300075d900923b0095d900902e0075d9009", + "0x95dc00944c0075dc00923b0095da5db12e0310075db00923b009007225", + "0x700900923b00900900903300751300923b0095130091250075dd00923b", + "0x95dd00944d0075ba00923b0095ba0092210075b900923b0095b900900e", + "0x90070ea00700723b00900712e0075dd5ba5b90095131fd0095dd00923b", + "0x12500724e5de12e23b00959000907800700723b0095d700905400700723b", + "0x23b0095b900900e00700900923b00900900903300751300923b009513009", + "0x1fd00701100923b00901100902e0075ba00923b0095ba0092210075b9009", + "0x5df1fd23b0091db01124e5ba5b90095131db5b30071db00923b0091db009", + "0x23b00900712e0075e60095e55e400923b12e5e30091b00075e35e25e15e0", + "0x5ea0095e95e800923b12e5e70091400075e700923b0095e40091b2007007", + "0x723b0095de00915200700723b0095e800905400700723b00900712e007", + "0x23b0095ec00902e0075ec00923b0090075b40075eb00923b009007229007", + "0x310075ee00923b0090072250075ed00923b0095ec5eb12e0300075ec009", + "0x95df0091250075f000923b0095ef00944c0075ef00923b0095ed5ee12e", + "0x75e100923b0095e100900e0075e000923b0095e00090330075df00923b", + "0x5e15e05df1fd0095f000923b0095f000944d0075e200923b0095e2009221", + "0x23b00900716c00700723b0095ea00905400700723b00900712e0075f05e2", + "0x75f300923b0095f20094690075f200923b0095f15de12e4680075f1009", + "0x95e100900e0075e000923b0095e00090330075df00923b0095df009125", + "0x95f300923b0095f300944d0075e200923b0095e20092210075e100923b", + "0x700723b0095de00915200700723b00900712e0075f35e25e15e05df1fd", + "0x95e00090330075df00923b0095df0091250075f400923b0095e600944c", + "0x75e200923b0095e20092210075e100923b0095e100900e0075e000923b", + "0x723b00900712e0075f45e25e15e05df1fd0095f400923b0095f400944d", + "0x723b00901100915500700723b0091db00915e00700723b0090070ea007", + "0x951300912500724d00923b0095be00944c00700723b009590009152007", + "0x75b900923b0095b900900e00700900923b00900900903300751300923b", + "0x5b90095131fd00924d00923b00924d00944d0075ba00923b0095ba009221", + "0x901100915500700723b00953500905400700723b00900712e00724d5ba", + "0x52800915e00700723b00951900915200700723b0091db00915e00700723b", + "0x902e0075f600923b0090075840075f500923b00900722900700723b009", + "0x923b0090072250075f700923b0095f65f512e0300075f600923b0095f6", + "0x1250075fa00923b0095f900944c0075f900923b0095f75f812e0310075f8", + "0x23b00951400900e00700900923b00900900903300751300923b009513009", + "0x1fd0095fa00923b0095fa00944d00751500923b009515009221007514009", + "0x56600700723b00949900911100700723b00900712e0075fa515514009513", + "0x7b12e23b00907b00936b0075fb00923b0090075b500700723b009025009", + "0x1060075fd00923b0095fd00902e0075fd00923b0095fb5fc12e14f0075fc", + "0x23b00907b00915500700723b00900712e0075ff0095fe00723b12e5fd009", + "0xea00700723b00900712e00760200960160000923b12e223009140007007", + "0x60324c22323b00900e00936900700723b00960000905400700723b009007", + "0x905700912500760b60a12e23b0096090095a7007609608607606605604", + "0x722900923b00922900922100702e00923b00902e00900e00705700923b", + "0x923b12e60f0090dd00760f60e60d60c00e23b00960b22902e05700e515", + "0x12500701f00923b00961000918e00700723b00900712e007612009611610", + "0x23b00960e00922100760d00923b00960d00900e00760c00923b00960c009", + "0x761300923b00961300902600761301f12e23b00901f00957900760e009", + "0x61561400e23b00961360e60d60c00e57b00701f00923b00901f01512e57a", + "0x700723b00900712e00761900961824b00923b12e6170093b9007617616", + "0x923b00961400912500761a00923b00900756300700723b00924b0093bb", + "0x12557d00761a00923b00961a00902600701f00923b00901f009026007614", + "0x761f00961e61d00923b12e61c0090dd00761c61b12e23b00961a01f614", + "0x923b00961500900e00762000923b00961d00918e00700723b00900712e", + "0xe45200762000923b00962000902600761600923b009616009221007615", + "0x962562400923b12e62300924400762362262112523b00962060a616615", + "0x62700905400762724a12e23b00962400945700700723b00900712e007626", + "0x12500762800923b00924a60860760660560460324c22314800700723b009", + "0x23b00962200922100762a00923b00962100900e00762900923b00961b009", + "0x900712e00700762d0090070ee00762c00923b0096280093f800762b009", + "0x1800958100700723b0091db00915e00700723b00901100915500700723b", + "0x937400700723b00960800937300700723b00924c00937000700723b009", + "0x37700700723b00960500937600700723b00960600937500700723b009607", + "0x62e00923b00962600944c00700723b00960300937100700723b009604009", + "0x62100900e00700900923b00900900903300761b00923b00961b009125007", + "0x62e00923b00962e00944d00762200923b00962200922100762100923b009", + "0x723b00960400937700700723b00900712e00762e62262100961b1fd009", + "0x23b0091db00915e00700723b00901100915500700723b009603009371007", + "0x960800937300700723b00924c00937000700723b009018009581007007", + "0x60500937600700723b00960600937500700723b00960700937400700723b", + "0x12500762f00923b00961f00944c00700723b00960a00937200700723b009", + "0x23b00961500900e00700900923b00900900903300761b00923b00961b009", + "0x1fd00962f00923b00962f00944d00761600923b009616009221007615009", + "0x37100700723b00960400937700700723b00900712e00762f61661500961b", + "0x700723b0091db00915e00700723b00901100915500700723b009603009", + "0x723b00960800937300700723b00924c00937000700723b009018009581", + "0x23b00960500937600700723b00960600937500700723b009607009374007", + "0x961900944c00700723b00901f00902000700723b00960a009372007007", + "0x700900923b00900900903300761400923b00961400912500763000923b", + "0x963000944d00761600923b00961600922100761500923b00961500900e", + "0x60400937700700723b00900712e0076306166150096141fd00963000923b", + "0x915500700723b00960300937100700723b00960a00937200700723b009", + "0x37000700723b00901800958100700723b0091db00915e00700723b009011", + "0x700723b00960700937400700723b00960800937300700723b00924c009", + "0x723b00901500956600700723b00960500937600700723b009606009375", + "0x900903300760c00923b00960c00912500763100923b00961200944c007", + "0x60e00923b00960e00922100760d00923b00960d00900e00700900923b009", + "0x23b00900712e00763160e60d00960c1fd00963100923b00963100944d007", + "0x23b00901500956600700723b00960200905400700723b0090070ea007007", + "0x922100762a00923b00902e00900e00762900923b009057009125007007", + "0x12523b00901800957100762c00923b00900e0093f800762b00923b009229", + "0x901f00700723b00963300915500700723b009632009101007634633632", + "0x23b00963600902000763763612e23b00963500901500763500923b009634", + "0x902000763a63912e23b00963800901500763800923b009007025007007", + "0x63c00923b00963a00902300763b00923b00963700902300700723b009639", + "0x12e00700763d00723b12e63c63b12e22c00763b00923b00963b009026007", + "0x15200700723b0091db00915e00700723b00901100915500700723b009007", + "0x763f00923b00900758400763e00923b00900722900700723b00962c009", + "0x900722500764000923b00963f63e12e03000763f00923b00963f00902e", + "0x64300923b00964200944c00764200923b00964064112e03100764100923b", + "0x62a00900e00700900923b00900900903300762900923b009629009125007", + "0x64300923b00964300944d00762b00923b00962b00922100762a00923b009", + "0x12e23b00962c00907800700723b00900712e00764362b62a0096291fd009", + "0x937000764d64c64b64a64964864764622323b009645009369007645644", + "0x37500700723b00964900937600700723b00964700937100700723b009646", + "0x700723b00964c00937300700723b00964b00937400700723b00964a009", + "0x23b00962b00922100762a00923b00962a00900e00700723b00964d009372", + "0x23b12e65000907b00765064f64e12523b00964862b62a1253da00762b009", + "0x765400923b00965100918700700723b00900712e007653009652651009", + "0x23b00900714c00700723b00965500915500765665512e23b009654009153", + "0x16300700723b00965800915500765965812e23b009657009153007657009", + "0x965b00915500765c65b12e23b00965a00915300765a00923b009656009", + "0x765f65e12e23b00965d00915300765d00923b00965900916300700723b", + "0x23b00965f00916300766000923b00965c00916300700723b00965e009155", + "0x902e00700723b00900710f00766200923b00966166012e14f007661009", + "0x23b00900712e00725600966300723b12e66200910600766200923b009662", + "0x6650090a500766500923b00966400914400766400923b00900716c007007", + "0x25600911100700723b00900712e0070076670090070ee00766600923b009", + "0xa500766900923b00966800911300766800923b00900716c00700723b009", + "0x23b00966a0090a500766a00923b00966600936e00766600923b009669009", + "0x700723b00900712e00766d00966c66b00923b12e66a00914000766a009", + "0x700723b0091db00915e00700723b00966b00905400700723b0090070ea", + "0x66e00923b00900722900700723b00964400915200700723b009011009155", + "0x66f66e12e03000766f00923b00966f00902e00766f00923b00900748b007", + "0x67200923b00967067112e03100767100923b00900722500767000923b009", + "0x900903300762900923b00962900912500767300923b00967200944c007", + "0x64f00923b00964f00922100764e00923b00964e00900e00700900923b009", + "0x23b00900712e00767364f64e0096291fd00967300923b00967300944d007", + "0x67867767667567422323b00964400936900700723b00966d009054007007", + "0x62900923b00962900912500767d67c12e23b00967800943100767b67a679", + "0x62900e43200764f00923b00964f00922100764e00923b00964e00900e007", + "0x968368200923b12e6810090cf00768168067f67e00e23b00967d64f64e", + "0x968500924600768500923b0096820091a800700723b00900712e007684", + "0x68912e23b00968700915300700723b00968600934f00768868768612523b", + "0x968b00915300768b00923b00900714300700723b00968900915500768a", + "0x768e00923b00968a00916300700723b00968c00915500768d68c12e23b", + "0x69000902e00769000923b00968f68e12e14f00768f00923b00968d009163", + "0x723b00900712e00725800969100723b12e69000910600769000923b009", + "0x6770093dd00700723b00900712e00769300969200723b12e688009106007", + "0x923b00968000922100767f00923b00967f00900e00769569412e23b009", + "0x923b12e69800907b00769869769612523b00969568067f1253de007680", + "0x15300769b00923b00969900918700700723b00900712e00725700969a699", + "0x923b00900714c00700723b00969c00915500769d69c12e23b00969b009", + "0x916300700723b00969f0091550076a069f12e23b00969e00915300769e", + "0x23b0096a26a112e14f0076a200923b0096a00091630076a100923b00969d", + "0x6a50096a400723b12e6a30091060076a300923b0096a300902e0076a3009", + "0x23b0096970092210076a600923b00969600900e00700723b00900712e007", + "0x900712e0070076a90090070ee0076a800923b0096940093e10076a7009", + "0x91db00915e00700723b0096a500911100700723b0090070ea00700723b", + "0x67b00937200700723b00969400937600700723b00901100915500700723b", + "0x937500700723b00967900937400700723b00967a00937300700723b009", + "0x37100700723b00967600937700700723b00967400937000700723b00967c", + "0x725500923b0090073e30076aa00923b00900722900700723b009675009", + "0x90072250076ab00923b0092556aa12e03000725500923b00925500902e", + "0x6ae00923b0096ad00944c0076ad00923b0096ab6ac12e0310076ac00923b", + "0x69600900e00700900923b00900900903300767e00923b00967e009125007", + "0x6ae00923b0096ae00944d00769700923b00969700922100769600923b009", + "0x700723b0090070ea00700723b00900712e0076ae69769600967e1fd009", + "0x723b00969400937600700723b00901100915500700723b0091db00915e", + "0x23b00967900937400700723b00967a00937300700723b00967b009372007", + "0x967600937700700723b00967400937000700723b00967c009375007007", + "0x91250076af00923b00925700944c00700723b00967500937100700723b", + "0x923b00969600900e00700900923b00900900903300767e00923b00967e", + "0x67e1fd0096af00923b0096af00944d00769700923b009697009221007696", + "0x900e00700723b00969300911100700723b00900712e0076af697696009", + "0x923b0096770093e10076a700923b0096800092210076a600923b00967f", + "0x23b00967b67a67967c6a867667567422314800700723b0090070ea0076a8", + "0x767e00923b00967e0091250076b26b112e23b0096b00090780076b0009", + "0x96a70092210076a600923b0096a600900e00700900923b009009009033", + "0x71db00923b0091db0091fd00701100923b00901100902e0076a700923b", + "0x91b00076b76b66b56b46b31fd23b0091db0116b26a76a600967e1db5b3", + "0x23b0096b80091b200700723b00900712e0076ba0096b96b800923b12e6b7", + "0x700723b00900712e0076bd0096bc6bb00923b12e254009140007254009", + "0x6be00923b00900722900700723b0096b100915200700723b0096bb009054", + "0x6bf6be12e0300076bf00923b0096bf00902e0076bf00923b0090075b4007", + "0x6c200923b0096c06c112e0310076c100923b0090072250076c000923b009", + "0x6b40090330076b300923b0096b300912500725300923b0096c200944c007", + "0x6b600923b0096b60092210076b500923b0096b500900e0076b400923b009", + "0x23b00900712e0072536b66b56b46b31fd00925300923b00925300944d007", + "0x6c36b112e4680076c300923b00900716c00700723b0096bd009054007007", + "0x6b300923b0096b30091250076c500923b0096c40094690076c400923b009", + "0x6b60092210076b500923b0096b500900e0076b400923b0096b4009033007", + "0x76c56b66b56b46b31fd0096c500923b0096c500944d0076b600923b009", + "0x6c600923b0096ba00944c00700723b0096b100915200700723b00900712e", + "0x6b500900e0076b400923b0096b40090330076b300923b0096b3009125007", + "0x6c600923b0096c600944d0076b600923b0096b60092210076b500923b009", + "0x700723b0090070ea00700723b00900712e0076c66b66b56b46b31fd009", + "0x723b00901100915500700723b0091db00915e00700723b009258009111", + "0x23b00967a00937300700723b00967b00937200700723b009675009371007", + "0x967400937000700723b00967c00937500700723b009679009374007007", + "0x68800915500700723b00967700937600700723b00967600937700700723b", + "0x902e0076c800923b0090074d10076c700923b00900722900700723b009", + "0x923b0090072250076c900923b0096c86c712e0300076c800923b0096c8", + "0x1250076cc00923b0096cb00944c0076cb00923b0096c96ca12e0310076ca", + "0x23b00967f00900e00700900923b00900900903300767e00923b00967e009", + "0x1fd0096cc00923b0096cc00944d00768000923b00968000922100767f009", + "0x915e00700723b0090070ea00700723b00900712e0076cc68067f00967e", + "0x37200700723b00967500937100700723b00901100915500700723b0091db", + "0x700723b00967900937400700723b00967a00937300700723b00967b009", + "0x723b00967600937700700723b00967400937000700723b00967c009375", + "0x967e0091250076cd00923b00968400944c00700723b009677009376007", + "0x767f00923b00967f00900e00700900923b00900900903300767e00923b", + "0x67f00967e1fd0096cd00923b0096cd00944d00768000923b009680009221", + "0x901100915500700723b0091db00915e00700723b00900712e0076cd680", + "0x91250076ce00923b00965300944c00700723b00964400915200700723b", + "0x923b00964e00900e00700900923b00900900903300762900923b009629", + "0x6291fd0096ce00923b0096ce00944d00764f00923b00964f00922100764e", + "0x958100700723b0095ff00911100700723b00900712e0076ce64f64e009", + "0x15300700723b00922300904a00700723b00901500956600700723b009018", + "0x923b0090075b600700723b0096cf0091550076d06cf12e23b00907b009", + "0x916300700723b0096d20091550076d36d212e23b0096d10091530076d1", + "0x23b0096d50091550076d66d512e23b0096d40091530076d400923b0096d0", + "0x1550076d96d812e23b0096d70091530076d700923b0096d3009163007007", + "0x923b0096d90091630076da00923b0096d600916300700723b0096d8009", + "0x1060076dc00923b0096dc00902e0076dc00923b0096db6da12e14f0076db", + "0x923b00900716c00700723b00900712e0076de0096dd00723b12e6dc009", + "0x70ee0076e100923b0096e00090a50076e000923b0096df0091440076df", + "0x900716c00700723b0096de00911100700723b00900712e0070076e2009", + "0x76e100923b0096e40090a50076e400923b0096e30091130076e300923b", + "0x12e6e50091400076e500923b0096e50090a50076e500923b0096e100936e", + "0x5400700723b0090070ea00700723b00900712e0076e80096e76e600923b", + "0x700723b00901100915500700723b0091db00915e00700723b0096e6009", + "0x6ea00923b0090075b70076e900923b00900722900700723b00900e009152", + "0x72250076eb00923b0096ea6e912e0300076ea00923b0096ea00902e007", + "0x923b0096ed00944c0076ed00923b0096eb6ec12e0310076ec00923b009", + "0x900e00700900923b00900900903300705700923b0090570091250076ee", + "0x923b0096ee00944d00722900923b00922900922100702e00923b00902e", + "0x23b0096e800905400700723b00900712e0076ee22902e0090571fd0096ee", + "0x723b00907600911100700723b00900712e0070076ef0090070ee007007", + "0x23b00922300904a00700723b00923c00956600700723b009018009581007", + "0x901500956600700723b00902500956600700723b009026009566007007", + "0x2e00900e00715500923b00905700912500700723b0090070ea00700723b", + "0x923b0091550091250076f16f012e23b00900e00907800715700923b009", + "0x922100715700923b00915700900e00700900923b009009009033007155", + "0x923b0091db0091fd00701100923b00901100902e00722900923b009229", + "0x76f66f56f46f36f21fd23b0091db0116f12291570091551db4190071db", + "0x25b0093bb00700723b00900712e0076f80096f725b00923b12e6f60093b9", + "0x76fa00923b0096f96f012e4680076f900923b00900716c00700723b009", + "0x96f30090330076f200923b0096f20091250076fb00923b0096fa009469", + "0x76f500923b0096f50092210076f400923b0096f400900e0076f300923b", + "0x723b00900712e0076fb6f56f46f36f21fd0096fb00923b0096fb00944d", + "0x96f20091250076fc00923b0096f800944c00700723b0096f0009152007", + "0x76f400923b0096f400900e0076f300923b0096f30090330076f200923b", + "0x6f46f36f21fd0096fc00923b0096fc00944d0076f500923b0096f5009221", + "0x91db00915e00700723b00901100915500700723b00900712e0076fc6f5", + "0xe00915200700723b00923c00956600700723b00912600910100700723b", + "0x956600700723b00902600956600700723b00922300904a00700723b009", + "0x44c00700723b00901b00956500700723b00901500956600700723b009025", + "0x23b00900900903300705700923b0090570091250076fd00923b00915d009", + "0x44d00722900923b00922900922100702e00923b00902e00900e007009009", + "0x700723b00900712e0076fd22902e0090571fd0096fd00923b0096fd009", + "0x723b00901100915500700723b0091db00915e00700723b00900e009152", + "0x23b00901b00956500700723b0091fd00936500700723b009015009566007", + "0x902600956600700723b00922300904a00700723b00923c009566007007", + "0x91250076fe00923b00903100944c00700723b00902500956600700723b", + "0x923b00902e00900e00700900923b00900900903300700700923b009007", + "0x71fd0096fe00923b0096fe00944d00722900923b00922900922100702e", + "0x714c00700e00923b00900725200700723b0090070ea0076fe22902e009", + "0x900923b00900900900e00700700923b0090070091250071fd00923b009", + "0x1fd00902e00712500923b00912500912300712e00923b00912e009221007", + "0x1fd12512e0090070115b900700e00923b00900e0095b80071fd00923b009", + "0x701f0096ff01b00923b12e0180095ba0070182231db01100e23b00900e", + "0x1500936500702302502001500e23b00901b0095bb00700723b00900712e", + "0x95bc00700723b00902300905400700723b00902500915500700723b009", + "0x923b00901100912500722c00923b0090260095be00702600923b009020", + "0x95bf00722300923b0092230092210071db00923b0091db00900e007011", + "0x95c000700723b00900712e00722c2231db01100e00922c00923b00922c", + "0x923b0091db00900e00701100923b00901100912500723c00923b00901f", + "0x1100e00923c00923b00923c0095bf00722300923b0092230092210071db", + "0x925100700e00923b00900e00930f00700723b0090070ea00723c2231db", + "0x71db00923b00900722900701100923b0090072290071fd00923b00900e", + "0x900700912500700723b0092230095c200701822312e23b0091fd0095c1", + "0x701800923b0090180095c300700900923b00900900900e00700700923b", + "0x90071fd5c40071db00923b0091db00915700701100923b009011009157", + "0x2500970002000923b12e0150095c500701501f01b12523b0091db011018", + "0x22c00905400722c02602312523b0090200095c600700723b00900712e007", + "0x700723b00923c00905700722923c12e23b00902300915900700723b009", + "0x2e00905700703002e12e23b00902600915900702c00923b009229009058", + "0x91fd00700723b00900710f00722500923b00903000905800700723b009", + "0x22502c12e01f00e5c700722500923b0092250091fd00702c00923b00902c", + "0x900716c00700723b00900712e00703622103312570104503112e23b12e", + "0x703a00923b00903100900e00703800923b0092190093b400721900923b", + "0x7020090070ee00712600923b0090380093b500703b00923b009045009221", + "0x903300900e00703c00923b0090360093b700700723b00900712e007007", + "0x712600923b00903c0093b500703b00923b00922100922100703a00923b", + "0x12e00704100970314100923b12e03e0093b900703e00923b0091260095c8", + "0x46800714500923b00914100925000700723b0090070ea00700723b009007", + "0x901b00912500714800923b00904300946900704300923b00914512512e", + "0x703b00923b00903b00922100703a00923b00903a00900e00701b00923b", + "0x700723b00900712e00714803b03a01b00e00914800923b00914800944d", + "0x4700923b00904100944c00700723b00912500915200700723b0090070ea", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00704703b03a01b00e00904700923b00904700944d00703b00923b009", + "0x704900923b00902500944c00700723b00912500915200700723b009007", + "0x912e00922100701f00923b00901f00900e00701b00923b00901b009125", + "0x75c900704912e01f01b00e00904900923b00904900944d00712e00923b", + "0x900721900700723b0090070ea00700723b0090071600071fd00923b009", + "0x12e23b12e01100900712503a00701100923b00901100903800701100923b", + "0x1f00923b00912e0095ca00700723b00900712e00701b01812e7042231db", + "0x23b12e01f0095cb0071db00923b0091db00912500700723b00900710f007", + "0x2300923b0090200095cd00700723b00900712e00702500970502001512e", + "0x90070ee00702600923b0090230095ce00700e00923b00901500916b007", + "0x922c0095cf00722c00923b00900716c00700723b00900712e007007706", + "0x702600923b00923c0095ce00700e00923b00902500916b00723c00923b", + "0x702c00970722900923b12e0260095d200700e00923b00900e1fd12e5d0", + "0x702e00923b0092290095d300700723b0090070ea00700723b00900712e", + "0x902e0091fd00722300923b00922300900e0071db00923b0091db009125", + "0x23b00912502e2231db00e5d400712500923b00912500915700702e00923b", + "0x23b00900712e00703300970804500923b12e03100906e007031225030125", + "0x5400721903612e23b00904500906f00722100923b00900e009241007007", + "0x923b00922500900e00703000923b00903000912500700723b009219009", + "0xe31600703600923b00903600915700722100923b009221009315007225", + "0x970912600923b12e03b00906e00703b03a03812523b009036221225030", + "0x14100905400714103e12e23b00912600906f00700723b00900712e00703c", + "0x714500923b00903a00900e00704100923b00903800912500700723b009", + "0x700723b00900712e00700770a0090070ee00704300923b00903e009157", + "0x903a00900e00703800923b00903800912500714800923b00903c00931b", + "0x900712e00714803a03812500914800923b00914800931a00703a00923b", + "0x912500704700923b00903300931b00700723b00900e0095d500700723b", + "0x923b00904700931a00722500923b00922500900e00703000923b009030", + "0x5400700723b0090070ea00700723b00900712e007047225030125009047", + "0x4100923b0091db00912500700723b00900e0095d500700723b00902c009", + "0x900716c00704300923b00912500915700714500923b00922300900e007", + "0x4c00923b00915000931900715000923b00904904312e31800704900923b", + "0x4c00931a00714500923b00914500900e00704100923b009041009125007", + "0x91fd0095d700700723b00900712e00704c14504112500904c00923b009", + "0x900722900700723b00912e0095d800700723b00912500905700700723b", + "0x3000715300923b00915300902e00715300923b00900705d00715200923b", + "0x915515712e03100715700923b00900722500715500923b00915315212e", + "0x701800923b00901800912500705400923b00905200931b00705200923b", + "0x5401b01812500905400923b00905400931a00701b00923b00901b00900e", + "0x923b0091fd0090380071fd00923b00900721900700723b0090070ea007", + "0x900712e00701822312e70b1db01112e23b12e1fd00900712503a0071fd", + "0x701100923b00901100912500701b00e12e23b00900e00936b00700723b", + "0x900e00915500700723b00900712e00701f00970c00723b12e01b009106", + "0x702000923b00901512e12e32700701500923b0091250095d900700723b", + "0x91db00900e00701100923b00901100912500702500923b009020009328", + "0x900712e0070251db01112500902500923b0090250093290071db00923b", + "0x916e00712e00923b00912e0091fd00700723b00901f00911100700723b", + "0x712e00723c00970d22c00923b12e02600907200702602312e23b00912e", + "0x702c00923b00900714300722900923b00922c12512e03000700723b009", + "0x1db00900e00701100923b00901100912500702e00923b00902c00e12e14f", + "0x22900923b00922900915700702300923b0090230091fd0071db00923b009", + "0x3012523b00902e2290231db0111fd32500702e00923b00902e00902e007", + "0x700723b00900712e00703300970e04500923b12e031009076007031225", + "0x932800721900923b00903622112e32700703622112e23b009045009180", + "0x923b00922500900e00703000923b00903000912500703800923b009219", + "0x723b00900712e00703822503012500903800923b009038009329007225", + "0x22500900e00703000923b00903000912500703a00923b00903300932a007", + "0x712e00703a22503012500903a00923b00903a00932900722500923b009", + "0x923f00700723b00912500905700700723b00900e00915500700723b009", + "0x23b00912600932800712600923b00903b02312e32700703b00923b00923c", + "0x3290071db00923b0091db00900e00701100923b00901100912500703c009", + "0x915500700723b00900712e00703c1db01112500903c00923b00903c009", + "0x22900700723b00912e00915e00700723b00912500905700700723b00900e", + "0x14100923b00914100902e00714100923b00900705d00703e00923b009007", + "0x14512e03100714500923b00900722500704100923b00914103e12e030007", + "0x923b00922300912500714800923b00904300932a00704300923b009041", + "0x22312500914800923b00914800932900701800923b00901800900e007223", + "0x5da00701100923b0090110091fd00700700923b009007009125007148018", + "0x701b00970f01800923b12e2230095db0072231db12e23b00901100712e", + "0x12e23b00901f0095dd00701f00923b0090180095dc00700723b00900712e", + "0xe00700900923b0090090090330071db00923b0091db009125007020015", + "0x23b00900e0095de00712500923b00912500922100712e00923b00912e009", + "0x2300923b00902300902e0070231fd12e23b0091fd00936b00702500e12e", + "0x23b00901502302512512e0091db1db5b300701500923b0090150091fd007", + "0x712e00703000971002e00923b12e02c0091b000702c22923c22c0261fd", + "0x71103100923b12e22500914000722500923b00902e0091b200700723b009", + "0x900e00915200700723b00903100905400700723b00900712e007045009", + "0x900716c00700723b00902000915e00700723b0091fd00915500700723b", + "0x703600923b00922100939900722100923b00903300911300703300923b", + "0x922c00903300702600923b00902600912500721900923b00903600939a", + "0x722900923b00922900922100723c00923b00923c00900e00722c00923b", + "0x723b00900712e00721922923c22c0261fd00921900923b00921900939b", + "0x3800936900703800e12e23b00900e0095de00700723b009045009054007", + "0x37100700723b00903a00937000714504114103e03c12603b03a22323b009", + "0x700723b00903e00937500700723b00903c00937600700723b00903b009", + "0x723b00914500937200700723b00904100937300700723b009141009374", + "0x23c1253da00722900923b00922900922100723c00923b00923c00900e007", + "0x715000971204900923b12e04700907b00704714804312523b009126229", + "0x723b12e04c00910600704c00923b00904900918700700723b00900712e", + "0xe00915200700723b0091fd00915500700723b00900712e007152009713", + "0x715500923b00915300901f00715300923b00902000901b00700723b009", + "0x23b00900702500700723b00915700902000705215712e23b009155009015", + "0x2300700723b00915900902000705715912e23b009054009015007054009", + "0x23b00905800902600705a00923b00905700902300705800923b009052009", + "0x16c00700723b00900712e00700771400723b12e05a05812e22c007058009", + "0x923b00905d0090a500705d00923b00915d00911300715d00923b009007", + "0x6000923b00900716c00700723b00900712e0070077150090070ee00715e", + "0x2600912500715e00923b00915f0090a500715f00923b009060009144007", + "0x16100923b00904300900e00706400923b00922c00903300716000923b009", + "0x90070ee00706700923b00915e0090a500716200923b009148009221007", + "0x902600912500700723b00915200911100700723b00900712e007007716", + "0x704300923b00904300900e00722c00923b00922c00903300702600923b", + "0x90200091fd0071fd00923b0091fd00902e00714800923b009148009221", + "0x16b1681661641fd23b0090201fd00e14804322c0261db58c00702000923b", + "0x1b200700723b00900712e00706f00971706e00923b12e06d0091b000706d", + "0x23b00916600903300716000923b00916400912500707100923b00906e009", + "0xa500716200923b00916b00922100716100923b00916800900e007064009", + "0x23b00916e00939a00716e00923b00906700939900706700923b009071009", + "0xe00706400923b00906400903300716000923b009160009125007072009", + "0x23b00907200939b00716200923b00916200922100716100923b009161009", + "0x906f00939c00700723b00900712e0070721621610641601fd009072009", + "0x716600923b00916600903300716400923b00916400912500707400923b", + "0x907400939b00716b00923b00916b00922100716800923b00916800900e", + "0x2000915e00700723b00900712e00707416b1681661641fd00907400923b", + "0x939c00700723b00900e00915200700723b0091fd00915500700723b009", + "0x923b00922c00903300702600923b00902600912500717400923b009150", + "0x939b00714800923b00914800922100704300923b00904300900e00722c", + "0x15200700723b00900712e00717414804322c0261fd00917400923b009174", + "0x700723b00902000915e00700723b0091fd00915500700723b00900e009", + "0x922c00903300702600923b00902600912500707600923b00903000939c", + "0x722900923b00922900922100723c00923b00923c00900e00722c00923b", + "0x723b00900712e00707622923c22c0261fd00907600923b00907600939b", + "0x23b00901b00939c00700723b0091fd00915500700723b00900e009152007", + "0xe00700900923b0090090090330071db00923b0091db009125007180009", + "0x23b00918000939b00712500923b00912500922100712e00923b00912e009", + "0x916e00700900923b0090090091fd00718012512e0091db1fd009180009", + "0x712e0071fd00971800e00923b12e12500907200712512e12e23b009009", + "0x900712e0072230097191db01112e23b12e00e00712e24e00700723b009", + "0x1fd00701100923b00901100912500701800923b0091db0095df00700723b", + "0x701812e01112500901800923b0090180095e000712e00923b00912e009", + "0x1f00923b00901b0095e100701b00923b00900716c00700723b00900712e", + "0x1f0095e000712e00923b00912e0091fd00722300923b009223009125007", + "0x91fd0095e100700723b00900712e00701f12e22312500901f00923b009", + "0x712e00923b00912e0091fd00700700923b00900700912500701500923b", + "0x12e23b12e00900712e5e200701512e00712500901500923b0090150095e0", + "0x71fd00923b0091250095e300700723b00900712e00700e00971a12512e", + "0x71b0090070ee0071db00923b0091fd0095e400701100923b00912e009125", + "0x23b0092230095e600722300923b00900716c00700723b00900712e007007", + "0x12e0091db00923b0090180095e400701100923b00900e009125007018009", + "0x12500917500712500923b00912e00901b00700723b0090070ea0071db011", + "0x23b0091fd00917100700723b00900712e00701100971c1fd00e12e23b12e", + "0xee00701800923b0091db0090ec00722300923b00900e0090b40071db009", + "0x90f000701b00923b00900716c00700723b00900712e00700771d009007", + "0x923b00901f0090ec00722300923b0090110090b400701f00923b00901b", + "0x916900701500923b0090150091fd00701500923b009223009058007018", + "0x23b00902000916500700723b00900712e00702500971e02000923b12e018", + "0x912500722c00923b00902300916300702600923b0090070f3007023009", + "0x923b0090150091fd00700900923b00900900900e00700700923b009007", + "0x1fd0f600722c00923b00922c00902e00702600923b009026009047007015", + "0x71f02e00923b12e02c0091db00702c22923c12523b00922c026015009007", + "0x901800703122512e23b00902e00922300700723b00900712e007030009", + "0x23b00904500911c00700723b00900712e00703300972004500923b12e031", + "0x5e700721900923b00903600912800700723b00922100923c00703622112e", + "0x903a0095ea00703a00923b00903822512e5e800703800923b009219009", + "0x722900923b00922900900e00723c00923b00923c00912500703b00923b", + "0x5ec00700723b00900712e00703b22923c12500903b00923b00903b0095eb", + "0x903c0095ea00703c00923b00912622512e5e800712600923b009033009", + "0x722900923b00922900900e00723c00923b00923c00912500703e00923b", + "0x5ed00700723b00900712e00703e22923c12500903e00923b00903e0095eb", + "0x23b00922900900e00723c00923b00923c00912500714100923b009030009", + "0x23b00900712e00714122923c12500914100923b0091410095eb007229009", + "0x90410095ec00704100923b00900716c00700723b009025009054007007", + "0x14800923b0090430095ea00704300923b00914501512e5e800714500923b", + "0x1480095eb00700900923b00900900900e00700700923b009007009125007", + "0x922100700700923b00900700900e00714800900712500914800923b009", + "0xe0095ef00700e12512e12523b00900900712e5ee00700900923b009009", + "0x923b0091fd0095f000700723b00900712e0070110097211fd00923b12e", + "0x701f01b01812523b0092230095f200722300923b0091db0095f10071db", + "0x923b00901b0095f300700723b00901f00910100700723b00901800934f", + "0x922100712e00923b00912e00900e00702000923b0090150095f4007015", + "0x12e00702012512e12500902000923b00902000924d00712500923b009125", + "0x12e00923b00912e00900e00702500923b0090110095f500700723b009007", + "0x12512e12500902500923b00902500924d00712500923b009125009221007", + "0x902e00712e00923b00912e00909900700700923b009007009125007025", + "0x5f70072231db01112523b0091fd00e12e00700e5f60071fd00923b0091fd", + "0x923b00901b00902600701b00923b00900702500701800923b009223009", + "0x702602302512572202001501f12523b12e01801b12500900e5f800701b", + "0x23b00922c00915500723c22c12e23b00902000915300700723b00900712e", + "0x915500702e02c12e23b00922900915300722900923b00900714c007007", + "0x22512e23b00903000915300703000923b00923c00916300700723b00902c", + "0x4500915300704500923b00902e00916300700723b009225009155007031", + "0x3600923b00903100916300700723b00903300915500722103312e23b009", + "0x3612e14f00703600923b00903600902e00721900923b009221009163007", + "0x923b00901f00900e00703800923b00903800902e00703800923b009219", + "0x703a00972300723b12e03800910600701500923b00901500922100701f", + "0x12600923b00903b00914400703b00923b00900716c00700723b00900712e", + "0x723b00900712e0070077240090070ee00703c00923b0091260090a5007", + "0x23b00903e00911300703e00923b00900716c00700723b00903a009111007", + "0x5f900704100923b00903c00936e00703c00923b0091410090a5007141009", + "0x23b00901500922100704300923b00901f00900e00714500923b009041009", + "0x900712e0070077250090070ee00704700923b0091450095fa007148009", + "0x22100704300923b00902500900e00704900923b0090260095fb00700723b", + "0x23b0090470095fc00704700923b0090490095fa00714800923b009023009", + "0x700723b00900712e00715200972604c00923b12e1500091b0007150009", + "0x915500939a00715500923b00915300939900715300923b00904c0091b2", + "0x704300923b00904300900e00701100923b00901100912500715700923b", + "0x915700939b00714800923b0091480092210071db00923b0091db009099", + "0x15200939c00700723b00900712e0071571481db0430111fd00915700923b", + "0x4300923b00904300900e00701100923b00901100912500705200923b009", + "0x5200939b00714800923b0091480092210071db00923b0091db009099007", + "0x700700923b00900700900e0070521481db0430111fd00905200923b009", + "0x54e00700e12512e12523b00900900712e54d00700900923b009009009221", + "0x91fd00955000700723b00900712e0070110097271fd00923b12e00e009", + "0x1b0181fd23b00922300955200722300923b0091db0095510071db00923b", + "0x910100700723b00901b00955400700723b00901800955300702001501f", + "0x702500923b00901500955500700723b00902000915500700723b00901f", + "0x912500922100712e00923b00912e00900e00702300923b009025009556", + "0x900712e00702312512e12500902300923b00902300955700712500923b", + "0x22100712e00923b00912e00900e00702600923b00901100955800700723b", + "0x702612512e12500902600923b00902600955700712500923b009125009", + "0x5fd00700723b0090070ea00700723b0090071600071fd00923b00900755f", + "0x701f01b0182231db1fd23b00901100935600701112512e23b009125009", + "0x723b00901800934f00700723b00922300915500700723b0091db009101", + "0x901500956100701500923b00901f0095ff00700723b00901b00934f007", + "0xe00923b00900e1fd12e57a00700e00923b00902000956200702000923b", + "0x902300937b00702300923b00900714c00702500923b00900e0090df007", + "0x23c1fd23b00922c00935600722c12512e23b0091250095fd00702600923b", + "0x34f00700723b00922900915500700723b00923c00910100703002e02c229", + "0x22500923b0090300095ff00700723b00902e00934f00700723b00902c009", + "0x12e00909900700900923b00900900900e00700700923b009007009125007", + "0x2600923b00902600960000722500923b00922500912300712e00923b009", + "0x1160200703100923b00903100902e00703102512e23b00902500936b007", + "0x923b12e03600924c00703622103304500e23b00903102622512e009007", + "0x937b00703a00923b00900714c00700723b00900712e007038009728219", + "0x3c00923b00903b00937d00712600923b00900760300703b00923b00903a", + "0x22112537e00712600923b00912600902e00703c00923b00903c00902e007", + "0x4100935600704112512e23b0091250095fd00714103e12e23b00912603c", + "0x914800934f00700723b0090430091550070490471480431451fd23b009", + "0x14500910200700723b00904900936500700723b00904700934f00700723b", + "0x15200923b00914100937b00704c00923b00915000910400715000923b009", + "0x3e12537e00715300923b00915300902e00715300923b00915200937d007", + "0x91250095fd00705200923b00915700937b00715715512e23b00904c153", + "0x15900910100715d05a0580571591fd23b00905400935600705412512e23b", + "0x936500700723b00905a00934f00700723b00905800934f00700723b009", + "0x15e00923b00905200937d00705d00923b00905700916300700723b00915d", + "0x715f06012e23b00905d15e15512537e00715e00923b00915e00902e007", + "0x1640671621610641fd23b00916000935600716012512e23b0091250095fd", + "0x23b00906700934f00700723b00916100915500700723b009064009101007", + "0x16600950500716600923b00916200950400700723b009164009365007007", + "0x6d00923b00916b00937d00716b00923b00915f00937b00716800923b009", + "0x706f06e12e23b00916806d06012537e00706d00923b00906d00902e007", + "0x15500700723b00907100910100717407407216e0711fd23b009125009356", + "0x700723b00917400936500700723b00907200934f00700723b00916e009", + "0x906f00937b00718000923b00907600950500707600923b009074009504", + "0x707800923b00907800902e00707800923b00907700937d00707700923b", + "0x37d00718700923b00907b00937b00707b18612e23b00918007806e12537e", + "0x2508d18612537e00708d00923b00908d00902e00708d00923b009187009", + "0x908f00936500709109008f12523b00921900960400708e07f12e23b009", + "0x937d00709200923b00908e00937b00700723b00909000960500700723b", + "0x909109307f12537e00709300923b00909300902e00709300923b009092", + "0x709700923b00900760600709600923b00909500937b00709509412e23b", + "0x909700902e00709800923b00909800902e00709800923b00909600937d", + "0x23b0091a500937b0071a509912e23b00909709809412537e00709700923b", + "0x33000703700923b0091a700932f0071a700923b00909c00937d00709c009", + "0x23b00903300900e00704500923b00904500912500705b00923b009037009", + "0xe00905b00923b00905b00933100709900923b009099009099007033009", + "0x909800700723b00902500915500700723b00900712e00705b099033045", + "0x4500923b00904500912500709f00923b00903800933200700723b009125", + "0x9f00933100722100923b00922100909900703300923b00903300900e007", + "0x72231db12e23b00900e00936a00709f22103304500e00909f00923b009", + "0x91fd00902e00712e00923b00912e00909900700700923b009007009125", + "0x1100960700701f01b01812523b0091fd22312e00700e5f60071fd00923b", + "0x702500923b00900702500702000923b00901f0095f700701500923b009", + "0x2602312e23b12e0150200251250091fd60800702500923b009025009026", + "0x3b400702c00923b00900716c00700723b00900712e00722923c22c125729", + "0x23b00902600922100703000923b00902300900e00702e00923b00902c009", + "0x900712e00700772a0090070ee00703100923b00902e0093b5007225009", + "0x22100703000923b00922c00900e00704500923b0092290093b700700723b", + "0x23b0090310095c800703100923b0090450093b500722500923b00923c009", + "0x700723b00900712e00703600972b22100923b12e0330093b9007033009", + "0x3800960a00703800923b0092191db12e60900721900923b009221009250", + "0x3000923b00903000900e00701800923b00901800912500703a00923b009", + "0x3a00960b00722500923b00922500922100701b00923b00901b009099007", + "0x937400700723b00900712e00703a22501b0300181fd00903a00923b009", + "0x1800923b00901800912500703b00923b00903600960c00700723b0091db", + "0x22500922100701b00923b00901b00909900703000923b00903000900e007", + "0x703b22501b0300181fd00903b00923b00903b00960b00722500923b009", + "0x91fd0091550070111fd12e23b00912500915300700e00923b009007229", + "0x5200700e00923b00900e00915700701100923b00901100902e00700723b", + "0x912e00960d00700723b0092230090540072231db12e23b00900e01112e", + "0x701501f12e23b0091db00915900701b00923b00900760e00701800923b", + "0x23b00901b00902e00702000923b00901500905800700723b00901f009057", + "0x23b12e02001b0180090071fd60f00702000923b0090200091fd00701b009", + "0x902600961000700723b00900712e00722923c22c12572c026023025125", + "0x703000923b00902300922100702e00923b00902500900e00702c00923b", + "0x700723b00900712e00700772d0090070ee00722500923b00902c009612", + "0x923c00922100702e00923b00922c00900e00703100923b009229009613", + "0x704500923b00922500961400722500923b00903100961200703000923b", + "0x3300961600700723b00900712e00722100972e03300923b12e045009615", + "0x21912e23b00903600961700703600923b0090360091fd00703600923b009", + "0x703b00972f03a00923b12e03800924b00700723b00921900915e007038", + "0x923b00912600939a00712600923b00903a00939900700723b00900712e", + "0x939b00703000923b00903000922100702e00923b00902e00900e00703c", + "0x3b00905400700723b00900712e00703c03002e12500903c00923b00903c", + "0x902e00714100923b00900761900703e00923b00900722900700723b009", + "0x923b00900722500704100923b00914103e12e03000714100923b009141", + "0xe00714800923b00904300939c00704300923b00904114512e031007145", + "0x23b00914800939b00703000923b00903000922100702e00923b00902e009", + "0x923b00922100939c00700723b00900712e00714803002e125009148009", + "0x939b00703000923b00903000922100702e00923b00902e00900e007047", + "0x93b500700900923b00900761a00704703002e12500904700923b009047", + "0x23b00900900712e61b00700900923b00900900902e00700700923b009007", + "0x700723b00900712e00700e00973012500923b12e12e0093b900712e009", + "0x901100961d00701100923b0091fd00961c0071fd00923b009125009250", + "0x723b00900712e0071db0090091db00923b0091db00961f0071db00923b", + "0x722300900922300923b00922300961f00722300923b00900e009620007", + "0x923b00900e00962100700e00923b00900e0093bd00700723b0090070ea", + "0x91fd0095c10071db00923b00900722900701100923b0090072290071fd", + "0x700700923b00900700912500700723b0092230095c200701822312e23b", + "0x901100915700701800923b0090180095c300700900923b00900900900e", + "0x91db0110180090071fd5c40071db00923b0091db00915700701100923b", + "0x900712e00702500973102000923b12e0150095c500701501f01b12523b", + "0x700723b00922c00905400722c02602312523b0090200095c600700723b", + "0x922900905800700723b00923c00905700722923c12e23b009023009159", + "0x700723b00902e00905700703002e12e23b00902600915900702c00923b", + "0x923b00902c0091fd00700723b00900710f00722500923b009030009058", + "0x3112e23b12e22502c12e01f00e5c700722500923b0092250091fd00702c", + "0x721900923b00900716c00700723b00900712e007036221033125732045", + "0x904500922100703a00923b00903100900e00703800923b0092190093b4", + "0x712e0070077330090070ee00712600923b0090380093b500703b00923b", + "0x703a00923b00903300900e00703c00923b0090360093b700700723b009", + "0x91260095c800712600923b00903c0093b500703b00923b009221009221", + "0x723b00900712e00704100973414100923b12e03e0093b900703e00923b", + "0x914512512e46800714500923b00914100925000700723b0090070ea007", + "0x701b00923b00901b00912500714800923b00904300946900704300923b", + "0x914800944d00703b00923b00903b00922100703a00923b00903a00900e", + "0x23b0090070ea00700723b00900712e00714803b03a01b00e00914800923b", + "0x1b00912500704700923b00904100944c00700723b009125009152007007", + "0x3b00923b00903b00922100703a00923b00903a00900e00701b00923b009", + "0x723b00900712e00704703b03a01b00e00904700923b00904700944d007", + "0x901b00912500704900923b00902500944c00700723b009125009152007", + "0x712e00923b00912e00922100701f00923b00901f00900e00701b00923b", + "0x1100923b00900715f00704912e01f01b00e00904900923b00904900944d", + "0x71db00923b00900722900700723b0090070ea00700723b009007160007", + "0x900700912500700723b00922300905700701822312e23b00900e009159", + "0x701800923b0090180090b400700900923b00900900900e00700700923b", + "0x1501f01b12523b0091db01800900700e0b60071db00923b0091db009157", + "0x906f00700723b00900712e00702500973502000923b12e01500906e007", + "0x923b00912500962200700723b00902600905400702602312e23b009020", + "0x905700702c22912e23b00902300915900723c00923b0090075b600722c", + "0x2e00700723b00900710f00702e00923b00902c00905800700723b009229", + "0x22c12e01f1fd60f00702e00923b00902e0091fd00723c00923b00923c009", + "0x700723b00900712e00722103304512573603122503012523b12e02e23c", + "0x922500922100721900923b00903000900e00703600923b009031009610", + "0x712e0070077370090070ee00703800923b0090360096120071fd00923b", + "0x721900923b00904500900e00703a00923b00922100961300700723b009", + "0x903800961400703800923b00903a0096120071fd00923b009033009221", + "0x12600923b12e03b0096150071fd00923b0091fd01112e16200703b00923b", + "0x912600961600700723b0090070ea00700723b00900712e00703c009738", + "0x721900923b00921900900e00701b00923b00901b00912500703e00923b", + "0x714504114112523b00903e21901b12517400703e00923b00903e0091fd", + "0x4300918000700723b00900712e00714800973904300923b12e145009076", + "0x15000923b12e04900907700700723b00904700915e00704904712e23b009", + "0x962400715200923b00915000962300700723b00900712e00704c00973a", + "0x923b00904100900e00714100923b00914100912500715300923b009152", + "0x14100e00915300923b0091530096260071fd00923b0091fd009221007041", + "0x900722900700723b00904c00905400700723b00900712e0071531fd041", + "0x3000715700923b00915700902e00715700923b00900761900715500923b", + "0x905205412e03100705400923b00900722500705200923b00915715512e", + "0x714100923b00914100912500705700923b00915900924a00715900923b", + "0x90570096260071fd00923b0091fd00922100704100923b00904100900e", + "0x914800924a00700723b00900712e0070571fd04114100e00905700923b", + "0x704100923b00904100900e00714100923b00914100912500705800923b", + "0x1fd04114100e00905800923b0090580096260071fd00923b0091fd009221", + "0x923b00903c00924a00700723b0090070ea00700723b00900712e007058", + "0x922100721900923b00921900900e00701b00923b00901b00912500705a", + "0x705a1fd21901b00e00905a00923b00905a0096260071fd00923b0091fd", + "0x700723b00912500962700700723b00901100906400700723b00900712e", + "0x901f00900e00701b00923b00901b00912500715d00923b00902500924a", + "0x915d00923b00915d00962600712e00923b00912e00922100701f00923b", + "0x3800700e00923b00900721900700723b0090070ea00715d12e01f01b00e", + "0x1db12e73b0111fd12e23b12e00e00900712503a00700e00923b00900e009", + "0x23b00900710f00701800923b00912e00901b00700723b00900712e007223", + "0x973c01f01b12e23b12e0180091750071fd00923b0091fd009125007007", + "0x901b0090b400702000923b00901f00917100700723b00900712e007015", + "0x712e00700773d0090070ee00702300923b0090200090ec00702500923b", + "0xb400722c00923b0090260090f000702600923b00900716c00700723b009", + "0x23b12e02300916900702300923b00922c0090ec00702500923b009015009", + "0x916500700723b0090070ea00700723b00900712e00722900973e23c009", + "0x923b00912500915700702c00923b00902c00902e00702c00923b00923c", + "0x5800700723b00903000905400703002e12e23b00912502c12e052007125", + "0x23b00901100900e0071fd00923b0091fd00912500722500923b009025009", + "0x3cb00702e00923b00902e00915700722500923b0092250091fd007011009", + "0x73f22100923b12e03300906e00703304503112523b00902e2250111fd00e", + "0x905400703821912e23b00922100906f00700723b00900712e007036009", + "0x3b00923b00904500900e00703a00923b00903100912500700723b009038", + "0x723b00900712e0070077400090070ee00712600923b009219009157007", + "0x4500900e00703100923b00903100912500703c00923b00903600931b007", + "0x712e00703c04503112500903c00923b00903c00931a00704500923b009", + "0x2500957200700723b00922900905400700723b0090070ea00700723b009", + "0x703b00923b00901100900e00703a00923b0091fd00912500700723b009", + "0x903e12612e31800703e00923b00900716c00712600923b009125009157", + "0x703a00923b00903a00912500704100923b00914100931900714100923b", + "0x4103b03a12500904100923b00904100931a00703b00923b00903b00900e", + "0x723b00912e00915e00700723b00912500905700700723b00900712e007", + "0x23b00904300902e00704300923b00900705d00714500923b009007229007", + "0x3100704700923b00900722500714800923b00904314512e030007043009", + "0x91db00912500715000923b00904900931b00704900923b00914804712e", + "0x915000923b00915000931a00722300923b00922300900e0071db00923b", + "0x5f700712500923b00900762800700723b00912e0093710071502231db125", + "0x923b0091fd0090260071fd00923b00900702500700e00923b009125009", + "0x1112523b12e00e1fd00900700e5f800700e00923b00900e0096290071fd", + "0x923b00922300962a00700723b00900712e00701f01b0181257412231db", + "0x962b00702500923b0091db00922100702000923b00901100900e007015", + "0x962c00700723b00900712e0070077420090070ee00702300923b009015", + "0x923b00901b00922100702000923b00901800900e00702600923b00901f", + "0x907b00722c00923b00902300962e00702300923b00902600962b007025", + "0x23b00923c00918700700723b00900712e00722900974323c00923b12e22c", + "0xe00703000923b00902e00933000702e00923b00902c00932f00702c009", + "0x23b00903000933100702500923b00902500922100702000923b009020009", + "0x923b00922900933200700723b00900712e007030025020125009030009", + "0x933100702500923b00902500922100702000923b00902000900e007225", + "0x762f00700723b00912e00937700722502502012500922500923b009225", + "0x71fd00923b00900702500700e00923b0091250095f700712500923b009", + "0x900700e5f800700e00923b00900e0096290071fd00923b0091fd009026", + "0x700723b00900712e00701f01b0181257442231db01112523b12e00e1fd", + "0x91db00922100702000923b00901100900e00701500923b00922300962a", + "0x712e0070077450090070ee00702300923b00901500962b00702500923b", + "0x702000923b00901800900e00702600923b00901f00962c00700723b009", + "0x902300962e00702300923b00902600962b00702500923b00901b009221", + "0x723b00900712e00722900974623c00923b12e22c00907b00722c00923b", + "0x2e00933000702e00923b00902c00932f00702c00923b00923c009187007", + "0x2500923b00902500922100702000923b00902000900e00703000923b009", + "0x700723b00900712e00703002502012500903000923b009030009331007", + "0x902500922100702000923b00902000900e00722500923b009229009332", + "0x12e00937600722502502012500922500923b00922500933100702500923b", + "0x2500700e00923b0091250095f700712500923b00900763000700723b009", + "0x923b00900e0096290071fd00923b0091fd0090260071fd00923b009007", + "0x701f01b0181257472231db01112523b12e00e1fd00900700e5f800700e", + "0x923b00901100900e00701500923b00922300962a00700723b00900712e", + "0x70ee00702300923b00901500962b00702500923b0091db009221007020", + "0x900e00702600923b00901f00962c00700723b00900712e007007748009", + "0x923b00902600962b00702500923b00901b00922100702000923b009018", + "0x22900974923c00923b12e22c00907b00722c00923b00902300962e007023", + "0x23b00902c00932f00702c00923b00923c00918700700723b00900712e007", + "0x22100702000923b00902000900e00703000923b00902e00933000702e009", + "0x703002502012500903000923b00903000933100702500923b009025009", + "0x923b00902000900e00722500923b00922900933200700723b00900712e", + "0x2012500922500923b00922500933100702500923b009025009221007020", + "0xe0095f700700e00923b00900763100700723b009125009370007225025", + "0x701100923b00901100902600701100923b0090070250071fd00923b009", + "0x182231db12523b12e1fd01112e00900e5f80071fd00923b0091fd009629", + "0x700700923b00900700912500700723b00900712e00701501f01b12574a", + "0x900e00702502012e23b00901800712e63200701800923b00901800902e", + "0x923b12e0250091b800722300923b0092230092210071db00923b0091db", + "0x12500722c00923b00902300963300700723b00900712e00702600974b023", + "0x23b00922300922100722900923b0091db00900e00723c00923b009020009", + "0x900712e00700774c0090070ee00702e00923b00922c00963400702c009", + "0x900763500703000923b00900722900700723b00902600905400700723b", + "0x3100923b00922503012e03000722500923b00922500902e00722500923b", + "0x3300963600703300923b00903104512e03100704500923b009007225007", + "0x1db00923b0091db00900e00702000923b00902000912500722100923b009", + "0x1db02000e00922100923b00922100963700722300923b009223009221007", + "0x700912500703600923b00901500963800700723b00900712e007221223", + "0x2c00923b00901f00922100722900923b00901b00900e00723c00923b009", + "0x2190093e600721900923b00902e00963900702e00923b009036009634007", + "0x923b0090380093e800700723b00900712e00703a00974d03800923b12e", + "0x912500703c00923b00912600963b00712600923b00903b00963a00703b", + "0x923b00902c00922100722900923b00922900900e00723c00923b00923c", + "0x23b00900712e00703c02c22923c00e00903c00923b00903c00963700702c", + "0x900e00723c00923b00923c00912500703e00923b00903a009636007007", + "0x923b00903e00963700702c00923b00902c00922100722900923b009229", + "0x912e00963c00712e00923b00900700963c00703e02c22923c00e00903e", + "0x71fd00923b00900900963c00700e00923b00912500963e00712500923b", + "0x900e0091530071db00923b00901100963e00701100923b0091fd00963c", + "0x1f01b12e23b0091db00915300700723b00922300915500701822312e23b", + "0x901f00916300701500923b00901800916300700723b00901b009155007", + "0x2500923b00902500902e00702500923b00902001512e14f00702000923b", + "0x900716c00700723b00900712e00702300974e00723b12e025009106007", + "0x723c00923b00922c0090a500722c00923b00902600914400702600923b", + "0x16c00700723b00902300911100700723b00900712e00700774f0090070ee", + "0x923b00902c0090a500702c00923b00922900911300722900923b009007", + "0x71fd00923b00912500963e00700e00923b00900763100723c00900923c", + "0x23b00912e0093e40071db00923b00900702500701100923b00900e0095f7", + "0x6290071db00923b0091db00902600700723b00901800937000701822312e", + "0x75001f01b12e23b12e1fd0111db0090071fd60800701100923b009011009", + "0x93b400702300923b00900716c00700723b00900712e007025020015125", + "0x923b00901f00922100722c00923b00901b00900e00702600923b009023", + "0x23b00900712e0070077510090070ee00722900923b0090260093b500723c", + "0x922100722c00923b00901500900e00702c00923b0090250093b7007007", + "0x923b0092290095c800722900923b00902c0093b500723c00923b009020", + "0x25000700723b00900712e00722500975203000923b12e02e0093b900702e", + "0x904500964000704500923b00903122312e63f00703100923b009030009", + "0x723c00923b00923c00922100722c00923b00922c00900e00703300923b", + "0x37000700723b00900712e00703323c22c12500903300923b009033009641", + "0x923b00922c00900e00722100923b00922500964200700723b009223009", + "0x22c12500922100923b00922100964100723c00923b00923c00922100722c", + "0xe00964300700e00923b00900e0093f500700723b0090070ea00722123c", + "0x5c10071db00923b00900722900701100923b0090072290071fd00923b009", + "0x23b00900700912500700723b0092230095c200701822312e23b0091fd009", + "0x15700701800923b0090180095c300700900923b00900900900e007007009", + "0x180090071fd5c40071db00923b0091db00915700701100923b009011009", + "0x702500975302000923b12e0150095c500701501f01b12523b0091db011", + "0x922c00905400722c02602312523b0090200095c600700723b00900712e", + "0x5800700723b00923c00905700722923c12e23b00902300915900700723b", + "0x902e00905700703002e12e23b00902600915900702c00923b009229009", + "0x2c0091fd00700723b00900710f00722500923b00903000905800700723b", + "0x12e22502c12e01f00e5c700722500923b0092250091fd00702c00923b009", + "0x23b00900716c00700723b00900712e00703622103312575404503112e23b", + "0x22100703a00923b00903100900e00703800923b0092190093b4007219009", + "0x77550090070ee00712600923b0090380093b500703b00923b009045009", + "0x23b00903300900e00703c00923b0090360093b700700723b00900712e007", + "0x5c800712600923b00903c0093b500703b00923b00922100922100703a009", + "0x712e00704100975614100923b12e03e0093b900703e00923b009126009", + "0x12e46800714500923b00914100925000700723b0090070ea00700723b009", + "0x23b00901b00912500714800923b00904300946900704300923b009145125", + "0x44d00703b00923b00903b00922100703a00923b00903a00900e00701b009", + "0xea00700723b00900712e00714803b03a01b00e00914800923b009148009", + "0x704700923b00904100944c00700723b00912500915200700723b009007", + "0x903b00922100703a00923b00903a00900e00701b00923b00901b009125", + "0x712e00704703b03a01b00e00904700923b00904700944d00703b00923b", + "0x12500704900923b00902500944c00700723b00912500915200700723b009", + "0x23b00912e00922100701f00923b00901f00900e00701b00923b00901b009", + "0x90070ea00704912e01f01b00e00904900923b00904900944d00712e009", + "0x12503a00700e00923b00900e00903800700e00923b00900721900700723b", + "0x56100700723b00900712e0072231db12e7570111fd12e23b12e00e009007", + "0x1fd00923b0091fd00912500700723b00900710f00701800923b00912e009", + "0x64500700723b00900712e00701500975801f01b12e23b12e018009644007", + "0x23b00902000964600702500923b00901b00956900702000923b00901f009", + "0x923b00900716c00700723b00900712e0070077590090070ee007023009", + "0x964600702500923b00901500956900722c00923b009026009647007026", + "0x923b00923c00912300723c00923b00902500912800702300923b00922c", + "0x56e00700723b00900712e00702c00975a22900923b12e02300964800723c", + "0x902e00964900722503012e23b00912500910700702e00923b009229009", + "0x723b00904500915500703304503112523b00902e00957100702e00923b", + "0x922100910700722100923b00903100910200700723b009033009572007", + "0x3a03812e23b00921900910700700723b00903600910100721903612e23b", + "0x3b00910100712603b12e23b00922500910700700723b009038009101007", + "0x712600923b00912600935a00703a00923b00903a00935a00700723b009", + "0x3e0090a500703e00923b00903c00936e00703c00923b00912603a12e64a", + "0x23b00900712e00704100975b14100923b12e03e00914000703e00923b009", + "0x23b00903000910100700723b00914100905400700723b0090070ea007007", + "0x23b00900764b00714500923b00900722900700723b00923c009365007007", + "0x714800923b00904314512e03000704300923b00904300902e007043009", + "0x904900964c00704900923b00914804712e03100704700923b009007225", + "0x701100923b00901100900e0071fd00923b0091fd00912500715000923b", + "0xea00700723b00900712e0071500111fd12500915000923b00915000964d", + "0x71fd00923b0091fd00912500700723b00904100905400700723b009007", + "0x903000935a00723c00923b00923c00912300701100923b00901100900e", + "0x15300940200715315204c12523b00903023c0111fd00e40100703000923b", + "0x12e23b00915500964e00700723b00900712e00715700975c15500923b12e", + "0x705700923b00915900965000715900923b00905405212e64f007054052", + "0x905700964d00715200923b00915200900e00704c00923b00904c009125", + "0x23b00915700964c00700723b00900712e00705715204c12500905700923b", + "0x64d00715200923b00915200900e00704c00923b00904c009125007058009", + "0x70ea00700723b00900712e00705815204c12500905800923b009058009", + "0x716c00700723b00912500910100700723b00902c00905400700723b009", + "0x923b00915d00965000715d00923b00905a23c12e64f00705a00923b009", + "0x964d00701100923b00901100900e0071fd00923b0091fd00912500705d", + "0x12e00936500700723b00900712e00705d0111fd12500905d00923b00905d", + "0x705d00715e00923b00900722900700723b00912500910100700723b009", + "0x923b00906015e12e03000706000923b00906000902e00706000923b009", + "0x964c00706400923b00915f16012e03100716000923b00900722500715f", + "0x923b00922300900e0071db00923b0091db00912500716100923b009064", + "0x23b0090070091250071612231db12500916100923b00916100964d007223", + "0x2231db12e23b00901100712e5da00701100923b0090110091fd007007009", + "0x95dc00700723b00900712e00701b00975d01800923b12e2230095db007", + "0x23b0091db00912500702001512e23b00901f0095dd00701f00923b009018", + "0x22100712e00923b00912e00900e00700900923b0090090090330071db009", + "0x91fd00936b00702500e12e23b00900e0095de00712500923b009125009", + "0x1500923b0090150091fd00702300923b00902300902e0070231fd12e23b", + "0x1b000702c22923c22c0261fd23b00901502302512512e0091db1db5b3007", + "0x902e0091b200700723b00900712e00703000975e02e00923b12e02c009", + "0x723b00900712e00704500975f03100923b12e22500914000722500923b", + "0x23b0091fd00915500700723b00900e00915200700723b009031009054007", + "0x23b0090075b400703300923b00900722900700723b00902000915e007007", + "0x703600923b00922103312e03000722100923b00922100902e007221009", + "0x903800962000703800923b00903621912e03100721900923b009007225", + "0x722c00923b00922c00903300702600923b00902600912500703a00923b", + "0x903a00961f00722900923b00922900922100723c00923b00923c00900e", + "0x4500905400700723b00900712e00703a22923c22c0261fd00903a00923b", + "0x12622323b00903b00936900703b00e12e23b00900e0095de00700723b009", + "0x23b00903c00937100700723b00912600937000714804314504114103e03c", + "0x914500937400700723b00904100937500700723b009141009376007007", + "0x23c00900e00700723b00914800937200700723b00904300937300700723b", + "0x23b00903e22923c1253da00722900923b00922900922100723c00923b009", + "0x23b00900712e00715200976004c00923b12e15000907b007150049047125", + "0x715500976100723b12e15300910600715300923b00904c009187007007", + "0x700723b00900e00915200700723b0091fd00915500700723b00900712e", + "0x905200901500705200923b00915700901f00715700923b00902000901b", + "0x1500705700923b00900702500700723b00905400902000715905412e23b", + "0x23b00915900902300700723b00905800902000705a05812e23b009057009", + "0x22c00715d00923b00915d00902600705d00923b00905a00902300715d009", + "0x923b00900722900700723b00900712e00700776200723b12e05d15d12e", + "0x15e12e03000706000923b00906000902e00706000923b00900758f00715e", + "0x923b00915f16012e03100716000923b00900722500715f00923b009060", + "0x903300702600923b00902600912500716100923b009064009620007064", + "0x923b00904900922100704700923b00904700900e00722c00923b00922c", + "0x900712e00716104904722c0261fd00916100923b00916100961f007049", + "0xe00706700923b00922c00903300716200923b00902600912500700723b", + "0x77630090070ee00716600923b00904900922100716400923b009047009", + "0x923b00902600912500700723b00915500911100700723b00900712e007", + "0x922100704700923b00904700900e00722c00923b00922c009033007026", + "0x923b0090200091fd0071fd00923b0091fd00902e00704900923b009049", + "0x706f06e06d16b1681fd23b0090201fd00e04904722c0261db58c007020", + "0x710091b200700723b00900712e00716e00976407100923b12e06f0091b0", + "0x23b00900712e00717400976507400923b12e07200914000707200923b009", + "0x23b00900758f00707600923b00900722900700723b009074009054007007", + "0x707700923b00918007612e03000718000923b00918000902e007180009", + "0x918600962000718600923b00907707812e03100707800923b009007225", + "0x716b00923b00916b00903300716800923b00916800912500707b00923b", + "0x907b00961f00706e00923b00906e00922100706d00923b00906d00900e", + "0x17400905400700723b00900712e00707b06e06d16b1681fd00907b00923b", + "0x706700923b00916b00903300716200923b00916800912500700723b009", + "0x23b00900716c00716600923b00906e00922100716400923b00906d00900e", + "0x61f00707f00923b00908d00961d00708d00923b00918700961c007187009", + "0x700723b00900712e00707f1661640671621fd00907f00923b00907f009", + "0x916b00903300716800923b00916800912500708e00923b00916e009620", + "0x706e00923b00906e00922100706d00923b00906d00900e00716b00923b", + "0x723b00900712e00708e06e06d16b1681fd00908e00923b00908e00961f", + "0x23b00900e00915200700723b0091fd00915500700723b00902000915e007", + "0x903300702600923b00902600912500708f00923b009152009620007007", + "0x923b00904900922100704700923b00904700900e00722c00923b00922c", + "0x900712e00708f04904722c0261fd00908f00923b00908f00961f007049", + "0x2000915e00700723b0091fd00915500700723b00900e00915200700723b", + "0x702600923b00902600912500709000923b00903000962000700723b009", + "0x922900922100723c00923b00923c00900e00722c00923b00922c009033", + "0x12e00709022923c22c0261fd00909000923b00909000961f00722900923b", + "0x62000700723b0091fd00915500700723b00900e00915200700723b009007", + "0x23b0090090090330071db00923b0091db00912500709100923b00901b009", + "0x61f00712500923b00912500922100712e00923b00912e00900e007009009", + "0x12e23b00901100915300709112512e0091db1fd00909100923b009091009", + "0x15500702001512e23b00901f00915300701f00923b00900714c00701b018", + "0x12e23b00902500915300702500923b00901b00916300700723b009015009", + "0x915300722c00923b00902000916300700723b009023009155007026023", + "0x923b00902600916300700723b00923c00915500722923c12e23b00922c", + "0x2e00703000923b00902e02c12e14f00702e00923b00922900916300702c", + "0x900712e00722500976600723b12e03000910600703000923b009030009", + "0x90a500704500923b00903100914400703100923b00900716c00700723b", + "0x911100700723b00900712e0070077670090070ee00703300923b009045", + "0x703600923b00922100911300722100923b00900716c00700723b009225", + "0x92190090a500721900923b00903300936e00703300923b0090360090a5", + "0x723b00900712e00703a00976803800923b12e21900914000721900923b", + "0x23b00922300915500700723b0091fd00915200700723b009038009054007", + "0x23b00900722900700723b00901800915500700723b0091db009155007007", + "0x12e03000712600923b00912600902e00712600923b0090073d800703b009", + "0x23b00903c03e12e03100703e00923b00900722500703c00923b00912603b", + "0x3300700700923b00900700912500704100923b009141009620007141009", + "0x23b00912500909900712e00923b00912e00900e00700900923b009009009", + "0x1100904100923b00904100961f00700e00923b00900e009221007125009", + "0x700723b00903a00905400700723b00900712e00704100e12512e009007", + "0xe12e12e14d00700e00923b00900e00922100712e00923b00912e00900e", + "0x712e00704900976904700923b12e14800914e00714804314512523b009", + "0x704c00923b00915000910a00715000923b00904700914900700723b009", + "0x923b00900765100715300923b00915200937b00715200923b00900714c", + "0x902e00715700923b00915700902e00715700923b00915300937d007155", + "0x4c00910c00705405212e23b00915515712512537e00715500923b009155", + "0x15900915500716216106416015f06015e05d15d05a05805715902023b009", + "0x915e00700723b00905800914700700723b00905700910100700723b009", + "0x14600700723b00915e00915500700723b00915d00915500700723b00905a", + "0x700723b00916000915e00700723b00915f00914700700723b009060009", + "0x723b00916200915e00700723b00916100902000700723b009064009020", + "0x16400902e00716400923b00906700937d00706700923b00905400937b007", + "0x23b00905d16405212537e00705d00923b00905d00902e00716400923b009", + "0x704300923b00904300922100714500923b00914500900e00716816612e", + "0x2e00716600923b00916600909900706e06d16b12523b00904314512e387", + "0x712e00707100976a06f00923b12e06e0090fd00716800923b009168009", + "0x707200923b00916e00910400716e00923b00906f00915100700723b009", + "0x917400902e00717400923b00907400937d00707400923b00916800937b", + "0x23b0091fd00936900718007612e23b00907217416612537e00717400923b", + "0x18600937700700723b00907700937000708e07f08d18707b186078077223", + "0x937400700723b00918700937500700723b00907b00937600700723b009", + "0xe00700723b00908e00937200700723b00907f00937300700723b00908d", + "0x7806d16b1253d200706d00923b00906d00922100716b00923b00916b009", + "0x23b00918000902e00707600923b00907600909900709109008f12523b009", + "0x700723b00900712e00709300976b09200923b12e09100907b007180009", + "0x909400937d00709500923b00909200918700709400923b00918000937b", + "0x12e23b00909509607612537e00709600923b00909600902e00709600923b", + "0x937d0071a500923b00900738600709900923b00909800937b007098097", + "0x923b0091a500902e00709c00923b00909c00902e00709c00923b009099", + "0x5b00923b00903700937b0070371a712e23b0091a509c09712537e0071a5", + "0x900903300700700923b00900700912500709f00923b00905b00937d007", + "0x1800923b00901800902e00709f00923b00909f00902e00700900923b009", + "0x701165300722300923b00922300902e0071db00923b0091db00902e007", + "0x71a700923b0091a70090990071b21b01ac12523b0092231db01809f009", + "0xa300905400700723b00900712e00704a00976c0a300923b12e1b2009140", + "0x902e0071b500923b0090075b40070a500923b00900722900700723b009", + "0x923b0090072250070a700923b0091b50a512e0300071b500923b0091b5", + "0x1250070ac00923b0091b80096200071b800923b0090a70a912e0310070a9", + "0x23b00908f00900e0071b000923b0091b00090330071ac00923b0091ac009", + "0x61f00709000923b0090900092210071a700923b0091a700909900708f009", + "0x723b00900712e0070ac0901a708f1b01ac0110090ac00923b0090ac009", + "0x23b0090ae00961c0070ae00923b00900716c00700723b00904a009054007", + "0x330071ac00923b0091ac0091250070b000923b0091bc00961d0071bc009", + "0x23b0091a700909900708f00923b00908f00900e0071b000923b0091b0009", + "0x110090b000923b0090b000961f00709000923b0090900092210071a7009", + "0x700723b00922300915500700723b00900712e0070b00901a708f1b01ac", + "0x723b00918000915500700723b00901800915500700723b0091db009155", + "0x900903300700700923b0090070091250070b200923b009093009620007", + "0x7600923b00907600909900708f00923b00908f00900e00700900923b009", + "0x90070110090b200923b0090b200961f00709000923b009090009221007", + "0x915500700723b0091fd00915200700723b00900712e0070b209007608f", + "0x15500700723b00901800915500700723b0091db00915500700723b009223", + "0x923b0090070091250071bd00923b00907100962000700723b009168009", + "0x909900716b00923b00916b00900e00700900923b009009009033007007", + "0x923b0091bd00961f00706d00923b00906d00922100716600923b009166", + "0x91fd00915200700723b00900712e0071bd06d16616b0090070110091bd", + "0x1800915500700723b0091db00915500700723b00922300915500700723b", + "0x700700923b0090070091250070b400923b00904900962000700723b009", + "0x912500909900714500923b00914500900e00700900923b009009009033", + "0x90b400923b0090b400961f00704300923b00904300922100712500923b", + "0x923b00900765400700723b0091250093750070b4043125145009007011", + "0x900900e00700700923b0090070091250071fd00923b00900702500700e", + "0x1fd00923b0091fd00902600712e00923b00912e00922100700900923b009", + "0x1100e23b00900e1fd12e0090071fd65600700e00923b00900e009655007", + "0x723b00900712e00701f00976d01b00923b12e0180096570070182231db", + "0x1500965a00701500923b00901500965900701500923b00901b009658007", + "0x23b00900712e00702300976e02500923b12e0200090cf00702000923b009", + "0x950000722c00923b0090260094ff00702600923b0090250091a8007007", + "0x923b0091db00900e00701100923b00901100912500723c00923b00922c", + "0x1100e00923c00923b00923c00950100722300923b0092230092210071db", + "0x912500722900923b00902300950200700723b00900712e00723c2231db", + "0x923b0092230092210071db00923b0091db00900e00701100923b009011", + "0x23b00900712e0072292231db01100e00922900923b009229009501007223", + "0x900e00701100923b00901100912500702c00923b00901f009502007007", + "0x923b00902c00950100722300923b0092230092210071db00923b0091db", + "0x900743f0071fd00e12e23b00912500965b00702c2231db01100e00902c", + "0x700723b0091db00934f0072231db12e23b00901100965b00701100923b", + "0x1b01812e65c00701b00923b00922300950400701800923b0091fd009504", + "0x700900923b00900900900e00700723b00900712e00700776f00723b12e", + "0x35f00702001501f12523b00912e00912e35e00712e00923b00912e009221", + "0x902500936100700723b00900712e00702300977002500923b12e020009", + "0xe12e23b00900e00936200722c02612e23b00902600936200702600923b", + "0x900712e00703002e12e77102c22912e23b12e23c22c00712536300723c", + "0x22900912500722500923b0090074b000700723b00902c00934f00700723b", + "0x22500923b00922500943400700e00923b00900e00943400722900923b009", + "0x77203300923b12e04500935f00704503112e23b00922500e2291254b1007", + "0x3112536300703600923b00903300936100700723b00900712e007221009", + "0x934f00700723b00900712e00703b03a12e77303821912e23b12e036026", + "0x703c00923b00912600944400712600923b00900716c00700723b009038", + "0x921900912500714100923b00903e00965e00703e00923b00903c00965d", + "0x701500923b00901500922100701f00923b00901f00900e00721900923b", + "0x700723b00900712e00714101501f21900e00914100923b00914100965f", + "0x923b0090410094cf00704100923b00900716c00700723b00903b00934f", + "0x912500714800923b00904300965e00704300923b00914500965d007145", + "0x923b00901500922100701f00923b00901f00900e00703a00923b00903a", + "0x23b00900712e00714801501f03a00e00914800923b00914800965f007015", + "0x3100912500704700923b00922100966000700723b00902600934f007007", + "0x1500923b00901500922100701f00923b00901f00900e00703100923b009", + "0x723b00900712e00704701501f03100e00904700923b00904700965f007", + "0x23b00900e00934f00700723b00902600934f00700723b00903000934f007", + "0x15000965d00715000923b00904900966100704900923b00900716c007007", + "0x2e00923b00902e00912500715200923b00904c00965e00704c00923b009", + "0x15200965f00701500923b00901500922100701f00923b00901f00900e007", + "0xe00934f00700723b00900712e00715201501f02e00e00915200923b009", + "0x700700923b00900700912500715300923b00902300966000700723b009", + "0x915300965f00701500923b00901500922100701f00923b00901f00900e", + "0x900e00934f00700723b00900712e00715301501f00700e00915300923b", + "0x965d00715700923b00915500943a00715500923b00900716c00700723b", + "0x923b00900700912500705400923b00905200965e00705200923b009157", + "0x965f00712e00923b00912e00922100700900923b00900900900e007007", + "0x77412e00923b00e00700966200705412e00900700e00905400923b009054", + "0x23b00e00900966200700723b00900712e0071fd00977600e009775125009", + "0x925600700723b00900712e0070180097792230097781db009777011009", + "0x12e23b00901100925600700723b00901b00905400701f01b12e23b00912e", + "0x39d00702500923b00902001f12e66400700723b009015009054007020015", + "0x5400700723b00900712e00700777a0090070ee00702300923b009025009", + "0x702600923b00900716c00700723b00912e00905400700723b0091db009", + "0x77a0090070ee00702300923b00922c0090a500722c00923b009026009113", + "0x23b00912e00905400700723b00922300905400700723b00900712e007007", + "0x2290090a500722900923b00923c00911300723c00923b00900716c007007", + "0x1800905400700723b00900712e00700777a0090070ee00702300923b009", + "0x911300702c00923b00900716c00700723b00912e00905400700723b009", + "0x923b00902300939d00702300923b00902e0090a500702e00923b00902c", + "0x923b00e00900966200700723b00900712e00700777b0090070ee007030", + "0x22500905400700723b00900712e00703300977e04500977d03100977c225", + "0x911300722100923b00900716c00700723b00912500905400700723b009", + "0x700777f0090070ee00721900923b0090360090a500703600923b009221", + "0x23b00903800905400703a03812e23b00912500925600700723b00900712e", + "0x12e66400700723b00903b00905400712603b12e23b009031009256007007", + "0x777f0090070ee00721900923b00903c00939d00703c00923b00912603a", + "0x723b00912500905400700723b00904500905400700723b00900712e007", + "0x91410090a500714100923b00903e00911300703e00923b00900716c007", + "0x903300905400700723b00900712e00700777f0090070ee00721900923b", + "0x4100911300704100923b00900716c00700723b00912500905400700723b", + "0x3000923b00921900939d00721900923b0091450090a500714500923b009", + "0x4300923b00e00900966200700723b00900712e00700777b0090070ee007", + "0x904300905400700723b00900712e007049009782047009781148009780", + "0x15000911300715000923b00900716c00700723b00900e00905400700723b", + "0x12e0070077830090070ee00715200923b00904c0090a500704c00923b009", + "0x16c00700723b00900e00905400700723b00914800905400700723b009007", + "0x923b0091550090a500715500923b00915300911300715300923b009007", + "0x12e23b00900e00925600700723b00900712e0070077830090070ee007152", + "0x5400715905412e23b00904700925600700723b009157009054007052157", + "0x23b00905700939d00705700923b00915905212e66400700723b009054009", + "0x23b00904900905400700723b00900712e0070077830090070ee007152009", + "0x905800911300705800923b00900716c00700723b00900e009054007007", + "0x703000923b00915200939d00715200923b00905a0090a500705a00923b", + "0x78415d00923b00e00900966200700723b00900712e00700777b0090070ee", + "0x23b00915d00905400700723b00900712e00706000978615e00978505d009", + "0x915f00911300715f00923b00900716c00700723b0091fd009054007007", + "0x712e0070077870090070ee00706400923b0091600090a500716000923b", + "0x716c00700723b0091fd00905400700723b00905d00905400700723b009", + "0x6400923b0091620090a500716200923b00916100911300716100923b009", + "0x700723b00915e00905400700723b00900712e0070077870090070ee007", + "0x923b00906700911300706700923b00900716c00700723b0091fd009054", + "0x23b00900712e0070077870090070ee00706400923b0091640090a5007164", + "0x925600700723b00916600905400716816612e23b0091fd009256007007", + "0x23b00906d16812e66400700723b00916b00905400706d16b12e23b009060", + "0x900903000923b00906400939d00706400923b00906e00939d00706e009", + "0x900700912500701100923b0090070250071fd00923b009007654007030", + "0x712e00923b00912e00922100700900923b00900900900e00700700923b", + "0x900e0091a10071fd00923b0091fd00965500701100923b009011009026", + "0x701b0182231db00e23b00900e1fd01112e00900701166500700e00923b", + "0x1f00966800700723b00900712e00701500978801f00923b12e01b009666", + "0x2500923b0090200095c800702000923b0090200093b500702000923b009", + "0x943100700723b00900712e00702600978902300923b12e0250093b9007", + "0x923b00902300925000700723b00923c00937500723c22c12e23b009125", + "0x12500702e00923b00902c00966a00702c00923b00922922c12e669007229", + "0x23b00901800922100722300923b00922300900e0071db00923b0091db009", + "0x900712e00702e0182231db00e00902e00923b00902e00966b007018009", + "0x912500703000923b00902600966d00700723b00912500937500700723b", + "0x923b00901800922100722300923b00922300900e0071db00923b0091db", + "0x23b00900712e0070300182231db00e00903000923b00903000966b007018", + "0x1db00912500722500923b00901500966d00700723b009125009375007007", + "0x1800923b00901800922100722300923b00922300900e0071db00923b009", + "0x23b00900700966e0072250182231db00e00922500923b00922500966b007", + "0x43c00712e00923b00912e00943c00712500923b00900900966e00712e009", + "0xea00700e00900900e00923b00912512e12e43d00712500923b009125009", + "0x701100923b0090072290071fd00923b00900e00966f00700723b009007", + "0x92230095c200701822312e23b0091fd0095c10071db00923b009007229", + "0x5c300700900923b00900900900e00700700923b00900700912500700723b", + "0x23b0091db00915700701100923b00901100915700701800923b009018009", + "0x150095c500701501f01b12523b0091db0110180090071fd5c40071db009", + "0x12523b0090200095c600700723b00900712e00702500978a02000923b12e", + "0x722923c12e23b00902300915900700723b00922c00905400722c026023", + "0x23b00902600915900702c00923b00922900905800700723b00923c009057", + "0x10f00722500923b00903000905800700723b00902e00905700703002e12e", + "0x22500923b0092250091fd00702c00923b00902c0091fd00700723b009007", + "0x712e00703622103312578b04503112e23b12e22502c12e01f00e5c7007", + "0xe00703800923b0092190093b400721900923b00900716c00700723b009", + "0x23b0090380093b500703b00923b00904500922100703a00923b009031009", + "0x23b0090360093b700700723b00900712e00700778c0090070ee007126009", + "0x3b500703b00923b00922100922100703a00923b00903300900e00703c009", + "0x23b12e03e0093b900703e00923b0091260095c800712600923b00903c009", + "0x925000700723b0090070ea00700723b00900712e00704100978d141009", + "0x23b00904300946900704300923b00914512512e46800714500923b009141", + "0x22100703a00923b00903a00900e00701b00923b00901b009125007148009", + "0x14803b03a01b00e00914800923b00914800944d00703b00923b00903b009", + "0x700723b00912500915200700723b0090070ea00700723b00900712e007", + "0x903a00900e00701b00923b00901b00912500704700923b00904100944c", + "0x904700923b00904700944d00703b00923b00903b00922100703a00923b", + "0x44c00700723b00912500915200700723b00900712e00704703b03a01b00e", + "0x23b00901f00900e00701b00923b00901b00912500704900923b009025009", + "0xe00904900923b00904900944d00712e00923b00912e00922100701f009", + "0x71fd00923b0091250090df00700e00923b00900767000704912e01f01b", + "0x23b00912e0095a70071db00923b00900702500701100923b00900e0095f7", + "0x6290071db00923b0091db00902600700723b00901800937200701822312e", + "0x78e01f01b12e23b12e1fd0111db0090071fd60800701100923b009011009", + "0x93b400702300923b00900716c00700723b00900712e007025020015125", + "0x923b00901f00922100722c00923b00901b00900e00702600923b009023", + "0x23b00900712e00700778f0090070ee00722900923b0090260093b500723c", + "0x922100722c00923b00901500900e00702c00923b0090250093b7007007", + "0x923b0092290095c800722900923b00902c0093b500723c00923b009020", + "0x25000700723b00900712e00722500979003000923b12e02e0093b900702e", + "0x904500967200704500923b00903122312e67100703100923b009030009", + "0x723c00923b00923c00922100722c00923b00922c00900e00703300923b", + "0x37200700723b00900712e00703323c22c12500903300923b009033009673", + "0x923b00922c00900e00722100923b00922500967400700723b009223009", + "0x22c12500922100923b00922100967300723c00923b00923c00922100722c", + "0x95f70071fd00923b0091250090df00700e00923b00900767500722123c", + "0x22312e23b00912e0095770071db00923b00900702500701100923b00900e", + "0x110096290071db00923b0091db00902600700723b009018009373007018", + "0x1512579101f01b12e23b12e1fd0111db0090071fd60800701100923b009", + "0x90230093b400702300923b00900716c00700723b00900712e007025020", + "0x723c00923b00901f00922100722c00923b00901b00900e00702600923b", + "0x700723b00900712e0070077920090070ee00722900923b0090260093b5", + "0x902000922100722c00923b00901500900e00702c00923b0090250093b7", + "0x702e00923b0092290095c800722900923b00902c0093b500723c00923b", + "0x3000925000700723b00900712e00722500979303000923b12e02e0093b9", + "0x923b00904500967700704500923b00903122312e67600703100923b009", + "0x967800723c00923b00923c00922100722c00923b00922c00900e007033", + "0x22300937300700723b00900712e00703323c22c12500903300923b009033", + "0x722c00923b00922c00900e00722100923b00922500967900700723b009", + "0x22123c22c12500922100923b00922100967800723c00923b00923c009221", + "0x23b0090070250071fd00923b00900e0095f700700e00923b009007628007", + "0x2600700723b0092230093710072231db12e23b00912e0093d1007011009", + "0x110090071fd6080071fd00923b0091fd00962900701100923b009011009", + "0x16c00700723b00900712e00702001501f12579401b01812e23b12e1251fd", + "0x923b00901800900e00702300923b0090250093b400702500923b009007", + "0x70ee00723c00923b0090230093b500722c00923b00901b009221007026", + "0x900e00722900923b0090200093b700700723b00900712e007007795009", + "0x923b0092290093b500722c00923b00901500922100702600923b00901f", + "0x3000979602e00923b12e02c0093b900702c00923b00923c0095c800723c", + "0x92251db12e67a00722500923b00902e00925000700723b00900712e007", + "0x702600923b00902600900e00704500923b00903100967b00703100923b", + "0x4522c02612500904500923b00904500967c00722c00923b00922c009221", + "0x923b00903000967d00700723b0091db00937100700723b00900712e007", + "0x967c00722c00923b00922c00922100702600923b00902600900e007033", + "0xe00946000700723b0090070ea00703322c02612500903300923b009033", + "0x701100923b0090072290071fd00923b00900e00967e00700e00923b009", + "0x92230095c200701822312e23b0091fd0095c10071db00923b009007229", + "0x5c300700900923b00900900900e00700700923b00900700912500700723b", + "0x23b0091db00915700701100923b00901100915700701800923b009018009", + "0x150095c500701501f01b12523b0091db0110180090071fd5c40071db009", + "0x12523b0090200095c600700723b00900712e00702500979702000923b12e", + "0x722923c12e23b00902300915900700723b00922c00905400722c026023", + "0x23b00902600915900702c00923b00922900905800700723b00923c009057", + "0x10f00722500923b00903000905800700723b00902e00905700703002e12e", + "0x22500923b0092250091fd00702c00923b00902c0091fd00700723b009007", + "0x712e00703622103312579804503112e23b12e22502c12e01f00e5c7007", + "0xe00703800923b0092190093b400721900923b00900716c00700723b009", + "0x23b0090380093b500703b00923b00904500922100703a00923b009031009", + "0x23b0090360093b700700723b00900712e0070077990090070ee007126009", + "0x3b500703b00923b00922100922100703a00923b00903300900e00703c009", + "0x23b12e03e0093b900703e00923b0091260095c800712600923b00903c009", + "0x925000700723b0090070ea00700723b00900712e00704100979a141009", + "0x23b00904300946900704300923b00914512512e46800714500923b009141", + "0x22100703a00923b00903a00900e00701b00923b00901b009125007148009", + "0x14803b03a01b00e00914800923b00914800944d00703b00923b00903b009", + "0x700723b00912500915200700723b0090070ea00700723b00900712e007", + "0x903a00900e00701b00923b00901b00912500704700923b00904100944c", + "0x904700923b00904700944d00703b00923b00903b00922100703a00923b", + "0x44c00700723b00912500915200700723b00900712e00704703b03a01b00e", + "0x23b00901f00900e00701b00923b00901b00912500704900923b009025009", + "0xe00904900923b00904900944d00712e00923b00912e00922100701f009", + "0x67f00700e00923b00900e00946400700723b0090070ea00704912e01f01b", + "0x1db00923b00900722900701100923b0090072290071fd00923b00900e009", + "0x700912500700723b0092230095c200701822312e23b0091fd0095c1007", + "0x1800923b0090180095c300700900923b00900900900e00700700923b009", + "0x71fd5c40071db00923b0091db00915700701100923b009011009157007", + "0x979b02000923b12e0150095c500701501f01b12523b0091db011018009", + "0x905400722c02602312523b0090200095c600700723b00900712e007025", + "0x723b00923c00905700722923c12e23b00902300915900700723b00922c", + "0x905700703002e12e23b00902600915900702c00923b009229009058007", + "0x1fd00700723b00900710f00722500923b00903000905800700723b00902e", + "0x2c12e01f00e5c700722500923b0092250091fd00702c00923b00902c009", + "0x716c00700723b00900712e00703622103312579c04503112e23b12e225", + "0x3a00923b00903100900e00703800923b0092190093b400721900923b009", + "0x90070ee00712600923b0090380093b500703b00923b009045009221007", + "0x3300900e00703c00923b0090360093b700700723b00900712e00700779d", + "0x12600923b00903c0093b500703b00923b00922100922100703a00923b009", + "0x704100979e14100923b12e03e0093b900703e00923b0091260095c8007", + "0x714500923b00914100925000700723b0090070ea00700723b00900712e", + "0x1b00912500714800923b00904300946900704300923b00914512512e468", + "0x3b00923b00903b00922100703a00923b00903a00900e00701b00923b009", + "0x723b00900712e00714803b03a01b00e00914800923b00914800944d007", + "0x923b00904100944c00700723b00912500915200700723b0090070ea007", + "0x922100703a00923b00903a00900e00701b00923b00901b009125007047", + "0x704703b03a01b00e00904700923b00904700944d00703b00923b00903b", + "0x4900923b00902500944c00700723b00912500915200700723b00900712e", + "0x12e00922100701f00923b00901f00900e00701b00923b00901b009125007", + "0x62f00704912e01f01b00e00904900923b00904900944d00712e00923b009", + "0x1100923b0090070250071fd00923b00900e0095f700700e00923b009007", + "0x1100902600700723b0092230093770072231db12e23b00912e0093d9007", + "0x1251fd0110090071fd6080071fd00923b0091fd00962900701100923b009", + "0x900716c00700723b00900712e00702001501f12579f01b01812e23b12e", + "0x702600923b00901800900e00702300923b0090250093b400702500923b", + "0x7a00090070ee00723c00923b0090230093b500722c00923b00901b009221", + "0x901f00900e00722900923b0090200093b700700723b00900712e007007", + "0x723c00923b0092290093b500722c00923b00901500922100702600923b", + "0x12e0070300097a102e00923b12e02c0093b900702c00923b00923c0095c8", + "0x923b0092251db12e68000722500923b00902e00925000700723b009007", + "0x922100702600923b00902600900e00704500923b009031009681007031", + "0x12e00704522c02612500904500923b00904500968200722c00923b00922c", + "0x703300923b00903000968400700723b0091db00937700700723b009007", + "0x903300968200722c00923b00922c00922100702600923b00902600900e", + "0x23b00900e00948100700723b0090070ea00703322c02612500903300923b", + "0x722900701100923b0090072290071fd00923b00900e00968500700e009", + "0x723b0092230095c200701822312e23b0091fd0095c10071db00923b009", + "0x180095c300700900923b00900900900e00700700923b009007009125007", + "0x1db00923b0091db00915700701100923b00901100915700701800923b009", + "0x23b12e0150095c500701501f01b12523b0091db0110180090071fd5c4007", + "0x2602312523b0090200095c600700723b00900712e0070250097a2020009", + "0x905700722923c12e23b00902300915900700723b00922c00905400722c", + "0x2e12e23b00902600915900702c00923b00922900905800700723b00923c", + "0x900710f00722500923b00903000905800700723b00902e009057007030", + "0x5c700722500923b0092250091fd00702c00923b00902c0091fd00700723b", + "0x23b00900712e0070362210331257a304503112e23b12e22502c12e01f00e", + "0x3100900e00703800923b0092190093b400721900923b00900716c007007", + "0x12600923b0090380093b500703b00923b00904500922100703a00923b009", + "0x3c00923b0090360093b700700723b00900712e0070077a40090070ee007", + "0x3c0093b500703b00923b00922100922100703a00923b00903300900e007", + "0x14100923b12e03e0093b900703e00923b0091260095c800712600923b009", + "0x914100925000700723b0090070ea00700723b00900712e0070410097a5", + "0x14800923b00904300946900704300923b00914512512e46800714500923b", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00714803b03a01b00e00914800923b00914800944d00703b00923b009", + "0x944c00700723b00912500915200700723b0090070ea00700723b009007", + "0x923b00903a00900e00701b00923b00901b00912500704700923b009041", + "0x1b00e00904700923b00904700944d00703b00923b00903b00922100703a", + "0x2500944c00700723b00912500915200700723b00900712e00704703b03a", + "0x1f00923b00901f00900e00701b00923b00901b00912500704900923b009", + "0x1f01b00e00904900923b00904900944d00712e00923b00912e009221007", + "0x70250071fd00923b00900e0095f700700e00923b00900763000704912e", + "0x723b0092230093760072231db12e23b00912e0093dd00701100923b009", + "0x71fd6080071fd00923b0091fd00962900701100923b009011009026007", + "0x723b00900712e00702001501f1257a601b01812e23b12e1251fd011009", + "0x901800900e00702300923b0090250093b400702500923b00900716c007", + "0x723c00923b0090230093b500722c00923b00901b00922100702600923b", + "0x722900923b0090200093b700700723b00900712e0070077a70090070ee", + "0x92290093b500722c00923b00901500922100702600923b00901f00900e", + "0x7a802e00923b12e02c0093b900702c00923b00923c0095c800723c00923b", + "0x1db12e68600722500923b00902e00925000700723b00900712e007030009", + "0x923b00902600900e00704500923b00903100968700703100923b009225", + "0x2612500904500923b00904500968800722c00923b00922c009221007026", + "0x903000968900700723b0091db00937600700723b00900712e00704522c", + "0x722c00923b00922c00922100702600923b00902600900e00703300923b", + "0x49b00700723b0090070ea00703322c02612500903300923b009033009688", + "0x923b0090072290071fd00923b00900e00968a00700e00923b00900e009", + "0x95c200701822312e23b0091fd0095c10071db00923b009007229007011", + "0x900923b00900900900e00700700923b00900700912500700723b009223", + "0x1db00915700701100923b00901100915700701800923b0090180095c3007", + "0x5c500701501f01b12523b0091db0110180090071fd5c40071db00923b009", + "0x90200095c600700723b00900712e0070250097a902000923b12e015009", + "0x23c12e23b00902300915900700723b00922c00905400722c02602312523b", + "0x2600915900702c00923b00922900905800700723b00923c009057007229", + "0x22500923b00903000905800700723b00902e00905700703002e12e23b009", + "0x23b0092250091fd00702c00923b00902c0091fd00700723b00900710f007", + "0x70362210331257aa04503112e23b12e22502c12e01f00e5c7007225009", + "0x3800923b0092190093b400721900923b00900716c00700723b00900712e", + "0x380093b500703b00923b00904500922100703a00923b00903100900e007", + "0x360093b700700723b00900712e0070077ab0090070ee00712600923b009", + "0x3b00923b00922100922100703a00923b00903300900e00703c00923b009", + "0x3e0093b900703e00923b0091260095c800712600923b00903c0093b5007", + "0x700723b0090070ea00700723b00900712e0070410097ac14100923b12e", + "0x4300946900704300923b00914512512e46800714500923b009141009250", + "0x3a00923b00903a00900e00701b00923b00901b00912500714800923b009", + "0x3a01b00e00914800923b00914800944d00703b00923b00903b009221007", + "0x23b00912500915200700723b0090070ea00700723b00900712e00714803b", + "0x900e00701b00923b00901b00912500704700923b00904100944c007007", + "0x923b00904700944d00703b00923b00903b00922100703a00923b00903a", + "0x723b00912500915200700723b00900712e00704703b03a01b00e009047", + "0x1f00900e00701b00923b00901b00912500704900923b00902500944c007", + "0x4900923b00904900944d00712e00923b00912e00922100701f00923b009", + "0x1fd12e7ad00e12512e23b12e12e00900712568b00704912e01f01b00e009", + "0x91250091250071db00923b00900e00968c00700723b00900712e007011", + "0x712e0070077ae0090070ee00701800923b0091db00968d00722300923b", + "0x722300923b0091fd00912500701b00923b00901100968e00700723b009", + "0x23b00901f00902e00701f00923b00900768f00701800923b00901b00968d", + "0x7af02000923b12e01500935f00701500923b00901f01812e69000701f009", + "0x230095f300702300923b00902000936100700723b00900712e007025009", + "0x22300923b00922300912500722c00923b0090260095f400702600923b009", + "0x5f500700723b00900712e00722c22312e00922c00923b00922c00924d007", + "0x23b00923c00924d00722300923b00922300912500723c00923b009025009", + "0xe00923b00900e0094b500700723b0090070ea00723c22312e00923c009", + "0x23b00900722900701100923b0090072290071fd00923b00900e009258007", + "0x12500700723b0092230095c200701822312e23b0091fd0095c10071db009", + "0x23b0090180095c300700900923b00900900900e00700700923b009007009", + "0x5c40071db00923b0091db00915700701100923b009011009157007018009", + "0x2000923b12e0150095c500701501f01b12523b0091db0110180090071fd", + "0x722c02602312523b0090200095c600700723b00900712e0070250097b0", + "0x923c00905700722923c12e23b00902300915900700723b00922c009054", + "0x703002e12e23b00902600915900702c00923b00922900905800700723b", + "0x723b00900710f00722500923b00903000905800700723b00902e009057", + "0x1f00e5c700722500923b0092250091fd00702c00923b00902c0091fd007", + "0x700723b00900712e0070362210331257b104503112e23b12e22502c12e", + "0x23b00903100900e00703800923b0092190093b400721900923b00900716c", + "0xee00712600923b0090380093b500703b00923b00904500922100703a009", + "0xe00703c00923b0090360093b700700723b00900712e0070077b2009007", + "0x23b00903c0093b500703b00923b00922100922100703a00923b009033009", + "0x97b314100923b12e03e0093b900703e00923b0091260095c8007126009", + "0x923b00914100925000700723b0090070ea00700723b00900712e007041", + "0x12500714800923b00904300946900704300923b00914512512e468007145", + "0x23b00903b00922100703a00923b00903a00900e00701b00923b00901b009", + "0x900712e00714803b03a01b00e00914800923b00914800944d00703b009", + "0x904100944c00700723b00912500915200700723b0090070ea00700723b", + "0x703a00923b00903a00900e00701b00923b00901b00912500704700923b", + "0x3b03a01b00e00904700923b00904700944d00703b00923b00903b009221", + "0x23b00902500944c00700723b00912500915200700723b00900712e007047", + "0x22100701f00923b00901f00900e00701b00923b00901b009125007049009", + "0x4912e01f01b00e00904900923b00904900944d00712e00923b00912e009", + "0x23b00900e00969300700e00923b00900e0094c700700723b0090070ea007", + "0x1fd0095c10071db00923b00900722900701100923b0090072290071fd009", + "0x700923b00900700912500700723b0092230095c200701822312e23b009", + "0x1100915700701800923b0090180095c300700900923b00900900900e007", + "0x1db0110180090071fd5c40071db00923b0091db00915700701100923b009", + "0x712e0070250097b402000923b12e0150095c500701501f01b12523b009", + "0x723b00922c00905400722c02602312523b0090200095c600700723b009", + "0x22900905800700723b00923c00905700722923c12e23b009023009159007", + "0x723b00902e00905700703002e12e23b00902600915900702c00923b009", + "0x23b00902c0091fd00700723b00900710f00722500923b009030009058007", + "0x12e23b12e22502c12e01f00e5c700722500923b0092250091fd00702c009", + "0x21900923b00900716c00700723b00900712e0070362210331257b5045031", + "0x4500922100703a00923b00903100900e00703800923b0092190093b4007", + "0x12e0070077b60090070ee00712600923b0090380093b500703b00923b009", + "0x3a00923b00903300900e00703c00923b0090360093b700700723b009007", + "0x1260095c800712600923b00903c0093b500703b00923b009221009221007", + "0x23b00900712e0070410097b714100923b12e03e0093b900703e00923b009", + "0x14512512e46800714500923b00914100925000700723b0090070ea007007", + "0x1b00923b00901b00912500714800923b00904300946900704300923b009", + "0x14800944d00703b00923b00903b00922100703a00923b00903a00900e007", + "0x90070ea00700723b00900712e00714803b03a01b00e00914800923b009", + "0x912500704700923b00904100944c00700723b00912500915200700723b", + "0x923b00903b00922100703a00923b00903a00900e00701b00923b00901b", + "0x23b00900712e00704703b03a01b00e00904700923b00904700944d00703b", + "0x1b00912500704900923b00902500944c00700723b009125009152007007", + "0x12e00923b00912e00922100701f00923b00901f00900e00701b00923b009", + "0x723b0090070ea00704912e01f01b00e00904900923b00904900944d007", + "0x90072290071fd00923b00900e00969400700e00923b00900e0094d7007", + "0x701822312e23b0091fd0095c10071db00923b00900722900701100923b", + "0x23b00900900900e00700700923b00900700912500700723b0092230095c2", + "0x15700701100923b00901100915700701800923b0090180095c3007009009", + "0x1501f01b12523b0091db0110180090071fd5c40071db00923b0091db009", + "0x95c600700723b00900712e0070250097b802000923b12e0150095c5007", + "0x23b00902300915900700723b00922c00905400722c02602312523b009020", + "0x15900702c00923b00922900905800700723b00923c00905700722923c12e", + "0x23b00903000905800700723b00902e00905700703002e12e23b009026009", + "0x2250091fd00702c00923b00902c0091fd00700723b00900710f007225009", + "0x2210331257b904503112e23b12e22502c12e01f00e5c700722500923b009", + "0x23b0092190093b400721900923b00900716c00700723b00900712e007036", + "0x3b500703b00923b00904500922100703a00923b00903100900e007038009", + "0x3b700700723b00900712e0070077ba0090070ee00712600923b009038009", + "0x23b00922100922100703a00923b00903300900e00703c00923b009036009", + "0x3b900703e00923b0091260095c800712600923b00903c0093b500703b009", + "0x23b0090070ea00700723b00900712e0070410097bb14100923b12e03e009", + "0x46900704300923b00914512512e46800714500923b009141009250007007", + "0x23b00903a00900e00701b00923b00901b00912500714800923b009043009", + "0xe00914800923b00914800944d00703b00923b00903b00922100703a009", + "0x12500915200700723b0090070ea00700723b00900712e00714803b03a01b", + "0x701b00923b00901b00912500704700923b00904100944c00700723b009", + "0x904700944d00703b00923b00903b00922100703a00923b00903a00900e", + "0x912500915200700723b00900712e00704703b03a01b00e00904700923b", + "0xe00701b00923b00901b00912500704900923b00902500944c00700723b", + "0x23b00904900944d00712e00923b00912e00922100701f00923b00901f009", + "0x23b00900e0094e700700723b0090070ea00704912e01f01b00e009049009", + "0x722900701100923b0090072290071fd00923b00900e00969500700e009", + "0x723b0092230095c200701822312e23b0091fd0095c10071db00923b009", + "0x180095c300700900923b00900900900e00700700923b009007009125007", + "0x1db00923b0091db00915700701100923b00901100915700701800923b009", + "0x23b12e0150095c500701501f01b12523b0091db0110180090071fd5c4007", + "0x2602312523b0090200095c600700723b00900712e0070250097bc020009", + "0x905700722923c12e23b00902300915900700723b00922c00905400722c", + "0x2e12e23b00902600915900702c00923b00922900905800700723b00923c", + "0x900710f00722500923b00903000905800700723b00902e009057007030", + "0x5c700722500923b0092250091fd00702c00923b00902c0091fd00700723b", + "0x23b00900712e0070362210331257bd04503112e23b12e22502c12e01f00e", + "0x3100900e00703800923b0092190093b400721900923b00900716c007007", + "0x12600923b0090380093b500703b00923b00904500922100703a00923b009", + "0x3c00923b0090360093b700700723b00900712e0070077be0090070ee007", + "0x3c0093b500703b00923b00922100922100703a00923b00903300900e007", + "0x14100923b12e03e0093b900703e00923b0091260095c800712600923b009", + "0x914100925000700723b0090070ea00700723b00900712e0070410097bf", + "0x14800923b00904300946900704300923b00914512512e46800714500923b", + "0x3b00922100703a00923b00903a00900e00701b00923b00901b009125007", + "0x12e00714803b03a01b00e00914800923b00914800944d00703b00923b009", + "0x944c00700723b00912500915200700723b0090070ea00700723b009007", + "0x923b00903a00900e00701b00923b00901b00912500704700923b009041", + "0x1b00e00904700923b00904700944d00703b00923b00903b00922100703a", + "0x2500944c00700723b00912500915200700723b00900712e00704703b03a", + "0x1f00923b00901f00900e00701b00923b00901b00912500704900923b009", + "0x1f01b00e00904900923b00904900944d00712e00923b00912e009221007", + "0xe0095f700700e00923b00900767500700723b00912500937300704912e", + "0x701100923b00901100902600701100923b0090070250071fd00923b009", + "0x182231db12523b12e1fd01112e00900e5f80071fd00923b0091fd009629", + "0x700700923b00900700912500700723b00900712e00701501f01b1257c0", + "0x900e00702502012e23b00901800712e69600701800923b00901800902e", + "0x923b12e02500969700722300923b0092230092210071db00923b0091db", + "0x12500722c00923b00902300969800700723b00900712e0070260097c1023", + "0x23b00922300922100722900923b0091db00900e00723c00923b009020009", + "0x900712e0070077c20090070ee00702e00923b00922c00969900702c009", + "0x900725700703000923b00900722900700723b00902600905400700723b", + "0x3100923b00922503012e03000722500923b00922500902e00722500923b", + "0x3300951400703300923b00903104512e03100704500923b009007225007", + "0x1db00923b0091db00900e00702000923b00902000912500722100923b009", + "0x1db02000e00922100923b00922100951300722300923b009223009221007", + "0x700912500703600923b00901500969b00700723b00900712e007221223", + "0x2c00923b00901f00922100722900923b00901b00900e00723c00923b009", + "0x2190090dd00721900923b00902e00969c00702e00923b009036009699007", + "0x923b00903800918e00700723b00900712e00703a0097c303800923b12e", + "0x912500703c00923b00912600951200712600923b00903b00951100703b", + "0x923b00902c00922100722900923b00922900900e00723c00923b00923c", + "0x23b00900712e00703c02c22923c00e00903c00923b00903c00951300702c", + "0x900e00723c00923b00923c00912500703e00923b00903a009514007007", + "0x923b00903e00951300702c00923b00902c00922100722900923b009229", + "0x923b00900767000700723b00912500937200703e02c22923c00e00903e", + "0x1100902600701100923b0090070250071fd00923b00900e0095f700700e", + "0x12e1fd01112e00900e5f80071fd00923b0091fd00962900701100923b009", + "0x700912500700723b00900712e00701501f01b1257c40182231db12523b", + "0x12e23b00901800712e69600701800923b00901800902e00700700923b009", + "0x69700722300923b0092230092210071db00923b0091db00900e007025020", + "0x902300969800700723b00900712e0070260097c502300923b12e025009", + "0x722900923b0091db00900e00723c00923b00902000912500722c00923b", + "0x7c60090070ee00702e00923b00922c00969900702c00923b009223009221", + "0x923b00900722900700723b00902600905400700723b00900712e007007", + "0x3012e03000722500923b00922500902e00722500923b009007257007030", + "0x923b00903104512e03100704500923b00900722500703100923b009225", + "0x900e00702000923b00902000912500722100923b009033009514007033", + "0x923b00922100951300722300923b0092230092210071db00923b0091db", + "0x923b00901500969b00700723b00900712e0072212231db02000e009221", + "0x922100722900923b00901b00900e00723c00923b009007009125007036", + "0x923b00902e00969c00702e00923b00903600969900702c00923b00901f", + "0x18e00700723b00900712e00703a0097c703800923b12e2190090dd007219", + "0x23b00912600951200712600923b00903b00951100703b00923b009038009", + "0x22100722900923b00922900900e00723c00923b00923c00912500703c009", + "0x3c02c22923c00e00903c00923b00903c00951300702c00923b00902c009", + "0x23b00923c00912500703e00923b00903a00951400700723b00900712e007", + "0x51300702c00923b00902c00922100722900923b00922900900e00723c009", + "0x12e00923b00e00700966200703e02c22923c00e00903e00923b00903e009", + "0x23b00900714c00700723b00900712e0071fd0097ca00e0097c91250097c8", + "0x2e00700723b0091db0091550072231db12e23b009011009153007011009", + "0x900922312e05200700900923b00900900915700722300923b009223009", + "0x701800923b00901800915700700723b00901b00905400701b01812e23b", + "0x1f00969e00700723b00901500905400701501f12e23b00901812e12e69d", + "0x900714300700723b00900712e0070077cb0090070ee00702000923b009", + "0x700723b00902300915500702602312e23b00902500915300702500923b", + "0x902612e05200700900923b00900900915700702600923b00902600902e", + "0x22c00923b00922c00915700700723b00923c00905400723c22c12e23b009", + "0x969e00700723b00902c00905400702c22912e23b00922c12512e69d007", + "0x740b00700723b00900712e0070077cb0090070ee00702000923b009229", + "0x723b00903000915500722503012e23b00902e00915300702e00923b009", + "0x22512e05200700900923b00900900915700722500923b00922500902e007", + "0x923b00903100915700700723b00904500905400704503112e23b009009", + "0x69e00700723b00922100905400722103312e23b00903100e12e69d007031", + "0x14b00700723b00900712e0070077cb0090070ee00702000923b009033009", + "0x23b00921900915500703821912e23b00903600915300703600923b009007", + "0x12e05200700900923b00900900915700703800923b00903800902e007007", + "0x23b00903a00915700700723b00903b00905400703b03a12e23b009009038", + "0x700723b00903c00905400703c12612e23b00903a1fd12e69d00703a009", + "0xea00703e02012e00903e00923b00900716c00702000923b00912600969e", + "0x1fd00923b00900e00969f00700e00923b00900e00953d00700723b009007", + "0x23b0091fd0095c10071db00923b00900722900701100923b009007229007", + "0xe00700700923b00900700912500700723b0092230095c200701822312e", + "0x23b00901100915700701800923b0090180095c300700900923b009009009", + "0x23b0091db0110180090071fd5c40071db00923b0091db009157007011009", + "0x23b00900712e0070250097cc02000923b12e0150095c500701501f01b125", + "0x15900700723b00922c00905400722c02602312523b0090200095c6007007", + "0x23b00922900905800700723b00923c00905700722923c12e23b009023009", + "0x5800700723b00902e00905700703002e12e23b00902600915900702c009", + "0x2c00923b00902c0091fd00700723b00900710f00722500923b009030009", + "0x4503112e23b12e22502c12e01f00e5c700722500923b0092250091fd007", + "0x3b400721900923b00900716c00700723b00900712e0070362210331257cd", + "0x23b00904500922100703a00923b00903100900e00703800923b009219009", + "0x900712e0070077ce0090070ee00712600923b0090380093b500703b009", + "0x22100703a00923b00903300900e00703c00923b0090360093b700700723b", + "0x23b0091260095c800712600923b00903c0093b500703b00923b009221009", + "0x700723b00900712e0070410097cf14100923b12e03e0093b900703e009", + "0x23b00914512512e46800714500923b00914100925000700723b0090070ea", + "0xe00701b00923b00901b00912500714800923b009043009469007043009", + "0x23b00914800944d00703b00923b00903b00922100703a00923b00903a009", + "0x723b0090070ea00700723b00900712e00714803b03a01b00e009148009", + "0x901b00912500704700923b00904100944c00700723b009125009152007", + "0x703b00923b00903b00922100703a00923b00903a00900e00701b00923b", + "0x700723b00900712e00704703b03a01b00e00904700923b00904700944d", + "0x23b00901b00912500704900923b00902500944c00700723b009125009152", + "0x44d00712e00923b00912e00922100701f00923b00901f00900e00701b009", + "0x700e00923b00900707100704912e01f01b00e00904900923b009049009", + "0x12500700723b0090070ea00700723b00900716000701100923b009007334", + "0x912e00712e33500712e00923b00912e0091fd00700700923b009007009", + "0x900712e00701b0097d01fd00923b12e0180093360070182231db12523b", + "0x701501f12e23b00922300916e00722300923b0092230091fd00700723b", + "0x70200097d112500923b12e0150090720071fd00923b0091fd01112e338", + "0x923b00900900900e0071db00923b0091db00912500700723b00900712e", + "0x17400712500923b00912500e12e07400701f00923b00901f0091fd007009", + "0x97d222c00923b12e02600907600702602302512523b00901f0091db125", + "0x2c00907700702c22912e23b00922c00918000700723b00900712e00723c", + "0x902e1251fd1256a000700723b00900712e0070300097d302e00923b12e", + "0x4500923b00903122912e6a200703100923b0092250096a100722500923b", + "0x2300900e00702500923b00902500912500703300923b0090450096a3007", + "0x712e00703302302512500903300923b0090330096a500702300923b009", + "0x96a600700723b00912500915500700723b0091fd00910100700723b009", + "0x23b0090360096a300703600923b00922122912e6a200722100923b009030", + "0x6a500702300923b00902300900e00702500923b009025009125007219009", + "0x915500700723b00900712e00721902302512500921900923b009219009", + "0x703800923b00923c0096a700700723b0091fd00910100700723b009125", + "0x90380096a500702300923b00902300900e00702500923b009025009125", + "0x23b0091fd00910100700723b00900712e00703802302512500903800923b", + "0x1f12e6a200703a00923b0090200096a600700723b00900e00907f007007", + "0x923b0091db00912500712600923b00903b0096a300703b00923b00903a", + "0x1db12500912600923b0091260096a500700900923b00900900900e0071db", + "0x901100935500700723b00900e00907f00700723b00900712e007126009", + "0x703e00923b00903c22312e6a200703c00923b00901b0096a600700723b", + "0x900900900e0071db00923b0091db00912500714100923b00903e0096a3", + "0x712e6a80071410091db12500914100923b0091410096a500700900923b", + "0x6aa00700723b00900712e0071db0111fd1257d400e12512e12523b12e009", + "0x23b00912500922100701800923b00912e00900e00722300923b00900e009", + "0x900712e0070077d50090070ee00701f00923b00922300925500701b009", + "0x22100701800923b0091fd00900e00701500923b0091db0096ab00700723b", + "0x23b00901f0096ac00701f00923b00901500925500701b00923b009011009", + "0x700723b00900712e0070230097d602500923b12e02000954e007020009", + "0x922c0096ae00722c00923b0090260096ad00702600923b009025009550", + "0x701b00923b00901b00922100701800923b00901800900e00723c00923b", + "0x6b000700723b00900712e00723c01b01812500923c00923b00923c0096af", + "0x23b00901b00922100701800923b00901800900e00722900923b009023009", + "0x90071256b100722901b01812500922900923b0092290096af00701b009", + "0x900e0096b200700723b00900712e0071fd0097d700e12512e23b12e12e", + "0x712500923b0091250091250071db00923b0090110096b300701100923b", + "0x722900700723b00900712e0071db12512e0091db00923b0091db0096b4", + "0x701800923b00901800902e00701800923b0090076b500722300923b009", + "0x1b01f12e03100701f00923b00900722500701b00923b00901822312e030", + "0x1fd00923b0091fd00912500702000923b0090150096b600701500923b009", + "0x71fd00923b00900715f0070201fd12e00902000923b0090200096b4007", + "0x700900923b00900900900e00700723b0090070ea00700723b009007160", + "0x1620071db00e01112523b00912e00912e14d00712e00923b00912e009221", + "0x12e0070180097d822300923b12e1db00914e00700e00923b00900e1fd12e", + "0x1f00923b00901b00910a00701b00923b00922300914900700723b009007", + "0x3122503002e02c22923c22c02602302502001502023b00901f00910c007", + "0x23b00902600915500700723b00902300915e00700723b009020009101007", + "0x902e00915e00700723b00923c00915500700723b00922c009155007007", + "0x15300722100923b00900714b00703304512e23b00901500915300700723b", + "0x23b00903300916300700723b00903600915500721903612e23b009221009", + "0x14f00703800923b00903800902e00703a00923b009219009163007038009", + "0x923b00903b00902e00700723b00900710f00703b00923b00903a03812e", + "0x96b700722900923b0092290096b800702500923b0090250096b700703b", + "0x923b00922500902600703000923b00903000902600702c00923b00902c", + "0x910600704500923b00904500902e00703100923b0090310091fd007225", + "0x3c00923b00900716c00700723b00900712e0071260097d900723b12e03b", + "0x3e0090a500714100923b00904500902e00703e00923b00903c009144007", + "0x12600911100700723b00900712e0070077da0090070ee00704100923b009", + "0x714800923b00900711800704314512e23b00904500915300700723b009", + "0x904300916300700723b00904700915500704904712e23b009148009153", + "0x15200923b00904c15012e14f00704c00923b00904900916300715000923b", + "0x12e0071530097db00723b12e15200910600715200923b00915200902e007", + "0x715700923b00915500914400715500923b00900716c00700723b009007", + "0x700723b00900712e0070077dc0090070ee00705200923b0091570090a5", + "0x923b00905400911300705400923b00900716c00700723b009153009111", + "0x90a500714100923b00914500902e00705200923b0091590090a5007159", + "0x900712e0070580097dd05700923b12e04100914000704100923b009052", + "0x22900914600700723b00902c00914700700723b00905700905400700723b", + "0x902000700723b00922500902000700723b00903100915e00700723b009", + "0x5d00923b00900714300715d05a12e23b00914100915300700723b009030", + "0x15d00916300700723b00915e00915500706015e12e23b00905d009153007", + "0x923b00916015f12e14f00716000923b00906000916300715f00923b009", + "0x71610097de00723b12e06400910600706400923b00906400902e007064", + "0x12e0070077df0090070ee00700723b00905a00915500700723b00900712e", + "0x6716212e23b00905a00915300700723b00916100911100700723b009007", + "0x23b00916400915300716400923b00900711500700723b009162009155007", + "0x16300716b00923b00906700916300700723b00916600915500716816612e", + "0x906e00902e00706e00923b00906d16b12e14f00706d00923b009168009", + "0x700723b00900712e00706f0097e000723b12e06e00910600706e00923b", + "0x2507100712525400707100923b0090710096b700707100923b0090076ba", + "0x23b0090070ea00700723b00900712e00717407412e7e107216e12e23b12e", + "0x1100900e00707600923b00916e00912500700723b009072009147007007", + "0x90070ea00700723b00900712e0070077e20090070ee00718000923b009", + "0x900722900700723b00912500902000700723b00917400914700700723b", + "0x3000707800923b00907800902e00707800923b0090076bb00707700923b", + "0x918607b12e03100707b00923b00900722500718600923b00907807712e", + "0x707400923b00907400912500708d00923b00918700962000718700923b", + "0x908d00961f00700e00923b00900e00922100701100923b00901100900e", + "0x23b0090070ea00700723b00900712e00708d00e01107400e00908d00923b", + "0x902500914700700723b00912500902000700723b00906f009111007007", + "0x8e00902e00708e00923b00900713b00707f00923b00900722900700723b", + "0x9000923b00900722500708f00923b00908e07f12e03000708e00923b009", + "0x912500709200923b00909100962000709100923b00908f09012e031007", + "0x923b00900e00922100701100923b00901100900e00700700923b009007", + "0x23b00900712e00709200e01100700e00909200923b00909200961f00700e", + "0x914100915500700723b00902500914700700723b009058009054007007", + "0x2500700723b00909300902000709409312e23b00903000901500700723b", + "0x23b00909600902000709709612e23b00909500901500709500923b009007", + "0x12e22c00709900923b00909700902300709800923b009094009023007007", + "0x723b00912500902000700723b00900712e0070077e300723b12e099098", + "0x23b00903100915e00700723b00922900914600700723b00902c009147007", + "0x723b00900712e0070077e40090070ee00700723b009225009020007007", + "0x900702500700723b0091a500902000709c1a512e23b009225009015007", + "0x700723b00903700902000705b03712e23b0091a70090150071a700923b", + "0x1ac09f12e22c0071ac00923b00905b00902300709f00923b00909c009023", + "0x14700700723b00912500902000700723b00900712e0070077e500723b12e", + "0x700723b00903100915e00700723b00922900914600700723b00902c009", + "0x71b200923b0090076bd0071b000923b00900722900700723b0090070ea", + "0x90072250070a300923b0091b21b012e0300071b200923b0091b200902e", + "0x1b500923b0090a50096200070a500923b0090a304a12e03100704a00923b", + "0xe00922100701100923b00901100900e00700700923b009007009125007", + "0x12e0071b500e01100700e0091b500923b0091b500961f00700e00923b009", + "0xa900923b0090a700901f0070a700923b00903100901b00700723b009007", + "0x900702500700723b0091b80090200070ac1b812e23b0090a9009015007", + "0x700723b0091bc0090200070b01bc12e23b0090ae0090150070ae00923b", + "0x90b20090260071bd00923b0090b00090230070b200923b0090ac009023", + "0x700723b00900712e0070077e600723b12e1bd0b212e22c0070b200923b", + "0x700723b00902c00914700700723b00912500902000700723b0090070ea", + "0xb600923b0090076be0070b400923b00900722900700723b009229009146", + "0x72250071bb00923b0090b60b412e0300070b600923b0090b600902e007", + "0x923b0090ba0096200070ba00923b0091bb0b812e0310070b800923b009", + "0x922100701100923b00901100900e00700700923b0090070091250071ba", + "0x71ba00e01100700e0091ba00923b0091ba00961f00700e00923b00900e", + "0x6bf0070bc00923b0090076bf00700723b0090070ea00700723b00900712e", + "0x923b00901100900e00700700923b0090070091250070be00923b009007", + "0x96b70070be00923b0090be0096b700722900923b0092290096b8007011", + "0xbe2290110070116c000702c00923b00902c0096b70070bc00923b0090bc", + "0x70c40097e71b600923b12e0c20096c10070c20c01b912523b00902c0bc", + "0xc60091460071b70c71b30c600e23b0091b60096c200700723b00900712e", + "0x6b70071b900923b0091b900912500700723b0091b700905400700723b009", + "0x90c90096b70070c90c712e23b0090c70092530071b300923b0091b3009", + "0x23b12e0cb0096c40070cb1ad12e23b0090c91b31b91256c30070c900923b", + "0x6b70070cf00923b0090076c500700723b00900712e0071aa0097e80cd009", + "0xd112e7e91a31a812e23b12e0c70cf1ad1252540070cf00923b0090cf009", + "0x23b0090cd0096c600700723b0091a300914700700723b00900712e0071a1", + "0x1252540070d500923b0090d50096b70070d500923b0090076c70071a0009", + "0x14700700723b00900712e0070da0d812e7ea19b19f12e23b12e1a00d51a8", + "0x923b0090c000900e00707600923b00919f00912500700723b00919b009", + "0x761256c900719800923b00919800902600719800923b0090076c8007180", + "0x902000700723b00900712e0070df18e12e7eb0dd19712e23b12e198125", + "0x2e00718a00923b0090076ca0070e100923b00900722900700723b0090dd", + "0x23b00900722500718900923b00918a0e112e03000718a00923b00918a009", + "0x718b00923b00918c00962000718c00923b00918918812e031007188009", + "0x900e00922100718000923b00918000900e00719700923b009197009125", + "0x712e00718b00e18019700e00918b00923b00918b00961f00700e00923b", + "0x961c0070e500923b00900716c00700723b0090df00902000700723b009", + "0x923b00918e00912500718300923b00918400961d00718400923b0090e5", + "0x961f00700e00923b00900e00922100718000923b00918000900e00718e", + "0x914700700723b00900712e00718300e18018e00e00918300923b009183", + "0x6bb0070a000923b00900722900700723b00912500902000700723b0090da", + "0x23b0090e80a012e0300070e800923b0090e800902e0070e800923b009007", + "0x6200070ea00923b00917917b12e03100717b00923b009007225007179009", + "0x23b0090c000900e0070d800923b0090d800912500717500923b0090ea009", + "0xe00917500923b00917500961f00700e00923b00900e0092210070c0009", + "0x902000700723b0091a100914700700723b00900712e00717500e0c00d8", + "0x6cc00717100923b00900722900700723b0090cd0096cb00700723b009125", + "0x23b0090ec17112e0300070ec00923b0090ec00902e0070ec00923b009007", + "0x6200070f000923b0090ee16c12e03100716c00923b0090072250070ee009", + "0x23b0090c000900e0070d100923b0090d100912500716900923b0090f0009", + "0xe00916900923b00916900961f00700e00923b00900e0092210070c0009", + "0x914700700723b00912500902000700723b00900712e00716900e0c00d1", + "0x1ad00923b0091ad00912500716500923b0091aa00962000700723b0090c7", + "0x16500961f00700e00923b00900e0092210070c000923b0090c000900e007", + "0x12500902000700723b00900712e00716500e0c01ad00e00916500923b009", + "0x71b900923b0091b90091250070f300923b0090c400962000700723b009", + "0x90f300961f00700e00923b00900e0092210070c000923b0090c000900e", + "0x912500902000700723b00900712e0070f300e0c01b900e0090f300923b", + "0xe00700700923b00900700912500716300923b00901800962000700723b", + "0x23b00916300961f00700e00923b00900e00922100701100923b009011009", + "0x7ec00e12512e23b12e12e0090071256cd00716300e01100700e009163009", + "0x91250071db00923b00900e0096ce00700723b00900712e0070111fd12e", + "0x70077ed0090070ee00701800923b0091db0096cf00722300923b009125", + "0x923b0091fd00912500701b00923b0090110096d000700723b00900712e", + "0x1f00902e00701f00923b0090076d100701800923b00901b0096cf007223", + "0x923b12e0150090dd00701500923b00901f01812e6d200701f00923b009", + "0x51100702300923b00902000918e00700723b00900712e0070250097ee020", + "0x23b00922300912500722c00923b00902600951200702600923b009023009", + "0x723b00900712e00722c22312e00922c00923b00922c009513007223009", + "0x23c00951300722300923b00922300912500723c00923b009025009514007", + "0x901b0071db01112e23b0090110096d300723c22312e00923c00923b009", + "0x12e23b00901800901500701800923b00922300901f00722300923b0091db", + "0x1500901500701500923b0090076d400700723b00901b00902000701f01b", + "0x2300923b00901f00902300700723b00902000902000702502012e23b009", + "0x2500902300700723b00902600902000722c02612e23b009023009015007", + "0x723b00922900902000702c22912e23b00923c00901500723c00923b009", + "0x2e00902600703000923b00902c00902300702e00923b00922c009023007", + "0x723b00900712e0070077ef00723b12e03002e12e22c00702e00923b009", + "0x23b00901100915e00700723b00900e00915200700723b0091fd009155007", + "0x3100939900703100923b00922500911300722500923b00900716c007007", + "0x700923b00900700912500703300923b00904500939a00704500923b009", + "0x12500922100712e00923b00912e00900e00700900923b009009009033007", + "0x703312512e0090071fd00903300923b00903300939b00712500923b009", + "0x923b00900702500703622112e23b0090110096d500700723b00900712e", + "0x912500703a00923b0090380096d600703800923b00903600901b007219", + "0x923b00921900902600703a00923b00903a0090b400700700923b009007", + "0x3c00923b12e1260096d800712603b12e23b00921903a0071256d7007219", + "0x916500714100923b00903c0096d900700723b00900712e00703e0097f0", + "0x23b00914500915e00704314512e23b0092210096d500704100923b009141", + "0x470096d600704700923b00904300901b00714800923b009007563007007", + "0x4900923b0090490090b400703b00923b00903b00912500704900923b009", + "0x704c15012e23b00914804903b1256d700714800923b009148009026007", + "0x12e0071530097f115200923b12e04c0096d800704100923b00904100902e", + "0x15700923b00915500916500715500923b0091520096d900700723b009007", + "0x5805715905422323b00905200936900705200e12e23b00900e0095de007", + "0x37600700723b00915900937100700723b00905400937000715e05d15d05a", + "0x700723b00915d00937400700723b00905a00937500700723b009058009", + "0x923b00912e00900e00700723b00915e00937200700723b00905d009373", + "0x15f06012523b00905712512e1253da00712500923b00912500922100712e", + "0x1610097f206400923b12e16000907b00715700923b00915700902e007160", + "0x23b00915700916300716200923b00904100916300700723b00900712e007", + "0x3300715000923b00915000912500716400923b009064009187007067009", + "0x916600902e0071661fd12e23b0091fd00936b00700900923b009009009", + "0x16816212e23b00916200936b00716400923b00916400902e00716600923b", + "0x902e00716b06712e23b00906700936b00716800923b00916800902e007", + "0x6f06e06d12523b00916b16816416600915001165300716b00923b00916b", + "0x905400700723b00900712e00716e0097f307100923b12e06f009140007", + "0x718607807718007617407407222323b00900e00936900700723b009071", + "0x723b00917400937700700723b00907400937100700723b009072009370", + "0x23b00907800937300700723b00907700937400700723b009180009375007", + "0x15f00922100706000923b00906000900e00700723b009186009372007007", + "0x8d00907b00708d18707b12523b00907615f0601253de00715f00923b009", + "0x923b00907f00918700700723b00900712e00708e0097f407f00923b12e", + "0x902e00706e00923b00906e00903300706d00923b00906d00912500708f", + "0x923b00916200902e00708f00923b00908f00902e0071fd00923b0091fd", + "0x23b00906716208f1fd06e06d01165300706700923b00906700902e007162", + "0x9400923b00909100903300709300923b009090009125007092091090125", + "0x920090a500709600923b00918700922100709500923b00907b00900e007", + "0x6700915500700723b00900712e0070077f50090070ee00709700923b009", + "0x939c00700723b0091fd00915500700723b00916200915500700723b009", + "0x923b00906e00903300706d00923b00906d00912500709800923b00908e", + "0x939b00718700923b00918700922100707b00923b00907b00900e00706e", + "0x5400700723b00900712e00709818707b06e06d1fd00909800923b009098", + "0x700723b00906700915500700723b0091fd00915500700723b00916e009", + "0x9900923b00900716c00700723b00900e00915200700723b009162009155", + "0x6e00903300709300923b00906d0091250071a500923b009099009144007", + "0x9600923b00915f00922100709500923b00906000900e00709400923b009", + "0x9c00939a00709c00923b00909700939900709700923b0091a50090a5007", + "0x9400923b00909400903300709300923b0090930091250071a700923b009", + "0x1a700939b00709600923b00909600922100709500923b00909500900e007", + "0x915500700723b00900712e0071a70960950940931fd0091a700923b009", + "0x15500700723b00904100915500700723b00900e00915200700723b0091fd", + "0x923b00915000912500703700923b00916100939c00700723b009157009", + "0x922100706000923b00906000900e00700900923b009009009033007150", + "0x3715f0600091501fd00903700923b00903700939b00715f00923b00915f", + "0x723b00900e00915200700723b0091fd00915500700723b00900712e007", + "0x915000912500705b00923b00915300939c00700723b009041009155007", + "0x712e00923b00912e00900e00700900923b00900900903300715000923b", + "0x12e0091501fd00905b00923b00905b00939b00712500923b009125009221", + "0x900e00915200700723b0091fd00915500700723b00900712e00705b125", + "0x912500709f00923b00903e00939c00700723b00922100915e00700723b", + "0x923b00912e00900e00700900923b00900900903300703b00923b00903b", + "0x3b1fd00909f00923b00909f00939b00712500923b00912500922100712e", + "0x923b0091db00901b0071db01112e23b0090110096d300709f12512e009", + "0x2000701f01b12e23b00901800901500701800923b00922300901f007223", + "0x2012e23b00901500901500701500923b0090076d400700723b00901b009", + "0x2300901500702300923b00901f00902300700723b009020009020007025", + "0x23c00923b00902500902300700723b00902600902000722c02612e23b009", + "0x22c00902300700723b00922900902000702c22912e23b00923c009015007", + "0x2e00923b00902e00902600703000923b00902c00902300702e00923b009", + "0x1fd00915500700723b00900712e0070077f600723b12e03002e12e22c007", + "0x716c00700723b00901100915e00700723b00900e00915200700723b009", + "0x4500923b00903100939900703100923b00922500911300722500923b009", + "0x900903300700700923b00900700912500703300923b00904500939a007", + "0x12500923b00912500922100712e00923b00912e00900e00700900923b009", + "0x23b00900712e00703312512e0090071fd00903300923b00903300939b007", + "0x901b00721900923b00900702500703622112e23b0090110096d5007007", + "0x923b00900700912500703a00923b0090380096d600703800923b009036", + "0x1256d700721900923b00921900902600703a00923b00903a0090b4007007", + "0x703e0097f703c00923b12e1260096d800712603b12e23b00921903a007", + "0x923b00914100916500714100923b00903c0096d900700723b00900712e", + "0x756300700723b00914500915e00704314512e23b0092210096d5007041", + "0x4900923b0090470096d600704700923b00904300901b00714800923b009", + "0x14800902600704900923b0090490090b400703b00923b00903b009125007", + "0x904100902e00704c15012e23b00914804903b1256d700714800923b009", + "0x723b00900712e0071530097f815200923b12e04c0096d800704100923b", + "0xe00936900715700923b00915500916500715500923b0091520096d9007", + "0x37700700723b00905200937000705d15d05a05805715905405222323b009", + "0x700723b00905800937500700723b00905700937600700723b009159009", + "0x723b00905d00937200700723b00915d00937300700723b00905a009374", + "0x12e1253d200712500923b00912500922100712e00923b00912e00900e007", + "0x15f00907b00715700923b00915700902e00715f06015e12523b009054125", + "0x923b00904100916300700723b00900712e0070640097f916000923b12e", + "0x912500706700923b00916000918700716200923b009157009163007161", + "0x923b0091fd00902e00700900923b00900900903300715000923b009150", + "0x902e00716100923b00916100902e00706700923b00906700902e0071fd", + "0x16816616412523b0091621610671fd00915001165300716200923b009162", + "0x16400912500706d00923b00916b00939a00716b00923b009168009399007", + "0x15e00923b00915e00900e00716600923b00916600903300716400923b009", + "0x1661641fd00906d00923b00906d00939b00706000923b009060009221007", + "0x15700915500700723b00904100915500700723b00900712e00706d06015e", + "0x12500706e00923b00906400939c00700723b0091fd00915500700723b009", + "0x23b00915e00900e00700900923b00900900903300715000923b009150009", + "0x1fd00906e00923b00906e00939b00706000923b00906000922100715e009", + "0x15500700723b0091fd00915500700723b00900712e00706e06015e009150", + "0x6f00923b00915300939c00700723b00900e00915200700723b009041009", + "0x12e00900e00700900923b00900900903300715000923b009150009125007", + "0x6f00923b00906f00939b00712500923b00912500922100712e00923b009", + "0x723b0091fd00915500700723b00900712e00706f12512e0091501fd009", + "0x23b00903e00939c00700723b00900e00915200700723b00922100915e007", + "0xe00700900923b00900900903300703b00923b00903b009125007071009", + "0x23b00907100939b00712500923b00912500922100712e00923b00912e009", + "0x90071600071db00923b00900715f00707112512e00903b1fd009071009", + "0x922300903800722300923b00900721900700723b0090070ea00700723b", + "0x12e00701501f12e7fa01b01812e23b12e22300900712503a00722300923b", + "0x12500700723b00900710f00702000923b00912500956100700723b009007", + "0x12e0070260097fb02302512e23b12e02000964400701800923b009018009", + "0x23c00923b00902500956900722c00923b00902300964500700723b009007", + "0x723b00900712e0070077fc0090070ee00722900923b00922c009646007", + "0x902600956900702e00923b00902c00964700702c00923b00900716c007", + "0x703000923b00923c00912800722900923b00902e00964600723c00923b", + "0x12e0070310097fd22500923b12e22900964800703000923b009030009123", + "0x4500923b00904500964900704500923b00922500956e00700723b009007", + "0x721903622112523b00903300957100703304512e23b009045009570007", + "0x923b00922100910200700723b00921900957200700723b009036009155", + "0x3c12603b12523b00903a00957100703a04512e23b009045009570007038", + "0x23b00912600916300700723b00903c00957200700723b00903b009101007", + "0x700723b00914100910100714504114112523b00904500957100703e009", + "0x23b0090430091fd00704300923b00914500905800700723b009041009155", + "0x111501257fe04904714812523b12e04303e03812e01b1fd6da007043009", + "0x723b0091db00906400700723b0090070ea00700723b00900712e00704c", + "0x714300715200923b0090491fd12e6db00704900923b0090490091fd007", + "0x923b00901800912500715500923b00915300e12e6dc00715300923b009", + "0x912300704700923b00904700922100714800923b00914800900e007018", + "0x923b0091520095b800715500923b00915500902e00703000923b009030", + "0x95ba00715905405215700e23b0091521550300471480180115b9007152", + "0x23b0090570095bb00700723b00900712e0070580097ff05700923b12e159", + "0x600096df00706000923b00915e05d15d05a00e6de00715e05d15d05a00e", + "0x5200923b00905200900e00715700923b00915700912500715f00923b009", + "0x5215700e00915f00923b00915f0096e000705400923b009054009221007", + "0x15700912500716000923b0090580096e100700723b00900712e00715f054", + "0x5400923b00905400922100705200923b00905200900e00715700923b009", + "0x723b00900712e00716005405215700e00916000923b0091600096e0007", + "0x723b0091fd00916800700723b00903000936500700723b0090070ea007", + "0x23b00916100902e00716100923b0090076e300706400923b009007229007", + "0x6700923b00900e16212e03000716200923b00916106412e030007161009", + "0x4c00915700715000923b00915000900e00701800923b009018009125007", + "0x923b0090111db12e16200706700923b00906700915700704c00923b009", + "0x23b12e1680095c500716816616412523b00906704c15001800e6e4007011", + "0x6f06e12523b00916b0095c600700723b00900712e00706d00980016b009", + "0x23b00900722500700723b00907100905400700723b00906e009057007071", + "0x707400923b0090720096e100707200923b00906f16e12e03100716e009", + "0x901100922100716600923b00916600900e00716400923b009164009125", + "0x712e00707401116616400e00907400923b0090740096e000701100923b", + "0x716400923b00916400912500717400923b00906d0096e100700723b009", + "0x91740096e000701100923b00901100922100716600923b00916600900e", + "0x23b0090070ea00700723b00900712e00717401116616400e00917400923b", + "0x23b00900716c00700723b0091db00906400700723b009031009054007007", + "0x923b0091800096df00718000923b00907600e1fd03000e6de007076009", + "0x922100701b00923b00901b00900e00701800923b009018009125007077", + "0x707712e01b01800e00907700923b0090770096e000712e00923b00912e", + "0x700723b00912500936500700723b00900e00915500700723b00900712e", + "0x7800923b00900722900700723b0091db00906400700723b0091fd009168", + "0x18607812e03000718600923b00918600902e00718600923b00900705d007", + "0x8d00923b00907b18712e03100718700923b00900722500707b00923b009", + "0x1500900e00701f00923b00901f00912500707f00923b00908d0096e1007", + "0x7f00923b00907f0096e000712e00923b00912e00922100701500923b009", + "0x23b0090090095c300700900923b0090070096e500707f12e01501f00e009", + "0x8011fd00923b02012e0096e600700723b0090070ea007009009009009009", + "0x1500980701f00980601b0098050180098042230098031db009802011009", + "0x23b00900712e00722c00980c02600980b02300980a025009809020009808", + "0x12512e03000723c00923b00923c00902e00723c00923b0090076e8007007", + "0x923b0092290091570071fd00923b0091fd00953d00722900923b00923c", + "0x2e02c12523b00900e2291fd1256e900700e00923b00900e009157007229", + "0x900900e00722500923b00900700912500700723b009030009054007030", + "0x3300923b00902e00915700704500923b00902c00915700703100923b009", + "0x722100923b0090076ea00700723b00900712e00700780d0090070ee007", + "0x700912500703600923b00922112512e03000722100923b00922100902e", + "0x1100923b00901100930f00700900923b00900900900e00700700923b009", + "0x71fd6eb00700e00923b00900e00915700703600923b009036009157007", + "0x980e03b00923b12e03a0095c500703a03821912523b00900e036011009", + "0x905400714103e03c12523b00903b0095c600700723b00900712e007126", + "0x3100923b00903800900e00722500923b00921900912500700723b009141", + "0x90070ee00703300923b00903e00915700704500923b00903c009157007", + "0x21900912500704100923b0091260096ec00700723b00900712e00700780d", + "0x4100923b0090410096ed00703800923b00903800900e00721900923b009", + "0x2e00714500923b0090076ee00700723b00900712e007041038219125009", + "0x91db0094b500704300923b00914512512e03000714500923b009145009", + "0x700e00923b00900e00915700704300923b0090430091570071db00923b", + "0x12500700723b00904900905400704904714812523b00900e0431db1256f0", + "0x23b00914800915700703100923b00900900900e00722500923b009007009", + "0x900712e00700780d0090070ee00703300923b009047009157007045009", + "0x12e03000715000923b00915000902e00715000923b0090076f100700723b", + "0x23b00904c00915700722300923b0092230094c700704c00923b009150125", + "0x15212523b00900e04c2231256f200700e00923b00900e00915700704c009", + "0x900e00722500923b00900700912500700723b009155009054007155153", + "0x923b00915300915700704500923b00915200915700703100923b009009", + "0x15700923b0090076f300700723b00900712e00700780d0090070ee007033", + "0x94d700705200923b00915712512e03000715700923b00915700902e007", + "0x923b00900e00915700705200923b00905200915700701800923b009018", + "0x723b00905700905400705715905412523b00900e0520181256f400700e", + "0x5400915700703100923b00900900900e00722500923b009007009125007", + "0x12e00700780d0090070ee00703300923b00915900915700704500923b009", + "0x705800923b00905800902e00705800923b0090076f500700723b009007", + "0x5a00915700701b00923b00901b0094e700705a00923b00905812512e030", + "0x23b00900e05a01b1256f600700e00923b00900e00915700705a00923b009", + "0x722500923b00900700912500700723b00915e00905400715e05d15d125", + "0x905d00915700704500923b00915d00915700703100923b00900900900e", + "0x23b00900725b00700723b00900712e00700780d0090070ee00703300923b", + "0x715f00923b00906012512e03000706000923b00906000902e007060009", + "0x15f01f1256f800700e00923b00900e00915700715f00923b00915f009157", + "0x23b00900700912500700723b00916100905400716106416012523b00900e", + "0x15700704500923b00916000915700703100923b00900900900e007225009", + "0x6f900700723b00900712e00700780d0090070ee00703300923b009064009", + "0x23b00916212512e03000716200923b00916200902e00716200923b009007", + "0x15700706700923b00906700915700701500923b009015009460007067009", + "0x5400716816616412523b00900e0670151256fa00700e00923b00900e009", + "0x923b00900900900e00722500923b00900700912500700723b009168009", + "0x70ee00703300923b00916600915700704500923b009164009157007031", + "0x16b00902e00716b00923b0090076fb00700723b00900712e00700780d009", + "0x923b00902000948100706d00923b00916b12512e03000716b00923b009", + "0x1256fc00700e00923b00900e00915700706d00923b00906d009157007020", + "0x700912500700723b00907100905400707106f06e12523b00900e06d020", + "0x4500923b00906e00915700703100923b00900900900e00722500923b009", + "0x723b00900712e00700780d0090070ee00703300923b00906f009157007", + "0x16e12512e03000716e00923b00916e00902e00716e00923b0090076fd007", + "0x7200923b00907200915700702500923b00902500949b00707200923b009", + "0x7617407412523b00900e0720251256fe00700e00923b00900e009157007", + "0x900900900e00722500923b00900700912500700723b009076009054007", + "0x703300923b00917400915700704500923b00907400915700703100923b", + "0x2e00718000923b00900780f00700723b00900712e00700780d0090070ee", + "0x90230093bd00707700923b00918012512e03000718000923b009180009", + "0x700e00923b00900e00915700707700923b00907700915700702300923b", + "0x12500700723b00907b00905400707b18607812523b00900e077023125810", + "0x23b00907800915700703100923b00900900900e00722500923b009007009", + "0x900712e00700780d0090070ee00703300923b009186009157007045009", + "0x12e03000718700923b00918700902e00718700923b00900781100700723b", + "0x23b00908d00915700702600923b0090260093f500708d00923b009187125", + "0x7f12523b00900e08d02612581200700e00923b00900e00915700708d009", + "0x900e00722500923b00900700912500700723b00908f00905400708f08e", + "0x923b00908e00915700704500923b00907f00915700703100923b009009", + "0x9000923b00900781300700723b00900712e00700780d0090070ee007033", + "0x946400709100923b00909012512e03000709000923b00909000902e007", + "0x923b00900e00915700709100923b00909100915700722c00923b00922c", + "0x723b00909400905400709409309212523b00900e09122c12581400700e", + "0x9200915700703100923b00900900900e00722500923b009007009125007", + "0x709500923b00900716c00703300923b00909300915700704500923b009", + "0x912500709700923b00909600981600709600923b009095033045125815", + "0x923b0090970096ed00703100923b00903100900e00722500923b009225", + "0x712e00712e00981800900923b12e007009817007097031225125009097", + "0x700e00923b00912500961d00712500923b00900900961c00700723b009", + "0x900722500700723b00900712e00700e00900900e00923b00900e00961f", + "0x1db00923b00901100962000701100923b00912e1fd12e0310071fd00923b", + "0x96d300700723b0090070ea0071db0090091db00923b0091db00961f007", + "0x23b0091fd00901b0071fd00923b00900e00981900700e12e12e23b00912e", + "0x701822312e23b0091db0090150071db00923b00901100901f007011009", + "0x23b00901b0090df00701b00923b00901800902300700723b009223009020", + "0x701500923b00901f12512e03000701f00923b00901f00902e00701f009", + "0x900900900e00700700923b00900700912500702000923b00912e009819", + "0x701500923b00901500915700702000923b0090200091fd00700900923b", + "0x22c00923b12e02600906e00702602302512523b00901502000900700e3cb", + "0x31800702c22912e23b00922c00906f00700723b00900712e00723c00981a", + "0x902500912500703000923b00902e00931900702e00923b00902c22912e", + "0x903000923b00903000931a00702300923b00902300900e00702500923b", + "0x12500722500923b00923c00931b00700723b00900712e007030023025125", + "0x23b00922500931a00702300923b00902300900e00702500923b009025009", + "0x12e00901b00712e00912e23b0090090096d3007225023025125009225009", + "0x1fd12e23b00900e00901500700e00923b00912500901f00712500923b009", + "0x91db0090150071db00923b0090076d400700723b0091fd009020007011", + "0x701b00923b00901100902300700723b00922300902000701822312e23b", + "0x1f01b12e22c00701b00923b00901b00902600701f00923b009018009023", + "0x1500912e23b0090090096d300700723b00900712e00700781b00723b12e", + "0x2500901500702500923b00902000901f00702000923b00901500901b007", + "0x722c00923b00900781c00700723b00902300902000702602312e23b009", + "0x902600902300700723b00923c00902000722923c12e23b00922c009015", + "0x702c00923b00902c00902600702e00923b00922900902300702c00923b", + "0x900900915e00700723b00900712e00700781d00723b12e02e02c12e22c", + "0x22500902e00722500923b00900781e00703000923b00900722900700723b", + "0x4500923b00900722500703100923b00922503012e03000722500923b009", + "0x912500722100923b00903300981f00703300923b00903104512e031007", + "0x712e00722100712e00922100923b00922100982000700700923b009007", + "0x96d300721900923b0090076d400703600923b00900702500700723b009", + "0x23b00903600902600703a00923b00903800901b00703800912e23b009009", + "0x12e23b12e21903603a00700e82100721900923b009219009026007036009", + "0x6d400703e00923b0090076d400700723b00900712e00703c00982212603b", + "0x923b00903e00902600704100923b00900900901b00714100923b009007", + "0xe82100712600923b0091260090b400714100923b00914100902600703e", + "0x5800700723b00900712e00714800982304314512e23b12e14103e04103b", + "0x904904712e82400704900923b00904300905800704700923b009126009", + "0x715200923b00904c00982600704c00923b00915000982500715000923b", + "0x715214512e00915200923b00915200982000714500923b009145009125", + "0x715300923b00900722900700723b00912600957200700723b00900712e", + "0x915515312e03000715500923b00915500902e00715500923b0090076b5", + "0x705400923b00915705212e03100705200923b00900722500715700923b", + "0x915900982000714800923b00914800912500715900923b00905400981f", + "0x723b00900900915e00700723b00900712e00715914812e00915900923b", + "0x23b00905800902e00705800923b0090076b500705700923b009007229007", + "0x3100715d00923b00900722500705a00923b00905805712e030007058009", + "0x903c00912500715e00923b00905d00981f00705d00923b00905a15d12e", + "0x23b00900712e00715e03c12e00915e00923b00915e00982000703c00923b", + "0x905700716015f12e23b00906000915900706000923b009007229007007", + "0x923b00906400912e82400706400923b00916000905800700723b00915f", + "0x912500706700923b00916200982600716200923b009161009825007161", + "0x900e00706700712e00906700923b00906700982000700700923b009007", + "0x23b00900900712e54d00700900923b00900900922100700700923b009007", + "0x23b00900712e0070110098271fd00923b12e00e00954e00700e12512e125", + "0x955200722300923b0091db0095510071db00923b0091fd009550007007", + "0x1f00910100700723b00901b00955400702001501f01b0181fd23b009223", + "0x982800700723b00902000915500700723b00901500910100700723b009", + "0x923b00912e00900e00702300923b00902500982900702500923b009018", + "0x12e12500902300923b00902300982a00712500923b00912500922100712e", + "0x12e00900e00702600923b00901100982b00700723b00900712e007023125", + "0x2600923b00902600982a00712500923b00912500922100712e00923b009", + "0x700e00923b00900782c00700723b00912e00937400702612512e125009", + "0x901100902e00701100923b0091fd00937d0071fd00923b00900e00937b", + "0x23b00922300937b0072231db12e23b00912501100912537e00701100923b", + "0x82d00701b00923b00901b00902e00701b00923b00901800937d007018009", + "0x1db00909900701f00923b00901f00912500701501f12e23b00901b00712e", + "0x982e0070151db01f12500901500923b0090150096550071db00923b009", + "0x23b00900900939900700723b00900712e00712e00982f00900923b12e007", + "0x900900e00923b00900e00939b00700e00923b00912500939a007125009", + "0x912e1fd12e0310071fd00923b00900722500700723b00900712e00700e", + "0x91db00923b0091db00939b0071db00923b00901100939c00701100923b", + "0x23b0090070ea00700723b0090071600071db00923b0090078300071db009", + "0x712503a00722300923b00922300903800722300923b009007219007007", + "0x956100700723b00900712e00701501f12e83101b01812e23b12e223009", + "0x701800923b00901800912500700723b00900710f00702000923b009125", + "0x964500700723b00900712e00702600983202302512e23b12e020009644", + "0x923b00922c00964600723c00923b00902500956900722c00923b009023", + "0x2c00923b00900716c00700723b00900712e0070078330090070ee007229", + "0x2e00964600723c00923b00902600956900702e00923b00902c009647007", + "0x923b0090111db12e83400701100923b00923c00912800722900923b009", + "0xea00700723b00900712e00722500983503000923b12e229009648007011", + "0x1800923b00901800912500703100923b00903000956e00700723b009007", + "0x3100964900712e00923b00912e00909900701b00923b00901b00900e007", + "0x7b00703622103304500e23b00903112e01b01800e83600703100923b009", + "0x921900918700700723b00900712e00703800983721900923b12e036009", + "0x12e23b00903a03b22112537e00703b00923b00900e00937d00703a00923b", + "0xe00704500923b00904500912500703e00923b00903c00937b00703c126", + "0x23b00901100912300712600923b00912600909900703300923b009033009", + "0x6020071fd00923b0091fd00902e00703e00923b00903e009600007011009", + "0x23b12e04300924c00704314504114100e23b0091fd03e011126033045011", + "0x15004912523b00914800960400700723b00900712e007047009838148009", + "0x715300923b00915200983a00715200923b00904c15004912583900704c", + "0x914500909900704100923b00904100900e00714100923b009141009125", + "0x712e00715314504114100e00915300923b00915300983b00714500923b", + "0x714100923b00914100912500715500923b00904700983c00700723b009", + "0x915500983b00714500923b00914500909900704100923b00904100900e", + "0x91fd00915500700723b00900712e00715514504114100e00915500923b", + "0x3800983c00700723b00900e00960500700723b00901100936500700723b", + "0x3300923b00903300900e00704500923b00904500912500715700923b009", + "0x3304500e00915700923b00915700983b00722100923b009221009099007", + "0x23b00922500905400700723b0090070ea00700723b00900712e007157221", + "0x37e00705400923b00905200937d00705200e12e23b00900e00983d007007", + "0x937d00705800923b00905700937b00705715912e23b0091fd05412e125", + "0x915d00983a00715d00923b00905a00e01112583900705a00923b009058", + "0x701b00923b00901b00900e00701800923b00901800912500705d00923b", + "0x15901b01800e00905d00923b00905d00983b00715900923b009159009099", + "0x23b00900e00960500700723b0091fd00915500700723b00900712e00705d", + "0x23b00900722900700723b00912500936500700723b0091db00983e007007", + "0x12e03000706000923b00906000902e00706000923b00900705d00715e009", + "0x23b00915f16012e03100716000923b00900722500715f00923b00906015e", + "0xe00701f00923b00901f00912500716100923b00906400983c007064009", + "0x23b00916100983b00712e00923b00912e00909900701500923b009015009", + "0x712e00984000900923b12e00700983f00716112e01501f00e009161009", + "0x923b00912500915d00712500923b00900900905a00700723b00900712e", + "0x22500700723b00900712e00700e00900900e00923b00900e00903600700e", + "0x23b00901100904500701100923b00912e1fd12e0310071fd00923b009007", + "0x923b00900700901b0071db0090091db00923b0091db0090360071db009", + "0x700723b00900712e00700e00984112512e12e23b12e009009175007009", + "0x91fd0090ec00701100923b00912e0090b40071fd00923b009125009171", + "0x23b00900716c00700723b00900712e0070078420090070ee0071db00923b", + "0xec00701100923b00900e0090b400701800923b0092230090f0007223009", + "0x23b00901b0091fd00701b00923b0090110090580071db00923b009018009", + "0x700723b00900712e00701500984301f00923b12e1db00916900701b009", + "0x902500915300702500923b00902000916300702000923b00901f009165", + "0x15300722c00923b00900714c00700723b00902300915500702602312e23b", + "0x23b00902600916300700723b00923c00915500722923c12e23b00922c009", + "0x16300700723b00902e00915500703002e12e23b00902c00915300702c009", + "0x903100915500704503112e23b00922500915300722500923b009229009", + "0x2e00722100923b00904500916300703300923b00903000916300700723b", + "0x903600902e00703600923b00922103312e14f00703300923b009033009", + "0x700723b00900712e00721900984400723b12e03600910600703600923b", + "0x23b00903a0090a500703a00923b00903800914400703800923b00900716c", + "0x23b00921900911100700723b00900712e0070078450090070ee00703b009", + "0x3c0090a500703c00923b00912600911300712600923b00900716c007007", + "0x14100923b00903e00925d00703e00923b00903b00936e00703b00923b009", + "0x14101b12e00914100923b00914100984600701b00923b00901b0091fd007", + "0x4100923b00900716c00700723b00901500905400700723b00900712e007", + "0x14500984600701b00923b00901b0091fd00714500923b009041009847007", + "0x712500984812e00923b12e00700981700714501b12e00914500923b009", + "0xe00923b00912e00961c00700723b00900900915500700723b00900712e", + "0x71fd0090091fd00923b0091fd00961f0071fd00923b00900e00961d007", + "0x701100923b00900722900700723b00912500905700700723b00900712e", + "0x1db22312e03100722300923b0090072250071db00923b00900901112e030", + "0x1b00923b00901b00961f00701b00923b00901800962000701800923b009", + "0x900900923b0090090095c300700900923b00900700984900701b009009", + "0x700723b00900712e00712e00984b00900923b12e00700984a007009009", + "0x900e00933100700e00923b00912500933000712500923b00900900932f", + "0x71fd00923b00900722500700723b00900712e00700e00900900e00923b", + "0x1db0093310071db00923b00901100933200701100923b00912e1fd12e031", + "0xe00984c12512e12e23b12e00900712e3a10071db0090091db00923b009", + "0x23b00912e0091250071fd00923b0091250093a300700723b00900712e007", + "0x900712e00700784d0090070ee0071db00923b0091fd0093a4007011009", + "0x912500701800923b0092230093a500722300923b00900716c00700723b", + "0x984e0071db01112e0091db00923b0090180093a400701100923b00900e", + "0x23b00900900963a00700723b00900712e00712e00984f00900923b12e007", + "0x900900e00923b00900e00963700700e00923b00912500963b007125009", + "0x912e1fd12e0310071fd00923b00900722500700723b00900712e00700e", + "0x91db00923b0091db0096370071db00923b00901100963600701100923b", + "0x900900900923b0090090095c300700900923b0090070098500071db009", + "0x910400712500923b00912e00910200712e00923b009007009102007009", + "0x923b0091fd0091020071fd00923b00900900910200700e00923b009125", + "0x15500701822312e23b00900e0091530071db00923b009011009104007011", + "0x23b00901b00915500701f01b12e23b0091db00915300700723b009223009", + "0x12e14f00702000923b00901f00916300701500923b009018009163007007", + "0x23b12e02500910600702500923b00902500902e00702500923b009020015", + "0x914400702600923b00900716c00700723b00900712e007023009851007", + "0x70078520090070ee00723c00923b00922c0090a500722c00923b009026", + "0x722900923b00900716c00700723b00902300911100700723b00900712e", + "0x36b00723c00900923c00923b00902c0090a500702c00923b009229009113", + "0x712e0071db00985300723b12e0110091060070111fd12e23b0091fd009", + "0x915500700723b00912e00915500700723b0091fd00915500700723b009", + "0x11300722300923b00900716c00700723b00912500915500700723b00900e", + "0x23b00900900903300700700923b00900700912500701800923b009223009", + "0x23b00900712e00701800900712500901800923b0090180090a5007009009", + "0x91fd00936b00701b00923b00900785400700723b0091db009111007007", + "0x923b00901500902e00701500923b00901b01f12e14f00701f1fd12e23b", + "0x915500700723b00900712e00702000985500723b12e015009106007015", + "0x15500700723b00900e00915500700723b00912e00915500700723b0091fd", + "0x2300923b00902500911300702500923b00900716c00700723b009125009", + "0x230090a500700900923b00900900903300700700923b009007009125007", + "0x902000911100700723b00900712e00702300900712500902300923b009", + "0x14f00722c00e12e23b00900e00936b00702600923b00900785400700723b", + "0x12e23c00910600723c00923b00923c00902e00723c00923b00902622c12e", + "0x15500700723b0091fd00915500700723b00900712e00722900985600723b", + "0x700723b00912500915500700723b00900e00915500700723b00912e009", + "0x23b00900700912500702e00923b00902c00911300702c00923b00900716c", + "0x12500902e00923b00902e0090a500700900923b009009009033007007009", + "0x712e25c00700723b00922900911100700723b00900712e00702e009007", + "0x922500985800700723b00900712e00703100985722503012e23b12e125", + "0x3300e12e23b00900e00936b00704500923b00922500985900722500923b", + "0x700723b00900712e00721900985a03622112e23b12e03303012e25c007", + "0x23b00900785b00703800923b00903600985900703600923b009036009858", + "0x902e00703a00923b00903a00902e00703b00923b00900785c00703a009", + "0x23b12e03b03a12e85d00722100923b00922100912500703b00923b00903b", + "0x85900712600923b00912600985800700723b00900712e00700785e126009", + "0x23b00903800985f00700900923b00900900903300703c00923b009126009", + "0x3e12e23b0091fd0380091258600071fd00923b0091fd00902e007038009", + "0x986300700723b00900712e00704100986200723b12e141009861007141", + "0x86300700723b00912e00915500700723b00900e00915500700723b009045", + "0x4300923b00914500911300714500923b00900716c00700723b00903c009", + "0x430090a500703e00923b00903e00903300722100923b009221009125007", + "0x904100986400700723b00900712e00704303e22112500904300923b009", + "0x703e00923b00903e00903300700723b00904700915500704714812e23b", + "0x3c03e12586000712e00923b00912e00902e00703c00923b00903c00985f", + "0x23b00904500985f00704900923b00904900903300715004912e23b00912e", + "0x4c12e23b00900e04504912586000700e00923b00900e00902e007045009", + "0x86500715300923b00915300985f00715315012e23b009150009865007152", + "0x15515312e86600715500923b00915500985f00715515212e23b009152009", + "0x723b00900712e00705200986700723b12e15700986100715700923b009", + "0x5412e23b00905200986400700723b00900712e0070078680090070ee007", + "0x12e14f00705714812e23b00914800936b00700723b009159009155007159", + "0x23b12e05800910600705800923b00905800902e00705800923b009057054", + "0x986300700723b00914800915500700723b00900712e00705a009869007", + "0x14400715d00923b00900716c00700723b00915000986300700723b009152", + "0x23b00904c00903300722100923b00922100912500705d00923b00915d009", + "0x23b00900712e00705d04c22112500905d00923b00905d0090a500704c009", + "0x15200985f00715000923b00915000985f00700723b00905a009111007007", + "0x723b12e15e00986100715e00923b00915215012e86a00715200923b009", + "0x90070ee00700723b00914800915500700723b00900712e00706000986b", + "0x915500716015f12e23b00906000986400700723b00900712e00700786c", + "0x923b00906400902e00706400923b00914815f12e14f00700723b009160", + "0x716c00700723b00900712e00716100986d00723b12e064009106007064", + "0x22100923b00922100912500706700923b00916200914400716200923b009", + "0x4c22112500906700923b0090670090a500704c00923b00904c009033007", + "0x923b00900716c00700723b00916100911100700723b00900712e007067", + "0x903300722100923b00922100912500716600923b009164009113007164", + "0x12e00716604c22112500916600923b0091660090a500704c00923b00904c", + "0x15500700723b00900e00915500700723b00904500986300700723b009007", + "0x700723b00903800986300700723b0091fd00915500700723b00912e009", + "0x23b00922100912500716b00923b00916800911300716800923b00900716c", + "0x12500916b00923b00916b0090a500700900923b009009009033007221009", + "0x4500986300700723b0091fd00915500700723b00900712e00716b009221", + "0x716c00700723b00912e00915500700723b00900e00915500700723b009", + "0x21900923b00921900912500706e00923b00906d00911300706d00923b009", + "0x921912500906e00923b00906e0090a500700900923b009009009033007", + "0x23b00912e00915500700723b0091fd00915500700723b00900712e00706e", + "0x906f00911300706f00923b00900716c00700723b00900e009155007007", + "0x700900923b00900900903300703100923b00903100912500707100923b", + "0xe12e23b00900e00986e00707100903112500907100923b0090710090a5", + "0x5f80071db12512e23b00912500957900701100923b0091fd0095f70071fd", + "0x900712e00702001501f12586f01b01822312523b12e0111db12e00900e", + "0x33d00701b00923b00901b00902e00700700923b00900700912500700723b", + "0x1800922100722300923b00922300900e00702302512e23b00901b00712e", + "0x23b00900712e00722c00987002600923b12e02300933e00701800923b009", + "0x925a00722900e12e23b00900e00986e00723c00923b009007508007007", + "0x912500957900702e00923b00902c22912e87100702c23c12e23b00923c", + "0x12e02e03001822300e5f800702e00923b00902e00962900703012512e23b", + "0x900750800700723b00900712e00703622103312587204503122512523b", + "0x723c00923b00923c00987300702500923b00902500912500721900923b", + "0xe00703a03812e23b00921923c02512587400721900923b009219009873", + "0x23b00904500902e00703100923b00903100922100722500923b009225009", + "0x700723b00900712e00712600987603b00923b12e03a009875007045009", + "0x3e00962900703e00923b00903c00e12e87100703c00923b00903b009877", + "0x4312587814504114112523b12e03e12503122500e5f800703e00923b009", + "0x87900704900923b00914504502612544000700723b00900712e007047148", + "0x23b00904c00987b00704c00923b00915000987a00715000923b009049009", + "0x22100714100923b00914100900e00703800923b009038009125007152009", + "0x15204114103800e00915200923b00915200987c00704100923b009041009", + "0x723b00902600934f00700723b00904500915500700723b00900712e007", + "0x15500987b00715500923b00915300987a00715300923b00904700987d007", + "0x4300923b00904300900e00703800923b00903800912500715700923b009", + "0x4303800e00915700923b00915700987c00714800923b009148009221007", + "0x902600934f00700723b00904500915500700723b00900712e007157148", + "0x12600987f00700723b00900e00987e00700723b00912500902000700723b", + "0x22500923b00922500900e00703800923b00903800912500705200923b009", + "0x22503800e00905200923b00905200987c00703100923b009031009221007", + "0x902600934f00700723b00900e00987e00700723b00900712e007052031", + "0x3600987d00700723b00912500902000700723b00923c00950c00700723b", + "0x5700923b00915900987b00715900923b00905400987a00705400923b009", + "0x22100922100703300923b00903300900e00702500923b009025009125007", + "0x12e00705722103302500e00905700923b00905700987c00722100923b009", + "0x2000700723b00900e00987e00700723b00922c00905400700723b009007", + "0x705a00923b00900788000705800923b00900722900700723b009125009", + "0x900722500715d00923b00905a05812e03000705a00923b00905a00902e", + "0x6000923b00915e00987f00715e00923b00915d05d12e03100705d00923b", + "0x1800922100722300923b00922300900e00702500923b009025009125007", + "0x12e00706001822302500e00906000923b00906000987c00701800923b009", + "0x87d00700723b00912500902000700723b00900e00987e00700723b009007", + "0x23b00916000987b00716000923b00915f00987a00715f00923b009020009", + "0x22100701f00923b00901f00900e00700700923b009007009125007064009", + "0x6401501f00700e00906400923b00906400987c00701500923b009015009", + "0x94ff00700723b00900712e00712e00988200900923b12e007009881007", + "0x923b00900e00950100700e00923b00912500950000712500923b009009", + "0x12e0310071fd00923b00900722500700723b00900712e00700e00900900e", + "0x23b0091db0095010071db00923b00901100950200701100923b00912e1fd", + "0x700723b00900900905400700723b0090070090540071db0090091db009", + "0x23b0091250090a500712500923b00912e00914400712e00923b00900716c", + "0x90110095050072231db01112523b0091fd009246007125009009125009", + "0x1f00923b00901b0095f700701b00e12e23b00900e00986e00701800923b", + "0x12e23b12e01801f01512e0091fd60800701512512e23b009125009579007", + "0x23c00923b00900750800700723b00900712e00722c026023125883025020", + "0x87100702c23c12e23b00923c00925a00722900e12e23b00900e00986e007", + "0x2000900e00703012512e23b00912500957900702e00923b00902c22912e", + "0x1db02e0300250201fd60800702e00923b00902e00962900702000923b009", + "0x900750800700723b00900712e00722103304512588403122512e23b12e", + "0x723c00923b00923c00987300700700923b00900700912500703600923b", + "0xe00703821912e23b00903623c00712587400703600923b009036009873", + "0x23b12e03800987500703100923b00903100922100722500923b009225009", + "0x712600923b00903a00987700700723b00900712e00703b00988503a009", + "0x2251fd60800703c00923b00903c00962900703c00923b00912600e12e871", + "0x723b00900712e00704314504112588614103e12e23b12e22303c125031", + "0x904700988700704700923b0091480093b400714800923b00900716c007", + "0x721900923b00921900912500715000923b00904900925900704900923b", + "0x915000988800714100923b00914100922100703e00923b00903e00900e", + "0x90430093b700700723b00900712e00715014103e21900e00915000923b", + "0x715300923b00915200925900715200923b00904c00988700704c00923b", + "0x914500922100704100923b00904100900e00721900923b009219009125", + "0x712e00715314504121900e00915300923b00915300988800714500923b", + "0x987e00700723b00912500902000700723b00922300915500700723b009", + "0x21900923b00921900912500715500923b00903b00988900700723b00900e", + "0x15500988800703100923b00903100922100722500923b00922500900e007", + "0xe00987e00700723b00900712e00715503122521900e00915500923b009", + "0x902000700723b00923c00950c00700723b00922300915500700723b009", + "0x5200923b00915700988700715700923b0092210093b700700723b009125", + "0x4500900e00700700923b00900700912500705400923b009052009259007", + "0x5400923b00905400988800703300923b00903300922100704500923b009", + "0x700723b00900e00987e00700723b00900712e00705403304500700e009", + "0x723b00912500902000700723b0091db00915500700723b009223009155", + "0x5700925900705700923b00915900988700715900923b00922c0093b7007", + "0x2300923b00902300900e00700700923b00900700912500705800923b009", + "0x2300700e00905800923b00905800988800702600923b009026009221007", + "0x900900900923b0090090095c300700900923b00900700988a007058026", + "0x900900900900923b0090090095c300700900923b00900700988b007009", + "0x700900900900900923b0090090095c300700900923b00900700988c007", + "0x88e00700900900900900923b0090090095c300700900923b00900700988d", + "0x988f00700900900900900923b0090090095c300700900923b009007009", + "0x23b00900900915500700723b00900712e00712500989012e00923b12e007", + "0x924d0071fd00923b00900e0095f400700e00923b00912e0095f3007007", + "0x23b00912500934f00700723b00900712e0071fd0090091fd00923b0091fd", + "0x72250071db00923b00900901112e03000701100923b009007229007007", + "0x923b0090180095f500701800923b0091db22312e03100722300923b009", + "0x900923b00900700989100701b00900901b00923b00901b00924d00701b", + "0x700900923b00900700989200700900900900900923b0090090095c3007", + "0x5c300700900923b00900700989300700900900900900923b0090090095c3", + "0x95c300700900923b00900700989400700900900900900923b009009009", + "0x989612512e12e23b12e00900712e89500700900900900900923b009009", + "0x912e0091250071fd00923b00912500989700700723b00900712e00700e", + "0x712e0070078990090070ee0071db00923b0091fd00989800701100923b", + "0x12500701800923b00922300989a00722300923b00900716c00700723b009", + "0x89b0071db01112e0091db00923b00901800989800701100923b00900e009", + "0x900900951100700723b00900712e00712e00989c00900923b12e007009", + "0x900e00923b00900e00951300700e00923b00912500951200712500923b", + "0x12e1fd12e0310071fd00923b00900722500700723b00900712e00700e009", + "0x1db00923b0091db0095130071db00923b00901100951400701100923b009", + "0x915700712e00923b00900716c00700723b0090070090540071db009009", + "0x95c300700900923b00900700989d00712e00912e00900900923b009009", + "0x712e00989f00900923b12e00700989e00700900900900900923b009009", + "0x923b0091250096ae00712500923b0090090096ad00700723b00900712e", + "0x22500700723b00900712e00700e00900900e00923b00900e0096af00700e", + "0x23b0090110096b000701100923b00912e1fd12e0310071fd00923b009007", + "0x700723b0090070ea0071db0090091db00923b0091db0096af0071db009", + "0x1100900712503a00701100923b00901100903800701100923b009007219", + "0x912e0098a100700723b00900712e00701b01812e8a02231db12e23b12e", + "0x98a20071db00923b0091db00912500700723b00900710f00701f00923b", + "0x90200098a400700723b00900712e0070250098a302001512e23b12e01f", + "0x722c00923b0090230098a600702600923b0090150098a500702300923b", + "0x8a800723c00923b00900716c00700723b00900712e0070078a70090070ee", + "0x23b0092290098a600702600923b0090250098a500722900923b00923c009", + "0x8aa00702c00923b00902c0096b800702c00923b0090260098a900722c009", + "0x902e0098ac00700723b00900712e0070300098ab02e00923b12e22c009", + "0x3122512e23b0092250098ae00722500923b0092250098ad00722500923b", + "0x914700700723b00904500915500722103304512523b0090310098af007", + "0x21900923b0090360098b000703600923b00903300950400700723b009221", + "0x712603b03a12523b0090380098af00703822512e23b0092250098ae007", + "0x923b0091260098b100700723b00903b00934f00700723b00903a009155", + "0x925300703c00923b00903c0096b70071db00923b0091db00912500703c", + "0x3e03c1db1258b200703e00923b00903e0096b700703e21912e23b009219", + "0x900712e0070430098b314500923b12e0410096c400704114112e23b009", + "0x6b700714100923b00914100912500714800923b0091450096c600700723b", + "0x14800e1411256c300714800923b0091480096b700700e00923b00900e009", + "0x900712e00704c0098b415000923b12e0490096c400704904712e23b009", + "0x700723b00915300934f00715515315212523b0092250098af00700723b", + "0x923b0090078b500715700923b00915200916300700723b009155009147", + "0x2e00715900923b0091500096c600705400923b00905215712e14f007052", + "0x900712e0070570098b600723b12e05400910600705400923b009054009", + "0x70581fd12e23b0091fd00925300704700923b00904700912500700723b", + "0x580471258b200721900923b0092190096b700705800923b0090580096b7", + "0x712e00715e0098b705d00923b12e15d0096c400715d05a12e23b009219", + "0x705a00923b00905a00912500706000923b00905d0096c600700723b009", + "0x12505a1256c300706000923b0090600096b700712500923b0091250096b7", + "0x712e0071610098b806400923b12e1600096c400716015f12e23b009060", + "0x706700923b00915f00912500716200923b0090640096c600700723b009", + "0x700723b00900712e0070078b90090070ee00716400923b0091620096b7", + "0x700723b00915900914700700723b0091fd00914700700723b0090070ea", + "0x23b00915f00912500716600923b0091610098ba00700723b00902c009146", + "0x12500916600923b0091660098bb00722300923b00922300900e00715f009", + "0x91fd00914700700723b0090070ea00700723b00900712e00716622315f", + "0x12500914700700723b00902c00914600700723b00915900914700700723b", + "0x705a00923b00905a00912500716800923b00915e0098ba00700723b009", + "0x16822305a12500916800923b0091680098bb00722300923b00922300900e", + "0x723b00921900914700700723b00905700911100700723b00900712e007", + "0x90070ea00716400923b0091250096b700706700923b009047009125007", + "0x6b800722300923b00922300900e00706700923b00906700912500700723b", + "0x23b0091590096b700716400923b0091640096b700702c00923b00902c009", + "0x91fd15916402c2230670116c00071fd00923b0091fd0096b7007159009", + "0x900712e0070710098bc06f00923b12e06e0096c100706e06d16b12523b", + "0x17407407216e00e8bd00717407407216e00e23b00906f0096c200700723b", + "0x16b00923b00916b00912500718000923b0090760098be00707600923b009", + "0x6d16b12500918000923b0091800098bb00706d00923b00906d00900e007", + "0x916b00912500707700923b0090710098ba00700723b00900712e007180", + "0x907700923b0090770098bb00706d00923b00906d00900e00716b00923b", + "0x1fd00914700700723b0090070ea00700723b00900712e00707706d16b125", + "0x914700700723b00902c00914600700723b0092250098bf00700723b009", + "0x707800923b00904c0098ba00700723b00921900914700700723b009125", + "0x90780098bb00722300923b00922300900e00704700923b009047009125", + "0x723b0090070ea00700723b00900712e00707822304712500907800923b", + "0x23b00902c00914600700723b0092250098bf00700723b0091fd009147007", + "0x900e00914700700723b00921900914700700723b009125009147007007", + "0xe00714100923b00914100912500718600923b0090430098ba00700723b", + "0x718622314112500918600923b0091860098bb00722300923b009223009", + "0x14700700723b00903000905400700723b0090070ea00700723b00900712e", + "0x907b12500e02c00e8bd00707b00923b00900716c00700723b0091fd009", + "0x71db00923b0091db00912500708d00923b0091870098be00718700923b", + "0x8d2231db12500908d00923b00908d0098bb00722300923b00922300900e", + "0x723b00900e00914700700723b0091fd00914700700723b00900712e007", + "0x923b00900722900700723b00912e00914600700723b009125009147007", + "0x7f12e03000708e00923b00908e00902e00708e00923b00900705d00707f", + "0x923b00908f09012e03100709000923b00900722500708f00923b00908e", + "0x900e00701800923b00901800912500709200923b0090910098ba007091", + "0x8c000709201b01812500909200923b0090920098bb00701b00923b00901b", + "0x700723b00900712e0070111fd12e8c100e12512e23b12e12e009007125", + "0x91db0098c300722300923b0091250091250071db00923b00900e0098c2", + "0x90110098c500700723b00900712e0070078c40090070ee00701800923b", + "0x701800923b00901b0098c300722300923b0091fd00912500701b00923b", + "0x901f01812e8c700701f00923b00901f00902e00701f00923b0090078c6", + "0x723b00900712e0070250098c802000923b12e0150096c400701500923b", + "0x260098ca00702600923b0090230098c900702300923b0090200096c6007", + "0x22c00923b00922c0098cb00722300923b00922300912500722c00923b009", + "0x12500723c00923b0090250098cc00700723b00900712e00722c22312e009", + "0x8cd00723c22312e00923c00923b00923c0098cb00722300923b009223009", + "0x900900915500700723b00900712e0071250098ce12e00923b12e007009", + "0x5130071fd00923b00900e00951200700e00923b00912e00951100700723b", + "0x912500902000700723b00900712e0071fd0090091fd00923b0091fd009", + "0x2250071db00923b00900901112e03000701100923b00900722900700723b", + "0x23b00901800951400701800923b0091db22312e03100722300923b009007", + "0x12e12e0090071258cf00701b00900901b00923b00901b00951300701b009", + "0x923b00900e0098d100700723b00900712e0071fd0098d000e12512e23b", + "0x98d300712500923b0091250091250071db00923b0090110098d2007011", + "0x23b00900722900700723b00900712e0071db12512e0091db00923b0091db", + "0x12e03000701800923b00901800902e00701800923b0090076b5007223009", + "0x23b00901b01f12e03100701f00923b00900722500701b00923b009018223", + "0x8d30071fd00923b0091fd00912500702000923b0090150098d4007015009", + "0x900721900700723b0090070ea0070201fd12e00902000923b009020009", + "0x12e23b12e00e00900712503a00700e00923b00900e00903800700e00923b", + "0x12500700723b00900710f00700723b00900712e0072231db12e8d50111fd", + "0x12e00701f0098d701b01812e23b12e12e0098d60071fd00923b0091fd009", + "0x2000923b00901500931f00701500923b00901b00916500700723b009007", + "0x90070ee00702300923b00902000932000702500923b009018009157007", + "0x902600932100702600923b00900716c00700723b00900712e0070078d8", + "0x702300923b00922c00932000702500923b00901f00915700722c00923b", + "0x90070ea00700723b00900712e0072290098d923c00923b12e023009072", + "0x71fd00923b0091fd00912500702c00923b00923c12512e03000700723b", + "0x902c00915700702500923b00902500915700701100923b00901100900e", + "0x2250095c500722503002e12523b00902c0250111fd00e6e400702c00923b", + "0x12523b0090310095c600700723b00900712e0070450098da03100923b12e", + "0x923b00921900981600721900923b009036221033125815007036221033", + "0x96ed00703000923b00903000900e00702e00923b00902e009125007038", + "0x450096ec00700723b00900712e00703803002e12500903800923b009038", + "0x3000923b00903000900e00702e00923b00902e00912500703a00923b009", + "0x700723b00900712e00703a03002e12500903a00923b00903a0096ed007", + "0x703b00923b00900716c00700723b00922900905400700723b0090070ea", + "0x912500703c00923b00912600981600712600923b00903b125025125815", + "0x923b00903c0096ed00701100923b00901100900e0071fd00923b0091fd", + "0x700723b00912e00905700700723b00900712e00703c0111fd12500903c", + "0x14100923b00900705d00703e00923b00900722900700723b009125009057", + "0x722500704100923b00914103e12e03000714100923b00914100902e007", + "0x923b0090430096ec00704300923b00904114512e03100714500923b009", + "0x96ed00722300923b00922300900e0071db00923b0091db009125007148", + "0x712500712e23b0090070098db0071482231db12500914800923b009148", + "0x900e00902e00700723b0091fd0091550071fd00e12e23b0091250098dc", + "0x1112e23b00900900e12e05200700900923b00900900915700700e00923b", + "0x915500701822312e23b0090070098dc00700723b0091db0090540071db", + "0x12e00923b00912e00915700701800923b00901800902e00700723b009223", + "0x716c00700723b00901f00905400701f01b12e23b00912e01812e052007", + "0x1b00923b00901b00915700701100923b00901100915700701500923b009", + "0xea00700723b00900716000701100923b0090078dd00701501b011125009", + "0x12e23b0091db0098df0071db12e12e23b00912e0098de00700723b009007", + "0x915700722300923b00922300902e00700723b0090180095d8007018223", + "0x901b00905400701b1fd12e23b00912522312e05200712500923b009125", + "0x12500700723b00901f00915500701501f12e23b00912e0098df00700723b", + "0x23b00901500931500700900923b00900900900e00700700923b009007009", + "0x71fd00923b0091fd01112e26200700e00923b00900e009157007015009", + "0x2600923b12e02300906e00702302502012523b00900e01500900700e8e0", + "0x5400722923c12e23b00902600906f00700723b00900712e00722c0098e1", + "0x23b00902c23c1fd12581500702c00923b00900716c00700723b009229009", + "0xe00702000923b00902000912500703000923b00902e00981600702e009", + "0x703002502012500903000923b0090300096ed00702500923b009025009", + "0x22500923b00922c0096ec00700723b0091fd00905700700723b00900712e", + "0x2250096ed00702500923b00902500900e00702000923b009020009125007", + "0x8e300712500712e23b0090070098e200722502502012500922500923b009", + "0x23b00900e00950400700723b0091fd0091550071fd00e12e23b009125009", + "0x722300923b0091db12e12e0300071db00923b009011009505007011009", + "0x901b00902e00700723b00901800934f00701b01812e23b0090070098e3", + "0x1f12e23b00922301b12e05200722300923b00922300915700701b00923b", + "0x900900915700702000923b00900716c00700723b009015009054007015", + "0x70098e400702001f00912500901f00923b00901f00915700700900923b", + "0x23b0091fd0091550071fd00e12e23b0091250098e500712500712e23b009", + "0x12e0300071db00923b00901100950500701100923b00900e009504007007", + "0x901800934f00701b01812e23b0090070098e500722300923b0091db12e", + "0x5200722300923b00922300915700701b00923b00901b00902e00700723b", + "0x23b00900716c00700723b00901500905400701501f12e23b00922301b12e", + "0x12500901f00923b00901f00915700700900923b009009009157007020009", + "0x712500923b00912500902e00712500923b0090070098e600702001f009", + "0x90540071fd00e12e23b00912e12512e05200712e00923b00912e009157", + "0x700900923b00900900915700701100923b00900716c00700723b0091fd", + "0x12500923b0090070098e700701100e00912500900e00923b00900e009157", + "0x12512e05200712e00923b00912e00915700712500923b00912500902e007", + "0x1100923b00900716c00700723b0091fd0090540071fd00e12e23b00912e", + "0xe00912500900e00923b00900e00915700700900923b009009009157007", + "0x900900915700712500923b00900716c00700723b0090070098e8007011", + "0x70098e900712512e00912500912e00923b00912e00915700700900923b", + "0x12e00923b00912e00915700712500923b00912500902e00712500923b009", + "0x716c00700723b0091fd0090540071fd00e12e23b00912e12512e052007", + "0xe00923b00900e00915700700900923b00900900915700701100923b009", + "0x923b00912500902e00712500923b0090070098ea00701100e009125009", + "0x71fd00e12e23b00912e12512e05200712e00923b00912e009157007125", + "0x923b00900900915700701100923b00900716c00700723b0091fd009054", + "0x23b0090070098eb00701100e00912500900e00923b00900e009157007009", + "0x5200712e00923b00912e00915700712500923b00912500902e007125009", + "0x23b00900716c00700723b0091fd0090540071fd00e12e23b00912e12512e", + "0x12500900e00923b00900e00915700700900923b009009009157007011009", + "0x712500923b0091250091bc00712500923b0090070098ec00701100e009", + "0x90540071fd00e12e23b00912e12512e8ed00712e00923b00912e009157", + "0x700900923b00900900915700701100923b00900716c00700723b0091fd", + "0x12500923b0090070098ee00701100e00912500900e00923b00900e009157", + "0x12512e05200700900923b00900900915700712500923b00912500902e007", + "0x1100923b00900716c00700723b0091fd0090540071fd00e12e23b009009", + "0x923b0090070098ef00701112e00e12500912e00923b00912e009157007", + "0x12e05200700900923b00900900915700712500923b00912500902e007125", + "0x923b00900716c00700723b0091fd0090540071fd00e12e23b009009125", + "0x923b00900755f00701112e00e12500912e00923b00912e009157007011", + "0x12e23b00912500957000700723b0090070ea00700723b0090071600071fd", + "0x700723b0091db0091010070182231db12523b009011009571007011125", + "0x900e1fd12e57a00700e00923b00901800901f00700723b009223009155", + "0x37b00701f00923b00900714c00701b00923b00900e0090df00700e00923b", + "0x902000957100702012512e23b00912500957000701500923b00901f009", + "0x700723b00902300915500700723b00902500910100702602302512523b", + "0x900900900e00700700923b00900700912500722c00923b009026009058", + "0x722c00923b00922c0091fd00712e00923b00912e00909900700900923b", + "0x23c00902e00723c01b12e23b00901b00936b00701500923b009015009600", + "0x3002e02c22900e23b00923c01522c12e0090070118f000723c00923b009", + "0x714c00700723b00900712e0070310098f222500923b12e0300098f1007", + "0x722100923b0090078f300703300923b00904500937b00704500923b009", + "0x922100902e00703600923b00903600902e00703600923b00903300937d", + "0x23b00912500957000703821912e23b00922103602e12537e00722100923b", + "0x723b00912600915500703c12603b12523b00903a00957100703a12512e", + "0x903e00910400703e00923b00903b00910200700723b00903c009572007", + "0x714500923b00904100937d00704100923b00903800937b00714100923b", + "0x37b00714804312e23b00914114521912537e00714500923b00914500902e", + "0x4900910100704c15004912523b00912500957100704700923b009148009", + "0x37d00715200923b00915000916300700723b00904c00957200700723b009", + "0x15215304312537e00715300923b00915300902e00715300923b009047009", + "0x923b00905200937d00705200923b00915700937b00715715512e23b009", + "0x5715912e23b00901b05415512537e00705400923b00905400902e007054", + "0x960500700723b00905800915e00715d05a05812523b0092250098f4007", + "0x15e00923b00905d00937d00705d00923b00905700937b00700723b00905a", + "0x715f06012e23b00915d15e15912537e00715e00923b00915e00902e007", + "0x23b00916000937d00706400923b0090078f500716000923b00915f00937b", + "0x37e00706400923b00906400902e00716100923b00916100902e007161009", + "0x937d00716400923b00906700937b00706716212e23b009064161060125", + "0x923b00916800933000716800923b00916600932f00716600923b009164", + "0x909900702c00923b00902c00900e00722900923b00922900912500716b", + "0x716b16202c22900e00916b00923b00916b00933100716200923b009162", + "0x700723b00912500958100700723b00901b00915500700723b00900712e", + "0x902c00900e00722900923b00922900912500706d00923b009031009332", + "0x906d00923b00906d00933100702e00923b00902e00909900702c00923b", + "0x23b12e12500986100712500912e23b00900900986500706d02e02c22900e", + "0x903300700723b00912e00915500700723b00900712e00700e0098f6007", + "0x70078f70090070ee00701100923b00900900985f0071fd00923b009007", + "0x71db00923b0090078f800700723b00900900986300700723b00900712e", + "0x701800923b0090180098fa00701822312e23b00900e12e1db00700e8f9", + "0x712e0070078fc01b00923b12e0180098fb00722300923b009223009033", + "0x701500923b00901f00985f00701f00923b00901b00985900700723b009", + "0x85f00702000923b0090078fe00700723b00900712e0070078fd0090070ee", + "0x23b00901500985f0071fd00923b00922300903300701500923b009020009", + "0x12e12e00986100712e00712e23b0090070098650070111fd12e009011009", + "0x85f00700723b00900700986300700723b00900712e0071250098ff00723b", + "0x12e00900986100700723b00900712e00700900900900900923b009009009", + "0x85f00700723b00912500990100700723b00900712e00700e00990000723b", + "0x900700986300700723b00900712e00700700900900700923b009007009", + "0x8fa00701100923b0091251fd12e9020071fd00923b0090078f800700723b", + "0x91db0098fa0071db00923b00900e01112e90200701100923b009011009", + "0x700723b00900712e00700790322300923b12e1db0098fb0071db00923b", + "0x9040090070ee00701b00923b00901800985f00701800923b009223009859", + "0x23b00901f00985f00701f00923b0090078fe00700723b00900712e007007", + "0x23b12e12e00986100712e00912e23b00900900986500701b00900901b009", + "0x985f00700723b00900900986300700723b00900712e007125009905007", + "0x23b00912500990100700723b00900712e00700700900900700923b009007", + "0x985f00700700923b00900700985f00700e00923b009009009906007007", + "0x1259070071fd0090091fd00923b00900e00712e86600700e00923b00900e", + "0x90900700723b00900712e0070111fd12e90800e12512e23b12e12e009007", + "0x23b0091db00990a00722300923b0091250091250071db00923b00900e009", + "0x23b00901100990c00700723b00900712e00700790b0090070ee007018009", + "0x90d00701800923b00901b00990a00722300923b0091fd00912500701b009", + "0x23b00901f01812e90e00701f00923b00901f00902e00701f00923b009007", + "0x700723b00900712e00702500990f02000923b12e015009875007015009", + "0x902600991100702600923b00902300991000702300923b009020009877", + "0x922c00923b00922c00991200722300923b00922300912500722c00923b", + "0x912500723c00923b00902500991300700723b00900712e00722c22312e", + "0x912500723c22312e00923c00923b00923c00991200722300923b009223", + "0x923b00912e0096b700700900923b0090090096b700700700923b009007", + "0x1fd00923b12e00e00991500700e12512e23b00912e00900712591400712e", + "0x98ca0071db00923b0091fd0098c900700723b00900712e007011009916", + "0x923b0092230098cb00712500923b00912500912500722300923b0091db", + "0x22900700723b00901100905400700723b00900712e00722312512e009223", + "0x1b00923b00901b00902e00701b00923b00900791700701800923b009007", + "0x1512e03100701500923b00900722500701f00923b00901b01812e030007", + "0x923b00912500912500702500923b0090200098cc00702000923b00901f", + "0x923b12e00700991800702512512e00902500923b0090250098cb007125", + "0x98c900700723b00900900915500700723b00900712e00712500991912e", + "0x923b0091fd0098cb0071fd00923b00900e0098ca00700e00923b00912e", + "0x722900700723b00912500914700700723b00900712e0071fd0090091fd", + "0x22300923b0090072250071db00923b00900901112e03000701100923b009", + "0x98cb00701b00923b0090180098cc00701800923b0091db22312e031007", + "0x23b00912e00991a00700723b0090070ea00701b00900901b00923b00901b", + "0x701100923b0091fd0095ca0071fd00923b00900e00991b00700e12e12e", + "0x22300902000701822312e23b0091db0090150071db00923b009011009240", + "0x701f00923b00901b0090df00701b00923b00901800902300700723b009", + "0x12e00991b00701500923b00901f12512e03000701f00923b00901f00902e", + "0x900923b00900900900e00700700923b00900700912500702000923b009", + "0x700e31600701500923b00901500915700702000923b009020009315007", + "0x23c00991c22c00923b12e02600906e00702602302512523b009015020009", + "0x2c22912e31800702c22912e23b00922c00906f00700723b00900712e007", + "0x2500923b00902500912500703000923b00902e00931900702e00923b009", + "0x2302512500903000923b00903000931a00702300923b00902300900e007", + "0x902500912500722500923b00923c00931b00700723b00900712e007030", + "0x922500923b00922500931a00702300923b00902300900e00702500923b", + "0x12500923b00912e00963e00712e00923b00900700963c007225023025125", + "0x1fd00902e00700723b00900e0091550071fd00e12e23b009125009153007", + "0x12e23b0090091fd12e05200700900923b0090090091570071fd00923b009", + "0x22301112e00922300923b00900716c00700723b0091db0090540071db011", + "0x923b00901100903800701100923b00900721900700723b0090070ea007", + "0x900712e00701b01812e91d2231db12e23b12e01100900712503a007011", + "0x1db00912500700723b00900710f00701f00923b00912500901b00700723b", + "0x900712e00702500991e02001512e23b12e01f0091750071db00923b009", + "0xec00702600923b0090150090b400702300923b00902000917100700723b", + "0x16c00700723b00900712e00700791f0090070ee00722c00923b009023009", + "0x923b0090250090b400722900923b00923c0090f000723c00923b009007", + "0x91fd00702c00923b00902600905800722c00923b0092290090ec007026", + "0x900712e00703000992002e00923b12e22c00916900702c00923b00902c", + "0x22500916300722500923b00902e00916500700723b0090070ea00700723b", + "0x3100923b00903100902e00704500923b00900e00937d00703100923b009", + "0x703600923b00922100937b00722103312e23b00903104512e12537e007", + "0x903300909900722300923b00922300900e0071db00923b0091db009125", + "0x703600923b00903600960000702c00923b00902c0091fd00703300923b", + "0x21900e23b0091fd03602c0332231db0118f00071fd00923b0091fd00902e", + "0x723b00900712e00703c00992112600923b12e03b0098f100703b03a038", + "0x14500923b00904114103e12592200704114103e12523b0091260098f4007", + "0x3800900e00721900923b00921900912500704300923b009145009923007", + "0x4300923b00904300926500703a00923b00903a00909900703800923b009", + "0x14800923b00903c00992400700723b00900712e00704303a03821900e009", + "0x3a00909900703800923b00903800900e00721900923b009219009125007", + "0x12e00714803a03821900e00914800923b00914800926500703a00923b009", + "0x983d00700723b00903000905400700723b0090070ea00700723b009007", + "0x1fd04912e12537e00704900923b00904700937d00704700e12e23b00900e", + "0x923b00915200937d00715200923b00904c00937b00704c15012e23b009", + "0x715700923b00915500992300715500923b00915300e02c125922007153", + "0x915000909900722300923b00922300900e0071db00923b0091db009125", + "0x712e0071571502231db00e00915700923b00915700926500715000923b", + "0x960500700723b00912500915e00700723b0091fd00915500700723b009", + "0x2e00705400923b00900705d00705200923b00900722900700723b00900e", + "0x23b00900722500715900923b00905405212e03000705400923b009054009", + "0x705a00923b00905800992400705800923b00915905712e031007057009", + "0x912e00909900701b00923b00901b00900e00701800923b009018009125", + "0x992500705a12e01b01800e00905a00923b00905a00926500712e00923b", + "0x23b00900900915500700723b00900712e00712500992612e00923b12e007", + "0x99120071fd00923b00900e00991100700e00923b00912e009910007007", + "0x23b00912500950c00700723b00900712e0071fd0090091fd00923b0091fd", + "0x72250071db00923b00900901112e03000701100923b009007229007007", + "0x923b00901800991300701800923b0091db22312e03100722300923b009", + "0x12523b00912e00912e92700701b00900901b00923b00901b00991200701b", + "0x71fd00923b0091fd00992800700700923b0090070091250071fd00e125", + "0x12512e92a00700723b0091db0090540071db01112e23b0091fd00712e929", + "0x23b00901800992b00701b01812e23b00922300926400722300923b00900e", + "0x10600701b00923b00901b0096b700701f00923b00901f00902e00701f009", + "0x23b00901b00992d00700723b00900712e00701500992c00723b12e01f009", + "0x900712e00700792f0090070ee00702500923b00902000992e007020009", + "0x900716c00700723b00901b00914700700723b00901500911100700723b", + "0x702500923b00902600992e00702600923b00902300993000702300923b", + "0x702501112e00902500923b00902500992e00701100923b009011009125", + "0x912e00912500712500923b00900716c00712e00923b00900900712e931", + "0x1371131231060071fd01f1131231060071fd11112512e12e00912e00923b", + "0x12512e00900713711312300700e01f11312300700e00700e12512e009007", + "0x1136800e12512e0090071371131231060071fd01f1131231060071fd0cf", + "0x4b01fd00e12512e00900713711312310600710701101f113123106007107", + "0x1071fd63b00e12512e0090071371131230071071fd01f1131230071071fd", + "0x11312300700e6d100e12512e0090071371131230071071fd01f113123007", + "0x11312300700e01f11312300700e89812512e00900713711312300700e01f", + "0x90071371131231060071fd01f1131231060071fd93212512e009007137", + "0x12512e0090071371131231060071fd01f1131231060071fd93300e12512e", + "0x12512e00900713711312310600710701101f11312310600710701193400e", + "0x700e93612512e00900713711312300700e01f11312300700e9351fd00e", + "0x700e01f11312300700e93712512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e93812512e009007137113123", + "0x700e93a12512e00900713711312300700e01f11312300700e93912512e", + "0x700e01f11312300700e93b12512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e93c12512e009007137113123", + "0x700e93e12512e00900713711312300700e01f11312300700e93d12512e", + "0x700e01f11312300700e93f12512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94012512e009007137113123", + "0x700e94212512e00900713711312300700e01f11312300700e94112512e", + "0x700e01f11312300700e94312512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94412512e009007137113123", + "0x700e94612512e00900713711312300700e01f11312300700e94512512e", + "0x700e01f11312300700e94712512e00900713711312300700e01f113123", + "0x900713711312300700e01f11312300700e94812512e009007137113123", + "0xe12512e0090071371131231060071fd01f1131231060071fd94912512e", + "0x1f12300712594b12512e00900713711312300700e01f11312300700e94a", + "0x1131231060071fd0380f611312310600701194c12e009007128123007125", + "0x1230071fd94e00900700e01812e01801512e94d1fd00e12512e00900713b", + "0x12501807812300700e94f00e12512e00900714311312300700e0380f6113", + "0x12501f12300712595100714601f12e01f00995012512e009007144123007", + "0x1131231060071fd0180150f61131231060071db95212e009007147123007", + "0x12e00900714c12300712501f1230071259530111fd00e12512e009007149", + "0x12e0090071431131071231060070110181010f6113107123106007223954", + "0x71491131071230071fd1010f61131071230070119551db0111fd00e125", + "0x71511131071230071fd0150f61131071230070119561fd00e12512e009", + "0x712501f00712e95800900700e01812e01806412e9571fd00e12512e009", + "0x12e00900715611312300700e0180600f611312300701195900900715401f", + "0x71fd95b12512e00900714412300712501801b12300700e95a1fd00e125", + "0x11312310600701195c00e12512e00900715611312300700e0180f6113123", + "0x11312310600701895d1fd00e12512e0090071491131231060071fd0150f6", + "0x2231db0111fd00e12512e0090071491131231060071fd0150150150150f6", + "0x900715c1131071231060070110150150150f611310712310600701895e", + "0x715c11312300700e0150f61131230071fd95f2231db0111fd00e12512e", + "0x12512e00900715c11312300700e0150f61131230071fd96000e12512e009", + "0x1fd96200e12512e00900715c11312300700e0150f61131230071fd96100e", + "0x11312300700e96300e12512e00900715c11312300700e0150f6113123007", + "0x11312300700e0f611312300700e96412512e00900715c11312300700e0f6", + "0x12512e00900715c11312300700e0f611312300700e96512512e00900715c", + "0x1131231250f611312312596712e0090071491131231250f6113123125966", + "0x12300700e96912e0090071491131231250f611312312596812e009007149", + "0x900700e01812e01805712e96a12512e00900716311312300700e0f6113", + "0x11312300700e96d00900700e01812e01816512e96c0071650090f600996b", + "0x11312300700e0f611312300700e96e12512e00900716911312300700e0f6", + "0x12512e00900716c11312300700e0f611312300700e96f12512e009007169", + "0xf612e9720090070640090150f612e97100900700e01812e0180ec12e970", + "0x1491131231060071fd0180150f61131231060071db973009007015009015", + "0x15c11312300700e0150150f61131230070119740111fd00e12512e009007", + "0x12e00900712812300712501503801f1230071fd9751fd00e12512e009007", + "0x17911312312511312312e97700900717511312312511312312e97600e125", + "0x715c1131231060071fd06401f01503b0f6113123106007018978009007", + "0x718411312300700e03b11312300700e9792231db0111fd00e12512e009", + "0xe12512e00900715c11312300700e08e0f61131230071fd97a12512e009", + "0x1801f1230071fd97c12512e00900714412300712501807f12300700e97b", + "0x1fd01f0150f61131231060071db97d00e12512e009007147123007125015", + "0x18801f00712501f00712e97e0111fd00e12512e009007151113123106007", + "0x18a12300712501f12300712598000900718900712e01500712e97f009007", + "0xd811310712300701198200900718e11312312511312312e98112e009007", + "0x11312312511312312e9831fd00e12512e0090071511131071230071fd015", + "0x1db98512512e00900714910712300700e10110712300700e984009007175", + "0x111fd00e12512e0090071981131071230071fd0640150d8113107123007", + "0x719f00905200998712512e00900715111312312501519b11312300e986", + "0x71fd98900e12512e00900715c11312300700e0970f61131230071fd988", + "0x1801f12300700e98a00e12512e0090071a111312300700e0181a0113123", + "0x12e0090071491131231250b411312312598b12512e009007144123007125", + "0x1131231250ac11312312598d12e0090071491131231250b011312312598c", + "0x98f12512e0090071a811312300700e0cb11312300700e98e12e009007149", + "0x12e0090071aa1131231250600cb11312300e99000900706400906006012e", + "0xe99200e12512e00900715c11312300700e0980f61131230071fd991125", + "0x150f61131231060071db99312512e0090071ad12300712506d03b123007", + "0x1071231060070189940111fd00e12512e00900719f1131231060071fd01f", + "0x1db0111fd00e12512e00900719f1131071231060070110150150150f6113", + "0x12300700e99612512e00900716311312300700e0c011312300700e995223", + "0x9980090070640090c40c412e99712512e0090071b311312300700e02c113", + "0xc40c412e99900e12512e0090071b611312300700e0570c01131230071fd", + "0x12512e00900715c11312300700e0930f61131230071fd99a009007064009", + "0xb811312300e99c12512e0090071b91131231250410bc11312300e99b00e", + "0x71bb1131231250150b411312300e99d12512e0090071ba113123125041", + "0xe12512e00900715c11312300700e0940f61131230071fd99e12512e009", + "0x12300e9a000e12512e00900715c11312300700e0990f61131230071fd99f", + "0x700e0950f61131230071fd9a112512e0090071bd1131231250150b0113", + "0x90071bc1131231250150ac11312300e9a200e12512e00900715c113123", + "0x9a400e12512e00900715c11312300700e0960f61131230071fd9a312512e", + "0x12300700e08f0f61131230071fd9a512e00900718e00712e02c02c007125", + "0x715c11312300700e0900f61131230071fd9a600e12512e00900715c113", + "0x12512e00900715c11312300700e0910f61131230071fd9a700e12512e009", + "0xe9a900e12512e00900715c11312300700e0920f61131230071fd9a800e", + "0xe0bc11312300700e9aa12512e00900716911312300700e0b8113123007", + "0x71fd9ac00900700e01812e0180c412e9ab12512e009007169113123007", + "0x12501f1230071259ad00e12512e00900715c11312300700e08d0f6113123", + "0x3a0071259af0090071b511312312511312312e9ae12e0090071b8123007", + "0x900719f11312300700e04111312300700e9b012e0090071ac00712e041", + "0xf61131231060071db9b212e00900716900712e0410410071259b112512e", + "0x1231060071db9b30111fd00e12512e0090071511131231060071fd01f015", + "0x70119b40111fd00e12512e0090071511131231060071fd01f0150f6113", + "0x908e0099b51fd00e12512e0090071a711312300700e07701503b113123", + "0x99b700e12512e0090071871230071250180181a51230071fd9b60071a5", + "0x12e9b912512e00900714412300712501801f12300700e9b800719f009052", + "0x700e9bb00900716e11312312511312312e9ba00900717400712e01f007", + "0x70119bd0071510091660099bc12512e00900716b1070071250150d8107", + "0x91620099be1fd00e12512e00900716410712300700e01502003b107123", + "0x970099c100900719f00901505212e9c000716101f12e01f0099bf007137", + "0x99c400900715400712e01500712e9c30071490091600099c20071a5009", + "0x119c700900706400906d06d12e9c60071a50090980099c50071a800915f", + "0x1230071fd9c81fd00e12512e009007064106007125015015015015106007", + "0x9ca0071630090580099c900e12512e00900715d11312300700e16b041113", + "0x15911312300700e05716b0411131230070119cb00900706400900e00e12e", + "0x99ce0071a50090940099cd0071a50090930099cc1fd00e12512e009007", + "0x1515712e9d10071a50090960099d00071a50090950099cf0071a5009099", + "0x90910099d40071a50090900099d30071a500908f0099d200900718e009", + "0x1530099d700900715500712e01500712e9d60071a50090920099d50071a5", + "0x99da0071a500908d0099d900900700e01812e01800e12e9d8007169009", + "0x12512e0090071501230071250090090090471230070119db0071b5009152", + "0x716900901514512e9dd12e00900714800712e0090090071259dc1fd00e", + "0x712501801812300700e9df12e00900714100712e04101b0071259de009", + "0x1fd9e112e00900700e01801812501801808d1259e012512e009007187123", + "0x12501801808f1259e200e12512e00900718712300712501801808e123007", + "0x1259e412e00900700e0180181250180180901259e312e00900700e018018", + "0x700e0180181250180180921259e512e00900700e018018125018018091", + "0x1250180180941259e712e00900700e0180181250180180931259e612e009", + "0x1259e912e00900700e0180181250180180951259e812e00900700e018018", + "0x700e0180181250180180971259ea12e00900700e018018125018018096", + "0x1250180180991259ec12e00900700e0180181250180180981259eb12e009", + "0x12e00900714910712300700e05b10712300700e9ed12e00900700e018018", + "0x900703600903603612e9ef12e00900703610612e0150361061259ee125", + "0x9f212e00900722100712e0110110071259f100900703600903603612e9f0", + "0xe9f400900714800901522912e9f312e00900714800712e009009007125", + "0x700e01812e01806012e9f512512e00900714412300712501807f123007", + "0x1fd00e12512e00900722c10712300700e01502001f1071230070119f6009", + "0x9f912e0090071fd00712e0090090071259f80090072210090151db12e9f7", + "0x9fa00900700e00712e12500712e" + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x233f7eb4ceacfd7c3e238afaf740a3ffcb352f9844a11df665e97c3b0370b6", + "function_idx": 4 + }, + { + "selector": "0x29ce6d1019e7bef00e94df2973d8d36e9e9b6c5f8783275441c9e466cb8b43", + "function_idx": 14 + }, + { + "selector": "0x7ec457cd7ed1630225a8328f826a29a327b19486f6b2882b4176545ebdbe3d", + "function_idx": 3 + }, + { + "selector": "0x9278fa5f64a571de10741418f1c4c0c4322aef645dd9d94a429c1f3e99a8a5", + "function_idx": 29 + }, + { + "selector": "0x960e70c0b7135476e33b1ba6a72e9b10cb5e261ebaa730d1ed01a0f21c22d3", + "function_idx": 12 + }, + { + "selector": "0xf2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd", + "function_idx": 6 + }, + { + "selector": "0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283", + "function_idx": 27 + }, + { + "selector": "0x139562604eb722f14da2b8c1f8f681c99d31226bf9d57f148ec8b4d611f92f8", + "function_idx": 24 + }, + { + "selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "function_idx": 1 + }, + { + "selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "function_idx": 0 + }, + { + "selector": "0x1746f7542cac71b5c88f0b2301e87cd9b0896dab1c83b8b515762697e521040", + "function_idx": 10 + }, + { + "selector": "0x178e27745484c91a084e6a72059b13e3dbebef761175a63f4330bec3ad4aaa0", + "function_idx": 21 + }, + { + "selector": "0x1a1e41f464a235695e5050a846a26ca22ecc27acac54be5f6666848031efb8f", + "function_idx": 7 + }, + { + "selector": "0x1e6d35df2b9d989fb4b6bbcebda1314e4254cbe5e589dd94ff4f29ea935e91c", + "function_idx": 5 + }, + { + "selector": "0x213dfe25e2ca309c4d615a09cfc95fdb2fc7dc73fbcad12c450fe93b1f2ff9e", + "function_idx": 31 + }, + { + "selector": "0x22e07fe65aff1304b57cc48ee7c75a04ce2583b5ef2e7866eb8acbe09be43e2", + "function_idx": 25 + }, + { + "selector": "0x231c71f842bf17eb7be2cd595e2ad846543dbbbe46c1381a6477a1022625d60", + "function_idx": 17 + }, + { + "selector": "0x24fd89f2d8a7798e705aa5361f39154ca43e03721c05188285138f16018955d", + "function_idx": 19 + }, + { + "selector": "0x26e71b81ea2af0a2b5c6bfceb639b4fc6faae9d8de072a61fc913d3301ff56b", + "function_idx": 13 + }, + { + "selector": "0x28420862938116cb3bbdbedee07451ccc54d4e9412dbef71142ad1980a30941", + "function_idx": 2 + }, + { + "selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "function_idx": 8 + }, + { + "selector": "0x29e211664c0b63c79638fbea474206ca74016b3e9a3dc4f9ac300ffd8bdf2cd", + "function_idx": 30 + }, + { + "selector": "0x2a4bb4205277617b698a9a2950b938d0a236dd4619f82f05bec02bdbd245fab", + "function_idx": 22 + }, + { + "selector": "0x2aa20ff86b29546fd697eb81064769cf566031d56b10b8bba2c70125bd8403a", + "function_idx": 28 + }, + { + "selector": "0x2ad0f031c5480fdb7c7a0a026c56d2281dcc7359b88bd9053a8cf10048d44c4", + "function_idx": 20 + }, + { + "selector": "0x309e00d93c6f8c0c2fcc1c8a01976f72e03b95841c3e3a1f7614048d5a77ead", + "function_idx": 11 + }, + { + "selector": "0x31341177714d81ad9ccd0c903211bc056a60e8af988d0fd918cc43874549653", + "function_idx": 23 + }, + { + "selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "function_idx": 9 + }, + { + "selector": "0x395b662db8770f18d407bbbfeebf45fffec4a7fa4f6c7cee13d084055a9387d", + "function_idx": 15 + }, + { + "selector": "0x3ad2979f59dc1535593f6af33e41945239f4811966bcd49314582a892ebcee8", + "function_idx": 16 + }, + { + "selector": "0x3ce4edd1dfe90e117a8b46482ea1d41700d9d00c1dccbce6a8e2f812c1882e4", + "function_idx": 26 + }, + { + "selector": "0x3ee0bfaf5b124501fef19bbd1312e71f6966d186c42eeb91d1bff729b91d1d4", + "function_idx": 18 + } + ], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 32 + } + ], + "L1_HANDLER": [] + }, + "abi": "[{\"type\": \"impl\", \"name\": \"Account\", \"interface_name\": \"argent::common::account::IAccount\"}, {\"type\": \"struct\", \"name\": \"core::starknet::account::Call\", \"members\": [{\"name\": \"to\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}]}, {\"type\": \"struct\", \"name\": \"core::array::Span::\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::\"}]}, {\"type\": \"interface\", \"name\": \"argent::common::account::IAccount\", \"items\": [{\"type\": \"function\", \"name\": \"__validate__\", \"inputs\": [{\"name\": \"calls\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"__execute__\", \"inputs\": [{\"name\": \"calls\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::>\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"is_valid_signature\", \"inputs\": [{\"name\": \"hash\", \"type\": \"core::felt252\"}, {\"name\": \"signature\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"ExecuteFromOutsideImpl\", \"interface_name\": \"argent::common::outside_execution::IOutsideExecution\"}, {\"type\": \"struct\", \"name\": \"core::array::Span::\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::\"}]}, {\"type\": \"struct\", \"name\": \"argent::common::outside_execution::OutsideExecution\", \"members\": [{\"name\": \"caller\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"nonce\", \"type\": \"core::felt252\"}, {\"name\": \"execute_after\", \"type\": \"core::integer::u64\"}, {\"name\": \"execute_before\", \"type\": \"core::integer::u64\"}, {\"name\": \"calls\", \"type\": \"core::array::Span::\"}]}, {\"type\": \"enum\", \"name\": \"core::bool\", \"variants\": [{\"name\": \"False\", \"type\": \"()\"}, {\"name\": \"True\", \"type\": \"()\"}]}, {\"type\": \"interface\", \"name\": \"argent::common::outside_execution::IOutsideExecution\", \"items\": [{\"type\": \"function\", \"name\": \"execute_from_outside\", \"inputs\": [{\"name\": \"outside_execution\", \"type\": \"argent::common::outside_execution::OutsideExecution\"}, {\"name\": \"signature\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::>\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"is_valid_outside_execution_nonce\", \"inputs\": [{\"name\": \"nonce\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::bool\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_outside_execution_message_hash\", \"inputs\": [{\"name\": \"outside_execution\", \"type\": \"argent::common::outside_execution::OutsideExecution\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"UpgradeableImpl\", \"interface_name\": \"argent::common::upgrade::IUpgradeable\"}, {\"type\": \"interface\", \"name\": \"argent::common::upgrade::IUpgradeable\", \"items\": [{\"type\": \"function\", \"name\": \"upgrade\", \"inputs\": [{\"name\": \"new_implementation\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"execute_after_upgrade\", \"inputs\": [{\"name\": \"data\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::array::Array::\"}], \"state_mutability\": \"external\"}]}, {\"type\": \"impl\", \"name\": \"ArgentAccountImpl\", \"interface_name\": \"argent::account::interface::IArgentAccount\"}, {\"type\": \"struct\", \"name\": \"argent::account::escape::Escape\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\"}, {\"name\": \"escape_type\", \"type\": \"core::felt252\"}, {\"name\": \"new_signer\", \"type\": \"core::felt252\"}]}, {\"type\": \"struct\", \"name\": \"argent::common::version::Version\", \"members\": [{\"name\": \"major\", \"type\": \"core::integer::u8\"}, {\"name\": \"minor\", \"type\": \"core::integer::u8\"}, {\"name\": \"patch\", \"type\": \"core::integer::u8\"}]}, {\"type\": \"enum\", \"name\": \"argent::account::escape::EscapeStatus\", \"variants\": [{\"name\": \"None\", \"type\": \"()\"}, {\"name\": \"NotReady\", \"type\": \"()\"}, {\"name\": \"Ready\", \"type\": \"()\"}, {\"name\": \"Expired\", \"type\": \"()\"}]}, {\"type\": \"interface\", \"name\": \"argent::account::interface::IArgentAccount\", \"items\": [{\"type\": \"function\", \"name\": \"__validate_declare__\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"__validate_deploy__\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::felt252\"}, {\"name\": \"contract_address_salt\", \"type\": \"core::felt252\"}, {\"name\": \"owner\", \"type\": \"core::felt252\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"change_owner\", \"inputs\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\"}, {\"name\": \"signature_r\", \"type\": \"core::felt252\"}, {\"name\": \"signature_s\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"change_guardian\", \"inputs\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"change_guardian_backup\", \"inputs\": [{\"name\": \"new_guardian_backup\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"trigger_escape_owner\", \"inputs\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"trigger_escape_guardian\", \"inputs\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"escape_owner\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"escape_guardian\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"cancel_escape\", \"inputs\": [], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"get_owner\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian_backup\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_escape\", \"inputs\": [], \"outputs\": [{\"type\": \"argent::account::escape::Escape\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_version\", \"inputs\": [], \"outputs\": [{\"type\": \"argent::common::version::Version\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_name\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_guardian_escape_attempts\", \"inputs\": [], \"outputs\": [{\"type\": \"core::integer::u32\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_owner_escape_attempts\", \"inputs\": [], \"outputs\": [{\"type\": \"core::integer::u32\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"get_escape_and_status\", \"inputs\": [], \"outputs\": [{\"type\": \"(argent::account::escape::Escape, argent::account::escape::EscapeStatus)\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"Erc165Impl\", \"interface_name\": \"argent::common::erc165::IErc165\"}, {\"type\": \"interface\", \"name\": \"argent::common::erc165::IErc165\", \"items\": [{\"type\": \"function\", \"name\": \"supports_interface\", \"inputs\": [{\"name\": \"interface_id\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::bool\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"impl\", \"name\": \"DeprecatedArgentAccountImpl\", \"interface_name\": \"argent::account::interface::IDeprecatedArgentAccount\"}, {\"type\": \"interface\", \"name\": \"argent::account::interface::IDeprecatedArgentAccount\", \"items\": [{\"type\": \"function\", \"name\": \"getVersion\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"getName\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"supportsInterface\", \"inputs\": [{\"name\": \"interface_id\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}, {\"type\": \"function\", \"name\": \"isValidSignature\", \"inputs\": [{\"name\": \"hash\", \"type\": \"core::felt252\"}, {\"name\": \"signatures\", \"type\": \"core::array::Array::\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"view\"}]}, {\"type\": \"constructor\", \"name\": \"constructor\", \"inputs\": [{\"name\": \"owner\", \"type\": \"core::felt252\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::AccountCreated\", \"kind\": \"struct\", \"members\": [{\"name\": \"owner\", \"type\": \"core::felt252\", \"kind\": \"key\"}, {\"name\": \"guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"struct\", \"name\": \"core::array::Span::>\", \"members\": [{\"name\": \"snapshot\", \"type\": \"@core::array::Array::>\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::TransactionExecuted\", \"kind\": \"struct\", \"members\": [{\"name\": \"hash\", \"type\": \"core::felt252\", \"kind\": \"key\"}, {\"name\": \"response\", \"type\": \"core::array::Span::>\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeOwnerTriggered\", \"kind\": \"struct\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\", \"kind\": \"data\"}, {\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeGuardianTriggered\", \"kind\": \"struct\", \"members\": [{\"name\": \"ready_at\", \"type\": \"core::integer::u64\", \"kind\": \"data\"}, {\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerEscaped\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianEscaped\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::EscapeCanceled\", \"kind\": \"struct\", \"members\": []}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::GuardianBackupChanged\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_guardian_backup\", \"type\": \"core::felt252\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::AccountUpgraded\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_implementation\", \"type\": \"core::starknet::class_hash::ClassHash\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerAdded\", \"kind\": \"struct\", \"members\": [{\"name\": \"new_owner_guid\", \"type\": \"core::felt252\", \"kind\": \"key\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::OwnerRemoved\", \"kind\": \"struct\", \"members\": [{\"name\": \"removed_owner_guid\", \"type\": \"core::felt252\", \"kind\": \"key\"}]}, {\"type\": \"event\", \"name\": \"argent::account::argent_account::ArgentAccount::Event\", \"kind\": \"enum\", \"variants\": [{\"name\": \"AccountCreated\", \"type\": \"argent::account::argent_account::ArgentAccount::AccountCreated\", \"kind\": \"nested\"}, {\"name\": \"TransactionExecuted\", \"type\": \"argent::account::argent_account::ArgentAccount::TransactionExecuted\", \"kind\": \"nested\"}, {\"name\": \"EscapeOwnerTriggered\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeOwnerTriggered\", \"kind\": \"nested\"}, {\"name\": \"EscapeGuardianTriggered\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeGuardianTriggered\", \"kind\": \"nested\"}, {\"name\": \"OwnerEscaped\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerEscaped\", \"kind\": \"nested\"}, {\"name\": \"GuardianEscaped\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianEscaped\", \"kind\": \"nested\"}, {\"name\": \"EscapeCanceled\", \"type\": \"argent::account::argent_account::ArgentAccount::EscapeCanceled\", \"kind\": \"nested\"}, {\"name\": \"OwnerChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerChanged\", \"kind\": \"nested\"}, {\"name\": \"GuardianChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianChanged\", \"kind\": \"nested\"}, {\"name\": \"GuardianBackupChanged\", \"type\": \"argent::account::argent_account::ArgentAccount::GuardianBackupChanged\", \"kind\": \"nested\"}, {\"name\": \"AccountUpgraded\", \"type\": \"argent::account::argent_account::ArgentAccount::AccountUpgraded\", \"kind\": \"nested\"}, {\"name\": \"OwnerAdded\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerAdded\", \"kind\": \"nested\"}, {\"name\": \"OwnerRemoved\", \"type\": \"argent::account::argent_account::ArgentAccount::OwnerRemoved\", \"kind\": \"nested\"}]}]" +} diff --git a/crates/papyrus_storage/resources/compiled_class.json b/crates/papyrus_storage/resources/compiled_class.json new file mode 100644 index 00000000000..711e201ad1d --- /dev/null +++ b/crates/papyrus_storage/resources/compiled_class.json @@ -0,0 +1,63 @@ +{ + "entry_points_by_type": { + "EXTERNAL": [ + { + "offset": 787, + "builtins": [ + "pedersen", + "range_check" + ], + "selector": "0x11dd528db174d6312644720bceeb9307ba53f6e2937246ac73d5fb30603016" + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "offset": 4305, + "builtins": [ + "range_check" + ], + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ] + }, + "bytecode": [ + "0x40780017fff7fff", + "0x2", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473" + ], + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "pythonic_hints": [ + [ + 2, + [ + "memory[ap + 0] = 0 <= memory[fp + -6]" + ] + ] + ], + "hints": [ + [ + 2, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ] + ], + "compiler_version": "1.0.0" +} diff --git a/crates/papyrus_storage/resources/deprecated_class.json b/crates/papyrus_storage/resources/deprecated_class.json new file mode 100644 index 00000000000..365d76b1f56 --- /dev/null +++ b/crates/papyrus_storage/resources/deprecated_class.json @@ -0,0 +1,5404 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + }, + { + "inputs": [], + "name": "without_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "with_arg", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "num", + "type": "felt" + } + ], + "name": "return_result", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "x", + "type": "felt" + }, + { + "name": "y", + "type": "felt" + } + ], + "name": "bitwise_and", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "value", + "type": "felt" + } + ], + "name": "sqrt", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_storage_read_write", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_long_retdata", + "outputs": [ + { + "name": "a", + "type": "felt" + }, + { + "name": "b", + "type": "felt" + }, + { + "name": "c", + "type": "felt" + }, + { + "name": "d", + "type": "felt" + }, + { + "name": "e", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_library_call", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "lib_selector", + "type": "felt" + }, + { + "name": "nested_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_nested_library_call", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "function_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_call_contract", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "test_replace_class", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deploy_from_zero", + "type": "felt" + } + ], + "name": "test_deploy", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_storage_var", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "salt", + "type": "felt" + }, + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "deployer_address", + "type": "felt" + } + ], + "name": "test_contract_address", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "foo", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "offset": 297, + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ], + "EXTERNAL": [ + { + "offset": 383, + "selector": "0xad451bd0dba3d8d97104e1bfc474f88605ccc7acbe1c846839a120fdf30d95" + }, + { + "offset": 645, + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b" + }, + { + "offset": 332, + "selector": "0xe7def693d16806ca2a2f398d8de5951344663ba77f340ed7a958da731872fc" + }, + { + "offset": 484, + "selector": "0x120c24672855cfe872cb35256ea85172417f2aada7a22c15908906dc5f3c69d" + }, + { + "offset": 407, + "selector": "0x137a07fa9c479e27114b8ae1fbf252f2065cf91a0d8615272e060a7ccf37309" + }, + { + "offset": 680, + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f" + }, + { + "offset": 799, + "selector": "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d" + }, + { + "offset": 615, + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c" + }, + { + "offset": 505, + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50" + }, + { + "offset": 731, + "selector": "0x36fa6de2810d05c3e1a0ebe23f60b9c2f4629bbead09e5a9704e1c5632630d5" + }, + { + "offset": 766, + "selector": "0x38215592552d97419658d30db8f189b242ec2056641de3dff8a7217745ec205" + }, + { + "offset": 316, + "selector": "0x382a967a31be13f23e23a5345f7a89b0362cc157d6fbe7564e6396a83cf4b4f" + }, + { + "offset": 359, + "selector": "0x39a1491f76903a16feed0a6433bec78de4c73194944e1118e226820ad479701" + }, + { + "offset": 577, + "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331" + }, + { + "offset": 442, + "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check", + "bitwise" + ], + "compiler_version": "0.11.1.1", + "data": [ + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x480280027ffb8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x482480017ffe8000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x43616c6c436f6e7472616374", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4c69627261727943616c6c", + "0x400280007ff97fff", + "0x400380017ff97ffa", + "0x400380027ff97ffb", + "0x400380037ff97ffc", + "0x400380047ff97ffd", + "0x482680017ff98000", + "0x7", + "0x480280057ff98000", + "0x480280067ff98000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x4465706c6f79", + "0x400280007ff87fff", + "0x400380017ff87ff9", + "0x400380027ff87ffa", + "0x400380037ff87ffb", + "0x400380047ff87ffc", + "0x400380057ff87ffd", + "0x482680017ff88000", + "0x9", + "0x480280067ff88000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x5265706c616365436c617373", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x3ffffffffffffffffffffffffffffff", + "0x480280017ffc8000", + "0x48307fff80007ffe", + "0x400280027ffc7fff", + "0x480280017ffc8000", + "0x484480017fff8000", + "0x100000000000000000000000000000000", + "0x480280007ffc8000", + "0x40317fff7ffe7ffd", + "0x482680017ffc8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0x10", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480680017fff8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x48127ffe7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7", + "0x482680017ffd8000", + "0x11000000000000000000000000000000000000000000000101", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x20680017fff7fff", + "0xc", + "0x40780017fff7fff", + "0xa", + "0x480680017fff8000", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff", + "0x480a7ffc7fff8000", + "0x48287ffd80007ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd8", + "0x10780017fff7fff", + "0x8", + "0x40780017fff7fff", + "0xb", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff89", + "0x400780017fff8000", + "0x0", + "0x400780017fff8001", + "0x0", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480280007ffb8000", + "0x1104800180018000", + "0x2b", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff79", + "0x40137ffd7fff8000", + "0x480280017ffb8000", + "0x40297ffd7fff8001", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x2", + "0x480a7ffb7fff8000", + "0x480280007ffc8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff66", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff6a", + "0x40137ffd7fff8000", + "0x480280017ffc8000", + "0x402580017fff8001", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x27", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff4d", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffc", + "0x5", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffc8000", + "0x800000000000011000000000000000000000000000000000000000000000000", + "0x40337fff7ffb8000", + "0x480a7ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffd7fff8000", + "0x48317ffd80008000", + "0x400080007ffd7ffe", + "0x480080007ffc8000", + "0x400080017ffc7fff", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x3", + "0x480080027ffa8000", + "0x20680017fff7ffb", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff8", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffa2", + "0x480a7ff77fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x535441524b4e45545f434f4e54524143545f41444452455353", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb6", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb3", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb0", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffad", + "0x480a7ffc7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffb9", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc2", + "0x480a7ff87fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff61", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x391a88f3badec8650b4d8356e18655269ee975e58e0060aa076396ce0b1dccb", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff03", + "0x480a7ffc7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff53", + "0x48127fe17fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff22", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2", + "0x480a7ff97fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff1b", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff13", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400780017fff7ffd", + "0x19", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff2", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffb7ffc", + "0x400380017ffb7ffd", + "0x480680017fff8000", + "0xf", + "0x400280027ffb7fff", + "0x482680017ffb8000", + "0x5", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280037ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff3", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff8000", + "0x9", + "0x480a7ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8e", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe83", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef", + "0x48127ff67fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x2", + "0x480680017fff8000", + "0x3", + "0x480680017fff8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ff8", + "0x4003800180007ff9", + "0x4003800280007ffa", + "0x4003800380007ffb", + "0x4003800480007ffc", + "0x4826800180008000", + "0x5", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe8", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe23", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x400780017fff7ffc", + "0x2", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x2", + "0x482480017ffb8000", + "0x1", + "0x482480017ffb8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde8", + "0x482480017fff8000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", + "0x40137fff7fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x5", + "0x480a80007fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdee", + "0x48127ffd7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde7", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280037ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x4", + "0x480280037ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x480280037ffd8000", + "0x482680017ffd8000", + "0x4", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc3", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe3", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffda9", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffeb", + "0x480280027ffb8000", + "0x48127ffc7fff8000", + "0x480280017ffb8000", + "0x482480017ffd8000", + "0x1", + "0x480280037ffb8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdbf", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd89", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff98000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffde", + "0x480280027ffb8000", + "0x48127ffe7fff8000", + "0x482480017ffe8000", + "0x1", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x48127ff47fff8000", + "0x480280017ffb8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x27", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe48", + "0x480680017fff8000", + "0x1", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe36", + "0x400680017fff7fff", + "0x27", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffea", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdea", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x480280027ffb8000", + "0x480280027ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x3", + "0x480280027ffd8000", + "0x48307fff7ffe8000", + "0x482480017fff8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280027ffb8000", + "0x480280017ffb8000", + "0x482480017ffe8000", + "0x1", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x3", + "0x480080007ff78000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", + "0x480280007ffb8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x480280037ffb8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffff", + "0x40780017fff7fff", + "0x1", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "19": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.call_contract" + ], + "code": "syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": 0 + } + } + } + ], + "31": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.library_call" + ], + "code": "syscall_handler.library_call(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.library_call.syscall_ptr": 1 + } + } + } + ], + "44": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.deploy" + ], + "code": "syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.deploy.syscall_ptr": 2 + } + } + } + ], + "52": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 3 + } + } + } + ], + "61": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 4 + } + } + } + ], + "68": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.replace_class" + ], + "code": "syscall_handler.replace_class(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": 5 + } + } + } + ], + "71": [ + { + "accessible_scopes": [ + "starkware.cairo.common.math", + "starkware.cairo.common.math.assert_250_bit" + ], + "code": "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)", + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 0 + }, + "reference_ids": { + "starkware.cairo.common.math.assert_250_bit.high": 8, + "starkware.cairo.common.math.assert_250_bit.low": 7, + "starkware.cairo.common.math.assert_250_bit.value": 6 + } + } + } + ], + "86": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_small": 10 + } + } + } + ], + "104": [ + { + "accessible_scopes": [ + "starkware.starknet.common.storage", + "starkware.starknet.common.storage.normalize_address" + ], + "code": "ids.is_250 = 1 if ids.addr < 2**250 else 0", + "flow_tracking_data": { + "ap_tracking": { + "group": 10, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.storage.normalize_address.addr": 9, + "starkware.starknet.common.storage.normalize_address.is_250": 11 + } + } + } + ], + "305": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.constructor" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 27, + "offset": 13 + }, + "reference_ids": {} + } + } + ], + "319": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.without_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 29, + "offset": 2 + }, + "reference_ids": {} + } + } + ], + "338": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.with_arg" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 31, + "offset": 4 + }, + "reference_ids": {} + } + } + ], + "350": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.return_result_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 33, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "391": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.bitwise_and" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 36, + "offset": 8 + }, + "reference_ids": {} + } + } + ], + "403": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.sqrt" + ], + "code": "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)", + "flow_tracking_data": { + "ap_tracking": { + "group": 37, + "offset": 1 + }, + "reference_ids": { + "__main__.sqrt.root": 13, + "__main__.sqrt.value": 12 + } + } + } + ], + "414": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.sqrt" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 38, + "offset": 7 + }, + "reference_ids": {} + } + } + ], + "433": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_read_write_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 40, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "471": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_long_retdata_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 43, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "568": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_nested_library_call_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 48, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "652": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_replace_class" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 53, + "offset": 11 + }, + "reference_ids": {} + } + } + ], + "671": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_deploy_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 55, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "737": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_storage_var" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 58, + "offset": 126 + }, + "reference_ids": {} + } + } + ], + "757": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_contract_address_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 61, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "802": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.foo" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 65, + "offset": 2 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.BitwiseBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "type": "alias" + }, + "__main__.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 375, + "type": "function" + }, + "__main__.bitwise_and.Args": { + "full_name": "__main__.bitwise_and.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.bitwise_and.ImplicitArgs": { + "full_name": "__main__.bitwise_and.ImplicitArgs", + "members": { + "bitwise_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.bitwise_and.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.call_contract": { + "destination": "starkware.starknet.common.syscalls.call_contract", + "type": "alias" + }, + "__main__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 291, + "type": "function" + }, + "__main__.constructor.Args": { + "full_name": "__main__.constructor.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.constructor.ImplicitArgs": { + "full_name": "__main__.constructor.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.constructor.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.deploy": { + "destination": "starkware.starknet.common.syscalls.deploy", + "type": "alias" + }, + "__main__.foo": { + "decorators": [ + "external" + ], + "pc": 798, + "type": "function" + }, + "__main__.foo.Args": { + "full_name": "__main__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.ImplicitArgs": { + "full_name": "__main__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.foo.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_contract_address": { + "destination": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address", + "type": "alias" + }, + "__main__.library_call": { + "destination": "starkware.starknet.common.syscalls.library_call", + "type": "alias" + }, + "__main__.number_map": { + "type": "namespace" + }, + "__main__.number_map.Args": { + "full_name": "__main__.number_map.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.number_map.ImplicitArgs": { + "full_name": "__main__.number_map.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.number_map.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.addr": { + "decorators": [], + "pc": 250, + "type": "function" + }, + "__main__.number_map.addr.Args": { + "full_name": "__main__.number_map.addr.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.addr.ImplicitArgs": { + "full_name": "__main__.number_map.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.number_map.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "__main__.number_map.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "__main__.number_map.read": { + "decorators": [], + "pc": 264, + "type": "function" + }, + "__main__.number_map.read.Args": { + "full_name": "__main__.number_map.read.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.number_map.read.ImplicitArgs": { + "full_name": "__main__.number_map.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "__main__.number_map.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.number_map.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.number_map.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.number_map.write": { + "decorators": [], + "pc": 278, + "type": "function" + }, + "__main__.number_map.write.Args": { + "full_name": "__main__.number_map.write.Args", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.number_map.write.ImplicitArgs": { + "full_name": "__main__.number_map.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.number_map.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.number_map.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.replace_class": { + "destination": "starkware.starknet.common.syscalls.replace_class", + "type": "alias" + }, + "__main__.return_result": { + "decorators": [ + "external" + ], + "pc": 348, + "type": "function" + }, + "__main__.return_result.Args": { + "full_name": "__main__.return_result.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.return_result.ImplicitArgs": { + "full_name": "__main__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.return_result.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.sqrt": { + "decorators": [ + "external" + ], + "pc": 401, + "type": "function" + }, + "__main__.sqrt.Args": { + "full_name": "__main__.sqrt.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.ImplicitArgs": { + "full_name": "__main__.sqrt.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.sqrt.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.sqrt.root": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.root", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ], + "type": "reference" + }, + "__main__.sqrt.value": { + "cairo_type": "felt", + "full_name": "__main__.sqrt.value", + "references": [ + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 607, + "type": "function" + }, + "__main__.test_call_contract.Args": { + "full_name": "__main__.test_call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_call_contract.ImplicitArgs": { + "full_name": "__main__.test_call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 747, + "type": "function" + }, + "__main__.test_contract_address.Args": { + "full_name": "__main__.test_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_contract_address.ImplicitArgs": { + "full_name": "__main__.test_contract_address.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 662, + "type": "function" + }, + "__main__.test_deploy.Args": { + "full_name": "__main__.test_deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_deploy.ImplicitArgs": { + "full_name": "__main__.test_deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "__main__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 497, + "type": "function" + }, + "__main__.test_library_call.Args": { + "full_name": "__main__.test_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "__main__.test_library_call.ImplicitArgs": { + "full_name": "__main__.test_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__main__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 460, + "type": "function" + }, + "__main__.test_long_retdata.Args": { + "full_name": "__main__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.ImplicitArgs": { + "full_name": "__main__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_long_retdata.Return": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "type": "type_definition" + }, + "__main__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 530, + "type": "function" + }, + "__main__.test_nested_library_call.Args": { + "full_name": "__main__.test_nested_library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_len": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "lib_selector": { + "cairo_type": "felt", + "offset": 1 + }, + "nested_selector": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 5, + "type": "struct" + }, + "__main__.test_nested_library_call.ImplicitArgs": { + "full_name": "__main__.test_nested_library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_nested_library_call.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__main__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 640, + "type": "function" + }, + "__main__.test_replace_class.Args": { + "full_name": "__main__.test_replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.ImplicitArgs": { + "full_name": "__main__.test_replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 424, + "type": "function" + }, + "__main__.test_storage_read_write.Args": { + "full_name": "__main__.test_storage_read_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_storage_read_write.ImplicitArgs": { + "full_name": "__main__.test_storage_read_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_storage_read_write.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "__main__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 712, + "type": "function" + }, + "__main__.test_storage_var.Args": { + "full_name": "__main__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.test_storage_var.ImplicitArgs": { + "full_name": "__main__.test_storage_var.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.test_storage_var.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.with_arg": { + "decorators": [ + "external" + ], + "pc": 329, + "type": "function" + }, + "__main__.with_arg.Args": { + "full_name": "__main__.with_arg.Args", + "members": { + "num": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.with_arg.ImplicitArgs": { + "full_name": "__main__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.with_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.without_arg": { + "decorators": [ + "external" + ], + "pc": 315, + "type": "function" + }, + "__main__.without_arg.Args": { + "full_name": "__main__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.ImplicitArgs": { + "full_name": "__main__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.without_arg.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and": { + "decorators": [ + "external" + ], + "pc": 383, + "type": "function" + }, + "__wrappers__.bitwise_and.Args": { + "full_name": "__wrappers__.bitwise_and.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.ImplicitArgs": { + "full_name": "__wrappers__.bitwise_and.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.bitwise_and.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: starkware.cairo.common.cairo_builtins.BitwiseBuiltin*, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.bitwise_and.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.bitwise_and.__wrapped_func": { + "destination": "__main__.bitwise_and", + "type": "alias" + }, + "__wrappers__.bitwise_and_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.constructor": { + "decorators": [ + "constructor" + ], + "pc": 297, + "type": "function" + }, + "__wrappers__.constructor.Args": { + "full_name": "__wrappers__.constructor.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.ImplicitArgs": { + "full_name": "__wrappers__.constructor.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.constructor.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.constructor.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.constructor.__wrapped_func": { + "destination": "__main__.constructor", + "type": "alias" + }, + "__wrappers__.constructor_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.foo": { + "decorators": [ + "external" + ], + "pc": 799, + "type": "function" + }, + "__wrappers__.foo.Args": { + "full_name": "__wrappers__.foo.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.ImplicitArgs": { + "full_name": "__wrappers__.foo.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.foo.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.foo.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.foo.__wrapped_func": { + "destination": "__main__.foo", + "type": "alias" + }, + "__wrappers__.foo_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.return_result": { + "decorators": [ + "external" + ], + "pc": 359, + "type": "function" + }, + "__wrappers__.return_result.Args": { + "full_name": "__wrappers__.return_result.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.ImplicitArgs": { + "full_name": "__wrappers__.return_result.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.return_result.__wrapped_func": { + "destination": "__main__.return_result", + "type": "alias" + }, + "__wrappers__.return_result_encode_return": { + "decorators": [], + "pc": 350, + "type": "function" + }, + "__wrappers__.return_result_encode_return.Args": { + "full_name": "__wrappers__.return_result_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.return_result_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.return_result_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.return_result_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.return_result_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.sqrt": { + "decorators": [ + "external" + ], + "pc": 407, + "type": "function" + }, + "__wrappers__.sqrt.Args": { + "full_name": "__wrappers__.sqrt.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.ImplicitArgs": { + "full_name": "__wrappers__.sqrt.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.sqrt.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.sqrt.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.sqrt.__wrapped_func": { + "destination": "__main__.sqrt", + "type": "alias" + }, + "__wrappers__.sqrt_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_call_contract": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 615, + "type": "function" + }, + "__wrappers__.test_call_contract.Args": { + "full_name": "__wrappers__.test_call_contract.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.ImplicitArgs": { + "full_name": "__wrappers__.test_call_contract.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_call_contract.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_call_contract.__wrapped_func": { + "destination": "__main__.test_call_contract", + "type": "alias" + }, + "__wrappers__.test_call_contract_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_contract_address": { + "decorators": [ + "external" + ], + "pc": 766, + "type": "function" + }, + "__wrappers__.test_contract_address.Args": { + "full_name": "__wrappers__.test_contract_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_contract_address.__wrapped_func": { + "destination": "__main__.test_contract_address", + "type": "alias" + }, + "__wrappers__.test_contract_address_encode_return": { + "decorators": [], + "pc": 757, + "type": "function" + }, + "__wrappers__.test_contract_address_encode_return.Args": { + "full_name": "__wrappers__.test_contract_address_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_contract_address_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_contract_address_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_contract_address_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_contract_address_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_deploy": { + "decorators": [ + "external" + ], + "pc": 680, + "type": "function" + }, + "__wrappers__.test_deploy.Args": { + "full_name": "__wrappers__.test_deploy.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_deploy.__wrapped_func": { + "destination": "__main__.test_deploy", + "type": "alias" + }, + "__wrappers__.test_deploy_encode_return": { + "decorators": [], + "pc": 671, + "type": "function" + }, + "__wrappers__.test_deploy_encode_return.Args": { + "full_name": "__wrappers__.test_deploy_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(contract_address: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_deploy_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_deploy_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_deploy_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_deploy_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_library_call": { + "decorators": [ + "external", + "raw_output" + ], + "pc": 505, + "type": "function" + }, + "__wrappers__.test_library_call.Args": { + "full_name": "__wrappers__.test_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_library_call.__wrapped_func": { + "destination": "__main__.test_library_call", + "type": "alias" + }, + "__wrappers__.test_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_long_retdata": { + "decorators": [ + "external" + ], + "pc": 484, + "type": "function" + }, + "__wrappers__.test_long_retdata.Args": { + "full_name": "__wrappers__.test_long_retdata.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_long_retdata.__wrapped_func": { + "destination": "__main__.test_long_retdata", + "type": "alias" + }, + "__wrappers__.test_long_retdata_encode_return": { + "decorators": [], + "pc": 471, + "type": "function" + }, + "__wrappers__.test_long_retdata_encode_return.Args": { + "full_name": "__wrappers__.test_long_retdata_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 5 + }, + "ret_value": { + "cairo_type": "(a: felt, b: felt, c: felt, d: felt, e: felt)", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_long_retdata_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_long_retdata_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_long_retdata_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_long_retdata_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_nested_library_call": { + "decorators": [ + "external" + ], + "pc": 577, + "type": "function" + }, + "__wrappers__.test_nested_library_call.Args": { + "full_name": "__wrappers__.test_nested_library_call.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_nested_library_call.__wrapped_func": { + "destination": "__main__.test_nested_library_call", + "type": "alias" + }, + "__wrappers__.test_nested_library_call_encode_return": { + "decorators": [], + "pc": 568, + "type": "function" + }, + "__wrappers__.test_nested_library_call_encode_return.Args": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_nested_library_call_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_nested_library_call_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_nested_library_call_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_nested_library_call_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_replace_class": { + "decorators": [ + "external" + ], + "pc": 645, + "type": "function" + }, + "__wrappers__.test_replace_class.Args": { + "full_name": "__wrappers__.test_replace_class.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.ImplicitArgs": { + "full_name": "__wrappers__.test_replace_class.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_replace_class.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_replace_class.__wrapped_func": { + "destination": "__main__.test_replace_class", + "type": "alias" + }, + "__wrappers__.test_replace_class_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_read_write": { + "decorators": [ + "external" + ], + "pc": 442, + "type": "function" + }, + "__wrappers__.test_storage_read_write.Args": { + "full_name": "__wrappers__.test_storage_read_write.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_read_write.__wrapped_func": { + "destination": "__main__.test_storage_read_write", + "type": "alias" + }, + "__wrappers__.test_storage_read_write_encode_return": { + "decorators": [], + "pc": 433, + "type": "function" + }, + "__wrappers__.test_storage_read_write_encode_return.Args": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(result: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_read_write_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_read_write_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_read_write_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.test_storage_read_write_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.test_storage_var": { + "decorators": [ + "external" + ], + "pc": 731, + "type": "function" + }, + "__wrappers__.test_storage_var.Args": { + "full_name": "__wrappers__.test_storage_var.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.ImplicitArgs": { + "full_name": "__wrappers__.test_storage_var.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_storage_var.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_storage_var.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_storage_var.__wrapped_func": { + "destination": "__main__.test_storage_var", + "type": "alias" + }, + "__wrappers__.test_storage_var_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.with_arg": { + "decorators": [ + "external" + ], + "pc": 332, + "type": "function" + }, + "__wrappers__.with_arg.Args": { + "full_name": "__wrappers__.with_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.ImplicitArgs": { + "full_name": "__wrappers__.with_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.with_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.with_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.with_arg.__wrapped_func": { + "destination": "__main__.with_arg", + "type": "alias" + }, + "__wrappers__.with_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.without_arg": { + "decorators": [ + "external" + ], + "pc": 316, + "type": "function" + }, + "__wrappers__.without_arg.Args": { + "full_name": "__wrappers__.without_arg.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.ImplicitArgs": { + "full_name": "__wrappers__.without_arg.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.without_arg.Return": { + "cairo_type": "(syscall_ptr: felt, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.without_arg.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.without_arg.__wrapped_func": { + "destination": "__main__.without_arg", + "type": "alias" + }, + "__wrappers__.without_arg_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash.hash2": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.hash.hash2.Args": { + "full_name": "starkware.cairo.common.hash.hash2.Args", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash.hash2.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash.hash2.Return": { + "cairo_type": "(result: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash.hash2.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.hash_state.HashState": { + "full_name": "starkware.cairo.common.hash_state.HashState", + "members": { + "current_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "n_words": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.get_fp_and_pc": { + "destination": "starkware.cairo.common.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "starkware.cairo.common.hash_state.hash_felts": { + "decorators": [], + "pc": 208, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.Args", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 0 + }, + "length": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding": { + "decorators": [], + "pc": 183, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 1 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "initial_hash": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals": { + "full_name": "starkware.cairo.common.hash_state.hash_felts_no_padding.LoopLocals", + "members": { + "cur_hash": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 0 + }, + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.hash_state.hash_felts_no_padding.hash_loop": { + "pc": 196, + "type": "label" + }, + "starkware.cairo.common.hash_state.hash_finalize": { + "decorators": [], + "pc": 177, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_finalize.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_finalize.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_finalize.Return": { + "cairo_type": "(hash: felt)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_finalize.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.hash_state.hash_init": { + "decorators": [], + "pc": 124, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_init.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_init.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_init.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_init.Return": { + "cairo_type": "(hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_init.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update": { + "decorators": [], + "pc": 134, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_single": { + "decorators": [], + "pc": 150, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_single.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.Args", + "members": { + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + }, + "item": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_single.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_single.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_single.SIZEOF_LOCALS": { + "type": "const", + "value": 2 + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain": { + "decorators": [], + "pc": 166, + "type": "function" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.Args", + "members": { + "data_length": { + "cairo_type": "felt", + "offset": 2 + }, + "data_ptr": { + "cairo_type": "felt*", + "offset": 1 + }, + "hash_state_ptr": { + "cairo_type": "starkware.cairo.common.hash_state.HashState*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs": { + "full_name": "starkware.cairo.common.hash_state.hash_update_with_hashchain.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.Return": { + "cairo_type": "(new_hash_state_ptr: starkware.cairo.common.hash_state.HashState*)", + "type": "type_definition" + }, + "starkware.cairo.common.hash_state.hash_update_with_hashchain.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.math.assert_250_bit": { + "decorators": [ + "known_ap_change" + ], + "pc": 71, + "type": "function" + }, + "starkware.cairo.common.math.assert_250_bit.Args": { + "full_name": "starkware.cairo.common.math.assert_250_bit.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.HIGH_BOUND": { + "type": "const", + "value": 5316911983139663491615228241121378304 + }, + "starkware.cairo.common.math.assert_250_bit.ImplicitArgs": { + "full_name": "starkware.cairo.common.math.assert_250_bit.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.cairo.common.math.assert_250_bit.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.cairo.common.math.assert_250_bit.SHIFT": { + "type": "const", + "value": 340282366920938463463374607431768211456 + }, + "starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND": { + "type": "const", + "value": 1809251394333065553493296640760748560207343510400633813116524750123642650624 + }, + "starkware.cairo.common.math.assert_250_bit.high": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.high", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.low": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.low", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.math.assert_250_bit.value": { + "cairo_type": "felt", + "full_name": "starkware.cairo.common.math.assert_250_bit.value", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.registers.get_ap": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_ap", + "type": "alias" + }, + "starkware.cairo.common.registers.get_fp_and_pc": { + "destination": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc", + "type": "alias" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap": { + "decorators": [ + "known_ap_change" + ], + "pc": 7, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_ap.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.Return": { + "cairo_type": "(ap_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_ap.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc": { + "decorators": [], + "pc": 6, + "type": "function" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs": { + "full_name": "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.Return": { + "cairo_type": "(fp_val: felt*, pc_val: felt*)", + "type": "type_definition" + }, + "starkware.cairo.lang.compiler.lib.registers.get_fp_and_pc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.storage.normalize_address": { + "decorators": [ + "known_ap_change" + ], + "pc": 84, + "type": "function" + }, + "starkware.starknet.common.storage.normalize_address.Args": { + "full_name": "starkware.starknet.common.storage.normalize_address.Args", + "members": { + "addr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.ImplicitArgs": { + "full_name": "starkware.starknet.common.storage.normalize_address.ImplicitArgs", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.storage.normalize_address.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.storage.normalize_address.addr": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.addr", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_250": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_250", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.normalize_address.is_small": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.storage.normalize_address.is_small", + "references": [ + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract": { + "decorators": [], + "pc": 12, + "type": "function" + }, + "starkware.starknet.common.syscalls.call_contract.Args": { + "full_name": "starkware.starknet.common.syscalls.call_contract.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.call_contract.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.call_contract.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.call_contract.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.call_contract.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 1 + }, + "pc": 19, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.deploy": { + "decorators": [], + "pc": 36, + "type": "function" + }, + "starkware.starknet.common.syscalls.deploy.Args": { + "full_name": "starkware.starknet.common.syscalls.deploy.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 1 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 4 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.deploy.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.deploy.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.deploy.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.deploy.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.deploy.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 1 + }, + "pc": 44, + "value": "cast([fp + (-8)] + 9, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.library_call": { + "decorators": [], + "pc": 24, + "type": "function" + }, + "starkware.starknet.common.syscalls.library_call.Args": { + "full_name": "starkware.starknet.common.syscalls.library_call.Args", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 0 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.library_call.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.library_call.Return": { + "cairo_type": "(retdata_size: felt, retdata: felt*)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.library_call.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.library_call.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.library_call.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 1 + }, + "pc": 31, + "value": "cast([fp + (-7)] + 7, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.replace_class": { + "decorators": [], + "pc": 64, + "type": "function" + }, + "starkware.starknet.common.syscalls.replace_class.Args": { + "full_name": "starkware.starknet.common.syscalls.replace_class.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.replace_class.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.replace_class.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.replace_class.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.replace_class.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.replace_class.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 68, + "value": "cast([fp + (-4)] + 2, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 48, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 1 + }, + "pc": 52, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 56, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 1 + }, + "pc": 61, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.core.os.contract_address.contract_address.CONTRACT_ADDRESS_PREFIX": { + "type": "const", + "value": 523065374597054866729014270389667305596563390979550329787219 + }, + "starkware.starknet.core.os.contract_address.contract_address.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address": { + "decorators": [], + "pc": 219, + "type": "function" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Args", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 3 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 2 + }, + "deployer_address": { + "cairo_type": "felt", + "offset": 4 + }, + "salt": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs": { + "full_name": "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.ImplicitArgs", + "members": { + "hash_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.Return": { + "cairo_type": "(contract_address: felt)", + "type": "type_definition" + }, + "starkware.starknet.core.os.contract_address.contract_address.get_contract_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_finalize": { + "destination": "starkware.cairo.common.hash_state.hash_finalize", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_init": { + "destination": "starkware.cairo.common.hash_state.hash_init", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update": { + "destination": "starkware.cairo.common.hash_state.hash_update", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_single": { + "destination": "starkware.cairo.common.hash_state.hash_update_single", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.hash_update_with_hashchain": { + "destination": "starkware.cairo.common.hash_state.hash_update_with_hashchain", + "type": "alias" + }, + "starkware.starknet.core.os.contract_address.contract_address.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 12, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 24, + "value": "[cast(fp + (-7), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 36, + "value": "[cast(fp + (-8), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 48, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 56, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 64, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 71, + "value": "[cast([fp + (-4)] + 1, felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 0 + }, + "pc": 84, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 1 + }, + "pc": 86, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 10, + "offset": 2 + }, + "pc": 104, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 0 + }, + "pc": 401, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 37, + "offset": 1 + }, + "pc": 403, + "value": "[cast(fp, felt*)]" + } + ] + } + } +} diff --git a/crates/papyrus_storage/resources/erc20_compiled_contract_class.json b/crates/papyrus_storage/resources/erc20_compiled_contract_class.json new file mode 100644 index 00000000000..33bea365b43 --- /dev/null +++ b/crates/papyrus_storage/resources/erc20_compiled_contract_class.json @@ -0,0 +1,7974 @@ +{ + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "compiler_version": "2.3.1", + "bytecode": [ + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffe2f0", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x5b", + "0x4825800180007ffa", + "0x1d10", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1255", + "0x482480017fff8000", + "0x1254", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x24", + "0x4824800180007ff7", + "0x0", + "0x400080007ff87fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x6f2", + "0x482480017fd88000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x6fc", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffe2f0", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x5b", + "0x4825800180007ffa", + "0x1d10", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x11e6", + "0x482480017fff8000", + "0x11e5", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x24", + "0x4824800180007ff7", + "0x0", + "0x400080007ff87fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x69d", + "0x482480017fd88000", + "0x1", + "0x20680017fff7ffc", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffe7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x68d", + "0x48127ff77fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffffdb7a", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x58", + "0x4825800180007ffa", + "0x2486", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1177", + "0x482480017fff8000", + "0x1176", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x21", + "0x4824800180007ff7", + "0x0", + "0x400080007ff87fff", + "0x482480017ff88000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x641", + "0x20680017fff7ffd", + "0xe", + "0x40780017fff7fff", + "0x1", + "0x400080007fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff9fac", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x5c", + "0x4825800180007ffa", + "0x6054", + "0x400280007ff97fff", + "0x48297ffc80007ffd", + "0x482680017ff98000", + "0x1", + "0x4824800180007ffe", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x110b", + "0x482480017fff8000", + "0x110a", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff7", + "0x0", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x25", + "0x4824800180007ff7", + "0x0", + "0x400080007ff87fff", + "0x482480017ff88000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x5ed", + "0x20680017fff7ffd", + "0x12", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x5fa", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff8314", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x78", + "0x4825800180007ffa", + "0x7cec", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x5c2", + "0x20680017fff7ffe", + "0x5e", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff67fff8000", + "0x48127fda7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1094", + "0x482480017fff8000", + "0x1093", + "0x480080007fff8000", + "0x480080007fff8000", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fd7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff07fff", + "0x10780017fff7fff", + "0x28", + "0x48307ffe80007fd7", + "0x400080007ff17fff", + "0x482480017ff18000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127ff17fff8000", + "0x1104800180018000", + "0x5c9", + "0x20680017fff7ffd", + "0x13", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x580", + "0x48127ff27fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017fed8000", + "0x1", + "0x48127fd17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xffffffffffffffffffffffffffff704a", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x91", + "0x4825800180007ffa", + "0x8fb6", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x535", + "0x20680017fff7ffe", + "0x77", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x52e", + "0x20680017fff7ffe", + "0x61", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff67fff8000", + "0x48127fbb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1000", + "0x482480017fff8000", + "0xfff", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x2", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fb7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fef7fff", + "0x10780017fff7fff", + "0x29", + "0x48307ffe80007fb7", + "0x400080007ff07fff", + "0x482480017ff08000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127fd17fff8000", + "0x48127fef7fff8000", + "0x1104800180018000", + "0x54d", + "0x20680017fff7ffd", + "0x13", + "0x40780017fff7fff", + "0x1", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x4e9", + "0x48127ff27fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017fec8000", + "0x1", + "0x48127fb17fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fbd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffd40d6", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8c", + "0x4825800180007ffa", + "0x2bf2a", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x48f", + "0x20680017fff7ffe", + "0x72", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x4f8", + "0x20680017fff7ffd", + "0x5c", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff57fff8000", + "0x48127fa67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xf5a", + "0x482480017fff8000", + "0xf59", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x4", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fa2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fee7fff", + "0x10780017fff7fff", + "0x24", + "0x48307ffe80007fa2", + "0x400080007fef7fff", + "0x482480017fef8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127fbc7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x528", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017feb8000", + "0x1", + "0x48127f9c7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127fa87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffbb72a", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xa3", + "0x4825800180007ffa", + "0x448d6", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3ee", + "0x20680017fff7ffe", + "0x89", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x3e7", + "0x20680017fff7ffe", + "0x73", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x450", + "0x20680017fff7ffd", + "0x5d", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff57fff8000", + "0x48127f877fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xeb2", + "0x482480017fff8000", + "0xeb1", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x8", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007f83", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fee7fff", + "0x10780017fff7fff", + "0x25", + "0x48307ffe80007f83", + "0x400080007fef7fff", + "0x482480017fef8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127f9d7fff8000", + "0x48127fbb7fff8000", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x1104800180018000", + "0x4b0", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017feb8000", + "0x1", + "0x48127f7d7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127f897fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fbd7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffee15c", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8c", + "0x4825800180007ffa", + "0x11ea4", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x336", + "0x20680017fff7ffe", + "0x72", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x39f", + "0x20680017fff7ffd", + "0x5c", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff57fff8000", + "0x48127fa67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xe01", + "0x482480017fff8000", + "0xe00", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x2", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fa2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fee7fff", + "0x10780017fff7fff", + "0x24", + "0x48307ffe80007fa2", + "0x400080007fef7fff", + "0x482480017fef8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127fbc7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x448", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017feb8000", + "0x1", + "0x48127f9c7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127fa87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffe460c", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8c", + "0x4825800180007ffa", + "0x1b9f4", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x295", + "0x20680017fff7ffe", + "0x72", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x2fe", + "0x20680017fff7ffd", + "0x5c", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff57fff8000", + "0x48127fa67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xd60", + "0x482480017fff8000", + "0xd5f", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x4", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fa2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fee7fff", + "0x10780017fff7fff", + "0x24", + "0x48307ffe80007fa2", + "0x400080007fef7fff", + "0x482480017fef8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127fbc7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x3d8", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017feb8000", + "0x1", + "0x48127f9c7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127fa87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffe460c", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x8c", + "0x4825800180007ffa", + "0x1b9f4", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x1f4", + "0x20680017fff7ffe", + "0x72", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x25d", + "0x20680017fff7ffd", + "0x5c", + "0x48307ffb80007ffc", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff57fff8000", + "0x48127fa67fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xcbf", + "0x482480017fff8000", + "0xcbe", + "0x480080007fff8000", + "0x480080007fff8000", + "0x484480017fff8000", + "0x4", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007fa2", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007fee7fff", + "0x10780017fff7fff", + "0x24", + "0x48307ffe80007fa2", + "0x400080007fef7fff", + "0x482480017fef8000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127fbc7fff8000", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x1104800180018000", + "0x391", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017feb8000", + "0x1", + "0x48127f9c7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127fa87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0xfffffffffffffffffffffffffffe05ca", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xe8", + "0x4825800180007ffa", + "0x1fa36", + "0x400280007ff97fff", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x389", + "0x482680017ff98000", + "0x1", + "0x20680017fff7ffd", + "0xce", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x381", + "0x20680017fff7ffe", + "0xb9", + "0x48307ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffb8000", + "0x1", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x92", + "0x48127feb7fff8000", + "0x480080007ffe8000", + "0x1104800180018000", + "0x38a", + "0x20680017fff7ffe", + "0x89", + "0x48127ffd7fff8000", + "0x48127fed7fff8000", + "0x48127fed7fff8000", + "0x1104800180018000", + "0x19b", + "0x20680017fff7ffd", + "0x73", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x1104800180018000", + "0x124", + "0x20680017fff7ffe", + "0x5d", + "0x48307ffc80007ffd", + "0x4824800180007fff", + "0x0", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x11", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff67fff8000", + "0x48127f747fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0xbf6", + "0x482480017fff8000", + "0xbf5", + "0x480080007fff8000", + "0x480080007fff8000", + "0x482480017fff8000", + "0x0", + "0xa0680017fff8000", + "0x8", + "0x48307ffe80007f71", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff07fff", + "0x10780017fff7fff", + "0x27", + "0x48307ffe80007f71", + "0x400080007ff17fff", + "0x482480017ff18000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ff87fff8000", + "0x480a7ffb7fff8000", + "0x48127f7b7fff8000", + "0x48127f8a7fff8000", + "0x48127f9c7fff8000", + "0x48127fce7fff8000", + "0x48127fce7fff8000", + "0x48127fec7fff8000", + "0x1104800180018000", + "0x36b", + "0x20680017fff7ffd", + "0xd", + "0x40780017fff7fff", + "0x1", + "0x48127ffa7fff8000", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482480017fed8000", + "0x1", + "0x48127f6b7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202335", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff87fff8000", + "0x48127f767fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202334", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ff77fff8000", + "0x48127f957fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fdd7fff8000", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202333", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ffc7fff8000", + "0x48127fc87fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127fed7fff8000", + "0x48127fdc7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x48127ffc7fff8000", + "0x48127feb7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x480a7ff87fff8000", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x380", + "0x20680017fff7ffd", + "0xa", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffd7ffb", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x397", + "0x20680017fff7ffd", + "0xa", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3b2", + "0x20680017fff7ffd", + "0xb", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3e9", + "0x20680017fff7ffd", + "0xa", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x400380007ffd7ffa", + "0x400380017ffd7ffb", + "0x480a7ffc7fff8000", + "0x482680017ffd8000", + "0x2", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x232", + "0x20680017fff7ffe", + "0x2b", + "0xa0680017fff8004", + "0xe", + "0x4824800180047ffe", + "0x800000000000000000000000000000000000000000000000000000000000000", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8002", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x402480017ffb7ffd", + "0xffffffffffffffeeffffffffffffffff", + "0x400280027ffb7ffd", + "0x10780017fff7fff", + "0x14", + "0x484480017fff8001", + "0x8000000000000000000000000000000", + "0x48307fff80007ffd", + "0x480280007ffb7ffd", + "0x480280017ffb7ffd", + "0x402480017ffc7ffe", + "0xf8000000000000000000000000000000", + "0x400280027ffb7ffe", + "0x40780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffb8000", + "0x3", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6", + "0x480a7ffb7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3bd", + "0x20680017fff7ffd", + "0xb", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3d4", + "0x20680017fff7ffd", + "0xb", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x44", + "0x480a7ffb7fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x3d9", + "0x20680017fff7ffe", + "0x39", + "0x48307ff180007ff2", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ff08000", + "0x1", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fed7fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ff07fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x15", + "0x48127ff67fff8000", + "0x480080007ffc8000", + "0x1104800180018000", + "0x3bc", + "0x20680017fff7ffe", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127fe67fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xd", + "0x48127fe97fff8000", + "0x48127fff7fff8000", + "0x48127fef7fff8000", + "0x48127fef7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x14", + "0x48127fe97fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0x21", + "0x480a7ffb7fff8000", + "0x48127fff7fff8000", + "0x48127fdb7fff8000", + "0x48127fdb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x3b1", + "0x20680017fff7ffd", + "0x22", + "0x480a7ff77fff8000", + "0x48127ffa7fff8000", + "0x480a7ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3ba", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x211", + "0x480a7ff77fff8000", + "0x48127de97fff8000", + "0x480a7ff97fff8000", + "0x48127de87fff8000", + "0x480680017fff8000", + "0x1", + "0x48127de87fff8000", + "0x48127de87fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x380", + "0x20680017fff7ffd", + "0x39", + "0x480a7ff67fff8000", + "0x48127ffa7fff8000", + "0x480a7ff87fff8000", + "0x48127ff97fff8000", + "0x480a7ffa7fff8000", + "0x48127ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x463", + "0x20680017fff7ffd", + "0x22", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x37d", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x211", + "0x48127de87fff8000", + "0x48127de87fff8000", + "0x48127de87fff8000", + "0x48127de87fff8000", + "0x480680017fff8000", + "0x1", + "0x48127de87fff8000", + "0x48127de87fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x378", + "0x480a7ff67fff8000", + "0x48127c827fff8000", + "0x480a7ff87fff8000", + "0x48127c817fff8000", + "0x480680017fff8000", + "0x1", + "0x48127c817fff8000", + "0x48127c817fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x338", + "0x20680017fff7ffd", + "0x22", + "0x480a7ff77fff8000", + "0x48127ffa7fff8000", + "0x480a7ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x48f", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xbd", + "0x480a7ff77fff8000", + "0x48127f3d7fff8000", + "0x480a7ff97fff8000", + "0x48127f3c7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f3c7fff8000", + "0x48127f3c7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x307", + "0x20680017fff7ffd", + "0x4b", + "0x480a7ff77fff8000", + "0x48127ffa7fff8000", + "0x480a7ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x2a2", + "0x20680017fff7ffd", + "0x36", + "0x48127ff97fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x4ac", + "0x20680017fff7ffd", + "0x22", + "0x48127ffc7fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127f6b7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x1104800180018000", + "0x44b", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xbd", + "0x48127f3f7fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f3c7fff8000", + "0x48127f3c7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf0", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x14d", + "0x480a7ff77fff8000", + "0x48127ead7fff8000", + "0x480a7ff97fff8000", + "0x48127eac7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127eac7fff8000", + "0x48127eac7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x2ad", + "0x20680017fff7ffd", + "0x4b", + "0x480a7ff77fff8000", + "0x48127ffa7fff8000", + "0x480a7ff97fff8000", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x248", + "0x20680017fff7ffd", + "0x36", + "0x48127ff97fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x46f", + "0x20680017fff7ffd", + "0x22", + "0x48127ffc7fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127f6b7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x1104800180018000", + "0x3f1", + "0x20680017fff7ffd", + "0xd", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xbd", + "0x48127f3f7fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f3c7fff8000", + "0x48127f3c7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf0", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f097fff8000", + "0x48127f097fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x14d", + "0x480a7ff77fff8000", + "0x48127ead7fff8000", + "0x480a7ff97fff8000", + "0x48127eac7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127eac7fff8000", + "0x48127eac7fff8000", + "0x208b7fff7fff7ffe", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x20680017fff7ffc", + "0x8", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x0", + "0x480080007ffa8000", + "0x208b7fff7fff7ffe", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x12", + "0x4825800180007ffd", + "0x100", + "0x4844800180008002", + "0x8000000000000110000000000000000", + "0x4830800080017ffe", + "0x480280007ffc7fff", + "0x482480017ffe8000", + "0xefffffffffffffde00000000000000ff", + "0x480280017ffc7fff", + "0x400280027ffc7ffb", + "0x402480017fff7ffb", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x11", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x482680017ffd8000", + "0xffffffffffffffffffffffffffffff00", + "0x400280017ffc7fff", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff57fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x1104800180018000", + "0x3fa", + "0x20680017fff7ffd", + "0x90", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ff97fff8000", + "0x1104800180018000", + "0x427", + "0x20680017fff7ffd", + "0x7e", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x454", + "0x20680017fff7ffd", + "0x6c", + "0x4825800180007ffd", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x13", + "0x40780017fff7fff", + "0xc8", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x45524332303a206d696e7420746f2074686520302061646472657373", + "0x400080007ffe7fff", + "0x480a7ff47fff8000", + "0x48127f2c7fff8000", + "0x480a7ff67fff8000", + "0x48127f2b7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ff77fff8000", + "0x48127ff77fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x460", + "0x20680017fff7ffd", + "0x39", + "0x480a7ff47fff8000", + "0x48127ffa7fff8000", + "0x480a7ff67fff8000", + "0x48127ff97fff8000", + "0x480a7ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x473", + "0x20680017fff7ffd", + "0x23", + "0x48127ffa7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x48c", + "0x20680017fff7ffd", + "0xd", + "0x48127f8b7fff8000", + "0x48127ffa7fff8000", + "0x48127f8b7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127f8b7fff8000", + "0x48127ffa7fff8000", + "0x48127f8b7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6e", + "0x48127f8b7fff8000", + "0x48127f8b7fff8000", + "0x48127f8b7fff8000", + "0x48127f8b7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f8b7fff8000", + "0x48127f8b7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xa7", + "0x480a7ff47fff8000", + "0x48127f537fff8000", + "0x480a7ff67fff8000", + "0x48127f527fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f527fff8000", + "0x48127f527fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xce", + "0x480a7ff47fff8000", + "0x48127f2c7fff8000", + "0x480a7ff67fff8000", + "0x48127f2b7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f2b7fff8000", + "0x48127f2b7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xe6", + "0x480a7ff47fff8000", + "0x48127f147fff8000", + "0x480a7ff67fff8000", + "0x48127f137fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f137fff8000", + "0x48127f137fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xfe", + "0x480a7ff47fff8000", + "0x48127efc7fff8000", + "0x480a7ff67fff8000", + "0x48127efb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127efb7fff8000", + "0x48127efb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x361458367e696363fbcc70777d07ebbd2394e89fd0adcaf147faccd1d294d60", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffd", + "0x400280037ffd7ffe", + "0x480280057ffd8000", + "0x20680017fff7fff", + "0xc", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280067ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffd8000", + "0x480280077ffd8000", + "0x1104800180018000", + "0x46a", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x216b05c387bab9ac31918a3e61672f4618601f3c598a2f3f2710f37053e1ea4", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffd", + "0x400280037ffd7ffe", + "0x480280057ffd8000", + "0x20680017fff7fff", + "0xc", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280067ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffd8000", + "0x480280077ffd8000", + "0x1104800180018000", + "0x439", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x4c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x400280027ffd7ffd", + "0x400280037ffd7ffe", + "0x480280057ffd8000", + "0x20680017fff7fff", + "0x25", + "0x480a7ffb7fff8000", + "0x480280067ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeca", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x7", + "0x20680017fff7ffc", + "0xc", + "0x48127ffb7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff87fff8000", + "0x10780017fff7fff", + "0x1c", + "0x40780017fff7fff", + "0x9", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53746f72655538202d206e6f6e207538", + "0x400080007ffe7fff", + "0x48127ff07fff8000", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x10", + "0x480a7ffb7fff8000", + "0x480280047ffd8000", + "0x482680017ffd8000", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480280067ffd8000", + "0x480280077ffd8000", + "0x1104800180018000", + "0x3f9", + "0x20680017fff7ffd", + "0xb", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1557182e4359a1f0c6301278e8f5b35a776ab58d39892581e357578fb287836", + "0x1104800180018000", + "0x3ea", + "0x20680017fff7ffc", + "0x19", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x451", + "0x20680017fff7ffd", + "0xa", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x8", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff27fff8000", + "0x48127ff27fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x43c", + "0x48127ffd7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x3ba", + "0x20680017fff7ffc", + "0x1b", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x421", + "0x20680017fff7ffd", + "0xb", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x8", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x430", + "0x48127ffd7fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x1104800180018000", + "0x386", + "0x20680017fff7ffc", + "0x1b", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x3ed", + "0x20680017fff7ffd", + "0xb", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x8", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x48127fc17fff8000", + "0x48127ff07fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff17fff8000", + "0x48127ff17fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x16", + "0x480280007ffc8003", + "0x480280017ffc8003", + "0x4844800180017ffe", + "0x100000000000000000000000000000000", + "0x483180017ffd7ffd", + "0x482480017fff7ffd", + "0x800000000000010fffffffffffffffff7ffffffffffffef0000000000000001", + "0x20680017fff7ffc", + "0x6", + "0x402480017fff7ffd", + "0xffffffffffffffffffffffffffffffff", + "0x10780017fff7fff", + "0x4", + "0x402480017ffe7ffd", + "0xf7ffffffffffffef0000000000000000", + "0x400280027ffc7ffd", + "0x20680017fff7ffe", + "0xe", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x10780017fff7fff", + "0x8", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x402", + "0x20680017fff7ffd", + "0xa", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480080027ffb8000", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x4825800180007ffa", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x13", + "0x40780017fff7fff", + "0x1fa", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x45524332303a207472616e736665722066726f6d2030", + "0x400080007ffe7fff", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x4825800180007ffb", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x13", + "0x40780017fff7fff", + "0x1f6", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x45524332303a207472616e7366657220746f2030", + "0x400080007ffe7fff", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff19", + "0x20680017fff7ffd", + "0x88", + "0x48127ff97fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x172", + "0x20680017fff7ffd", + "0x74", + "0x48127ffc7fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x480a7ffa7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x23e", + "0x20680017fff7ffd", + "0x5e", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffefc", + "0x20680017fff7ffd", + "0x4a", + "0x48127ff97fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x138", + "0x20680017fff7ffd", + "0x36", + "0x48127ffc7fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x48127fc67fff8000", + "0x480a7ffb7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x1104800180018000", + "0x221", + "0x20680017fff7ffd", + "0x20", + "0x48127ffa7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x39a", + "0x20680017fff7ffd", + "0xd", + "0x48127f8d7fff8000", + "0x48127ffa7fff8000", + "0x48127f8d7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127f8d7fff8000", + "0x48127ffa7fff8000", + "0x48127f8d7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6c", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xa5", + "0x48127f577fff8000", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f547fff8000", + "0x48127f547fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xd8", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f217fff8000", + "0x48127f217fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x132", + "0x48127ec77fff8000", + "0x48127ec77fff8000", + "0x48127ec77fff8000", + "0x48127ec77fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ec77fff8000", + "0x48127ec77fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x16b", + "0x48127e917fff8000", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127e8e7fff8000", + "0x48127e8e7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x19e", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127e5b7fff8000", + "0x48127e5b7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeb1", + "0x20680017fff7ffd", + "0x61", + "0x4824800180007ffe", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x9", + "0x40780017fff7fff", + "0x2", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x10", + "0x4824800180007ffe", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x6", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffe7fff8000", + "0x20680017fff7fff", + "0x33", + "0x48127ff47fff8000", + "0x48127ff87fff8000", + "0x48127ffc7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xba", + "0x20680017fff7ffd", + "0x1f", + "0x48127ffc7fff8000", + "0x48127fc17fff8000", + "0x48127fc17fff8000", + "0x48127fc17fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x1104800180018000", + "0x3c", + "0x20680017fff7ffd", + "0x8", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x10780017fff7fff", + "0x1e", + "0x40780017fff7fff", + "0x4", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xc1", + "0x48127f3b7fff8000", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f387fff8000", + "0x48127f387fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf0", + "0x48127f047fff8000", + "0x48127f047fff8000", + "0x48127f047fff8000", + "0x48127f047fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0xf9", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f007fff8000", + "0x48127f007fff8000", + "0x208b7fff7fff7ffe", + "0x4825800180007ffb", + "0x0", + "0x20680017fff7fff", + "0x6", + "0x480680017fff8000", + "0x1", + "0x10780017fff7fff", + "0x4", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x13", + "0x40780017fff7fff", + "0xa6", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x45524332303a20617070726f76652066726f6d2030", + "0x400080007ffe7fff", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x2ee", + "0x20680017fff7ffd", + "0x20", + "0x48127ffa7fff8000", + "0x48127ffb7fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x30b", + "0x20680017fff7ffd", + "0xd", + "0x48127f8d7fff8000", + "0x48127ffa7fff8000", + "0x48127f8d7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127f8d7fff8000", + "0x48127ffa7fff8000", + "0x48127f8d7fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x6c", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127f8d7fff8000", + "0x48127f8d7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x32d", + "0x20680017fff7ffd", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235365f616464204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x32a", + "0x20680017fff7ffd", + "0xa", + "0x40780017fff7fff", + "0x2", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x753235365f737562204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x361458367e696363fbcc70777d07ebbd2394e89fd0adcaf147faccd1d294d60", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x30c", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x216b05c387bab9ac31918a3e61672f4618601f3c598a2f3f2710f37053e1ea4", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x2d8", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x4c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x2a4", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1557182e4359a1f0c6301278e8f5b35a776ab58d39892581e357578fb287836", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x296", + "0x1104800180018000", + "0x286", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff77fff8000", + "0x480a7ff97fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x102", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x274", + "0x1104800180018000", + "0x264", + "0x20680017fff7ffd", + "0xd", + "0x48127fe57fff8000", + "0x48127ff57fff8000", + "0x48127fe47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127fe57fff8000", + "0x48127ff57fff8000", + "0x48127fe47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x288", + "0x40780017fff7fff", + "0x1", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff77fff8000", + "0x1104800180018000", + "0x27f", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff87fff", + "0x400380017ff87ff7", + "0x400280027ff87ffb", + "0x400280037ff87ffc", + "0x400280047ff87ffd", + "0x400280057ff87ffe", + "0x480280077ff88000", + "0x20680017fff7fff", + "0xd", + "0x480280067ff88000", + "0x482680017ff88000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280067ff88000", + "0x482680017ff88000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff88000", + "0x480280097ff88000", + "0x1104800180018000", + "0x215", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffb7fff", + "0x400380017ffb7ffa", + "0x400380027ffb7ffc", + "0x400380037ffb7ffd", + "0x480280057ffb8000", + "0x20680017fff7fff", + "0x5a", + "0x480a7ff97fff8000", + "0x480280067ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc98", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x7", + "0x20680017fff7ffc", + "0x3f", + "0x482680017ffd8000", + "0x1", + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400080007ffd7fff", + "0x400080017ffd7ffc", + "0x400180027ffd7ffc", + "0x400080037ffd7ffe", + "0x480080057ffd8000", + "0x20680017fff7fff", + "0x27", + "0x48127ff87fff8000", + "0x480080067ffb8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc84", + "0x480080047fef8000", + "0x482480017fee8000", + "0x7", + "0x20680017fff7ffc", + "0xe", + "0x40780017fff7fff", + "0x2", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe47fff8000", + "0x48127ff57fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53746f726555313238202d206e6f6e2075313238", + "0x400080007ffe7fff", + "0x48127ff97fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x11", + "0x48127fe77fff8000", + "0x480080047fea8000", + "0x482480017fe98000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480080067fe68000", + "0x480080077fe58000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x12", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x53746f726555313238202d206e6f6e2075313238", + "0x400080007ffe7fff", + "0x48127fe77fff8000", + "0x48127fe97fff8000", + "0x48127fe97fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x482480017ff88000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x23", + "0x480a7ff97fff8000", + "0x480280047ffb8000", + "0x482680017ffb8000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x1", + "0x480280067ffb8000", + "0x480280077ffb8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x25b1ef8ee6544359221f3cf316f768360e83448109193bdcef77f52a79d95c4", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x480280027ffc8000", + "0xa0680017fff8005", + "0xe", + "0x4824800180057ffe", + "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8003", + "0x480280007ffb7ffc", + "0x480280017ffb7ffc", + "0x482480017ffb7ffd", + "0xffffffffffffffeefffffffffffffeff", + "0x400280027ffb7ffc", + "0x10780017fff7fff", + "0x11", + "0x48127ffe7fff8005", + "0x484480017ffe8000", + "0x8000000000000000000000000000000", + "0x48307ffe7fff8003", + "0x480280007ffb7ffd", + "0x482480017ffc7ffe", + "0xf0000000000000000000000000000100", + "0x480280017ffb7ffd", + "0x400280027ffb7ff9", + "0x402480017ffd7ff9", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7ffd", + "0x4", + "0x402780017fff7fff", + "0x1", + "0x482680017ffb8000", + "0x3", + "0x482680017ffc8000", + "0x3", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0xbf4c436d6f8521e5c6189511c75075de702ad597ce22c1786275e8e5167ec7", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x480280027ffb8000", + "0x400280037ffb7fff", + "0x400380047ffb7ffd", + "0x480280057ffb8000", + "0xa0680017fff8005", + "0xe", + "0x4824800180057ffe", + "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "0x484480017ffe8000", + "0x110000000000000000", + "0x48307ffe7fff8003", + "0x480280007ffa7ffc", + "0x480280017ffa7ffc", + "0x482480017ffb7ffd", + "0xffffffffffffffeefffffffffffffeff", + "0x400280027ffa7ffc", + "0x10780017fff7fff", + "0x11", + "0x48127ffe7fff8005", + "0x484480017ffe8000", + "0x8000000000000000000000000000000", + "0x48307ffe7fff8003", + "0x480280007ffa7ffd", + "0x482480017ffc7ffe", + "0xf0000000000000000000000000000100", + "0x480280017ffa7ffd", + "0x400280027ffa7ff9", + "0x402480017ffd7ff9", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7ffd", + "0x4", + "0x402780017fff7fff", + "0x1", + "0x482680017ffa8000", + "0x3", + "0x482680017ffb8000", + "0x6", + "0x48127ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x476574457865637574696f6e496e666f", + "0x400280007ffd7fff", + "0x400380017ffd7ffc", + "0x480280037ffd8000", + "0x20680017fff7fff", + "0xc", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x5", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480280047ffd8000", + "0x10780017fff7fff", + "0x9", + "0x480280027ffd8000", + "0x482680017ffd8000", + "0x6", + "0x480680017fff8000", + "0x1", + "0x480280047ffd8000", + "0x480280057ffd8000", + "0x1104800180018000", + "0x172", + "0x20680017fff7ffd", + "0xa", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x168", + "0x40780017fff7fff", + "0x1", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff77fff8000", + "0x1104800180018000", + "0x123", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400280027ff97ffb", + "0x400280037ff97ffc", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xd", + "0x480280067ff98000", + "0x482680017ff98000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0xb9", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ff87fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff5d", + "0x480a7ff77fff8000", + "0x480a7ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xa6", + "0x1104800180018000", + "0x96", + "0x20680017fff7ffd", + "0xd", + "0x48127fe57fff8000", + "0x48127ff57fff8000", + "0x48127fe47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127fe57fff8000", + "0x48127ff57fff8000", + "0x48127fe47fff8000", + "0x48127ff47fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xfe", + "0x40780017fff7fff", + "0x1", + "0x40780017fff7fff", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x48127ff77fff8000", + "0x1104800180018000", + "0xb2", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x456d69744576656e74", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400280027ff97ffb", + "0x400280037ff97ffc", + "0x400280047ff97ffd", + "0x400280057ff97ffe", + "0x480280077ff98000", + "0x20680017fff7fff", + "0xd", + "0x480280067ff98000", + "0x482680017ff98000", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280067ff98000", + "0x482680017ff98000", + "0xa", + "0x480680017fff8000", + "0x1", + "0x480280087ff98000", + "0x480280097ff98000", + "0x1104800180018000", + "0x48", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xba", + "0x20680017fff7fff", + "0x8", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xe4", + "0x20680017fff7fff", + "0x8", + "0x480680017fff8000", + "0x0", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ff97fff", + "0x400380017ff97ff8", + "0x400380027ff97ffa", + "0x400380037ff97ffb", + "0x400380047ff97ffc", + "0x480280067ff98000", + "0x20680017fff7fff", + "0x21", + "0x480280057ff98000", + "0x482680017ffb8000", + "0x1", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280077ff97fff", + "0x400280087ff97ffd", + "0x400380097ff97ffa", + "0x4002800a7ff97ffe", + "0x4003800b7ff97ffd", + "0x4802800d7ff98000", + "0x20680017fff7fff", + "0xc", + "0x4802800c7ff98000", + "0x482680017ff98000", + "0xe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x4802800c7ff98000", + "0x482680017ff98000", + "0x10", + "0x480680017fff8000", + "0x1", + "0x4802800e7ff98000", + "0x4802800f7ff98000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x4", + "0x480280057ff98000", + "0x482680017ff98000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ff98000", + "0x480280087ff98000", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ff5", + "0x16", + "0x480680017fff8000", + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x400280007ffb7fff", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xbe", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x10780017fff7fff", + "0x14", + "0x480680017fff8000", + "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff", + "0x400280007ffb7fff", + "0x480a7ff67fff8000", + "0x480a7ff77fff8000", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x480a7ffa7fff8000", + "0x482680017ffb8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0xbf", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x8", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x482a7ffd7ffb8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ff97fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ff98000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x7", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x482a7ffc7ffa8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080007ffa7fff", + "0x10780017fff7fff", + "0xc", + "0x400080007ffb7fff", + "0x40780017fff7fff", + "0x5", + "0x482480017ff68000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x1c", + "0x480680017fff8000", + "0x1", + "0x48307fff7ffa8001", + "0xa0680017fff7fff", + "0x7", + "0x4824800180007fff", + "0x100000000000000000000000000000000", + "0x400080017ff67fff", + "0x10780017fff7fff", + "0xc", + "0x400080017ff77fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x8", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48297ffd80017ffb", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xc", + "0x400280007ff97fff", + "0x40780017fff7fff", + "0x1", + "0x482680017ff98000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x7", + "0x482680017ff98000", + "0x1", + "0x48127ffe7fff8000", + "0x480680017fff8000", + "0x1", + "0x48297ffc80017ffa", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ffa7fff", + "0x10780017fff7fff", + "0xc", + "0x400080007ffb7fff", + "0x40780017fff7fff", + "0x5", + "0x482480017ff68000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x1c", + "0x480680017fff8000", + "0x1", + "0x48307fff80017ffa", + "0xa0680017fff7fff", + "0x7", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080017ff67fff", + "0x10780017fff7fff", + "0xc", + "0x400080017ff77fff", + "0x40780017fff7fff", + "0x1", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffc7fff8000", + "0x48127ff57fff8000", + "0x10780017fff7fff", + "0x8", + "0x482480017ff68000", + "0x2", + "0x48127ffa7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x27", + "0x480a7ff77fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x22", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff533", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ff67fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x12", + "0x480a7ff77fff8000", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0xd", + "0x480a7ff87fff8000", + "0x480a7ff97fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff51e", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffff4cb", + "0x48127ffe7fff8000", + "0x48127ffe7fff8000", + "0x208b7fff7fff7ffe" + ], + "hints": [ + [ + 0, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1d10" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 19, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 38, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 58, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 81, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 96, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 111, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1d10" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 130, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 149, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 169, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 192, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 207, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 222, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x2486" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 241, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 260, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 280, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 300, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 315, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 330, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x6054" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 349, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 368, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -8 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 388, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 412, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 427, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 442, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x7cec" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 467, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 490, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -40 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 510, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 536, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 552, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 567, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 583, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x8fb6" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 615, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 640, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -72 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 661, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 687, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 703, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 718, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 733, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 749, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x2bf2a" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 781, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 806, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -93 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 828, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 848, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 864, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 879, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 894, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 910, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x448d6" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 949, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 974, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -124 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 997, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1017, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1033, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1048, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1063, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1078, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1094, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x11ea4" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1126, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1151, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -93 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1173, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1193, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1209, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1224, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1239, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1255, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1b9f4" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1287, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1312, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -93 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1334, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1354, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1370, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1385, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1400, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1416, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1b9f4" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1448, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1473, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -93 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1495, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1515, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1531, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1546, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1561, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1577, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x1fa36" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1649, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1672, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Deref": { + "register": "AP", + "offset": -142 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1697, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1717, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1733, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1748, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1769, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1784, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1799, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1814, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 1936, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x800000000000000000000000000000000000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 1940, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 3 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 1950, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -2 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -1 + }, + "y": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2530, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2534, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "scalar": { + "Immediate": "0x8000000000000110000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": 0 + }, + "y": { + "register": "AP", + "offset": 1 + } + } + } + ] + ], + [ + 2606, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 2738, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 2787, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 2836, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 2860, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3052, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3054, + [ + { + "DivMod": { + "lhs": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "quotient": { + "register": "AP", + "offset": 3 + }, + "remainder": { + "register": "AP", + "offset": 4 + } + } + } + ] + ], + [ + 3129, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3161, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3463, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3548, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3577, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3600, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3652, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3704, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 3820, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3822, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3847, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -8 + } + } + } + } + ] + ], + [ + 3920, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -5 + } + } + } + } + ] + ], + [ + 3940, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "AP", + "offset": -3 + } + } + } + } + ] + ], + [ + 3964, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 3995, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4041, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + }, + "dst": { + "register": "AP", + "offset": 5 + } + } + } + ] + ], + [ + 4045, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 4 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4056, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 4 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4084, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "rhs": { + "Immediate": "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + }, + "dst": { + "register": "AP", + "offset": 5 + } + } + } + ] + ], + [ + 4088, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 4 + } + }, + "scalar": { + "Immediate": "0x110000000000000000" + }, + "max_x": { + "Immediate": "0xffffffffffffffffffffffffffffffff" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4099, + [ + { + "LinearSplit": { + "value": { + "Deref": { + "register": "AP", + "offset": 4 + } + }, + "scalar": { + "Immediate": "0x8000000000000000000000000000000" + }, + "max_x": { + "Immediate": "0xfffffffffffffffffffffffffffffffe" + }, + "x": { + "register": "AP", + "offset": -2 + }, + "y": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4123, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -3 + } + } + } + } + ] + ], + [ + 4168, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4170, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4195, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 4281, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4283, + [ + { + "AllocSegment": { + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 4308, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 4422, + [ + { + "SystemCall": { + "system": { + "Deref": { + "register": "FP", + "offset": -7 + } + } + } + } + ] + ], + [ + 4435, + [ + { + "SystemCall": { + "system": { + "BinOp": { + "op": "Add", + "a": { + "register": "FP", + "offset": -7 + }, + "b": { + "Immediate": "0x7" + } + } + } + } + } + ] + ], + [ + 4541, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4564, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4584, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4609, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4632, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ], + [ + 4652, + [ + { + "TestLessThan": { + "lhs": { + "Deref": { + "register": "AP", + "offset": 0 + } + }, + "rhs": { + "Immediate": "0x100000000000000000000000000000000" + }, + "dst": { + "register": "AP", + "offset": -1 + } + } + } + ] + ] + ], + "pythonic_hints": [ + [ + 0, + [ + "memory[ap + 0] = 7440 <= memory[fp + -6]" + ] + ], + [ + 19, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 38, + [ + "memory[ap + 0] = 0 <= memory[ap + -8]" + ] + ], + [ + 58, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 81, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 96, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 111, + [ + "memory[ap + 0] = 7440 <= memory[fp + -6]" + ] + ], + [ + 130, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 149, + [ + "memory[ap + 0] = 0 <= memory[ap + -8]" + ] + ], + [ + 169, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 192, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 207, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 222, + [ + "memory[ap + 0] = 9350 <= memory[fp + -6]" + ] + ], + [ + 241, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 260, + [ + "memory[ap + 0] = 0 <= memory[ap + -8]" + ] + ], + [ + 280, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 300, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 315, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 330, + [ + "memory[ap + 0] = 24660 <= memory[fp + -6]" + ] + ], + [ + 349, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 368, + [ + "memory[ap + 0] = 0 <= memory[ap + -8]" + ] + ], + [ + 388, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 412, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 427, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 442, + [ + "memory[ap + 0] = 31980 <= memory[fp + -6]" + ] + ], + [ + 467, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 490, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -40]" + ] + ], + [ + 510, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 536, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 552, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 567, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 583, + [ + "memory[ap + 0] = 36790 <= memory[fp + -6]" + ] + ], + [ + 615, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 640, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -72]" + ] + ], + [ + 661, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 687, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 703, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 718, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 733, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 749, + [ + "memory[ap + 0] = 180010 <= memory[fp + -6]" + ] + ], + [ + 781, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 806, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -93]" + ] + ], + [ + 828, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 848, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 864, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 879, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 894, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 910, + [ + "memory[ap + 0] = 280790 <= memory[fp + -6]" + ] + ], + [ + 949, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 974, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -124]" + ] + ], + [ + 997, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1017, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1033, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1048, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1063, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1078, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1094, + [ + "memory[ap + 0] = 73380 <= memory[fp + -6]" + ] + ], + [ + 1126, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1151, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -93]" + ] + ], + [ + 1173, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1193, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1209, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1224, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1239, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1255, + [ + "memory[ap + 0] = 113140 <= memory[fp + -6]" + ] + ], + [ + 1287, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1312, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -93]" + ] + ], + [ + 1334, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1354, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1370, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1385, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1400, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1416, + [ + "memory[ap + 0] = 113140 <= memory[fp + -6]" + ] + ], + [ + 1448, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1473, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -93]" + ] + ], + [ + 1495, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1515, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1531, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1546, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1561, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1577, + [ + "memory[ap + 0] = 129590 <= memory[fp + -6]" + ] + ], + [ + 1649, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1672, + [ + "memory[ap + 0] = memory[ap + -1] <= memory[ap + -142]" + ] + ], + [ + 1697, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1717, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1733, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1748, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1769, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1784, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1799, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1814, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 1936, + [ + "memory[ap + 4] = memory[ap + -1] < 3618502788666131106986593281521497120414687020801267626233049500247285301248" + ] + ], + [ + 1940, + [ + "\n(value, scalar) = (memory[ap + 3], 313594649253062377472)\nx = min(value // scalar, 340282366920938463463374607431768211455)\ny = value - x * scalar\nmemory[ap + -2] = x\nmemory[ap + -1] = y\n" + ] + ], + [ + 1950, + [ + "\n(value, scalar) = (memory[ap + -2], 10633823966279326983230456482242756608)\nx = min(value // scalar, 340282366920938463463374607431768211455)\ny = value - x * scalar\nmemory[ap + -1] = x\nmemory[ap + 0] = y\n" + ] + ], + [ + 2530, + [ + "memory[ap + 0] = memory[fp + -3] < 256" + ] + ], + [ + 2534, + [ + "\n(value, scalar) = (memory[ap + -1], 10633823966279327296825105735305134080)\nx = min(value // scalar, 340282366920938463463374607431768211454)\ny = value - x * scalar\nmemory[ap + 0] = x\nmemory[ap + 1] = y\n" + ] + ], + [ + 2606, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 2738, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -3])" + ] + ], + [ + 2787, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -3])" + ] + ], + [ + 2836, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -3])" + ] + ], + [ + 2860, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3052, + [ + "memory[ap + 0] = memory[fp + -3] < 340282366920938463463374607431768211456" + ] + ], + [ + 3054, + [ + "(memory[ap + 3], memory[ap + 4]) = divmod(memory[fp + -3], 340282366920938463463374607431768211456)" + ] + ], + [ + 3129, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3161, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3463, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3548, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3577, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3600, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -4])" + ] + ], + [ + 3652, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -4])" + ] + ], + [ + 3704, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -4])" + ] + ], + [ + 3820, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3822, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3847, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -8])" + ] + ], + [ + 3920, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -5])" + ] + ], + [ + 3940, + [ + "syscall_handler.syscall(syscall_ptr=memory[ap + -3])" + ] + ], + [ + 3964, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 3995, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 4041, + [ + "memory[ap + 5] = memory[ap + -1] < 3618502788666131106986593281521497120414687020801267626233049500247285300992" + ] + ], + [ + 4045, + [ + "\n(value, scalar) = (memory[ap + 4], 313594649253062377472)\nx = min(value // scalar, 340282366920938463463374607431768211455)\ny = value - x * scalar\nmemory[ap + -2] = x\nmemory[ap + -1] = y\n" + ] + ], + [ + 4056, + [ + "\n(value, scalar) = (memory[ap + 4], 10633823966279326983230456482242756608)\nx = min(value // scalar, 340282366920938463463374607431768211454)\ny = value - x * scalar\nmemory[ap + -2] = x\nmemory[ap + -1] = y\n" + ] + ], + [ + 4084, + [ + "memory[ap + 5] = memory[ap + -1] < 3618502788666131106986593281521497120414687020801267626233049500247285300992" + ] + ], + [ + 4088, + [ + "\n(value, scalar) = (memory[ap + 4], 313594649253062377472)\nx = min(value // scalar, 340282366920938463463374607431768211455)\ny = value - x * scalar\nmemory[ap + -2] = x\nmemory[ap + -1] = y\n" + ] + ], + [ + 4099, + [ + "\n(value, scalar) = (memory[ap + 4], 10633823966279326983230456482242756608)\nx = min(value // scalar, 340282366920938463463374607431768211454)\ny = value - x * scalar\nmemory[ap + -2] = x\nmemory[ap + -1] = y\n" + ] + ], + [ + 4123, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -3])" + ] + ], + [ + 4168, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 4170, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 4195, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -7])" + ] + ], + [ + 4281, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 4283, + [ + "memory[ap + 0] = segments.add()" + ] + ], + [ + 4308, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -7])" + ] + ], + [ + 4422, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -7])" + ] + ], + [ + 4435, + [ + "syscall_handler.syscall(syscall_ptr=memory[fp + -7] + 7)" + ] + ], + [ + 4541, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ], + [ + 4564, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ], + [ + 4584, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ], + [ + 4609, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ], + [ + 4632, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ], + [ + 4652, + [ + "memory[ap + -1] = memory[ap + 0] < 340282366920938463463374607431768211456" + ] + ] + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "offset": 749, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x16d9d5d83f8eecc5d7450519aad7e6e649be1a6c9d6df85bd0b177cc59a926a", + "offset": 222, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x1d13ab0a76d7407b1d5faccd4b3d8a9efe42f3d3c21766431d4fafb30f45bd4", + "offset": 1255, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x1e888a1026b19c8c0b57c72d63ed1737106aa10034105b980ba117bd0c29fe1", + "offset": 583, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "offset": 1094, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x2819e8b2b82ee4c56798709651ab9e8537f644c0823e42ba017efce4f2077e4", + "offset": 330, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x31341177714d81ad9ccd0c903211bc056a60e8af988d0fd918cc43874549653", + "offset": 0, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x351ccc9e7b13b17e701a7d4f5f85b525bac37b7648419fe194e6c15bc73da47", + "offset": 111, + "builtins": [ + "range_check" + ] + }, + { + "selector": "0x35a73cd311a05d46deda634c5ee045db92f811b4e74bca4437fcb5302b7af33", + "offset": 442, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x3704ffe8fba161be0e994951751a5033b1462b918ff785c0a636be718dfdb68", + "offset": 910, + "builtins": [ + "pedersen", + "range_check" + ] + }, + { + "selector": "0x3b076186c19fe96221e4dfacd40c519f612eae02e0555e4e115a2a6cf2f1c1f", + "offset": 1416, + "builtins": [ + "pedersen", + "range_check" + ] + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "offset": 1577, + "builtins": [ + "pedersen", + "range_check" + ] + } + ] + } +} diff --git a/crates/papyrus_storage/resources/program.json b/crates/papyrus_storage/resources/program.json new file mode 100644 index 00000000000..bc65a08509d --- /dev/null +++ b/crates/papyrus_storage/resources/program.json @@ -0,0 +1 @@ +{"attributes":null,"builtins":["pedersen","range_check","bitwise"],"data":["0x40780017fff7fff","0x1","0x208b7fff7fff7ffe","0x400380007ffb7ffc","0x400380017ffb7ffd","0x482680017ffb8000","0x3","0x480280027ffb8000","0x208b7fff7fff7ffe","0x20780017fff7ffd","0x3","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480080007fff8000","0x400080007ffd7fff","0x482480017ffd8001","0x1","0x482480017ffd8001","0x1","0xa0680017fff7ffe","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb","0x402a7ffc7ffd7fff","0x208b7fff7fff7ffe","0x20780017fff7ffd","0x4","0x400780017fff7ffd","0x1","0x208b7fff7fff7ffe","0x400380007ffc7ffd","0x482680017ffc8000","0x1","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x48297ffc80007ffd","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffb","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6","0x208b7fff7fff7ffe","0x480680017fff8000","0x3ffffffffffffffffffffffffffffff","0x480280017ffc8000","0x48307fff80007ffe","0x400280027ffc7fff","0x480280017ffc8000","0x484480017fff8000","0x100000000000000000000000000000000","0x480280007ffc8000","0x40317fff7ffe7ffd","0x482680017ffc8000","0x3","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x20680017fff7fff","0x10","0x480a7ffc7fff8000","0x482680017ffd8000","0x11000000000000000000000000000000000000000000000101","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed","0x480680017fff8000","0x800000000000011000000000000000000000000000000000000000000000000","0x48127ffe7fff8000","0x48287ffd80007ffe","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe7","0x482680017ffd8000","0x11000000000000000000000000000000000000000000000101","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x20680017fff7fff","0xc","0x40780017fff7fff","0xa","0x480680017fff8000","0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff","0x480a7ffc7fff8000","0x48287ffd80007ffe","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd8","0x10780017fff7fff","0x8","0x40780017fff7fff","0xb","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd0","0x480a7ffd7fff8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x43616c6c436f6e7472616374","0x400280007ff97fff","0x400380017ff97ffa","0x400380027ff97ffb","0x400380037ff97ffc","0x400380047ff97ffd","0x482680017ff98000","0x7","0x480280057ff98000","0x480280067ff98000","0x208b7fff7fff7ffe","0x480680017fff8000","0x44656c656761746543616c6c","0x400280007ff97fff","0x400380017ff97ffa","0x400380027ff97ffb","0x400380037ff97ffc","0x400380047ff97ffd","0x482680017ff98000","0x7","0x480280057ff98000","0x480280067ff98000","0x208b7fff7fff7ffe","0x480680017fff8000","0x47657443616c6c657241646472657373","0x400280007ffd7fff","0x482680017ffd8000","0x2","0x480280017ffd8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x47657453657175656e63657241646472657373","0x400280007ffd7fff","0x482680017ffd8000","0x2","0x480280017ffd8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x476574436f6e747261637441646472657373","0x400280007ffd7fff","0x482680017ffd8000","0x2","0x480280017ffd8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x47657454785369676e6174757265","0x400280007ffd7fff","0x482680017ffd8000","0x3","0x480280017ffd8000","0x480280027ffd8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x53746f7261676552656164","0x400280007ffc7fff","0x400380017ffc7ffd","0x482680017ffc8000","0x3","0x480280027ffc8000","0x208b7fff7fff7ffe","0x480680017fff8000","0x53746f726167655772697465","0x400280007ffb7fff","0x400380017ffb7ffc","0x400380027ffb7ffd","0x482680017ffb8000","0x3","0x208b7fff7fff7ffe","0x400380007ffb7ffc","0x400380017ffb7ffd","0x482680017ffb8000","0x5","0x480280037ffb8000","0x208b7fff7fff7ffe","0x208b7fff7fff7ffe","0x480680017fff8000","0x53656e644d657373616765546f4c31","0x400280007ffa7fff","0x400380017ffa7ffb","0x400380027ffa7ffc","0x400380037ffa7ffd","0x482680017ffa8000","0x4","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x480680017fff8000","0x2691cb735b18f3f656c3b82bd97a32b65d15019b64117513f8604d1e06fe58b","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff47","0x480a7ffc7fff8000","0x48127ffe7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff7c","0x48127fe17fff8000","0x48127ffd7fff8000","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0","0x480a7ffa7fff8000","0x48127ffe7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffcc","0x48127ffe7fff8000","0x482480017ff78000","0x1","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc7","0x48127ffe7fff8000","0x48127fee7fff8000","0x48127fee7fff8000","0x48127ff57fff8000","0x48127ffb7fff8000","0x208b7fff7fff7ffe","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdc","0x480a7ff87fff8000","0x48127ffe7fff8000","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffbf","0x482480017ff88000","0x1","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffba","0x48127ff07fff8000","0x48127ff07fff8000","0x208b7fff7fff7ffe","0x400780017fff7ffc","0x2","0x480a7ff87fff8000","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd5","0x480280007ffd8000","0x480280017ffd8000","0x48127ff97fff8000","0x48127ff97fff8000","0x48127ff97fff8000","0x480a7ffb7fff8000","0x48307ffa7ff88000","0x48307ffa7ff88000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdf","0x208b7fff7fff7ffe","0x480280027ffb8000","0x480280017ffd8000","0x400080007ffe7fff","0x482680017ffd8000","0x2","0x480280017ffd8000","0x48307fff7ffe8000","0x402a7ffd7ffc7fff","0x480280027ffb8000","0x480280007ffb8000","0x480280017ffb8000","0x482480017ffd8000","0x1","0x480280007ffd8000","0x480280017ffd8000","0x482680017ffd8000","0x2","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdd","0x40780017fff7fff","0x1","0x48127ffc7fff8000","0x48127ffc7fff8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ff97fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff82","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280017ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1","0x40780017fff7fff","0x1","0x48127ffc7fff8000","0x48127ffc7fff8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ff77fff8000","0x480a7ff87fff8000","0x480a7ff97fff8000","0x480a7ffb7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff8b","0x480a7ffa7fff8000","0x48127ffd7fff8000","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff68","0x48127ffe7fff8000","0x48127ff77fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff63","0x48127fed7fff8000","0x48127fed7fff8000","0x48127fed7fff8000","0x480a7ffb7fff8000","0x48127ff47fff8000","0x48127ffa7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff8d","0x48127fbb7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x3","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x480280027ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffdd","0x40780017fff7fff","0x1","0x48127ffb7fff8000","0x48127ffb7fff8000","0x48127ffb7fff8000","0x48127ffb7fff8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe96","0x40137fff7fff8000","0x4003800080007ffb","0x4003800180007ffc","0x4003800280007ffd","0x4826800180008000","0x3","0x480a7ff87fff8000","0x480a7ffa7fff8000","0x480680017fff8000","0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb","0x4828800080007ffc","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeec","0x48127ffd7fff8000","0x480a7ff97fff8000","0x208b7fff7fff7ffe","0x480a7ff87fff8000","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe6","0x208b7fff7fff7ffe","0x482680017ffd8000","0x4","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x480280027ffd8000","0x480280037ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffef","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffef5","0x400680017fff7ffe","0x2","0x48127ffd7fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff23","0x480080007fba8000","0x480080017fb98000","0x48127ff97fff8000","0x48127ff97fff8000","0x48127ff97fff8000","0x480a7ffd7fff8000","0x48307ffa7ff88000","0x48307ffa7ff88000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffff2d","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280017ffb8000","0x480280027ffb8000","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe3","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x48127ffb7fff8000","0x48127ffb7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffed9","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffeba","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x4003800080007ffc","0x4826800180008000","0x1","0x480a7ffd7fff8000","0x4828800080007ffe","0x480a80007fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee","0x480280027ffb8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0","0x48127ff67fff8000","0x480280017ffb8000","0x48127ffb7fff8000","0x480280037ffb8000","0x48127ffa7fff8000","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x480680017fff8000","0xf","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe9a","0x48127ffe7fff8000","0x480680017fff8000","0xf","0x482480017ffd8000","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe9b","0x480680017fff8000","0xf","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe8f","0x402480017ff27fff","0x1","0x48127ffe7fff8000","0x480a7ffd7fff8000","0x208b7fff7fff7ffe","0x402b7ffd7ffc7ffd","0x480280007ffb8000","0x480280017ffb8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe9","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x48127ffd7fff8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffd7fff8000","0x480680017fff8000","0x11","0x480680017fff8000","0x55","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe01","0x480a7ffc7fff8000","0x480680017fff8000","0x1","0x480680017fff8000","0x2","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdd7","0x400680017fff7fff","0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026","0x48127ffe7fff8000","0x48127ff77fff8000","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x4003800080007ffc","0x4826800180008000","0x1","0x480a7ffd7fff8000","0x4828800080007ffe","0x480a80007fff8000","0x208b7fff7fff7ffe","0x402b7ffd7ffc7ffd","0x480280017ffb8000","0x480280027ffb8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1","0x48127ffe7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff2","0x480280007ffb8000","0x48127ff47fff8000","0x48127ffb7fff8000","0x480280037ffb8000","0x48127ffa7fff8000","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x2","0x400780017fff8000","0xc","0x400780017fff8001","0x22","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe5d","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x480680017fff8000","0x2","0x48127ffb7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe57","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdf2","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x480280027ffb8000","0x480280027ffd8000","0x400080007ffe7fff","0x482680017ffd8000","0x3","0x480280027ffd8000","0x48307fff7ffe8000","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x480280027ffd8000","0x482680017ffd8000","0x3","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffea","0x40780017fff7fff","0x1","0x480280027ffb8000","0x48127ffd7fff8000","0x480280017ffb8000","0x482480017ffd8000","0x1","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ff97fff8000","0x208b7fff7fff7ffe","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdd9","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x480280027ffb8000","0x480280027ffd8000","0x400080007ffe7fff","0x482680017ffd8000","0x3","0x480280027ffd8000","0x48307fff7ffe8000","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x480280027ffd8000","0x482680017ffd8000","0x3","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffea","0x40780017fff7fff","0x1","0x480280027ffb8000","0x48127ffd7fff8000","0x480280017ffb8000","0x482480017ffd8000","0x1","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ff97fff8000","0x208b7fff7fff7ffe","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd49","0x400180007fff7ffd","0x480680017fff8000","0x0","0x400080017ffe7fff","0x480a7ff97fff8000","0x480a7ffb7fff8000","0x480a7ffa7fff8000","0x480a7ffc7fff8000","0x480680017fff8000","0x2","0x48127ff97fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe29","0x48127ffd7fff8000","0x48127ffe7fff8000","0x48127ffc7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280017ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe6","0x40780017fff7fff","0x1","0x48127ffc7fff8000","0x48127ffd7fff8000","0x48127ffb7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd9d","0x400a7ffd7fff7fff","0x48127ffe7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd8d","0x400a7ffd7fff7fff","0x48127ffe7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd7d","0x400a7ffd7fff7fff","0x48127ffe7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffa7fff8000","0x480a7ffd7fff8000","0x480680017fff8000","0x7c7","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe9f","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd53","0x400680017fff7fff","0x0","0x48127ffe7fff8000","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x480680017fff8000","0x7e5","0x1104800180018000","0xf2","0x48127ffe7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffea7","0x400680017fff7fff","0x7c7","0x48127ffe7fff8000","0x48127ff37fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0xfa","0x400680017fff7fff","0x7e5","0x48127ffd7fff8000","0x48127ffd7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd7","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffa7fff8000","0x480680017fff8000","0x5","0x480680017fff8000","0x64","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe68","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0xed","0x48127ffe7fff8000","0x480680017fff8000","0x5","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe76","0x402680017ffd7fff","0x64","0x48127ffe7fff8000","0x48127ff37fff8000","0x480a7ffc7fff8000","0x480680017fff8000","0x5","0x1104800180018000","0xc8","0x480680017fff8000","0x22b","0x40487ffd7fff7ffe","0x48127ffc7fff8000","0x48127ffc7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffda","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffb7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcef","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc89","0x48127ffc7fff8000","0x480a7ffc7fff8000","0x48127ffb7fff8000","0x48127ffa7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0xcd","0x480680017fff8000","0x22b","0x48127ffd7fff8000","0x480680017fff8000","0x5","0x48487ffd7ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe28","0x48127ff27fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe5","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x20780017fff7ffd","0x5","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x208b7fff7fff7ffe","0x480a7ffa7fff8000","0x480680017fff8000","0x5","0x1104800180018000","0x22","0x480a7ffb7fff8000","0x480a7ffc7fff8000","0x480a7ffc7fff8000","0x482680017ffd8000","0x800000000000011000000000000000000000000000000000000000000000000","0x1104800180018000","0xa0","0x48127ffe7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe86","0x48127fef7fff8000","0x208b7fff7fff7ffe","0x482680017ffd8000","0x2","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280027ffb8000","0x480280007ffd8000","0x480280017ffd8000","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe3","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ffc7fff8000","0x480a7ffd7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcb9","0x48127ffe7fff8000","0x480a7ffd7fff8000","0x482480017ffd8000","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffcbb","0x208b7fff7fff7ffe","0x482680017ffd8000","0x1","0x402a7ffd7ffc7fff","0x480280007ffb8000","0x480280007ffd8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1","0x40780017fff7fff","0x1","0x48127ffe7fff8000","0x480280017ffb8000","0x480280027ffb8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x20780017fff7ffc","0x5","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x208b7fff7fff7ffe","0x480a7ff97fff8000","0x480a7ffa7fff8000","0x480a7ffb7fff8000","0x480a7ffb7fff8000","0x482680017ffc8000","0x800000000000011000000000000000000000000000000000000000000000000","0x480a7ffd7fff8000","0x1104800180018000","0x71","0x208b7fff7fff7ffe","0x480280027ffb8000","0x480280017ffd8000","0x400080007ffe7fff","0x482680017ffd8000","0x2","0x480280017ffd8000","0x48307fff7ffe8000","0x402a7ffd7ffc7fff","0x480280027ffb8000","0x480280007ffb8000","0x482480017ffe8000","0x1","0x480280007ffd8000","0x480280017ffd8000","0x482680017ffd8000","0x2","0x1104800180018000","0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe2","0x40780017fff7fff","0x1","0x48127ffd7fff8000","0x480280017ffb8000","0x48127ffc7fff8000","0x480280037ffb8000","0x480680017fff8000","0x0","0x48127ffa7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbd9","0x40137fff7fff8000","0x4003800080007ffc","0x4003800180007ffd","0x4826800180008000","0x2","0x480a7ff97fff8000","0x480a7ffb7fff8000","0x480680017fff8000","0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3","0x4828800080007ffc","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc30","0x48127ffd7fff8000","0x480a7ffa7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbc5","0x40137fff7fff8000","0x4003800080007ffd","0x4826800180008000","0x1","0x480a7ffa7fff8000","0x480a7ffc7fff8000","0x480680017fff8000","0x26813d396fdb198e9ead934e4f7a592a8b88a059e45ab0eb6ee53494e8d45b0","0x4828800080007ffc","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc1d","0x482480017fff8000","0x1","0x40307ffe7ffd7fff","0x48127ffc7fff8000","0x480a7ffb7fff8000","0x480080007ffc8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbae","0x40137fff7fff8000","0x4003800080007ffd","0x4826800180008000","0x1","0x480a7ffa7fff8000","0x480a7ffc7fff8000","0x480680017fff8000","0x8a2a3272a92492ded6c04f7c85df9c53134cef398564465f12af3c9c986d41","0x4828800080007ffc","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffc06","0x48127ffd7fff8000","0x480a7ffb7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x1","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb9b","0x40137fff7fff8000","0x4003800080007ffc","0x4003800180007ffd","0x4826800180008000","0x2","0x480a7ff97fff8000","0x480a7ffb7fff8000","0x480680017fff8000","0x1b1343fe0f4a16bed5e5133b5ca9f03ab15976bb2df2b6d263ac3170b8b6a13","0x4828800080007ffc","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbf2","0x48127ffd7fff8000","0x480a7ffa7fff8000","0x208b7fff7fff7ffe","0x40780017fff7fff","0x3","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb87","0x40137fff7fff8000","0x4003800080007ffb","0x4003800180007ffc","0x400380007ff97ffc","0x402780017ff98001","0x1","0x4826800180008000","0x2","0x40297ffc7fff8002","0x4826800180008000","0x2","0x480a7ffd7fff8000","0x480a7ffc7fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffb81","0x480a7ff87fff8000","0x480a7ffa7fff8000","0x480680017fff8000","0x5fbd85570830519219bb4ad6951316f96fce363f86909d1f8adb1fdc836471","0x4829800080008002","0x480a80007fff8000","0x1104800180018000","0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffbd4","0x48127ffd7fff8000","0x480a80017fff8000","0x208b7fff7fff7ffe"],"debug_info":null,"hints":{"0":[{"accessible_scopes":["starkware.cairo.common.alloc","starkware.cairo.common.alloc.alloc"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":0,"offset":0},"reference_ids":{}}}],"1009":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.increase_value"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":78,"offset":19},"reference_ids":{"__wrappers__.increase_value.__calldata_actual_size":663,"__wrappers__.increase_value.__calldata_arg_address":661,"__wrappers__.increase_value.__calldata_ptr":662,"__wrappers__.increase_value.__temp58":664,"__wrappers__.increase_value.bitwise_ptr":659,"__wrappers__.increase_value.pedersen_ptr":657,"__wrappers__.increase_value.range_check_ptr":658,"__wrappers__.increase_value.ret_struct":666,"__wrappers__.increase_value.syscall_ptr":665}}}],"1052":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_call_with_array"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":82,"offset":0},"reference_ids":{"__wrappers__.test_call_with_array.__calldata_actual_size":692,"__wrappers__.test_call_with_array.__calldata_arg_arr":688,"__wrappers__.test_call_with_array.__calldata_arg_arr_len":683,"__wrappers__.test_call_with_array.__calldata_arg_self_address":681,"__wrappers__.test_call_with_array.__calldata_ptr":691,"__wrappers__.test_call_with_array.__temp59":685,"__wrappers__.test_call_with_array.__temp60":686,"__wrappers__.test_call_with_array.__temp61":689,"__wrappers__.test_call_with_array.__temp62":690,"__wrappers__.test_call_with_array.__temp63":693,"__wrappers__.test_call_with_array.bitwise_ptr":679,"__wrappers__.test_call_with_array.pedersen_ptr":677,"__wrappers__.test_call_with_array.range_check_ptr":695,"__wrappers__.test_call_with_array.ret_struct":696,"__wrappers__.test_call_with_array.syscall_ptr":694}}}],"107":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.call_contract"],"code":"syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":9,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.call_contract.__temp9":56,"starkware.starknet.common.syscalls.call_contract.calldata":53,"starkware.starknet.common.syscalls.call_contract.calldata_size":52,"starkware.starknet.common.syscalls.call_contract.contract_address":50,"starkware.starknet.common.syscalls.call_contract.function_selector":51,"starkware.starknet.common.syscalls.call_contract.syscall":55,"starkware.starknet.common.syscalls.call_contract.syscall_ptr":54}}}],"119":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.delegate_call"],"code":"syscall_handler.delegate_call(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":10,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.delegate_call.__temp10":65,"starkware.starknet.common.syscalls.delegate_call.calldata":62,"starkware.starknet.common.syscalls.delegate_call.calldata_size":61,"starkware.starknet.common.syscalls.delegate_call.contract_address":59,"starkware.starknet.common.syscalls.delegate_call.function_selector":60,"starkware.starknet.common.syscalls.delegate_call.syscall":64,"starkware.starknet.common.syscalls.delegate_call.syscall_ptr":63}}}],"12":[{"accessible_scopes":["starkware.cairo.common.memcpy","starkware.cairo.common.memcpy.memcpy"],"code":"vm_enter_scope({'n': ids.len})","flow_tracking_data":{"ap_tracking":{"group":2,"offset":0},"reference_ids":{"starkware.cairo.common.memcpy.memcpy.dst":5,"starkware.cairo.common.memcpy.memcpy.len":7,"starkware.cairo.common.memcpy.memcpy.src":6}}}],"127":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.get_caller_address"],"code":"syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":11,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.get_caller_address.__temp11":70,"starkware.starknet.common.syscalls.get_caller_address.syscall":69,"starkware.starknet.common.syscalls.get_caller_address.syscall_ptr":68}}}],"134":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.get_sequencer_address"],"code":"syscall_handler.get_sequencer_address(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":12,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.get_sequencer_address.__temp12":74,"starkware.starknet.common.syscalls.get_sequencer_address.syscall":73,"starkware.starknet.common.syscalls.get_sequencer_address.syscall_ptr":72}}}],"141":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.get_contract_address"],"code":"syscall_handler.get_contract_address(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":13,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.get_contract_address.__temp13":78,"starkware.starknet.common.syscalls.get_contract_address.syscall":77,"starkware.starknet.common.syscalls.get_contract_address.syscall_ptr":76}}}],"148":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.get_tx_signature"],"code":"syscall_handler.get_tx_signature(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":14,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.get_tx_signature.__temp14":82,"starkware.starknet.common.syscalls.get_tx_signature.syscall":81,"starkware.starknet.common.syscalls.get_tx_signature.syscall_ptr":80}}}],"157":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.storage_read"],"code":"syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":15,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.storage_read.__temp15":87,"starkware.starknet.common.syscalls.storage_read.address":84,"starkware.starknet.common.syscalls.storage_read.syscall":86,"starkware.starknet.common.syscalls.storage_read.syscall_ptr":85}}}],"166":[{"accessible_scopes":["starkware.starknet.common.syscalls","starkware.starknet.common.syscalls.storage_write"],"code":"syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":16,"offset":1},"reference_ids":{"starkware.starknet.common.syscalls.storage_write.__temp16":93,"starkware.starknet.common.syscalls.storage_write.address":90,"starkware.starknet.common.syscalls.storage_write.syscall_ptr":92,"starkware.starknet.common.syscalls.storage_write.value":91}}}],"182":[{"accessible_scopes":["starkware.starknet.common.messages","starkware.starknet.common.messages.send_message_to_l1"],"code":"syscall_handler.send_message_to_l1(segments=segments, syscall_ptr=ids.syscall_ptr)","flow_tracking_data":{"ap_tracking":{"group":19,"offset":1},"reference_ids":{"starkware.starknet.common.messages.send_message_to_l1.__temp17":106,"starkware.starknet.common.messages.send_message_to_l1.payload":104,"starkware.starknet.common.messages.send_message_to_l1.payload_size":103,"starkware.starknet.common.messages.send_message_to_l1.syscall_ptr":105,"starkware.starknet.common.messages.send_message_to_l1.to_address":102}}}],"20":[{"accessible_scopes":["starkware.cairo.common.memcpy","starkware.cairo.common.memcpy.memcpy"],"code":"n -= 1\nids.continue_copying = 1 if n > 0 else 0","flow_tracking_data":{"ap_tracking":{"group":2,"offset":5},"reference_ids":{"starkware.cairo.common.memcpy.memcpy.__temp0":10,"starkware.cairo.common.memcpy.memcpy.continue_copying":11,"starkware.cairo.common.memcpy.memcpy.dst":5,"starkware.cairo.common.memcpy.memcpy.frame":9,"starkware.cairo.common.memcpy.memcpy.len":7,"starkware.cairo.common.memcpy.memcpy.next_frame":12,"starkware.cairo.common.memcpy.memcpy.src":6}}}],"23":[{"accessible_scopes":["starkware.cairo.common.memcpy","starkware.cairo.common.memcpy.memcpy"],"code":"vm_exit_scope()","flow_tracking_data":{"ap_tracking":{"group":2,"offset":6},"reference_ids":{"starkware.cairo.common.memcpy.memcpy.__temp0":10,"starkware.cairo.common.memcpy.memcpy.continue_copying":11,"starkware.cairo.common.memcpy.memcpy.dst":5,"starkware.cairo.common.memcpy.memcpy.frame":9,"starkware.cairo.common.memcpy.memcpy.len":7,"starkware.cairo.common.memcpy.memcpy.next_frame":12,"starkware.cairo.common.memcpy.memcpy.src":6}}}],"24":[{"accessible_scopes":["starkware.cairo.common.math","starkware.cairo.common.math.assert_not_zero"],"code":"from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'","flow_tracking_data":{"ap_tracking":{"group":3,"offset":0},"reference_ids":{"starkware.cairo.common.math.assert_not_zero.value":13}}}],"275":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.advance_counter"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":24,"offset":152},"reference_ids":{"__wrappers__.advance_counter.__calldata_actual_size":173,"__wrappers__.advance_counter.__calldata_arg_diffs":169,"__wrappers__.advance_counter.__calldata_arg_diffs_len":164,"__wrappers__.advance_counter.__calldata_arg_index":162,"__wrappers__.advance_counter.__calldata_ptr":172,"__wrappers__.advance_counter.__temp20":166,"__wrappers__.advance_counter.__temp21":167,"__wrappers__.advance_counter.__temp22":170,"__wrappers__.advance_counter.__temp23":171,"__wrappers__.advance_counter.__temp24":174,"__wrappers__.advance_counter.bitwise_ptr":160,"__wrappers__.advance_counter.pedersen_ptr":176,"__wrappers__.advance_counter.range_check_ptr":177,"__wrappers__.advance_counter.ret_struct":178,"__wrappers__.advance_counter.syscall_ptr":175}}}],"29":[{"accessible_scopes":["starkware.cairo.common.math","starkware.cairo.common.math.assert_nn"],"code":"from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'","flow_tracking_data":{"ap_tracking":{"group":4,"offset":0},"reference_ids":{"starkware.cairo.common.math.assert_nn.a":14,"starkware.cairo.common.math.assert_nn.range_check_ptr":15}}}],"303":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.constructor"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":26,"offset":17},"reference_ids":{"__wrappers__.constructor.__calldata_actual_size":196,"__wrappers__.constructor.__calldata_arg_address":192,"__wrappers__.constructor.__calldata_arg_value":194,"__wrappers__.constructor.__calldata_ptr":195,"__wrappers__.constructor.__temp25":197,"__wrappers__.constructor.bitwise_ptr":190,"__wrappers__.constructor.pedersen_ptr":199,"__wrappers__.constructor.range_check_ptr":200,"__wrappers__.constructor.ret_struct":201,"__wrappers__.constructor.syscall_ptr":198}}}],"351":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.xor_counters"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":28,"offset":161},"reference_ids":{"__wrappers__.xor_counters.__calldata_actual_size":230,"__wrappers__.xor_counters.__calldata_arg_index_and_x":228,"__wrappers__.xor_counters.__calldata_ptr":229,"__wrappers__.xor_counters.__temp26":231,"__wrappers__.xor_counters.bitwise_ptr":235,"__wrappers__.xor_counters.pedersen_ptr":233,"__wrappers__.xor_counters.range_check_ptr":234,"__wrappers__.xor_counters.ret_struct":236,"__wrappers__.xor_counters.syscall_ptr":232}}}],"402":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.call_xor_counters"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":31,"offset":35},"reference_ids":{"__wrappers__.call_xor_counters.__calldata_actual_size":267,"__wrappers__.call_xor_counters.__calldata_arg_address":263,"__wrappers__.call_xor_counters.__calldata_arg_index_and_x":265,"__wrappers__.call_xor_counters.__calldata_ptr":266,"__wrappers__.call_xor_counters.__temp28":268,"__wrappers__.call_xor_counters.bitwise_ptr":261,"__wrappers__.call_xor_counters.pedersen_ptr":259,"__wrappers__.call_xor_counters.range_check_ptr":270,"__wrappers__.call_xor_counters.ret_struct":271,"__wrappers__.call_xor_counters.syscall_ptr":269}}}],"444":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.add_signature_to_counters"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":33,"offset":153},"reference_ids":{"__wrappers__.add_signature_to_counters.__calldata_actual_size":297,"__wrappers__.add_signature_to_counters.__calldata_arg_index":295,"__wrappers__.add_signature_to_counters.__calldata_ptr":296,"__wrappers__.add_signature_to_counters.__temp31":298,"__wrappers__.add_signature_to_counters.bitwise_ptr":293,"__wrappers__.add_signature_to_counters.pedersen_ptr":299,"__wrappers__.add_signature_to_counters.range_check_ptr":300,"__wrappers__.add_signature_to_counters.ret_struct":302,"__wrappers__.add_signature_to_counters.syscall_ptr":301}}}],"468":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.set_value"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":35,"offset":13},"reference_ids":{"__wrappers__.set_value.__calldata_actual_size":318,"__wrappers__.set_value.__calldata_arg_address":314,"__wrappers__.set_value.__calldata_arg_value":316,"__wrappers__.set_value.__calldata_ptr":317,"__wrappers__.set_value.__temp32":319,"__wrappers__.set_value.bitwise_ptr":312,"__wrappers__.set_value.pedersen_ptr":310,"__wrappers__.set_value.range_check_ptr":311,"__wrappers__.set_value.ret_struct":321,"__wrappers__.set_value.syscall_ptr":320}}}],"47":[{"accessible_scopes":["starkware.cairo.common.math","starkware.cairo.common.math.assert_250_bit"],"code":"from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)","flow_tracking_data":{"ap_tracking":{"group":7,"offset":0},"reference_ids":{"starkware.cairo.common.math.assert_250_bit.high":29,"starkware.cairo.common.math.assert_250_bit.low":28,"starkware.cairo.common.math.assert_250_bit.range_check_ptr":27,"starkware.cairo.common.math.assert_250_bit.value":26}}}],"483":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.get_value_encode_return"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":37,"offset":0},"reference_ids":{"__wrappers__.get_value_encode_return.range_check_ptr":329,"__wrappers__.get_value_encode_return.ret_struct":328}}}],"535":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.entry_point"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":40,"offset":26},"reference_ids":{"__wrappers__.entry_point.__calldata_actual_size":360,"__wrappers__.entry_point.__calldata_ptr":359,"__wrappers__.entry_point.bitwise_ptr":358,"__wrappers__.entry_point.pedersen_ptr":362,"__wrappers__.entry_point.range_check_ptr":357,"__wrappers__.entry_point.ret_struct":363,"__wrappers__.entry_point.syscall_ptr":361}}}],"565":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_builtins_encode_return"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":42,"offset":0},"reference_ids":{"__wrappers__.test_builtins_encode_return.range_check_ptr":372,"__wrappers__.test_builtins_encode_return.ret_struct":371}}}],"612":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.send_message"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":45,"offset":17},"reference_ids":{"__wrappers__.send_message.__calldata_actual_size":401,"__wrappers__.send_message.__calldata_arg_to_address":399,"__wrappers__.send_message.__calldata_ptr":400,"__wrappers__.send_message.__temp36":402,"__wrappers__.send_message.bitwise_ptr":397,"__wrappers__.send_message.pedersen_ptr":395,"__wrappers__.send_message.range_check_ptr":396,"__wrappers__.send_message.ret_struct":404,"__wrappers__.send_message.syscall_ptr":403}}}],"62":[{"accessible_scopes":["starkware.starknet.common.storage","starkware.starknet.common.storage.normalize_address"],"code":"# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.\nADDR_BOUND = ids.ADDR_BOUND % PRIME\nassert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (\n ADDR_BOUND * 2 > PRIME), \\\n 'normalize_address() cannot be used with the current constants.'\nids.is_small = 1 if ids.addr < ADDR_BOUND else 0","flow_tracking_data":{"ap_tracking":{"group":8,"offset":1},"reference_ids":{"starkware.starknet.common.storage.normalize_address.addr":37,"starkware.starknet.common.storage.normalize_address.is_small":39,"starkware.starknet.common.storage.normalize_address.range_check_ptr":38}}}],"647":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_call_contract"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":47,"offset":24},"reference_ids":{"__wrappers__.test_call_contract.__calldata_actual_size":431,"__wrappers__.test_call_contract.__calldata_arg_calldata":427,"__wrappers__.test_call_contract.__calldata_arg_calldata_len":422,"__wrappers__.test_call_contract.__calldata_arg_contract_address":418,"__wrappers__.test_call_contract.__calldata_arg_function_selector":420,"__wrappers__.test_call_contract.__calldata_ptr":430,"__wrappers__.test_call_contract.__temp37":424,"__wrappers__.test_call_contract.__temp38":425,"__wrappers__.test_call_contract.__temp39":428,"__wrappers__.test_call_contract.__temp40":429,"__wrappers__.test_call_contract.bitwise_ptr":416,"__wrappers__.test_call_contract.pedersen_ptr":414,"__wrappers__.test_call_contract.range_check_ptr":426,"__wrappers__.test_call_contract.ret_struct":433,"__wrappers__.test_call_contract.syscall_ptr":432}}}],"684":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_delegate_call"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":49,"offset":24},"reference_ids":{"__wrappers__.test_delegate_call.__calldata_actual_size":461,"__wrappers__.test_delegate_call.__calldata_arg_calldata":457,"__wrappers__.test_delegate_call.__calldata_arg_calldata_len":452,"__wrappers__.test_delegate_call.__calldata_arg_contract_address":448,"__wrappers__.test_delegate_call.__calldata_arg_function_selector":450,"__wrappers__.test_delegate_call.__calldata_ptr":460,"__wrappers__.test_delegate_call.__temp42":454,"__wrappers__.test_delegate_call.__temp43":455,"__wrappers__.test_delegate_call.__temp44":458,"__wrappers__.test_delegate_call.__temp45":459,"__wrappers__.test_delegate_call.bitwise_ptr":446,"__wrappers__.test_delegate_call.pedersen_ptr":444,"__wrappers__.test_delegate_call.range_check_ptr":456,"__wrappers__.test_delegate_call.ret_struct":463,"__wrappers__.test_delegate_call.syscall_ptr":462}}}],"725":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.deposit"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":51,"offset":161},"reference_ids":{"__wrappers__.deposit.__calldata_actual_size":486,"__wrappers__.deposit.__calldata_arg_amount":484,"__wrappers__.deposit.__calldata_arg_from_address":482,"__wrappers__.deposit.__calldata_ptr":485,"__wrappers__.deposit.__temp48":487,"__wrappers__.deposit.bitwise_ptr":480,"__wrappers__.deposit.pedersen_ptr":490,"__wrappers__.deposit.range_check_ptr":489,"__wrappers__.deposit.ret_struct":491,"__wrappers__.deposit.syscall_ptr":488}}}],"748":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_get_caller_address"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":53,"offset":12},"reference_ids":{"__wrappers__.test_get_caller_address.__calldata_actual_size":505,"__wrappers__.test_get_caller_address.__calldata_arg_expected_address":503,"__wrappers__.test_get_caller_address.__calldata_ptr":504,"__wrappers__.test_get_caller_address.__temp49":506,"__wrappers__.test_get_caller_address.bitwise_ptr":501,"__wrappers__.test_get_caller_address.pedersen_ptr":499,"__wrappers__.test_get_caller_address.range_check_ptr":500,"__wrappers__.test_get_caller_address.ret_struct":508,"__wrappers__.test_get_caller_address.syscall_ptr":507}}}],"771":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_get_sequencer_address"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":55,"offset":12},"reference_ids":{"__wrappers__.test_get_sequencer_address.__calldata_actual_size":522,"__wrappers__.test_get_sequencer_address.__calldata_arg_expected_address":520,"__wrappers__.test_get_sequencer_address.__calldata_ptr":521,"__wrappers__.test_get_sequencer_address.__temp50":523,"__wrappers__.test_get_sequencer_address.bitwise_ptr":518,"__wrappers__.test_get_sequencer_address.pedersen_ptr":516,"__wrappers__.test_get_sequencer_address.range_check_ptr":517,"__wrappers__.test_get_sequencer_address.ret_struct":525,"__wrappers__.test_get_sequencer_address.syscall_ptr":524}}}],"794":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_get_contract_address"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":57,"offset":12},"reference_ids":{"__wrappers__.test_get_contract_address.__calldata_actual_size":539,"__wrappers__.test_get_contract_address.__calldata_arg_expected_address":537,"__wrappers__.test_get_contract_address.__calldata_ptr":538,"__wrappers__.test_get_contract_address.__temp51":540,"__wrappers__.test_get_contract_address.bitwise_ptr":535,"__wrappers__.test_get_contract_address.pedersen_ptr":533,"__wrappers__.test_get_contract_address.range_check_ptr":534,"__wrappers__.test_get_contract_address.ret_struct":542,"__wrappers__.test_get_contract_address.syscall_ptr":541}}}],"80":[{"accessible_scopes":["starkware.starknet.common.storage","starkware.starknet.common.storage.normalize_address"],"code":"ids.is_250 = 1 if ids.addr < 2**250 else 0","flow_tracking_data":{"ap_tracking":{"group":8,"offset":2},"reference_ids":{"starkware.starknet.common.storage.normalize_address.addr":37,"starkware.starknet.common.storage.normalize_address.is_250":45,"starkware.starknet.common.storage.normalize_address.is_small":39,"starkware.starknet.common.storage.normalize_address.range_check_ptr":38}}}],"848":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_call_storage_consistency"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":62,"offset":0},"reference_ids":{"__wrappers__.test_call_storage_consistency.__calldata_actual_size":568,"__wrappers__.test_call_storage_consistency.__calldata_arg_address":566,"__wrappers__.test_call_storage_consistency.__calldata_arg_other_contract_address":564,"__wrappers__.test_call_storage_consistency.__calldata_ptr":567,"__wrappers__.test_call_storage_consistency.__temp52":569,"__wrappers__.test_call_storage_consistency.bitwise_ptr":562,"__wrappers__.test_call_storage_consistency.pedersen_ptr":560,"__wrappers__.test_call_storage_consistency.range_check_ptr":571,"__wrappers__.test_call_storage_consistency.ret_struct":572,"__wrappers__.test_call_storage_consistency.syscall_ptr":570}}}],"899":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.test_re_entrance"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":67,"offset":0},"reference_ids":{"__wrappers__.test_re_entrance.__calldata_actual_size":597,"__wrappers__.test_re_entrance.__calldata_arg_depth":595,"__wrappers__.test_re_entrance.__calldata_arg_other_contract_address":593,"__wrappers__.test_re_entrance.__calldata_ptr":596,"__wrappers__.test_re_entrance.__temp54":598,"__wrappers__.test_re_entrance.bitwise_ptr":591,"__wrappers__.test_re_entrance.pedersen_ptr":589,"__wrappers__.test_re_entrance.range_check_ptr":600,"__wrappers__.test_re_entrance.ret_struct":601,"__wrappers__.test_re_entrance.syscall_ptr":599}}}],"939":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.add_value"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":71,"offset":0},"reference_ids":{"__wrappers__.add_value.__calldata_actual_size":620,"__wrappers__.add_value.__calldata_arg_value":618,"__wrappers__.add_value.__calldata_ptr":619,"__wrappers__.add_value.__temp56":621,"__wrappers__.add_value.bitwise_ptr":616,"__wrappers__.add_value.pedersen_ptr":614,"__wrappers__.add_value.range_check_ptr":623,"__wrappers__.add_value.ret_struct":624,"__wrappers__.add_value.syscall_ptr":622}}}],"981":[{"accessible_scopes":["__main__","__main__","__wrappers__","__wrappers__.recursive_add_value"],"code":"memory[ap] = segments.add()","flow_tracking_data":{"ap_tracking":{"group":76,"offset":0},"reference_ids":{"__wrappers__.recursive_add_value.__calldata_actual_size":644,"__wrappers__.recursive_add_value.__calldata_arg_self_address":640,"__wrappers__.recursive_add_value.__calldata_arg_value":642,"__wrappers__.recursive_add_value.__calldata_ptr":643,"__wrappers__.recursive_add_value.__temp57":645,"__wrappers__.recursive_add_value.bitwise_ptr":638,"__wrappers__.recursive_add_value.pedersen_ptr":636,"__wrappers__.recursive_add_value.range_check_ptr":647,"__wrappers__.recursive_add_value.ret_struct":648,"__wrappers__.recursive_add_value.syscall_ptr":646}}}]},"identifiers":{"__main__.BitwiseBuiltin":{"destination":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin","type":"alias"},"__main__.HashBuiltin":{"destination":"starkware.cairo.common.cairo_builtins.HashBuiltin","type":"alias"},"__main__.IndexAndValues":{"full_name":"__main__.IndexAndValues","members":{"index":{"cairo_type":"felt","offset":0},"values":{"cairo_type":"(felt, felt)","offset":1}},"size":3,"type":"struct"},"__main__.MyContract":{"type":"namespace"},"__main__.MyContract.Args":{"full_name":"__main__.MyContract.Args","members":{},"size":0,"type":"struct"},"__main__.MyContract.ImplicitArgs":{"full_name":"__main__.MyContract.ImplicitArgs","members":{},"size":0,"type":"struct"},"__main__.MyContract.Return":{"full_name":"__main__.MyContract.Return","members":{},"size":0,"type":"struct"},"__main__.MyContract.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.MyContract.XOR_COUNTERS_SELECTOR":{"type":"const","value":211046736873364296151239729186038899848347343952293323847223056826502574523},"__main__.MyContract.alloc":{"destination":"starkware.cairo.common.alloc.alloc","type":"alias"},"__main__.MyContract.call_contract":{"destination":"starkware.starknet.common.syscalls.call_contract","type":"alias"},"__main__.MyContract.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__main__.MyContract.xor_counters":{"decorators":[],"pc":361,"type":"function"},"__main__.MyContract.xor_counters.Args":{"full_name":"__main__.MyContract.xor_counters.Args","members":{"contract_address":{"cairo_type":"felt","offset":0},"index_and_x":{"cairo_type":"__main__.IndexAndValues","offset":1}},"size":4,"type":"struct"},"__main__.MyContract.xor_counters.ImplicitArgs":{"full_name":"__main__.MyContract.xor_counters.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.MyContract.xor_counters.Return":{"full_name":"__main__.MyContract.xor_counters.Return","members":{},"size":0,"type":"struct"},"__main__.MyContract.xor_counters.SIZEOF_LOCALS":{"type":"const","value":1},"__main__.MyContract.xor_counters.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.MyContract.xor_counters.__calldata_ptr","references":[{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":369,"value":"cast([fp] + 3, felt*)"}],"type":"reference"},"__main__.MyContract.xor_counters.__calldata_tmp":{"cairo_type":"felt*","full_name":"__main__.MyContract.xor_counters.__calldata_tmp","references":[{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"cast(fp + (-5), felt*)"}],"type":"reference"},"__main__.MyContract.xor_counters.__temp27":{"cairo_type":"felt","full_name":"__main__.MyContract.xor_counters.__temp27","references":[{"ap_tracking_data":{"group":29,"offset":5},"pc":371,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.MyContract.xor_counters.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.MyContract.xor_counters.calldata_ptr_start","references":[{"ap_tracking_data":{"group":29,"offset":4},"pc":365,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.MyContract.xor_counters.contract_address":{"cairo_type":"felt","full_name":"__main__.MyContract.xor_counters.contract_address","references":[{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.MyContract.xor_counters.index_and_x":{"cairo_type":"__main__.IndexAndValues","full_name":"__main__.MyContract.xor_counters.index_and_x","references":[{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"}],"type":"reference"},"__main__.MyContract.xor_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.MyContract.xor_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-7), felt*)]"}],"type":"reference"},"__main__.MyContract.xor_counters.retdata":{"cairo_type":"felt*","full_name":"__main__.MyContract.xor_counters.retdata","references":[{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.MyContract.xor_counters.retdata_size":{"cairo_type":"felt","full_name":"__main__.MyContract.xor_counters.retdata_size","references":[{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.MyContract.xor_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.MyContract.xor_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract":{"type":"namespace"},"__main__.TestContract.ADD_VALUE_SELECTOR":{"type":"const","value":244116128358498188146337218061232635775543270890529169229936851982759783745},"__main__.TestContract.Args":{"full_name":"__main__.TestContract.Args","members":{},"size":0,"type":"struct"},"__main__.TestContract.GET_VALUE_SELECTOR":{"type":"const","value":1088514629534027837943348492744869453336870381453867699032131389309368223152},"__main__.TestContract.ImplicitArgs":{"full_name":"__main__.TestContract.ImplicitArgs","members":{},"size":0,"type":"struct"},"__main__.TestContract.RECURSIVE_ADD_VALUE_SELECTOR":{"type":"const","value":765405392026302060765493145401186690085677257617346482214524097030498511379},"__main__.TestContract.Return":{"full_name":"__main__.TestContract.Return","members":{},"size":0,"type":"struct"},"__main__.TestContract.SET_VALUE_SELECTOR":{"type":"const","value":1737806834891659957988373423388711239891733974125793472992920296585311412419},"__main__.TestContract.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.TestContract.TEST_CALL_WITH_ARRAY_SELECTOR":{"type":"const","value":169158496051934688234187956926971713028507353560320644280269082964139402353},"__main__.TestContract.add_value":{"decorators":[],"pc":1105,"type":"function"},"__main__.TestContract.add_value.Args":{"full_name":"__main__.TestContract.add_value.Args","members":{"contract_address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.TestContract.add_value.ImplicitArgs":{"full_name":"__main__.TestContract.add_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.add_value.Return":{"full_name":"__main__.TestContract.add_value.Return","members":{},"size":0,"type":"struct"},"__main__.TestContract.add_value.SIZEOF_LOCALS":{"type":"const","value":1},"__main__.TestContract.add_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.add_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":85,"offset":4},"pc":1110,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1111,"value":"cast([fp] + 1, felt*)"}],"type":"reference"},"__main__.TestContract.add_value.__temp67":{"cairo_type":"felt","full_name":"__main__.TestContract.add_value.__temp67","references":[{"ap_tracking_data":{"group":85,"offset":5},"pc":1113,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.add_value.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.TestContract.add_value.calldata_ptr_start","references":[{"ap_tracking_data":{"group":85,"offset":4},"pc":1109,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1110,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.TestContract.add_value.contract_address":{"cairo_type":"felt","full_name":"__main__.TestContract.add_value.contract_address","references":[{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.TestContract.add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.TestContract.add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.TestContract.add_value.retdata":{"cairo_type":"felt*","full_name":"__main__.TestContract.add_value.retdata","references":[{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.TestContract.add_value.retdata_size":{"cairo_type":"felt","full_name":"__main__.TestContract.add_value.retdata_size","references":[{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.TestContract.add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract.add_value.value":{"cairo_type":"felt","full_name":"__main__.TestContract.add_value.value","references":[{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.TestContract.alloc":{"destination":"starkware.cairo.common.alloc.alloc","type":"alias"},"__main__.TestContract.call_contract":{"destination":"starkware.starknet.common.syscalls.call_contract","type":"alias"},"__main__.TestContract.get_value":{"decorators":[],"pc":1082,"type":"function"},"__main__.TestContract.get_value.Args":{"full_name":"__main__.TestContract.get_value.Args","members":{"address":{"cairo_type":"felt","offset":1},"contract_address":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.get_value.ImplicitArgs":{"full_name":"__main__.TestContract.get_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.get_value.Return":{"full_name":"__main__.TestContract.get_value.Return","members":{"res":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.TestContract.get_value.SIZEOF_LOCALS":{"type":"const","value":1},"__main__.TestContract.get_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.get_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":84,"offset":4},"pc":1087,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1088,"value":"cast([fp] + 1, felt*)"}],"type":"reference"},"__main__.TestContract.get_value.__return_value_actual_size":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.__return_value_actual_size","references":[{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"cast([ap + (-1)] + 1 - [ap + (-1)], felt)"}],"type":"reference"},"__main__.TestContract.get_value.__return_value_arg_res":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.__return_value_arg_res","references":[{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast([ap + (-1)], felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.__return_value_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.get_value.__return_value_ptr","references":[{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"cast([ap + (-1)] + 1, felt*)"}],"type":"reference"},"__main__.TestContract.get_value.__temp65":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.__temp65","references":[{"ap_tracking_data":{"group":84,"offset":5},"pc":1090,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.__temp66":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.__temp66","references":[{"ap_tracking_data":{"group":84,"offset":17},"pc":1100,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.address":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.address","references":[{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.TestContract.get_value.calldata_ptr_start","references":[{"ap_tracking_data":{"group":84,"offset":4},"pc":1086,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1087,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.TestContract.get_value.contract_address":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.contract_address","references":[{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.range_check_ptr","references":[{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.retdata":{"cairo_type":"felt*","full_name":"__main__.TestContract.get_value.retdata","references":[{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.TestContract.get_value.retdata_size":{"cairo_type":"felt","full_name":"__main__.TestContract.get_value.retdata_size","references":[{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.TestContract.get_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.get_value.syscall_ptr","references":[{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__main__.TestContract.recursive_add_value":{"decorators":[],"pc":1124,"type":"function"},"__main__.TestContract.recursive_add_value.Args":{"full_name":"__main__.TestContract.recursive_add_value.Args","members":{"contract_address":{"cairo_type":"felt","offset":0},"self_address":{"cairo_type":"felt","offset":1},"value":{"cairo_type":"felt","offset":2}},"size":3,"type":"struct"},"__main__.TestContract.recursive_add_value.ImplicitArgs":{"full_name":"__main__.TestContract.recursive_add_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.recursive_add_value.Return":{"full_name":"__main__.TestContract.recursive_add_value.Return","members":{},"size":0,"type":"struct"},"__main__.TestContract.recursive_add_value.SIZEOF_LOCALS":{"type":"const","value":1},"__main__.TestContract.recursive_add_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.recursive_add_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":86,"offset":4},"pc":1129,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1130,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1131,"value":"cast([fp] + 2, felt*)"}],"type":"reference"},"__main__.TestContract.recursive_add_value.__temp68":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.__temp68","references":[{"ap_tracking_data":{"group":86,"offset":5},"pc":1133,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.TestContract.recursive_add_value.calldata_ptr_start","references":[{"ap_tracking_data":{"group":86,"offset":4},"pc":1128,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1129,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.contract_address":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.contract_address","references":[{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.retdata":{"cairo_type":"felt*","full_name":"__main__.TestContract.recursive_add_value.retdata","references":[{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.retdata_size":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.retdata_size","references":[{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.self_address":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.self_address","references":[{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.recursive_add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract.recursive_add_value.value":{"cairo_type":"felt","full_name":"__main__.TestContract.recursive_add_value.value","references":[{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value":{"decorators":[],"pc":1062,"type":"function"},"__main__.TestContract.set_value.Args":{"full_name":"__main__.TestContract.set_value.Args","members":{"address":{"cairo_type":"felt","offset":1},"contract_address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":2}},"size":3,"type":"struct"},"__main__.TestContract.set_value.ImplicitArgs":{"full_name":"__main__.TestContract.set_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.set_value.Return":{"full_name":"__main__.TestContract.set_value.Return","members":{},"size":0,"type":"struct"},"__main__.TestContract.set_value.SIZEOF_LOCALS":{"type":"const","value":1},"__main__.TestContract.set_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.set_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":83,"offset":4},"pc":1067,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1068,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1069,"value":"cast([fp] + 2, felt*)"}],"type":"reference"},"__main__.TestContract.set_value.__temp64":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.__temp64","references":[{"ap_tracking_data":{"group":83,"offset":5},"pc":1071,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value.address":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.address","references":[{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.TestContract.set_value.calldata_ptr_start","references":[{"ap_tracking_data":{"group":83,"offset":4},"pc":1066,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1067,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.TestContract.set_value.contract_address":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.contract_address","references":[{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.range_check_ptr","references":[{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value.retdata":{"cairo_type":"felt*","full_name":"__main__.TestContract.set_value.retdata","references":[{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.TestContract.set_value.retdata_size":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.retdata_size","references":[{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.TestContract.set_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.set_value.syscall_ptr","references":[{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract.set_value.value":{"cairo_type":"felt","full_name":"__main__.TestContract.set_value.value","references":[{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array":{"decorators":[],"pc":1144,"type":"function"},"__main__.TestContract.test_call_with_array.Args":{"full_name":"__main__.TestContract.test_call_with_array.Args","members":{"arr":{"cairo_type":"felt*","offset":3},"arr_len":{"cairo_type":"felt","offset":2},"contract_address":{"cairo_type":"felt","offset":0},"self_address":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"__main__.TestContract.test_call_with_array.ImplicitArgs":{"full_name":"__main__.TestContract.test_call_with_array.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.TestContract.test_call_with_array.Return":{"full_name":"__main__.TestContract.test_call_with_array.Return","members":{},"size":0,"type":"struct"},"__main__.TestContract.test_call_with_array.SIZEOF_LOCALS":{"type":"const","value":3},"__main__.TestContract.test_call_with_array.__calldata_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.__calldata_ptr","references":[{"ap_tracking_data":{"group":87,"offset":6},"pc":1149,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1150,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1151,"value":"cast([fp] + 2, felt*)"},{"ap_tracking_data":{"group":87,"offset":7},"pc":1157,"value":"[cast(fp + 2, felt**)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.__calldata_ptr_copy":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.__calldata_ptr_copy","references":[{"ap_tracking_data":{"group":87,"offset":6},"pc":1154,"value":"cast([fp] + 2, felt*)"}],"type":"reference"},"__main__.TestContract.test_call_with_array.__temp69":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.__temp69","references":[{"ap_tracking_data":{"group":87,"offset":7},"pc":1156,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.arr":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.arr","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.arr_len":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.arr_len","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.calldata_ptr_start":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.calldata_ptr_start","references":[{"ap_tracking_data":{"group":87,"offset":6},"pc":1148,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1149,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.contract_address":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.contract_address","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.range_check_ptr","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1154,"value":"[cast(fp + 1, felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.retdata":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.retdata","references":[{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.retdata_size":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.retdata_size","references":[{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.self_address":{"cairo_type":"felt","full_name":"__main__.TestContract.test_call_with_array.self_address","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.TestContract.test_call_with_array.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.TestContract.test_call_with_array.syscall_ptr","references":[{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.add_signature_to_counters":{"decorators":["external"],"pc":412,"type":"function"},"__main__.add_signature_to_counters.Args":{"full_name":"__main__.add_signature_to_counters.Args","members":{"index":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.add_signature_to_counters.ImplicitArgs":{"full_name":"__main__.add_signature_to_counters.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":0},"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":2}},"size":3,"type":"struct"},"__main__.add_signature_to_counters.Return":{"full_name":"__main__.add_signature_to_counters.Return","members":{},"size":0,"type":"struct"},"__main__.add_signature_to_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.add_signature_to_counters.__temp29":{"cairo_type":"felt","full_name":"__main__.add_signature_to_counters.__temp29","references":[{"ap_tracking_data":{"group":32,"offset":77},"pc":424,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_signature_to_counters.__temp30":{"cairo_type":"felt","full_name":"__main__.add_signature_to_counters.__temp30","references":[{"ap_tracking_data":{"group":32,"offset":78},"pc":425,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_signature_to_counters.index":{"cairo_type":"felt","full_name":"__main__.add_signature_to_counters.index","references":[{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.add_signature_to_counters.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.add_signature_to_counters.pedersen_ptr","references":[{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.add_signature_to_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.add_signature_to_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_signature_to_counters.signature":{"cairo_type":"felt*","full_name":"__main__.add_signature_to_counters.signature","references":[{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.add_signature_to_counters.signature_len":{"cairo_type":"felt","full_name":"__main__.add_signature_to_counters.signature_len","references":[{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.add_signature_to_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.add_signature_to_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.add_signature_to_counters.val":{"cairo_type":"(felt, felt)","full_name":"__main__.add_signature_to_counters.val","references":[{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-2), (felt, felt)*)]"}],"type":"reference"},"__main__.add_value":{"decorators":["external"],"pc":909,"type":"function"},"__main__.add_value.Args":{"full_name":"__main__.add_value.Args","members":{"value":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.add_value.ImplicitArgs":{"full_name":"__main__.add_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.add_value.Return":{"full_name":"__main__.add_value.Return","members":{},"size":0,"type":"struct"},"__main__.add_value.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.add_value.__temp55":{"cairo_type":"felt","full_name":"__main__.add_value.__temp55","references":[{"ap_tracking_data":{"group":69,"offset":1},"pc":923,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_value.caller_address":{"cairo_type":"felt","full_name":"__main__.add_value.caller_address","references":[{"ap_tracking_data":{"group":68,"offset":6},"pc":912,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":69,"offset":0},"pc":921,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":68,"offset":6},"pc":912,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":69,"offset":0},"pc":921,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":69,"offset":13},"pc":929,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.add_value.value":{"cairo_type":"felt","full_name":"__main__.add_value.value","references":[{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.advance_counter":{"decorators":["external"],"pc":237,"type":"function"},"__main__.advance_counter.Args":{"full_name":"__main__.advance_counter.Args","members":{"diffs":{"cairo_type":"felt*","offset":2},"diffs_len":{"cairo_type":"felt","offset":1},"index":{"cairo_type":"felt","offset":0}},"size":3,"type":"struct"},"__main__.advance_counter.ImplicitArgs":{"full_name":"__main__.advance_counter.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":3,"type":"struct"},"__main__.advance_counter.Return":{"full_name":"__main__.advance_counter.Return","members":{},"size":0,"type":"struct"},"__main__.advance_counter.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.advance_counter.__temp18":{"cairo_type":"felt","full_name":"__main__.advance_counter.__temp18","references":[{"ap_tracking_data":{"group":23,"offset":70},"pc":246,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.advance_counter.__temp19":{"cairo_type":"felt","full_name":"__main__.advance_counter.__temp19","references":[{"ap_tracking_data":{"group":23,"offset":71},"pc":247,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.advance_counter.diffs":{"cairo_type":"felt*","full_name":"__main__.advance_counter.diffs","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__main__.advance_counter.diffs_len":{"cairo_type":"felt","full_name":"__main__.advance_counter.diffs_len","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.advance_counter.index":{"cairo_type":"felt","full_name":"__main__.advance_counter.index","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.advance_counter.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.advance_counter.pedersen_ptr","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-7), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.advance_counter.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.advance_counter.range_check_ptr","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.advance_counter.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.advance_counter.syscall_ptr","references":[{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.advance_counter.val":{"cairo_type":"(felt, felt)","full_name":"__main__.advance_counter.val","references":[{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-2), (felt, felt)*)]"}],"type":"reference"},"__main__.alloc":{"destination":"starkware.cairo.common.alloc.alloc","type":"alias"},"__main__.assert_nn_le":{"destination":"starkware.cairo.common.math.assert_nn_le","type":"alias"},"__main__.assert_not_zero":{"destination":"starkware.cairo.common.math.assert_not_zero","type":"alias"},"__main__.bitwise_xor":{"destination":"starkware.cairo.common.bitwise.bitwise_xor","type":"alias"},"__main__.call_contract":{"destination":"starkware.starknet.common.syscalls.call_contract","type":"alias"},"__main__.call_xor_counters":{"decorators":["external"],"pc":382,"type":"function"},"__main__.call_xor_counters.Args":{"full_name":"__main__.call_xor_counters.Args","members":{"address":{"cairo_type":"felt","offset":0},"index_and_x":{"cairo_type":"__main__.IndexAndValues","offset":1}},"size":4,"type":"struct"},"__main__.call_xor_counters.ImplicitArgs":{"full_name":"__main__.call_xor_counters.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.call_xor_counters.Return":{"full_name":"__main__.call_xor_counters.Return","members":{},"size":0,"type":"struct"},"__main__.call_xor_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.call_xor_counters.address":{"cairo_type":"felt","full_name":"__main__.call_xor_counters.address","references":[{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.call_xor_counters.index_and_x":{"cairo_type":"__main__.IndexAndValues","full_name":"__main__.call_xor_counters.index_and_x","references":[{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"}],"type":"reference"},"__main__.call_xor_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.call_xor_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":30,"offset":26},"pc":390,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.call_xor_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.call_xor_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":30,"offset":26},"pc":390,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.constructor":{"decorators":["constructor"],"pc":285,"type":"function"},"__main__.constructor.Args":{"full_name":"__main__.constructor.Args","members":{"address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.constructor.ImplicitArgs":{"full_name":"__main__.constructor.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":3,"type":"struct"},"__main__.constructor.Return":{"full_name":"__main__.constructor.Return","members":{},"size":0,"type":"struct"},"__main__.constructor.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.constructor.address":{"cairo_type":"felt","full_name":"__main__.constructor.address","references":[{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.constructor.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.constructor.pedersen_ptr","references":[{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.constructor.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.constructor.range_check_ptr","references":[{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.constructor.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.constructor.syscall_ptr","references":[{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":25,"offset":7},"pc":290,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.constructor.value":{"cairo_type":"felt","full_name":"__main__.constructor.value","references":[{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.delegate_call":{"destination":"starkware.starknet.common.syscalls.delegate_call","type":"alias"},"__main__.deposit":{"decorators":["l1_handler"],"pc":696,"type":"function"},"__main__.deposit.Args":{"full_name":"__main__.deposit.Args","members":{"amount":{"cairo_type":"felt","offset":1},"from_address":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"__main__.deposit.ImplicitArgs":{"full_name":"__main__.deposit.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":2},"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":3,"type":"struct"},"__main__.deposit.Return":{"full_name":"__main__.deposit.Return","members":{},"size":0,"type":"struct"},"__main__.deposit.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.deposit.__temp47":{"cairo_type":"felt","full_name":"__main__.deposit.__temp47","references":[{"ap_tracking_data":{"group":50,"offset":4},"pc":701,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.deposit.amount":{"cairo_type":"felt","full_name":"__main__.deposit.amount","references":[{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.deposit.diffs":{"cairo_type":"felt*","full_name":"__main__.deposit.diffs","references":[{"ap_tracking_data":{"group":50,"offset":3},"pc":698,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.deposit.from_address":{"cairo_type":"felt","full_name":"__main__.deposit.from_address","references":[{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.deposit.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.deposit.pedersen_ptr","references":[{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.deposit.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.deposit.range_check_ptr","references":[{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.deposit.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.deposit.syscall_ptr","references":[{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.entry_point":{"decorators":["external"],"pc":509,"type":"function"},"__main__.entry_point.Args":{"full_name":"__main__.entry_point.Args","members":{},"size":0,"type":"struct"},"__main__.entry_point.ImplicitArgs":{"full_name":"__main__.entry_point.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.entry_point.Return":{"full_name":"__main__.entry_point.Return","members":{},"size":0,"type":"struct"},"__main__.entry_point.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.entry_point.address":{"type":"const","value":15},"__main__.entry_point.new_value":{"cairo_type":"felt","full_name":"__main__.entry_point.new_value","references":[{"ap_tracking_data":{"group":39,"offset":20},"pc":525,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.entry_point.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.entry_point.pedersen_ptr","references":[{"ap_tracking_data":{"group":39,"offset":0},"pc":509,"value":"[cast(fp + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.entry_point.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.entry_point.syscall_ptr","references":[{"ap_tracking_data":{"group":39,"offset":0},"pc":509,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":39,"offset":7},"pc":514,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":39,"offset":14},"pc":521,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":39,"offset":20},"pc":525,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.entry_point.value":{"cairo_type":"felt","full_name":"__main__.entry_point.value","references":[{"ap_tracking_data":{"group":39,"offset":7},"pc":514,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.get_caller_address":{"destination":"starkware.starknet.common.syscalls.get_caller_address","type":"alias"},"__main__.get_contract_address":{"destination":"starkware.starknet.common.syscalls.get_contract_address","type":"alias"},"__main__.get_fp_and_pc":{"destination":"starkware.cairo.common.registers.get_fp_and_pc","type":"alias"},"__main__.get_sequencer_address":{"destination":"starkware.starknet.common.syscalls.get_sequencer_address","type":"alias"},"__main__.get_tx_signature":{"destination":"starkware.starknet.common.syscalls.get_tx_signature","type":"alias"},"__main__.get_value":{"decorators":["external"],"pc":478,"type":"function"},"__main__.get_value.Args":{"full_name":"__main__.get_value.Args","members":{"address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.get_value.ImplicitArgs":{"full_name":"__main__.get_value.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.get_value.Return":{"full_name":"__main__.get_value.Return","members":{"res":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.get_value.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.get_value.address":{"cairo_type":"felt","full_name":"__main__.get_value.address","references":[{"ap_tracking_data":{"group":36,"offset":0},"pc":478,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.get_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.get_value.syscall_ptr","references":[{"ap_tracking_data":{"group":36,"offset":0},"pc":478,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":36,"offset":7},"pc":482,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.get_value.value":{"cairo_type":"felt","full_name":"__main__.get_value.value","references":[{"ap_tracking_data":{"group":36,"offset":7},"pc":482,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.hash2":{"destination":"starkware.cairo.common.hash.hash2","type":"alias"},"__main__.increase_value":{"decorators":["external"],"pc":991,"type":"function"},"__main__.increase_value.Args":{"full_name":"__main__.increase_value.Args","members":{"address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.increase_value.ImplicitArgs":{"full_name":"__main__.increase_value.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.increase_value.Return":{"full_name":"__main__.increase_value.Return","members":{},"size":0,"type":"struct"},"__main__.increase_value.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.increase_value.address":{"cairo_type":"felt","full_name":"__main__.increase_value.address","references":[{"ap_tracking_data":{"group":77,"offset":0},"pc":991,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.increase_value.prev_value":{"cairo_type":"felt","full_name":"__main__.increase_value.prev_value","references":[{"ap_tracking_data":{"group":77,"offset":7},"pc":995,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.increase_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.increase_value.syscall_ptr","references":[{"ap_tracking_data":{"group":77,"offset":0},"pc":991,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":77,"offset":7},"pc":995,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":77,"offset":14},"pc":1001,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.recursive_add_value":{"decorators":["external"],"pc":949,"type":"function"},"__main__.recursive_add_value.Args":{"full_name":"__main__.recursive_add_value.Args","members":{"self_address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.recursive_add_value.ImplicitArgs":{"full_name":"__main__.recursive_add_value.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.recursive_add_value.Return":{"full_name":"__main__.recursive_add_value.Return","members":{},"size":0,"type":"struct"},"__main__.recursive_add_value.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.recursive_add_value._anon_label24":{"pc":954,"type":"label"},"__main__.recursive_add_value._anon_label25":{"pc":954,"type":"label"},"__main__.recursive_add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.recursive_add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":74,"offset":0},"pc":966,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.recursive_add_value.self_address":{"cairo_type":"felt","full_name":"__main__.recursive_add_value.self_address","references":[{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.recursive_add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.recursive_add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":73,"offset":0},"pc":959,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":74,"offset":0},"pc":966,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":74,"offset":16},"pc":970,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.recursive_add_value.value":{"cairo_type":"felt","full_name":"__main__.recursive_add_value.value","references":[{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.send_message":{"decorators":["external"],"pc":589,"type":"function"},"__main__.send_message.Args":{"full_name":"__main__.send_message.Args","members":{"to_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.send_message.ImplicitArgs":{"full_name":"__main__.send_message.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.send_message.Return":{"full_name":"__main__.send_message.Return","members":{},"size":0,"type":"struct"},"__main__.send_message.SIZEOF_LOCALS":{"type":"const","value":2},"__main__.send_message.__fp__":{"cairo_type":"felt","full_name":"__main__.send_message.__fp__","references":[{"ap_tracking_data":{"group":44,"offset":4},"pc":597,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.send_message.payload":{"cairo_type":"(felt, felt)","full_name":"__main__.send_message.payload","references":[{"ap_tracking_data":{"group":44,"offset":2},"pc":595,"value":"[cast(fp, (felt, felt)*)]"}],"type":"reference"},"__main__.send_message.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.send_message.syscall_ptr","references":[{"ap_tracking_data":{"group":44,"offset":0},"pc":589,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":44,"offset":12},"pc":604,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.send_message.to_address":{"cairo_type":"felt","full_name":"__main__.send_message.to_address","references":[{"ap_tracking_data":{"group":44,"offset":0},"pc":589,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.send_message_to_l1":{"destination":"starkware.starknet.common.messages.send_message_to_l1","type":"alias"},"__main__.set_value":{"decorators":["external"],"pc":454,"type":"function"},"__main__.set_value.Args":{"full_name":"__main__.set_value.Args","members":{"address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.set_value.ImplicitArgs":{"full_name":"__main__.set_value.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.set_value.Return":{"full_name":"__main__.set_value.Return","members":{},"size":0,"type":"struct"},"__main__.set_value.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.set_value.address":{"cairo_type":"felt","full_name":"__main__.set_value.address","references":[{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.set_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.set_value.syscall_ptr","references":[{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":34,"offset":7},"pc":459,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.set_value.value":{"cairo_type":"felt","full_name":"__main__.set_value.value","references":[{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.storage_read":{"destination":"starkware.starknet.common.syscalls.storage_read","type":"alias"},"__main__.storage_write":{"destination":"starkware.starknet.common.syscalls.storage_write","type":"alias"},"__main__.test_builtins":{"decorators":["external"],"pc":545,"type":"function"},"__main__.test_builtins.Args":{"full_name":"__main__.test_builtins.Args","members":{},"size":0,"type":"struct"},"__main__.test_builtins.ImplicitArgs":{"full_name":"__main__.test_builtins.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":0},"range_check_ptr":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.test_builtins.Return":{"full_name":"__main__.test_builtins.Return","members":{"result":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.test_builtins.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_builtins.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.test_builtins.pedersen_ptr","references":[{"ap_tracking_data":{"group":41,"offset":0},"pc":545,"value":"[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":41,"offset":26},"pc":559,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.test_builtins.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.test_builtins.range_check_ptr","references":[{"ap_tracking_data":{"group":41,"offset":0},"pc":545,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":41,"offset":19},"pc":552,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_builtins.result":{"cairo_type":"felt","full_name":"__main__.test_builtins.result","references":[{"ap_tracking_data":{"group":41,"offset":26},"pc":559,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_call_contract":{"decorators":["external"],"pc":622,"type":"function"},"__main__.test_call_contract.Args":{"full_name":"__main__.test_call_contract.Args","members":{"calldata":{"cairo_type":"felt*","offset":3},"calldata_len":{"cairo_type":"felt","offset":2},"contract_address":{"cairo_type":"felt","offset":0},"function_selector":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"__main__.test_call_contract.ImplicitArgs":{"full_name":"__main__.test_call_contract.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.test_call_contract.Return":{"full_name":"__main__.test_call_contract.Return","members":{},"size":0,"type":"struct"},"__main__.test_call_contract.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_call_contract.calldata":{"cairo_type":"felt*","full_name":"__main__.test_call_contract.calldata","references":[{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__main__.test_call_contract.calldata_len":{"cairo_type":"felt","full_name":"__main__.test_call_contract.calldata_len","references":[{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.test_call_contract.contract_address":{"cairo_type":"felt","full_name":"__main__.test_call_contract.contract_address","references":[{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.test_call_contract.function_selector":{"cairo_type":"felt","full_name":"__main__.test_call_contract.function_selector","references":[{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.test_call_contract.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_call_contract.syscall_ptr","references":[{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":46,"offset":11},"pc":629,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.test_call_storage_consistency":{"decorators":["external"],"pc":804,"type":"function"},"__main__.test_call_storage_consistency.Args":{"full_name":"__main__.test_call_storage_consistency.Args","members":{"address":{"cairo_type":"felt","offset":1},"other_contract_address":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"__main__.test_call_storage_consistency.ImplicitArgs":{"full_name":"__main__.test_call_storage_consistency.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.test_call_storage_consistency.Return":{"full_name":"__main__.test_call_storage_consistency.Return","members":{},"size":0,"type":"struct"},"__main__.test_call_storage_consistency.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_call_storage_consistency.address":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.address","references":[{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.test_call_storage_consistency.caller_address":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.caller_address","references":[{"ap_tracking_data":{"group":58,"offset":17},"pc":812,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_call_storage_consistency.other_contract_address":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.other_contract_address","references":[{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.test_call_storage_consistency.other_value":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.other_value","references":[{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_call_storage_consistency.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.range_check_ptr","references":[{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":59,"offset":0},"pc":822,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.test_call_storage_consistency.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_call_storage_consistency.syscall_ptr","references":[{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":58,"offset":12},"pc":810,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":58,"offset":17},"pc":812,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":59,"offset":0},"pc":822,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":59,"offset":11},"pc":826,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.test_call_storage_consistency.value":{"cairo_type":"felt","full_name":"__main__.test_call_storage_consistency.value","references":[{"ap_tracking_data":{"group":59,"offset":11},"pc":826,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_call_with_array":{"decorators":["external"],"pc":1019,"type":"function"},"__main__.test_call_with_array.Args":{"full_name":"__main__.test_call_with_array.Args","members":{"arr":{"cairo_type":"felt*","offset":2},"arr_len":{"cairo_type":"felt","offset":1},"self_address":{"cairo_type":"felt","offset":0}},"size":3,"type":"struct"},"__main__.test_call_with_array.ImplicitArgs":{"full_name":"__main__.test_call_with_array.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.test_call_with_array.Return":{"full_name":"__main__.test_call_with_array.Return","members":{},"size":0,"type":"struct"},"__main__.test_call_with_array.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_call_with_array._anon_label26":{"pc":1024,"type":"label"},"__main__.test_call_with_array._anon_label27":{"pc":1024,"type":"label"},"__main__.test_call_with_array.arr":{"cairo_type":"felt*","full_name":"__main__.test_call_with_array.arr","references":[{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__main__.test_call_with_array.arr_len":{"cairo_type":"felt","full_name":"__main__.test_call_with_array.arr_len","references":[{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.test_call_with_array.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.test_call_with_array.range_check_ptr","references":[{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":80,"offset":0},"pc":1033,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_call_with_array.self_address":{"cairo_type":"felt","full_name":"__main__.test_call_with_array.self_address","references":[{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.test_call_with_array.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_call_with_array.syscall_ptr","references":[{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":80,"offset":0},"pc":1033,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.test_delegate_call":{"decorators":["external"],"pc":659,"type":"function"},"__main__.test_delegate_call.Args":{"full_name":"__main__.test_delegate_call.Args","members":{"calldata":{"cairo_type":"felt*","offset":3},"calldata_len":{"cairo_type":"felt","offset":2},"contract_address":{"cairo_type":"felt","offset":0},"function_selector":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"__main__.test_delegate_call.ImplicitArgs":{"full_name":"__main__.test_delegate_call.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.test_delegate_call.Return":{"full_name":"__main__.test_delegate_call.Return","members":{},"size":0,"type":"struct"},"__main__.test_delegate_call.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_delegate_call.calldata":{"cairo_type":"felt*","full_name":"__main__.test_delegate_call.calldata","references":[{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__main__.test_delegate_call.calldata_len":{"cairo_type":"felt","full_name":"__main__.test_delegate_call.calldata_len","references":[{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.test_delegate_call.contract_address":{"cairo_type":"felt","full_name":"__main__.test_delegate_call.contract_address","references":[{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"__main__.test_delegate_call.function_selector":{"cairo_type":"felt","full_name":"__main__.test_delegate_call.function_selector","references":[{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.test_delegate_call.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_delegate_call.syscall_ptr","references":[{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":48,"offset":11},"pc":666,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.test_get_caller_address":{"decorators":["external"],"pc":735,"type":"function"},"__main__.test_get_caller_address.Args":{"full_name":"__main__.test_get_caller_address.Args","members":{"expected_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.test_get_caller_address.ImplicitArgs":{"full_name":"__main__.test_get_caller_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.test_get_caller_address.Return":{"full_name":"__main__.test_get_caller_address.Return","members":{},"size":0,"type":"struct"},"__main__.test_get_caller_address.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_get_caller_address.caller_address":{"cairo_type":"felt","full_name":"__main__.test_get_caller_address.caller_address","references":[{"ap_tracking_data":{"group":52,"offset":6},"pc":738,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_get_caller_address.expected_address":{"cairo_type":"felt","full_name":"__main__.test_get_caller_address.expected_address","references":[{"ap_tracking_data":{"group":52,"offset":0},"pc":735,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.test_get_caller_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_get_caller_address.syscall_ptr","references":[{"ap_tracking_data":{"group":52,"offset":0},"pc":735,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":52,"offset":6},"pc":738,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.test_get_contract_address":{"decorators":["external"],"pc":781,"type":"function"},"__main__.test_get_contract_address.Args":{"full_name":"__main__.test_get_contract_address.Args","members":{"expected_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.test_get_contract_address.ImplicitArgs":{"full_name":"__main__.test_get_contract_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.test_get_contract_address.Return":{"full_name":"__main__.test_get_contract_address.Return","members":{},"size":0,"type":"struct"},"__main__.test_get_contract_address.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_get_contract_address.contract_address":{"cairo_type":"felt","full_name":"__main__.test_get_contract_address.contract_address","references":[{"ap_tracking_data":{"group":56,"offset":6},"pc":784,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_get_contract_address.expected_address":{"cairo_type":"felt","full_name":"__main__.test_get_contract_address.expected_address","references":[{"ap_tracking_data":{"group":56,"offset":0},"pc":781,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.test_get_contract_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_get_contract_address.syscall_ptr","references":[{"ap_tracking_data":{"group":56,"offset":0},"pc":781,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":56,"offset":6},"pc":784,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.test_get_sequencer_address":{"decorators":["external"],"pc":758,"type":"function"},"__main__.test_get_sequencer_address.Args":{"full_name":"__main__.test_get_sequencer_address.Args","members":{"expected_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.test_get_sequencer_address.ImplicitArgs":{"full_name":"__main__.test_get_sequencer_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"__main__.test_get_sequencer_address.Return":{"full_name":"__main__.test_get_sequencer_address.Return","members":{},"size":0,"type":"struct"},"__main__.test_get_sequencer_address.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_get_sequencer_address.expected_address":{"cairo_type":"felt","full_name":"__main__.test_get_sequencer_address.expected_address","references":[{"ap_tracking_data":{"group":54,"offset":0},"pc":758,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.test_get_sequencer_address.sequencer_address":{"cairo_type":"felt","full_name":"__main__.test_get_sequencer_address.sequencer_address","references":[{"ap_tracking_data":{"group":54,"offset":6},"pc":761,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_get_sequencer_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_get_sequencer_address.syscall_ptr","references":[{"ap_tracking_data":{"group":54,"offset":0},"pc":758,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":54,"offset":6},"pc":761,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__main__.test_re_entrance":{"decorators":["external"],"pc":858,"type":"function"},"__main__.test_re_entrance.Args":{"full_name":"__main__.test_re_entrance.Args","members":{"depth":{"cairo_type":"felt","offset":1},"other_contract_address":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"__main__.test_re_entrance.ImplicitArgs":{"full_name":"__main__.test_re_entrance.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":2,"type":"struct"},"__main__.test_re_entrance.Return":{"full_name":"__main__.test_re_entrance.Return","members":{},"size":0,"type":"struct"},"__main__.test_re_entrance.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.test_re_entrance.__temp53":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.__temp53","references":[{"ap_tracking_data":{"group":65,"offset":1},"pc":886,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.depth":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.depth","references":[{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.dummy_value":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.dummy_value","references":[{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.final_value":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.final_value","references":[{"ap_tracking_data":{"group":64,"offset":11},"pc":875,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.other_contract_address":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.other_contract_address","references":[{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.test_re_entrance.range_check_ptr","references":[{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":64,"offset":0},"pc":870,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.test_re_entrance.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.test_re_entrance.syscall_ptr","references":[{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":63,"offset":12},"pc":865,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":64,"offset":0},"pc":870,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":64,"offset":11},"pc":875,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.two_counters":{"type":"namespace"},"__main__.two_counters.Args":{"full_name":"__main__.two_counters.Args","members":{},"size":0,"type":"struct"},"__main__.two_counters.HashBuiltin":{"destination":"starkware.cairo.common.cairo_builtins.HashBuiltin","type":"alias"},"__main__.two_counters.ImplicitArgs":{"full_name":"__main__.two_counters.ImplicitArgs","members":{},"size":0,"type":"struct"},"__main__.two_counters.Return":{"full_name":"__main__.two_counters.Return","members":{},"size":0,"type":"struct"},"__main__.two_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.two_counters.addr":{"decorators":[],"pc":185,"type":"function"},"__main__.two_counters.addr.Args":{"full_name":"__main__.two_counters.addr.Args","members":{"index":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.two_counters.addr.ImplicitArgs":{"full_name":"__main__.two_counters.addr.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":0},"range_check_ptr":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"__main__.two_counters.addr.Return":{"full_name":"__main__.two_counters.addr.Return","members":{"res":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.two_counters.addr.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.two_counters.addr.index":{"cairo_type":"felt","full_name":"__main__.two_counters.addr.index","references":[{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.two_counters.addr.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.two_counters.addr.pedersen_ptr","references":[{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":20,"offset":7},"pc":191,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.two_counters.addr.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.two_counters.addr.range_check_ptr","references":[{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":20,"offset":36},"pc":195,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.two_counters.addr.res":{"cairo_type":"felt","full_name":"__main__.two_counters.addr.res","references":[{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"cast(1090342827190808580885637187050034007524108436288464842432620195147420788107, felt)"},{"ap_tracking_data":{"group":20,"offset":7},"pc":191,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":20,"offset":36},"pc":195,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.hash2":{"destination":"starkware.cairo.common.hash.hash2","type":"alias"},"__main__.two_counters.normalize_address":{"destination":"starkware.starknet.common.storage.normalize_address","type":"alias"},"__main__.two_counters.read":{"decorators":[],"pc":199,"type":"function"},"__main__.two_counters.read.Args":{"full_name":"__main__.two_counters.read.Args","members":{"index":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"__main__.two_counters.read.ImplicitArgs":{"full_name":"__main__.two_counters.read.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":3,"type":"struct"},"__main__.two_counters.read.Return":{"full_name":"__main__.two_counters.read.Return","members":{"res":{"cairo_type":"(felt, felt)","offset":0}},"size":2,"type":"struct"},"__main__.two_counters.read.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.two_counters.read.__storage_var_temp0":{"cairo_type":"felt","full_name":"__main__.two_counters.read.__storage_var_temp0","references":[{"ap_tracking_data":{"group":21,"offset":51},"pc":208,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":62},"pc":217,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.read.__storage_var_temp1":{"cairo_type":"felt","full_name":"__main__.two_counters.read.__storage_var_temp1","references":[{"ap_tracking_data":{"group":21,"offset":58},"pc":213,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":63},"pc":218,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.read.index":{"cairo_type":"felt","full_name":"__main__.two_counters.read.index","references":[{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__main__.two_counters.read.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.two_counters.read.pedersen_ptr","references":[{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":21,"offset":60},"pc":215,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.two_counters.read.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.two_counters.read.range_check_ptr","references":[{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":21,"offset":61},"pc":216,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.read.storage_addr":{"cairo_type":"felt","full_name":"__main__.two_counters.read.storage_addr","references":[{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.read.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.two_counters.read.syscall_ptr","references":[{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":21,"offset":51},"pc":208,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":21,"offset":58},"pc":213,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":21,"offset":59},"pc":214,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.two_counters.storage_read":{"destination":"starkware.starknet.common.syscalls.storage_read","type":"alias"},"__main__.two_counters.storage_write":{"destination":"starkware.starknet.common.syscalls.storage_write","type":"alias"},"__main__.two_counters.write":{"decorators":[],"pc":219,"type":"function"},"__main__.two_counters.write.Args":{"full_name":"__main__.two_counters.write.Args","members":{"index":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"(felt, felt)","offset":1}},"size":3,"type":"struct"},"__main__.two_counters.write.ImplicitArgs":{"full_name":"__main__.two_counters.write.ImplicitArgs","members":{"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":3,"type":"struct"},"__main__.two_counters.write.Return":{"full_name":"__main__.two_counters.write.Return","members":{},"size":0,"type":"struct"},"__main__.two_counters.write.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.two_counters.write.index":{"cairo_type":"felt","full_name":"__main__.two_counters.write.index","references":[{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.two_counters.write.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.two_counters.write.pedersen_ptr","references":[{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-7), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.two_counters.write.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.two_counters.write.range_check_ptr","references":[{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__main__.two_counters.write.storage_addr":{"cairo_type":"felt","full_name":"__main__.two_counters.write.storage_addr","references":[{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.two_counters.write.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.two_counters.write.syscall_ptr","references":[{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":22,"offset":51},"pc":229,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":22,"offset":57},"pc":234,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__main__.two_counters.write.value":{"cairo_type":"(felt, felt)","full_name":"__main__.two_counters.write.value","references":[{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-4), (felt, felt)*)]"}],"type":"reference"},"__main__.xor_counters":{"decorators":["external"],"pc":313,"type":"function"},"__main__.xor_counters.Args":{"full_name":"__main__.xor_counters.Args","members":{"index_and_x":{"cairo_type":"__main__.IndexAndValues","offset":0}},"size":3,"type":"struct"},"__main__.xor_counters.ImplicitArgs":{"full_name":"__main__.xor_counters.ImplicitArgs","members":{"bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":4,"type":"struct"},"__main__.xor_counters.Return":{"full_name":"__main__.xor_counters.Return","members":{},"size":0,"type":"struct"},"__main__.xor_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__main__.xor_counters.bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","full_name":"__main__.xor_counters.bitwise_ptr","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":76},"pc":324,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":83},"pc":329,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"}],"type":"reference"},"__main__.xor_counters.index":{"cairo_type":"felt","full_name":"__main__.xor_counters.index","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"__main__.xor_counters.index_and_x":{"cairo_type":"__main__.IndexAndValues","full_name":"__main__.xor_counters.index_and_x","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"}],"type":"reference"},"__main__.xor_counters.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__main__.xor_counters.pedersen_ptr","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-8), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__main__.xor_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__main__.xor_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.xor_counters.res0":{"cairo_type":"felt","full_name":"__main__.xor_counters.res0","references":[{"ap_tracking_data":{"group":27,"offset":76},"pc":324,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.xor_counters.res1":{"cairo_type":"felt","full_name":"__main__.xor_counters.res1","references":[{"ap_tracking_data":{"group":27,"offset":83},"pc":329,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__main__.xor_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__main__.xor_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-9), felt**)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__main__.xor_counters.val":{"cairo_type":"(felt, felt)","full_name":"__main__.xor_counters.val","references":[{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-2), (felt, felt)*)]"}],"type":"reference"},"__main__.xor_counters.x0":{"cairo_type":"felt","full_name":"__main__.xor_counters.x0","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"__main__.xor_counters.x1":{"cairo_type":"felt","full_name":"__main__.xor_counters.x1","references":[{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters":{"decorators":["external"],"pc":435,"type":"function"},"__wrappers__.add_signature_to_counters.Args":{"full_name":"__wrappers__.add_signature_to_counters.Args","members":{},"size":0,"type":"struct"},"__wrappers__.add_signature_to_counters.ImplicitArgs":{"full_name":"__wrappers__.add_signature_to_counters.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.add_signature_to_counters.Return":{"full_name":"__wrappers__.add_signature_to_counters.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.add_signature_to_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.add_signature_to_counters.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.__calldata_actual_size","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.add_signature_to_counters.__calldata_arg_index":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.__calldata_arg_index","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.add_signature_to_counters.__calldata_ptr","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.add_signature_to_counters.__temp31":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.__temp31","references":[{"ap_tracking_data":{"group":33,"offset":1},"pc":437,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.__wrapped_func":{"destination":"__main__.add_signature_to_counters","type":"alias"},"__wrappers__.add_signature_to_counters.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.bitwise_ptr","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.add_signature_to_counters.pedersen_ptr","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.ret_struct":{"cairo_type":"__main__.add_signature_to_counters.Return","full_name":"__wrappers__.add_signature_to_counters.ret_struct","references":[{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + 0, __main__.add_signature_to_counters.Return*)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.add_signature_to_counters.retdata","references":[{"ap_tracking_data":{"group":33,"offset":154},"pc":446,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.add_signature_to_counters.retdata_size","references":[{"ap_tracking_data":{"group":33,"offset":154},"pc":446,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.add_signature_to_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.add_signature_to_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.add_signature_to_counters_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.add_value":{"decorators":["external"],"pc":931,"type":"function"},"__wrappers__.add_value.Args":{"full_name":"__wrappers__.add_value.Args","members":{},"size":0,"type":"struct"},"__wrappers__.add_value.ImplicitArgs":{"full_name":"__wrappers__.add_value.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.add_value.Return":{"full_name":"__wrappers__.add_value.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.add_value.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.add_value.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.add_value.__calldata_actual_size","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.add_value.__calldata_arg_value":{"cairo_type":"felt","full_name":"__wrappers__.add_value.__calldata_arg_value","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.add_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.add_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.add_value.__temp56":{"cairo_type":"felt","full_name":"__wrappers__.add_value.__temp56","references":[{"ap_tracking_data":{"group":70,"offset":1},"pc":933,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.add_value.__wrapped_func":{"destination":"__main__.add_value","type":"alias"},"__wrappers__.add_value.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.add_value.bitwise_ptr","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.add_value.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.add_value.pedersen_ptr","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.add_value.ret_struct":{"cairo_type":"__main__.add_value.Return","full_name":"__wrappers__.add_value.ret_struct","references":[{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + 0, __main__.add_value.Return*)]"}],"type":"reference"},"__wrappers__.add_value.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.add_value.retdata","references":[{"ap_tracking_data":{"group":71,"offset":1},"pc":941,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.add_value.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.add_value.retdata_size","references":[{"ap_tracking_data":{"group":71,"offset":1},"pc":941,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.add_value_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.advance_counter":{"decorators":["external"],"pc":256,"type":"function"},"__wrappers__.advance_counter.Args":{"full_name":"__wrappers__.advance_counter.Args","members":{},"size":0,"type":"struct"},"__wrappers__.advance_counter.ImplicitArgs":{"full_name":"__wrappers__.advance_counter.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.advance_counter.Return":{"full_name":"__wrappers__.advance_counter.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.advance_counter.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.advance_counter.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__calldata_actual_size","references":[{"ap_tracking_data":{"group":24,"offset":5},"pc":263,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.advance_counter.__calldata_arg_diffs":{"cairo_type":"felt*","full_name":"__wrappers__.advance_counter.__calldata_arg_diffs","references":[{"ap_tracking_data":{"group":24,"offset":2},"pc":259,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.advance_counter.__calldata_arg_diffs_len":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__calldata_arg_diffs_len","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__calldata_arg_index":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__calldata_arg_index","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.advance_counter.__calldata_ptr","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":24,"offset":5},"pc":263,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.advance_counter.__temp20":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__temp20","references":[{"ap_tracking_data":{"group":24,"offset":1},"pc":257,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__temp21":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__temp21","references":[{"ap_tracking_data":{"group":24,"offset":2},"pc":258,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__temp22":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__temp22","references":[{"ap_tracking_data":{"group":24,"offset":3},"pc":261,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__temp23":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__temp23","references":[{"ap_tracking_data":{"group":24,"offset":4},"pc":262,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__temp24":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.__temp24","references":[{"ap_tracking_data":{"group":24,"offset":6},"pc":265,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.__wrapped_func":{"destination":"__main__.advance_counter","type":"alias"},"__wrappers__.advance_counter.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.bitwise_ptr","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.advance_counter.pedersen_ptr","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.advance_counter.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.range_check_ptr","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":24,"offset":2},"pc":259,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.advance_counter.ret_struct":{"cairo_type":"__main__.advance_counter.Return","full_name":"__wrappers__.advance_counter.ret_struct","references":[{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + 0, __main__.advance_counter.Return*)]"}],"type":"reference"},"__wrappers__.advance_counter.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.advance_counter.retdata","references":[{"ap_tracking_data":{"group":24,"offset":153},"pc":277,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.advance_counter.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.advance_counter.retdata_size","references":[{"ap_tracking_data":{"group":24,"offset":153},"pc":277,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.advance_counter.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.advance_counter.syscall_ptr","references":[{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__wrappers__.advance_counter_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.call_xor_counters":{"decorators":["external"],"pc":391,"type":"function"},"__wrappers__.call_xor_counters.Args":{"full_name":"__wrappers__.call_xor_counters.Args","members":{},"size":0,"type":"struct"},"__wrappers__.call_xor_counters.ImplicitArgs":{"full_name":"__wrappers__.call_xor_counters.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.call_xor_counters.Return":{"full_name":"__wrappers__.call_xor_counters.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.call_xor_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.call_xor_counters.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.__calldata_actual_size","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 4 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.call_xor_counters.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.__calldata_arg_address","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.__calldata_arg_index_and_x":{"cairo_type":"__main__.IndexAndValues","full_name":"__wrappers__.call_xor_counters.__calldata_arg_index_and_x","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-3)] + 1, __main__.IndexAndValues*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.call_xor_counters.__calldata_ptr","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 4, felt*)"}],"type":"reference"},"__wrappers__.call_xor_counters.__temp28":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.__temp28","references":[{"ap_tracking_data":{"group":31,"offset":1},"pc":393,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.__wrapped_func":{"destination":"__main__.call_xor_counters","type":"alias"},"__wrappers__.call_xor_counters.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.bitwise_ptr","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.pedersen_ptr","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.ret_struct":{"cairo_type":"__main__.call_xor_counters.Return","full_name":"__wrappers__.call_xor_counters.ret_struct","references":[{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + 0, __main__.call_xor_counters.Return*)]"}],"type":"reference"},"__wrappers__.call_xor_counters.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.call_xor_counters.retdata","references":[{"ap_tracking_data":{"group":31,"offset":36},"pc":404,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.call_xor_counters.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.call_xor_counters.retdata_size","references":[{"ap_tracking_data":{"group":31,"offset":36},"pc":404,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.call_xor_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.call_xor_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.call_xor_counters_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.constructor":{"decorators":["constructor"],"pc":293,"type":"function"},"__wrappers__.constructor.Args":{"full_name":"__wrappers__.constructor.Args","members":{},"size":0,"type":"struct"},"__wrappers__.constructor.ImplicitArgs":{"full_name":"__wrappers__.constructor.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.constructor.Return":{"full_name":"__wrappers__.constructor.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.constructor.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.constructor.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.constructor.__calldata_actual_size","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.constructor.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.constructor.__calldata_arg_address","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.constructor.__calldata_arg_value":{"cairo_type":"felt","full_name":"__wrappers__.constructor.__calldata_arg_value","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.constructor.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.constructor.__calldata_ptr","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.constructor.__temp25":{"cairo_type":"felt","full_name":"__wrappers__.constructor.__temp25","references":[{"ap_tracking_data":{"group":26,"offset":1},"pc":295,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.constructor.__wrapped_func":{"destination":"__main__.constructor","type":"alias"},"__wrappers__.constructor.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.constructor.bitwise_ptr","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.constructor.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.constructor.pedersen_ptr","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.constructor.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.constructor.range_check_ptr","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.constructor.ret_struct":{"cairo_type":"__main__.constructor.Return","full_name":"__wrappers__.constructor.ret_struct","references":[{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + 0, __main__.constructor.Return*)]"}],"type":"reference"},"__wrappers__.constructor.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.constructor.retdata","references":[{"ap_tracking_data":{"group":26,"offset":18},"pc":305,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.constructor.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.constructor.retdata_size","references":[{"ap_tracking_data":{"group":26,"offset":18},"pc":305,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.constructor.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.constructor.syscall_ptr","references":[{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__wrappers__.constructor_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.deposit":{"decorators":["l1_handler"],"pc":715,"type":"function"},"__wrappers__.deposit.Args":{"full_name":"__wrappers__.deposit.Args","members":{},"size":0,"type":"struct"},"__wrappers__.deposit.ImplicitArgs":{"full_name":"__wrappers__.deposit.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.deposit.Return":{"full_name":"__wrappers__.deposit.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.deposit.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.deposit.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.deposit.__calldata_actual_size","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.deposit.__calldata_arg_amount":{"cairo_type":"felt","full_name":"__wrappers__.deposit.__calldata_arg_amount","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.deposit.__calldata_arg_from_address":{"cairo_type":"felt","full_name":"__wrappers__.deposit.__calldata_arg_from_address","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.deposit.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.deposit.__calldata_ptr","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.deposit.__temp48":{"cairo_type":"felt","full_name":"__wrappers__.deposit.__temp48","references":[{"ap_tracking_data":{"group":51,"offset":1},"pc":717,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.deposit.__wrapped_func":{"destination":"__main__.deposit","type":"alias"},"__wrappers__.deposit.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.deposit.bitwise_ptr","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.deposit.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.deposit.pedersen_ptr","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.deposit.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.deposit.range_check_ptr","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__wrappers__.deposit.ret_struct":{"cairo_type":"__main__.deposit.Return","full_name":"__wrappers__.deposit.ret_struct","references":[{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + 0, __main__.deposit.Return*)]"}],"type":"reference"},"__wrappers__.deposit.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.deposit.retdata","references":[{"ap_tracking_data":{"group":51,"offset":162},"pc":727,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.deposit.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.deposit.retdata_size","references":[{"ap_tracking_data":{"group":51,"offset":162},"pc":727,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.deposit.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.deposit.syscall_ptr","references":[{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-3), felt**)]"}],"type":"reference"},"__wrappers__.deposit_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.entry_point":{"decorators":["external"],"pc":530,"type":"function"},"__wrappers__.entry_point.Args":{"full_name":"__wrappers__.entry_point.Args","members":{},"size":0,"type":"struct"},"__wrappers__.entry_point.ImplicitArgs":{"full_name":"__wrappers__.entry_point.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.entry_point.Return":{"full_name":"__wrappers__.entry_point.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.entry_point.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.entry_point.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.entry_point.__calldata_actual_size","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"cast([fp + (-3)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.entry_point.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.entry_point.__calldata_ptr","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__wrappers__.entry_point.__wrapped_func":{"destination":"__main__.entry_point","type":"alias"},"__wrappers__.entry_point.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.entry_point.bitwise_ptr","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.entry_point.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.entry_point.pedersen_ptr","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.entry_point.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.entry_point.range_check_ptr","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.entry_point.ret_struct":{"cairo_type":"__main__.entry_point.Return","full_name":"__wrappers__.entry_point.ret_struct","references":[{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + 0, __main__.entry_point.Return*)]"}],"type":"reference"},"__wrappers__.entry_point.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.entry_point.retdata","references":[{"ap_tracking_data":{"group":40,"offset":27},"pc":537,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.entry_point.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.entry_point.retdata_size","references":[{"ap_tracking_data":{"group":40,"offset":27},"pc":537,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.entry_point.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.entry_point.syscall_ptr","references":[{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.entry_point_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.get_value":{"decorators":["external"],"pc":492,"type":"function"},"__wrappers__.get_value.Args":{"full_name":"__wrappers__.get_value.Args","members":{},"size":0,"type":"struct"},"__wrappers__.get_value.ImplicitArgs":{"full_name":"__wrappers__.get_value.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.get_value.Return":{"full_name":"__wrappers__.get_value.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.get_value.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.get_value.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.get_value.__calldata_actual_size","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.get_value.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.get_value.__calldata_arg_address","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.get_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.get_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.get_value.__temp34":{"cairo_type":"felt","full_name":"__wrappers__.get_value.__temp34","references":[{"ap_tracking_data":{"group":38,"offset":1},"pc":494,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.get_value.__wrapped_func":{"destination":"__main__.get_value","type":"alias"},"__wrappers__.get_value.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.get_value.bitwise_ptr","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.get_value.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.get_value.pedersen_ptr","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.get_value.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.get_value.range_check_ptr","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-3), felt*)]"}],"type":"reference"},"__wrappers__.get_value.ret_struct":{"cairo_type":"__main__.get_value.Return","full_name":"__wrappers__.get_value.ret_struct","references":[{"ap_tracking_data":{"group":38,"offset":12},"pc":499,"value":"[cast(ap + (-1), __main__.get_value.Return*)]"}],"type":"reference"},"__wrappers__.get_value.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.get_value.retdata","references":[{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.get_value.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.get_value.retdata_size","references":[{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__wrappers__.get_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.get_value.syscall_ptr","references":[{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":38,"offset":12},"pc":499,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.get_value_encode_return":{"decorators":[],"pc":483,"type":"function"},"__wrappers__.get_value_encode_return.Args":{"full_name":"__wrappers__.get_value_encode_return.Args","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"ret_struct":{"cairo_type":"__main__.get_value.Return","offset":0}},"size":2,"type":"struct"},"__wrappers__.get_value_encode_return.ImplicitArgs":{"full_name":"__wrappers__.get_value_encode_return.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.get_value_encode_return.Return":{"full_name":"__wrappers__.get_value_encode_return.Return","members":{"data":{"cairo_type":"felt*","offset":2},"data_len":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":3,"type":"struct"},"__wrappers__.get_value_encode_return.SIZEOF_LOCALS":{"type":"const","value":1},"__wrappers__.get_value_encode_return.__return_value_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.get_value_encode_return.__return_value_ptr","references":[{"ap_tracking_data":{"group":37,"offset":1},"pc":485,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":37,"offset":1},"pc":486,"value":"cast([fp] + 1, felt*)"}],"type":"reference"},"__wrappers__.get_value_encode_return.__return_value_ptr_start":{"cairo_type":"felt*","full_name":"__wrappers__.get_value_encode_return.__return_value_ptr_start","references":[{"ap_tracking_data":{"group":37,"offset":1},"pc":485,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__wrappers__.get_value_encode_return.__temp33":{"cairo_type":"felt","full_name":"__wrappers__.get_value_encode_return.__temp33","references":[{"ap_tracking_data":{"group":37,"offset":2},"pc":488,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.get_value_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.get_value_encode_return.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.get_value_encode_return.range_check_ptr","references":[{"ap_tracking_data":{"group":37,"offset":0},"pc":483,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__wrappers__.get_value_encode_return.ret_struct":{"cairo_type":"__main__.get_value.Return","full_name":"__wrappers__.get_value_encode_return.ret_struct","references":[{"ap_tracking_data":{"group":37,"offset":0},"pc":483,"value":"[cast(fp + (-4), __main__.get_value.Return*)]"}],"type":"reference"},"__wrappers__.increase_value":{"decorators":["external"],"pc":1002,"type":"function"},"__wrappers__.increase_value.Args":{"full_name":"__wrappers__.increase_value.Args","members":{},"size":0,"type":"struct"},"__wrappers__.increase_value.ImplicitArgs":{"full_name":"__wrappers__.increase_value.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.increase_value.Return":{"full_name":"__wrappers__.increase_value.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.increase_value.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.increase_value.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.__calldata_actual_size","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.increase_value.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.__calldata_arg_address","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.increase_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.increase_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.increase_value.__temp58":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.__temp58","references":[{"ap_tracking_data":{"group":78,"offset":1},"pc":1004,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.increase_value.__wrapped_func":{"destination":"__main__.increase_value","type":"alias"},"__wrappers__.increase_value.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.bitwise_ptr","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.increase_value.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.pedersen_ptr","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.increase_value.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.range_check_ptr","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.increase_value.ret_struct":{"cairo_type":"__main__.increase_value.Return","full_name":"__wrappers__.increase_value.ret_struct","references":[{"ap_tracking_data":{"group":78,"offset":19},"pc":1009,"value":"[cast(ap + 0, __main__.increase_value.Return*)]"}],"type":"reference"},"__wrappers__.increase_value.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.increase_value.retdata","references":[{"ap_tracking_data":{"group":78,"offset":20},"pc":1011,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.increase_value.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.increase_value.retdata_size","references":[{"ap_tracking_data":{"group":78,"offset":20},"pc":1011,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.increase_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.increase_value.syscall_ptr","references":[{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":78,"offset":19},"pc":1009,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.increase_value_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.recursive_add_value":{"decorators":["external"],"pc":972,"type":"function"},"__wrappers__.recursive_add_value.Args":{"full_name":"__wrappers__.recursive_add_value.Args","members":{},"size":0,"type":"struct"},"__wrappers__.recursive_add_value.ImplicitArgs":{"full_name":"__wrappers__.recursive_add_value.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.recursive_add_value.Return":{"full_name":"__wrappers__.recursive_add_value.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.recursive_add_value.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.recursive_add_value.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.__calldata_actual_size","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.recursive_add_value.__calldata_arg_self_address":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.__calldata_arg_self_address","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.__calldata_arg_value":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.__calldata_arg_value","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.recursive_add_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.recursive_add_value.__temp57":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.__temp57","references":[{"ap_tracking_data":{"group":75,"offset":1},"pc":974,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.__wrapped_func":{"destination":"__main__.recursive_add_value","type":"alias"},"__wrappers__.recursive_add_value.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.bitwise_ptr","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.pedersen_ptr","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.range_check_ptr","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.ret_struct":{"cairo_type":"__main__.recursive_add_value.Return","full_name":"__wrappers__.recursive_add_value.ret_struct","references":[{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + 0, __main__.recursive_add_value.Return*)]"}],"type":"reference"},"__wrappers__.recursive_add_value.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.recursive_add_value.retdata","references":[{"ap_tracking_data":{"group":76,"offset":1},"pc":983,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.recursive_add_value.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.recursive_add_value.retdata_size","references":[{"ap_tracking_data":{"group":76,"offset":1},"pc":983,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.recursive_add_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.recursive_add_value.syscall_ptr","references":[{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.recursive_add_value_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.send_message":{"decorators":["external"],"pc":605,"type":"function"},"__wrappers__.send_message.Args":{"full_name":"__wrappers__.send_message.Args","members":{},"size":0,"type":"struct"},"__wrappers__.send_message.ImplicitArgs":{"full_name":"__wrappers__.send_message.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.send_message.Return":{"full_name":"__wrappers__.send_message.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.send_message.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.send_message.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.send_message.__calldata_actual_size","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.send_message.__calldata_arg_to_address":{"cairo_type":"felt","full_name":"__wrappers__.send_message.__calldata_arg_to_address","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.send_message.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.send_message.__calldata_ptr","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.send_message.__temp36":{"cairo_type":"felt","full_name":"__wrappers__.send_message.__temp36","references":[{"ap_tracking_data":{"group":45,"offset":1},"pc":607,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.send_message.__wrapped_func":{"destination":"__main__.send_message","type":"alias"},"__wrappers__.send_message.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.send_message.bitwise_ptr","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.send_message.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.send_message.pedersen_ptr","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.send_message.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.send_message.range_check_ptr","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.send_message.ret_struct":{"cairo_type":"__main__.send_message.Return","full_name":"__wrappers__.send_message.ret_struct","references":[{"ap_tracking_data":{"group":45,"offset":17},"pc":612,"value":"[cast(ap + 0, __main__.send_message.Return*)]"}],"type":"reference"},"__wrappers__.send_message.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.send_message.retdata","references":[{"ap_tracking_data":{"group":45,"offset":18},"pc":614,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.send_message.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.send_message.retdata_size","references":[{"ap_tracking_data":{"group":45,"offset":18},"pc":614,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.send_message.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.send_message.syscall_ptr","references":[{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":45,"offset":17},"pc":612,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.send_message_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.set_value":{"decorators":["external"],"pc":460,"type":"function"},"__wrappers__.set_value.Args":{"full_name":"__wrappers__.set_value.Args","members":{},"size":0,"type":"struct"},"__wrappers__.set_value.ImplicitArgs":{"full_name":"__wrappers__.set_value.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.set_value.Return":{"full_name":"__wrappers__.set_value.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.set_value.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.set_value.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.set_value.__calldata_actual_size","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.set_value.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.set_value.__calldata_arg_address","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.set_value.__calldata_arg_value":{"cairo_type":"felt","full_name":"__wrappers__.set_value.__calldata_arg_value","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.set_value.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.set_value.__calldata_ptr","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.set_value.__temp32":{"cairo_type":"felt","full_name":"__wrappers__.set_value.__temp32","references":[{"ap_tracking_data":{"group":35,"offset":1},"pc":462,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.set_value.__wrapped_func":{"destination":"__main__.set_value","type":"alias"},"__wrappers__.set_value.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.set_value.bitwise_ptr","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.set_value.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.set_value.pedersen_ptr","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.set_value.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.set_value.range_check_ptr","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.set_value.ret_struct":{"cairo_type":"__main__.set_value.Return","full_name":"__wrappers__.set_value.ret_struct","references":[{"ap_tracking_data":{"group":35,"offset":13},"pc":468,"value":"[cast(ap + 0, __main__.set_value.Return*)]"}],"type":"reference"},"__wrappers__.set_value.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.set_value.retdata","references":[{"ap_tracking_data":{"group":35,"offset":14},"pc":470,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.set_value.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.set_value.retdata_size","references":[{"ap_tracking_data":{"group":35,"offset":14},"pc":470,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.set_value.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.set_value.syscall_ptr","references":[{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":35,"offset":13},"pc":468,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.set_value_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_builtins":{"decorators":["external"],"pc":574,"type":"function"},"__wrappers__.test_builtins.Args":{"full_name":"__wrappers__.test_builtins.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_builtins.ImplicitArgs":{"full_name":"__wrappers__.test_builtins.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_builtins.Return":{"full_name":"__wrappers__.test_builtins.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_builtins.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_builtins.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins.__calldata_actual_size","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"cast([fp + (-3)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_builtins.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_builtins.__calldata_ptr","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"__wrappers__.test_builtins.__wrapped_func":{"destination":"__main__.test_builtins","type":"alias"},"__wrappers__.test_builtins.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins.bitwise_ptr","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_builtins.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.test_builtins.pedersen_ptr","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.test_builtins.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins.range_check_ptr","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-3), felt*)]"}],"type":"reference"},"__wrappers__.test_builtins.ret_struct":{"cairo_type":"__main__.test_builtins.Return","full_name":"__wrappers__.test_builtins.ret_struct","references":[{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-1), __main__.test_builtins.Return*)]"}],"type":"reference"},"__wrappers__.test_builtins.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_builtins.retdata","references":[{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_builtins.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins.retdata_size","references":[{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__wrappers__.test_builtins.syscall_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins.syscall_ptr","references":[{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)], felt*)]"}],"type":"reference"},"__wrappers__.test_builtins_encode_return":{"decorators":[],"pc":565,"type":"function"},"__wrappers__.test_builtins_encode_return.Args":{"full_name":"__wrappers__.test_builtins_encode_return.Args","members":{"range_check_ptr":{"cairo_type":"felt","offset":1},"ret_struct":{"cairo_type":"__main__.test_builtins.Return","offset":0}},"size":2,"type":"struct"},"__wrappers__.test_builtins_encode_return.ImplicitArgs":{"full_name":"__wrappers__.test_builtins_encode_return.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_builtins_encode_return.Return":{"full_name":"__wrappers__.test_builtins_encode_return.Return","members":{"data":{"cairo_type":"felt*","offset":2},"data_len":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":3,"type":"struct"},"__wrappers__.test_builtins_encode_return.SIZEOF_LOCALS":{"type":"const","value":1},"__wrappers__.test_builtins_encode_return.__return_value_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_builtins_encode_return.__return_value_ptr","references":[{"ap_tracking_data":{"group":42,"offset":1},"pc":567,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":42,"offset":1},"pc":568,"value":"cast([fp] + 1, felt*)"}],"type":"reference"},"__wrappers__.test_builtins_encode_return.__return_value_ptr_start":{"cairo_type":"felt*","full_name":"__wrappers__.test_builtins_encode_return.__return_value_ptr_start","references":[{"ap_tracking_data":{"group":42,"offset":1},"pc":567,"value":"[cast(fp, felt**)]"}],"type":"reference"},"__wrappers__.test_builtins_encode_return.__temp35":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins_encode_return.__temp35","references":[{"ap_tracking_data":{"group":42,"offset":2},"pc":570,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_builtins_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_builtins_encode_return.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_builtins_encode_return.range_check_ptr","references":[{"ap_tracking_data":{"group":42,"offset":0},"pc":565,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"__wrappers__.test_builtins_encode_return.ret_struct":{"cairo_type":"__main__.test_builtins.Return","full_name":"__wrappers__.test_builtins_encode_return.ret_struct","references":[{"ap_tracking_data":{"group":42,"offset":0},"pc":565,"value":"[cast(fp + (-4), __main__.test_builtins.Return*)]"}],"type":"reference"},"__wrappers__.test_call_contract":{"decorators":["external"],"pc":631,"type":"function"},"__wrappers__.test_call_contract.Args":{"full_name":"__wrappers__.test_call_contract.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_contract.ImplicitArgs":{"full_name":"__wrappers__.test_call_contract.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_contract.Return":{"full_name":"__wrappers__.test_call_contract.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_call_contract.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_call_contract.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__calldata_actual_size","references":[{"ap_tracking_data":{"group":47,"offset":5},"pc":638,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_call_contract.__calldata_arg_calldata":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_contract.__calldata_arg_calldata","references":[{"ap_tracking_data":{"group":47,"offset":2},"pc":634,"value":"cast([fp + (-3)] + 3, felt*)"}],"type":"reference"},"__wrappers__.test_call_contract.__calldata_arg_calldata_len":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__calldata_arg_calldata_len","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__calldata_arg_contract_address":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__calldata_arg_contract_address","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__calldata_arg_function_selector":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__calldata_arg_function_selector","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_contract.__calldata_ptr","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":47,"offset":5},"pc":638,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_contract.__temp37":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__temp37","references":[{"ap_tracking_data":{"group":47,"offset":1},"pc":632,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__temp38":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__temp38","references":[{"ap_tracking_data":{"group":47,"offset":2},"pc":633,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__temp39":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__temp39","references":[{"ap_tracking_data":{"group":47,"offset":3},"pc":636,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__temp40":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__temp40","references":[{"ap_tracking_data":{"group":47,"offset":4},"pc":637,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__temp41":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.__temp41","references":[{"ap_tracking_data":{"group":47,"offset":26},"pc":650,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.__wrapped_func":{"destination":"__main__.test_call_contract","type":"alias"},"__wrappers__.test_call_contract.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.bitwise_ptr","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.pedersen_ptr","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_contract.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.range_check_ptr","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":47,"offset":2},"pc":634,"value":"cast([[fp + (-5)] + 2] + 1, felt)"}],"type":"reference"},"__wrappers__.test_call_contract.ret_struct":{"cairo_type":"__main__.test_call_contract.Return","full_name":"__wrappers__.test_call_contract.ret_struct","references":[{"ap_tracking_data":{"group":47,"offset":24},"pc":647,"value":"[cast(ap + 0, __main__.test_call_contract.Return*)]"}],"type":"reference"},"__wrappers__.test_call_contract.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_contract.retdata","references":[{"ap_tracking_data":{"group":47,"offset":25},"pc":649,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_contract.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_contract.retdata_size","references":[{"ap_tracking_data":{"group":47,"offset":25},"pc":649,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_call_contract.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_contract.syscall_ptr","references":[{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":47,"offset":24},"pc":647,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_contract_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_call_storage_consistency":{"decorators":["external"],"pc":839,"type":"function"},"__wrappers__.test_call_storage_consistency.Args":{"full_name":"__wrappers__.test_call_storage_consistency.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_storage_consistency.ImplicitArgs":{"full_name":"__wrappers__.test_call_storage_consistency.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_storage_consistency.Return":{"full_name":"__wrappers__.test_call_storage_consistency.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_call_storage_consistency.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_call_storage_consistency.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.__calldata_actual_size","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.__calldata_arg_address":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.__calldata_arg_address","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.__calldata_arg_other_contract_address":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.__calldata_arg_other_contract_address","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_storage_consistency.__calldata_ptr","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.__temp52":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.__temp52","references":[{"ap_tracking_data":{"group":61,"offset":1},"pc":841,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.__wrapped_func":{"destination":"__main__.test_call_storage_consistency","type":"alias"},"__wrappers__.test_call_storage_consistency.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.bitwise_ptr","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.pedersen_ptr","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.range_check_ptr","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.ret_struct":{"cairo_type":"__main__.test_call_storage_consistency.Return","full_name":"__wrappers__.test_call_storage_consistency.ret_struct","references":[{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + 0, __main__.test_call_storage_consistency.Return*)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_storage_consistency.retdata","references":[{"ap_tracking_data":{"group":62,"offset":1},"pc":850,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_storage_consistency.retdata_size","references":[{"ap_tracking_data":{"group":62,"offset":1},"pc":850,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_call_storage_consistency.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_storage_consistency.syscall_ptr","references":[{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.test_call_storage_consistency_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_call_with_array":{"decorators":["external"],"pc":1034,"type":"function"},"__wrappers__.test_call_with_array.Args":{"full_name":"__wrappers__.test_call_with_array.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_with_array.ImplicitArgs":{"full_name":"__wrappers__.test_call_with_array.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_call_with_array.Return":{"full_name":"__wrappers__.test_call_with_array.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_call_with_array.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_call_with_array.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__calldata_actual_size","references":[{"ap_tracking_data":{"group":81,"offset":5},"pc":1041,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_call_with_array.__calldata_arg_arr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_with_array.__calldata_arg_arr","references":[{"ap_tracking_data":{"group":81,"offset":2},"pc":1037,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.test_call_with_array.__calldata_arg_arr_len":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__calldata_arg_arr_len","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__calldata_arg_self_address":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__calldata_arg_self_address","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_with_array.__calldata_ptr","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":81,"offset":5},"pc":1041,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__temp59":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__temp59","references":[{"ap_tracking_data":{"group":81,"offset":1},"pc":1035,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__temp60":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__temp60","references":[{"ap_tracking_data":{"group":81,"offset":2},"pc":1036,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__temp61":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__temp61","references":[{"ap_tracking_data":{"group":81,"offset":3},"pc":1039,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__temp62":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__temp62","references":[{"ap_tracking_data":{"group":81,"offset":4},"pc":1040,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__temp63":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.__temp63","references":[{"ap_tracking_data":{"group":81,"offset":6},"pc":1043,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.__wrapped_func":{"destination":"__main__.test_call_with_array","type":"alias"},"__wrappers__.test_call_with_array.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.bitwise_ptr","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.pedersen_ptr","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.range_check_ptr","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":81,"offset":2},"pc":1037,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.ret_struct":{"cairo_type":"__main__.test_call_with_array.Return","full_name":"__wrappers__.test_call_with_array.ret_struct","references":[{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + 0, __main__.test_call_with_array.Return*)]"}],"type":"reference"},"__wrappers__.test_call_with_array.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_with_array.retdata","references":[{"ap_tracking_data":{"group":82,"offset":1},"pc":1054,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_call_with_array.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_call_with_array.retdata_size","references":[{"ap_tracking_data":{"group":82,"offset":1},"pc":1054,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_call_with_array.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_call_with_array.syscall_ptr","references":[{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.test_call_with_array_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_delegate_call":{"decorators":["external"],"pc":668,"type":"function"},"__wrappers__.test_delegate_call.Args":{"full_name":"__wrappers__.test_delegate_call.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_delegate_call.ImplicitArgs":{"full_name":"__wrappers__.test_delegate_call.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_delegate_call.Return":{"full_name":"__wrappers__.test_delegate_call.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_delegate_call.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_delegate_call.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__calldata_actual_size","references":[{"ap_tracking_data":{"group":49,"offset":5},"pc":675,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_delegate_call.__calldata_arg_calldata":{"cairo_type":"felt*","full_name":"__wrappers__.test_delegate_call.__calldata_arg_calldata","references":[{"ap_tracking_data":{"group":49,"offset":2},"pc":671,"value":"cast([fp + (-3)] + 3, felt*)"}],"type":"reference"},"__wrappers__.test_delegate_call.__calldata_arg_calldata_len":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__calldata_arg_calldata_len","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__calldata_arg_contract_address":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__calldata_arg_contract_address","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__calldata_arg_function_selector":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__calldata_arg_function_selector","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_delegate_call.__calldata_ptr","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":49,"offset":5},"pc":675,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__temp42":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__temp42","references":[{"ap_tracking_data":{"group":49,"offset":1},"pc":669,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__temp43":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__temp43","references":[{"ap_tracking_data":{"group":49,"offset":2},"pc":670,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__temp44":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__temp44","references":[{"ap_tracking_data":{"group":49,"offset":3},"pc":673,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__temp45":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__temp45","references":[{"ap_tracking_data":{"group":49,"offset":4},"pc":674,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__temp46":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.__temp46","references":[{"ap_tracking_data":{"group":49,"offset":26},"pc":687,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.__wrapped_func":{"destination":"__main__.test_delegate_call","type":"alias"},"__wrappers__.test_delegate_call.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.bitwise_ptr","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.pedersen_ptr","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.range_check_ptr","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":49,"offset":2},"pc":671,"value":"cast([[fp + (-5)] + 2] + 1, felt)"}],"type":"reference"},"__wrappers__.test_delegate_call.ret_struct":{"cairo_type":"__main__.test_delegate_call.Return","full_name":"__wrappers__.test_delegate_call.ret_struct","references":[{"ap_tracking_data":{"group":49,"offset":24},"pc":684,"value":"[cast(ap + 0, __main__.test_delegate_call.Return*)]"}],"type":"reference"},"__wrappers__.test_delegate_call.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_delegate_call.retdata","references":[{"ap_tracking_data":{"group":49,"offset":25},"pc":686,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_delegate_call.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_delegate_call.retdata_size","references":[{"ap_tracking_data":{"group":49,"offset":25},"pc":686,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_delegate_call.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_delegate_call.syscall_ptr","references":[{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":49,"offset":24},"pc":684,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_delegate_call_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_get_caller_address":{"decorators":["external"],"pc":741,"type":"function"},"__wrappers__.test_get_caller_address.Args":{"full_name":"__wrappers__.test_get_caller_address.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_caller_address.ImplicitArgs":{"full_name":"__wrappers__.test_get_caller_address.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_caller_address.Return":{"full_name":"__wrappers__.test_get_caller_address.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_get_caller_address.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_get_caller_address.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.__calldata_actual_size","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_get_caller_address.__calldata_arg_expected_address":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.__calldata_arg_expected_address","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_caller_address.__calldata_ptr","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.test_get_caller_address.__temp49":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.__temp49","references":[{"ap_tracking_data":{"group":53,"offset":1},"pc":743,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.__wrapped_func":{"destination":"__main__.test_get_caller_address","type":"alias"},"__wrappers__.test_get_caller_address.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.bitwise_ptr","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.pedersen_ptr","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.range_check_ptr","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.ret_struct":{"cairo_type":"__main__.test_get_caller_address.Return","full_name":"__wrappers__.test_get_caller_address.ret_struct","references":[{"ap_tracking_data":{"group":53,"offset":12},"pc":748,"value":"[cast(ap + 0, __main__.test_get_caller_address.Return*)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_caller_address.retdata","references":[{"ap_tracking_data":{"group":53,"offset":13},"pc":750,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_caller_address.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_caller_address.retdata_size","references":[{"ap_tracking_data":{"group":53,"offset":13},"pc":750,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_get_caller_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_caller_address.syscall_ptr","references":[{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":53,"offset":12},"pc":748,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_caller_address_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_get_contract_address":{"decorators":["external"],"pc":787,"type":"function"},"__wrappers__.test_get_contract_address.Args":{"full_name":"__wrappers__.test_get_contract_address.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_contract_address.ImplicitArgs":{"full_name":"__wrappers__.test_get_contract_address.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_contract_address.Return":{"full_name":"__wrappers__.test_get_contract_address.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_get_contract_address.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_get_contract_address.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.__calldata_actual_size","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_get_contract_address.__calldata_arg_expected_address":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.__calldata_arg_expected_address","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_contract_address.__calldata_ptr","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.test_get_contract_address.__temp51":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.__temp51","references":[{"ap_tracking_data":{"group":57,"offset":1},"pc":789,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.__wrapped_func":{"destination":"__main__.test_get_contract_address","type":"alias"},"__wrappers__.test_get_contract_address.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.bitwise_ptr","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.pedersen_ptr","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.range_check_ptr","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.ret_struct":{"cairo_type":"__main__.test_get_contract_address.Return","full_name":"__wrappers__.test_get_contract_address.ret_struct","references":[{"ap_tracking_data":{"group":57,"offset":12},"pc":794,"value":"[cast(ap + 0, __main__.test_get_contract_address.Return*)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_contract_address.retdata","references":[{"ap_tracking_data":{"group":57,"offset":13},"pc":796,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_contract_address.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_contract_address.retdata_size","references":[{"ap_tracking_data":{"group":57,"offset":13},"pc":796,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_get_contract_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_contract_address.syscall_ptr","references":[{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":57,"offset":12},"pc":794,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_contract_address_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_get_sequencer_address":{"decorators":["external"],"pc":764,"type":"function"},"__wrappers__.test_get_sequencer_address.Args":{"full_name":"__wrappers__.test_get_sequencer_address.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_sequencer_address.ImplicitArgs":{"full_name":"__wrappers__.test_get_sequencer_address.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_get_sequencer_address.Return":{"full_name":"__wrappers__.test_get_sequencer_address.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_get_sequencer_address.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_get_sequencer_address.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.__calldata_actual_size","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.__calldata_arg_expected_address":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.__calldata_arg_expected_address","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_sequencer_address.__calldata_ptr","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"cast([fp + (-3)] + 1, felt*)"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.__temp50":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.__temp50","references":[{"ap_tracking_data":{"group":55,"offset":1},"pc":766,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.__wrapped_func":{"destination":"__main__.test_get_sequencer_address","type":"alias"},"__wrappers__.test_get_sequencer_address.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.bitwise_ptr","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.pedersen_ptr","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.range_check_ptr","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.ret_struct":{"cairo_type":"__main__.test_get_sequencer_address.Return","full_name":"__wrappers__.test_get_sequencer_address.ret_struct","references":[{"ap_tracking_data":{"group":55,"offset":12},"pc":771,"value":"[cast(ap + 0, __main__.test_get_sequencer_address.Return*)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_sequencer_address.retdata","references":[{"ap_tracking_data":{"group":55,"offset":13},"pc":773,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_get_sequencer_address.retdata_size","references":[{"ap_tracking_data":{"group":55,"offset":13},"pc":773,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_get_sequencer_address.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_get_sequencer_address.syscall_ptr","references":[{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":55,"offset":12},"pc":771,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_get_sequencer_address_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.test_re_entrance":{"decorators":["external"],"pc":890,"type":"function"},"__wrappers__.test_re_entrance.Args":{"full_name":"__wrappers__.test_re_entrance.Args","members":{},"size":0,"type":"struct"},"__wrappers__.test_re_entrance.ImplicitArgs":{"full_name":"__wrappers__.test_re_entrance.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.test_re_entrance.Return":{"full_name":"__wrappers__.test_re_entrance.Return","members":{"bitwise_ptr":{"cairo_type":"felt","offset":3},"pedersen_ptr":{"cairo_type":"felt","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.test_re_entrance.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.test_re_entrance.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.__calldata_actual_size","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.test_re_entrance.__calldata_arg_depth":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.__calldata_arg_depth","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-3)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.__calldata_arg_other_contract_address":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.__calldata_arg_other_contract_address","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-3)], felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_re_entrance.__calldata_ptr","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"__wrappers__.test_re_entrance.__temp54":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.__temp54","references":[{"ap_tracking_data":{"group":66,"offset":1},"pc":892,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.__wrapped_func":{"destination":"__main__.test_re_entrance","type":"alias"},"__wrappers__.test_re_entrance.bitwise_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.bitwise_ptr","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.pedersen_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.pedersen_ptr","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 1, felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.range_check_ptr","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.ret_struct":{"cairo_type":"__main__.test_re_entrance.Return","full_name":"__wrappers__.test_re_entrance.ret_struct","references":[{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + 0, __main__.test_re_entrance.Return*)]"}],"type":"reference"},"__wrappers__.test_re_entrance.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.test_re_entrance.retdata","references":[{"ap_tracking_data":{"group":67,"offset":1},"pc":901,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.test_re_entrance.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.test_re_entrance.retdata_size","references":[{"ap_tracking_data":{"group":67,"offset":1},"pc":901,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.test_re_entrance.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.test_re_entrance.syscall_ptr","references":[{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + (-2), felt**)]"}],"type":"reference"},"__wrappers__.test_re_entrance_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"__wrappers__.xor_counters":{"decorators":["external"],"pc":339,"type":"function"},"__wrappers__.xor_counters.Args":{"full_name":"__wrappers__.xor_counters.Args","members":{},"size":0,"type":"struct"},"__wrappers__.xor_counters.ImplicitArgs":{"full_name":"__wrappers__.xor_counters.ImplicitArgs","members":{},"size":0,"type":"struct"},"__wrappers__.xor_counters.Return":{"full_name":"__wrappers__.xor_counters.Return","members":{"bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","offset":3},"pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":1},"range_check_ptr":{"cairo_type":"felt","offset":2},"retdata":{"cairo_type":"felt*","offset":5},"size":{"cairo_type":"felt","offset":4},"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":6,"type":"struct"},"__wrappers__.xor_counters.SIZEOF_LOCALS":{"type":"const","value":0},"__wrappers__.xor_counters.__calldata_actual_size":{"cairo_type":"felt","full_name":"__wrappers__.xor_counters.__calldata_actual_size","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"cast([fp + (-3)] + 3 - [fp + (-3)], felt)"}],"type":"reference"},"__wrappers__.xor_counters.__calldata_arg_index_and_x":{"cairo_type":"__main__.IndexAndValues","full_name":"__wrappers__.xor_counters.__calldata_arg_index_and_x","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-3)], __main__.IndexAndValues*)]"}],"type":"reference"},"__wrappers__.xor_counters.__calldata_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.xor_counters.__calldata_ptr","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"cast([fp + (-3)] + 3, felt*)"}],"type":"reference"},"__wrappers__.xor_counters.__temp26":{"cairo_type":"felt","full_name":"__wrappers__.xor_counters.__temp26","references":[{"ap_tracking_data":{"group":28,"offset":1},"pc":341,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"__wrappers__.xor_counters.__wrapped_func":{"destination":"__main__.xor_counters","type":"alias"},"__wrappers__.xor_counters.bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","full_name":"__wrappers__.xor_counters.bitwise_ptr","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 3, starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"}],"type":"reference"},"__wrappers__.xor_counters.pedersen_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"__wrappers__.xor_counters.pedersen_ptr","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"}],"type":"reference"},"__wrappers__.xor_counters.range_check_ptr":{"cairo_type":"felt","full_name":"__wrappers__.xor_counters.range_check_ptr","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-2), felt*)]"}],"type":"reference"},"__wrappers__.xor_counters.ret_struct":{"cairo_type":"__main__.xor_counters.Return","full_name":"__wrappers__.xor_counters.ret_struct","references":[{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + 0, __main__.xor_counters.Return*)]"}],"type":"reference"},"__wrappers__.xor_counters.retdata":{"cairo_type":"felt*","full_name":"__wrappers__.xor_counters.retdata","references":[{"ap_tracking_data":{"group":28,"offset":162},"pc":353,"value":"[cast(ap + (-1), felt**)]"}],"type":"reference"},"__wrappers__.xor_counters.retdata_size":{"cairo_type":"felt","full_name":"__wrappers__.xor_counters.retdata_size","references":[{"ap_tracking_data":{"group":28,"offset":162},"pc":353,"value":"cast(0, felt)"}],"type":"reference"},"__wrappers__.xor_counters.syscall_ptr":{"cairo_type":"felt*","full_name":"__wrappers__.xor_counters.syscall_ptr","references":[{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-4), felt**)]"}],"type":"reference"},"__wrappers__.xor_counters_encode_return.memcpy":{"destination":"starkware.cairo.common.memcpy.memcpy","type":"alias"},"starkware.cairo.common.alloc.alloc":{"decorators":[],"pc":0,"type":"function"},"starkware.cairo.common.alloc.alloc.Args":{"full_name":"starkware.cairo.common.alloc.alloc.Args","members":{},"size":0,"type":"struct"},"starkware.cairo.common.alloc.alloc.ImplicitArgs":{"full_name":"starkware.cairo.common.alloc.alloc.ImplicitArgs","members":{},"size":0,"type":"struct"},"starkware.cairo.common.alloc.alloc.Return":{"full_name":"starkware.cairo.common.alloc.alloc.Return","members":{"ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.bitwise.ALL_ONES":{"type":"const","value":-106710729501573572985208420194530329073740042555888586719234},"starkware.cairo.common.bitwise.BitwiseBuiltin":{"destination":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin","type":"alias"},"starkware.cairo.common.bitwise.bitwise_xor":{"decorators":[],"pc":169,"type":"function"},"starkware.cairo.common.bitwise.bitwise_xor.Args":{"full_name":"starkware.cairo.common.bitwise.bitwise_xor.Args","members":{"x":{"cairo_type":"felt","offset":0},"y":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.bitwise.bitwise_xor.ImplicitArgs":{"full_name":"starkware.cairo.common.bitwise.bitwise_xor.ImplicitArgs","members":{"bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.bitwise.bitwise_xor.Return":{"full_name":"starkware.cairo.common.bitwise.bitwise_xor.Return","members":{"x_xor_y":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.bitwise.bitwise_xor.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.bitwise.bitwise_xor.bitwise_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin*","full_name":"starkware.cairo.common.bitwise.bitwise_xor.bitwise_ptr","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"cast([fp + (-5)] + 5, starkware.cairo.common.cairo_builtins.BitwiseBuiltin*)"}],"type":"reference"},"starkware.cairo.common.bitwise.bitwise_xor.x":{"cairo_type":"felt","full_name":"starkware.cairo.common.bitwise.bitwise_xor.x","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.cairo.common.bitwise.bitwise_xor.x_and_y":{"cairo_type":"felt","full_name":"starkware.cairo.common.bitwise.bitwise_xor.x_and_y","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"starkware.cairo.common.bitwise.bitwise_xor.x_or_y":{"cairo_type":"felt","full_name":"starkware.cairo.common.bitwise.bitwise_xor.x_or_y","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 4, felt*)]"}],"type":"reference"},"starkware.cairo.common.bitwise.bitwise_xor.x_xor_y":{"cairo_type":"felt","full_name":"starkware.cairo.common.bitwise.bitwise_xor.x_xor_y","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 3, felt*)]"}],"type":"reference"},"starkware.cairo.common.bitwise.bitwise_xor.y":{"cairo_type":"felt","full_name":"starkware.cairo.common.bitwise.bitwise_xor.y","references":[{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.cairo_builtins.BitwiseBuiltin":{"full_name":"starkware.cairo.common.cairo_builtins.BitwiseBuiltin","members":{"x":{"cairo_type":"felt","offset":0},"x_and_y":{"cairo_type":"felt","offset":2},"x_or_y":{"cairo_type":"felt","offset":4},"x_xor_y":{"cairo_type":"felt","offset":3},"y":{"cairo_type":"felt","offset":1}},"size":5,"type":"struct"},"starkware.cairo.common.cairo_builtins.EcOpBuiltin":{"full_name":"starkware.cairo.common.cairo_builtins.EcOpBuiltin","members":{"m":{"cairo_type":"felt","offset":4},"p":{"cairo_type":"starkware.cairo.common.ec_point.EcPoint","offset":0},"q":{"cairo_type":"starkware.cairo.common.ec_point.EcPoint","offset":2},"r":{"cairo_type":"starkware.cairo.common.ec_point.EcPoint","offset":5}},"size":7,"type":"struct"},"starkware.cairo.common.cairo_builtins.EcPoint":{"destination":"starkware.cairo.common.ec_point.EcPoint","type":"alias"},"starkware.cairo.common.cairo_builtins.HashBuiltin":{"full_name":"starkware.cairo.common.cairo_builtins.HashBuiltin","members":{"result":{"cairo_type":"felt","offset":2},"x":{"cairo_type":"felt","offset":0},"y":{"cairo_type":"felt","offset":1}},"size":3,"type":"struct"},"starkware.cairo.common.cairo_builtins.SignatureBuiltin":{"full_name":"starkware.cairo.common.cairo_builtins.SignatureBuiltin","members":{"message":{"cairo_type":"felt","offset":1},"pub_key":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.cairo.common.dict_access.DictAccess":{"full_name":"starkware.cairo.common.dict_access.DictAccess","members":{"key":{"cairo_type":"felt","offset":0},"new_value":{"cairo_type":"felt","offset":2},"prev_value":{"cairo_type":"felt","offset":1}},"size":3,"type":"struct"},"starkware.cairo.common.ec_point.EcPoint":{"full_name":"starkware.cairo.common.ec_point.EcPoint","members":{"x":{"cairo_type":"felt","offset":0},"y":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.hash.HashBuiltin":{"destination":"starkware.cairo.common.cairo_builtins.HashBuiltin","type":"alias"},"starkware.cairo.common.hash.hash2":{"decorators":[],"pc":3,"type":"function"},"starkware.cairo.common.hash.hash2.Args":{"full_name":"starkware.cairo.common.hash.hash2.Args","members":{"x":{"cairo_type":"felt","offset":0},"y":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.hash.hash2.ImplicitArgs":{"full_name":"starkware.cairo.common.hash.hash2.ImplicitArgs","members":{"hash_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.hash.hash2.Return":{"full_name":"starkware.cairo.common.hash.hash2.Return","members":{"result":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.hash.hash2.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.hash.hash2.hash_ptr":{"cairo_type":"starkware.cairo.common.cairo_builtins.HashBuiltin*","full_name":"starkware.cairo.common.hash.hash2.hash_ptr","references":[{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":1,"offset":0},"pc":5,"value":"cast([fp + (-5)] + 3, starkware.cairo.common.cairo_builtins.HashBuiltin*)"}],"type":"reference"},"starkware.cairo.common.hash.hash2.result":{"cairo_type":"felt","full_name":"starkware.cairo.common.hash.hash2.result","references":[{"ap_tracking_data":{"group":1,"offset":0},"pc":5,"value":"[cast([fp + (-5)] + 2, felt*)]"}],"type":"reference"},"starkware.cairo.common.hash.hash2.x":{"cairo_type":"felt","full_name":"starkware.cairo.common.hash.hash2.x","references":[{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.cairo.common.hash.hash2.y":{"cairo_type":"felt","full_name":"starkware.cairo.common.hash.hash2.y","references":[{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit":{"decorators":["known_ap_change"],"pc":47,"type":"function"},"starkware.cairo.common.math.assert_250_bit.Args":{"full_name":"starkware.cairo.common.math.assert_250_bit.Args","members":{"value":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_250_bit.HIGH_BOUND":{"type":"const","value":5316911983139663491615228241121378304},"starkware.cairo.common.math.assert_250_bit.ImplicitArgs":{"full_name":"starkware.cairo.common.math.assert_250_bit.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_250_bit.Return":{"full_name":"starkware.cairo.common.math.assert_250_bit.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_250_bit.SHIFT":{"type":"const","value":340282366920938463463374607431768211456},"starkware.cairo.common.math.assert_250_bit.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.math.assert_250_bit.UPPER_BOUND":{"type":"const","value":1809251394333065553493296640760748560207343510400633813116524750123642650624},"starkware.cairo.common.math.assert_250_bit.__temp1":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp1","references":[{"ap_tracking_data":{"group":7,"offset":1},"pc":49,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.__temp2":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp2","references":[{"ap_tracking_data":{"group":7,"offset":2},"pc":50,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.__temp3":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp3","references":[{"ap_tracking_data":{"group":7,"offset":3},"pc":51,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.__temp4":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp4","references":[{"ap_tracking_data":{"group":7,"offset":4},"pc":53,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.__temp5":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp5","references":[{"ap_tracking_data":{"group":7,"offset":5},"pc":55,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.__temp6":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.__temp6","references":[{"ap_tracking_data":{"group":7,"offset":6},"pc":56,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.high":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.high","references":[{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast([fp + (-4)] + 1, felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.low":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.low","references":[{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast([fp + (-4)], felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.range_check_ptr":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.range_check_ptr","references":[{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":7,"offset":6},"pc":57,"value":"cast([fp + (-4)] + 3, felt)"}],"type":"reference"},"starkware.cairo.common.math.assert_250_bit.value":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_250_bit.value","references":[{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_le":{"decorators":[],"pc":33,"type":"function"},"starkware.cairo.common.math.assert_le.Args":{"full_name":"starkware.cairo.common.math.assert_le.Args","members":{"a":{"cairo_type":"felt","offset":0},"b":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.math.assert_le.ImplicitArgs":{"full_name":"starkware.cairo.common.math.assert_le.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_le.Return":{"full_name":"starkware.cairo.common.math.assert_le.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_le.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.math.assert_le.a":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_le.a","references":[{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_le.b":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_le.b","references":[{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_le.range_check_ptr":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_le.range_check_ptr","references":[{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":5,"offset":5},"pc":37,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_nn":{"decorators":[],"pc":29,"type":"function"},"starkware.cairo.common.math.assert_nn.Args":{"full_name":"starkware.cairo.common.math.assert_nn.Args","members":{"a":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_nn.ImplicitArgs":{"full_name":"starkware.cairo.common.math.assert_nn.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_nn.Return":{"full_name":"starkware.cairo.common.math.assert_nn.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_nn.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.math.assert_nn.a":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_nn.a","references":[{"ap_tracking_data":{"group":4,"offset":0},"pc":29,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_nn.range_check_ptr":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_nn.range_check_ptr","references":[{"ap_tracking_data":{"group":4,"offset":0},"pc":29,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":4,"offset":0},"pc":30,"value":"cast([fp + (-4)] + 1, felt)"}],"type":"reference"},"starkware.cairo.common.math.assert_nn_le":{"decorators":[],"pc":38,"type":"function"},"starkware.cairo.common.math.assert_nn_le.Args":{"full_name":"starkware.cairo.common.math.assert_nn_le.Args","members":{"a":{"cairo_type":"felt","offset":0},"b":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.math.assert_nn_le.ImplicitArgs":{"full_name":"starkware.cairo.common.math.assert_nn_le.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_nn_le.Return":{"full_name":"starkware.cairo.common.math.assert_nn_le.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_nn_le.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.math.assert_nn_le.a":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_nn_le.a","references":[{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_nn_le.b":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_nn_le.b","references":[{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_nn_le.range_check_ptr":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_nn_le.range_check_ptr","references":[{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":6,"offset":5},"pc":42,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":6,"offset":14},"pc":46,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.math.assert_not_zero":{"decorators":[],"pc":24,"type":"function"},"starkware.cairo.common.math.assert_not_zero.Args":{"full_name":"starkware.cairo.common.math.assert_not_zero.Args","members":{"value":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.cairo.common.math.assert_not_zero.ImplicitArgs":{"full_name":"starkware.cairo.common.math.assert_not_zero.ImplicitArgs","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_not_zero.Return":{"full_name":"starkware.cairo.common.math.assert_not_zero.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.math.assert_not_zero.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.math.assert_not_zero._anon_label2":{"pc":28,"type":"label"},"starkware.cairo.common.math.assert_not_zero._anon_label3":{"pc":28,"type":"label"},"starkware.cairo.common.math.assert_not_zero.value":{"cairo_type":"felt","full_name":"starkware.cairo.common.math.assert_not_zero.value","references":[{"ap_tracking_data":{"group":3,"offset":0},"pc":24,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy":{"decorators":[],"pc":9,"type":"function"},"starkware.cairo.common.memcpy.memcpy.Args":{"full_name":"starkware.cairo.common.memcpy.memcpy.Args","members":{"dst":{"cairo_type":"felt*","offset":0},"len":{"cairo_type":"felt","offset":2},"src":{"cairo_type":"felt*","offset":1}},"size":3,"type":"struct"},"starkware.cairo.common.memcpy.memcpy.ImplicitArgs":{"full_name":"starkware.cairo.common.memcpy.memcpy.ImplicitArgs","members":{},"size":0,"type":"struct"},"starkware.cairo.common.memcpy.memcpy.LoopFrame":{"full_name":"starkware.cairo.common.memcpy.memcpy.LoopFrame","members":{"dst":{"cairo_type":"felt*","offset":0},"src":{"cairo_type":"felt*","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.memcpy.memcpy.Return":{"full_name":"starkware.cairo.common.memcpy.memcpy.Return","members":{},"size":0,"type":"struct"},"starkware.cairo.common.memcpy.memcpy.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.cairo.common.memcpy.memcpy.__temp0":{"cairo_type":"felt","full_name":"starkware.cairo.common.memcpy.memcpy.__temp0","references":[{"ap_tracking_data":{"group":2,"offset":3},"pc":15,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy._anon_label0":{"pc":12,"type":"label"},"starkware.cairo.common.memcpy.memcpy._anon_label1":{"pc":12,"type":"label"},"starkware.cairo.common.memcpy.memcpy.continue_copying":{"cairo_type":"felt","full_name":"starkware.cairo.common.memcpy.memcpy.continue_copying","references":[{"ap_tracking_data":{"group":2,"offset":3},"pc":16,"value":"[cast(ap, felt*)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy.dst":{"cairo_type":"felt*","full_name":"starkware.cairo.common.memcpy.memcpy.dst","references":[{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-5), felt**)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy.frame":{"cairo_type":"starkware.cairo.common.memcpy.memcpy.LoopFrame","full_name":"starkware.cairo.common.memcpy.memcpy.frame","references":[{"ap_tracking_data":{"group":2,"offset":2},"pc":14,"value":"[cast(ap + (-2), starkware.cairo.common.memcpy.memcpy.LoopFrame*)]"},{"ap_tracking_data":{"group":2,"offset":2},"pc":14,"value":"[cast(ap + (-2), starkware.cairo.common.memcpy.memcpy.LoopFrame*)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy.len":{"cairo_type":"felt","full_name":"starkware.cairo.common.memcpy.memcpy.len","references":[{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy.loop":{"pc":14,"type":"label"},"starkware.cairo.common.memcpy.memcpy.next_frame":{"cairo_type":"starkware.cairo.common.memcpy.memcpy.LoopFrame*","full_name":"starkware.cairo.common.memcpy.memcpy.next_frame","references":[{"ap_tracking_data":{"group":2,"offset":3},"pc":16,"value":"cast(ap + 1, starkware.cairo.common.memcpy.memcpy.LoopFrame*)"}],"type":"reference"},"starkware.cairo.common.memcpy.memcpy.src":{"cairo_type":"felt*","full_name":"starkware.cairo.common.memcpy.memcpy.src","references":[{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-4), felt**)]"}],"type":"reference"},"starkware.cairo.common.registers.get_fp_and_pc":{"decorators":[],"pc":175,"type":"function"},"starkware.cairo.common.registers.get_fp_and_pc.Args":{"full_name":"starkware.cairo.common.registers.get_fp_and_pc.Args","members":{},"size":0,"type":"struct"},"starkware.cairo.common.registers.get_fp_and_pc.ImplicitArgs":{"full_name":"starkware.cairo.common.registers.get_fp_and_pc.ImplicitArgs","members":{},"size":0,"type":"struct"},"starkware.cairo.common.registers.get_fp_and_pc.Return":{"full_name":"starkware.cairo.common.registers.get_fp_and_pc.Return","members":{"fp_val":{"cairo_type":"felt","offset":0},"pc_val":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.cairo.common.registers.get_fp_and_pc.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.messages.SEND_MESSAGE_TO_L1_SELECTOR":{"destination":"starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR","type":"alias"},"starkware.starknet.common.messages.SendMessageToL1SysCall":{"destination":"starkware.starknet.common.syscalls.SendMessageToL1SysCall","type":"alias"},"starkware.starknet.common.messages.send_message_to_l1":{"decorators":[],"pc":176,"type":"function"},"starkware.starknet.common.messages.send_message_to_l1.Args":{"full_name":"starkware.starknet.common.messages.send_message_to_l1.Args","members":{"payload":{"cairo_type":"felt*","offset":2},"payload_size":{"cairo_type":"felt","offset":1},"to_address":{"cairo_type":"felt","offset":0}},"size":3,"type":"struct"},"starkware.starknet.common.messages.send_message_to_l1.ImplicitArgs":{"full_name":"starkware.starknet.common.messages.send_message_to_l1.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.messages.send_message_to_l1.Return":{"full_name":"starkware.starknet.common.messages.send_message_to_l1.Return","members":{},"size":0,"type":"struct"},"starkware.starknet.common.messages.send_message_to_l1.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.messages.send_message_to_l1.__temp17":{"cairo_type":"felt","full_name":"starkware.starknet.common.messages.send_message_to_l1.__temp17","references":[{"ap_tracking_data":{"group":19,"offset":1},"pc":178,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.messages.send_message_to_l1.payload":{"cairo_type":"felt*","full_name":"starkware.starknet.common.messages.send_message_to_l1.payload","references":[{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"starkware.starknet.common.messages.send_message_to_l1.payload_size":{"cairo_type":"felt","full_name":"starkware.starknet.common.messages.send_message_to_l1.payload_size","references":[{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.starknet.common.messages.send_message_to_l1.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.messages.send_message_to_l1.syscall_ptr","references":[{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":19,"offset":1},"pc":182,"value":"cast([fp + (-6)] + 4, felt*)"}],"type":"reference"},"starkware.starknet.common.messages.send_message_to_l1.to_address":{"cairo_type":"felt","full_name":"starkware.starknet.common.messages.send_message_to_l1.to_address","references":[{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.ADDR_BOUND":{"type":"const","value":-106710729501573572985208420194530329073740042555888586719489},"starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE":{"type":"const","value":256},"starkware.starknet.common.storage.assert_250_bit":{"destination":"starkware.cairo.common.math.assert_250_bit","type":"alias"},"starkware.starknet.common.storage.normalize_address":{"decorators":["known_ap_change"],"pc":60,"type":"function"},"starkware.starknet.common.storage.normalize_address.Args":{"full_name":"starkware.starknet.common.storage.normalize_address.Args","members":{"addr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.storage.normalize_address.ImplicitArgs":{"full_name":"starkware.starknet.common.storage.normalize_address.ImplicitArgs","members":{"range_check_ptr":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.storage.normalize_address.Return":{"full_name":"starkware.starknet.common.storage.normalize_address.Return","members":{"res":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.storage.normalize_address.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.storage.normalize_address.__temp7":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.__temp7","references":[{"ap_tracking_data":{"group":8,"offset":13},"pc":71,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.__temp8":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.__temp8","references":[{"ap_tracking_data":{"group":8,"offset":13},"pc":86,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address._anon_label20":{"pc":78,"type":"label"},"starkware.starknet.common.storage.normalize_address._anon_label21":{"pc":100,"type":"label"},"starkware.starknet.common.storage.normalize_address._anon_label22":{"pc":92,"type":"label"},"starkware.starknet.common.storage.normalize_address._anon_label23":{"pc":98,"type":"label"},"starkware.starknet.common.storage.normalize_address.addr":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.addr","references":[{"ap_tracking_data":{"group":8,"offset":0},"pc":60,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.is_250":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.is_250","references":[{"ap_tracking_data":{"group":8,"offset":2},"pc":80,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.is_small":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.is_small","references":[{"ap_tracking_data":{"group":8,"offset":1},"pc":62,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.range_check_ptr":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.range_check_ptr","references":[{"ap_tracking_data":{"group":8,"offset":0},"pc":60,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":8,"offset":12},"pc":69,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":75,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":90,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":98,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.x":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.x","references":[{"ap_tracking_data":{"group":8,"offset":1},"pc":64,"value":"cast([fp + (-3)] + 106710729501573572985208420194530329073740042555888586719489, felt)"}],"type":"reference"},"starkware.starknet.common.storage.normalize_address.y":{"cairo_type":"felt","full_name":"starkware.starknet.common.storage.normalize_address.y","references":[{"ap_tracking_data":{"group":8,"offset":1},"pc":64,"value":"cast((-1) - [fp + (-3)], felt)"}],"type":"reference"},"starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR":{"type":"const","value":20853273475220472486191784820},"starkware.starknet.common.syscalls.CallContract":{"full_name":"starkware.starknet.common.syscalls.CallContract","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.CallContractRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.CallContractResponse","offset":5}},"size":7,"type":"struct"},"starkware.starknet.common.syscalls.CallContractRequest":{"full_name":"starkware.starknet.common.syscalls.CallContractRequest","members":{"calldata":{"cairo_type":"felt*","offset":4},"calldata_size":{"cairo_type":"felt","offset":3},"contract_address":{"cairo_type":"felt","offset":1},"function_selector":{"cairo_type":"felt","offset":2},"selector":{"cairo_type":"felt","offset":0}},"size":5,"type":"struct"},"starkware.starknet.common.syscalls.CallContractResponse":{"full_name":"starkware.starknet.common.syscalls.CallContractResponse","members":{"retdata":{"cairo_type":"felt*","offset":1},"retdata_size":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR":{"type":"const","value":21167594061783206823196716140},"starkware.starknet.common.syscalls.DictAccess":{"destination":"starkware.cairo.common.dict_access.DictAccess","type":"alias"},"starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR":{"type":"const","value":94901967781393078444254803017658102643},"starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR":{"type":"const","value":6219495360805491471215297013070624192820083},"starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR":{"type":"const","value":1592190833581991703053805829594610833820054387},"starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR":{"type":"const","value":1448089128652340074717162277007973},"starkware.starknet.common.syscalls.GetCallerAddress":{"full_name":"starkware.starknet.common.syscalls.GetCallerAddress","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.GetCallerAddressRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.GetCallerAddressResponse","offset":1}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.GetCallerAddressRequest":{"full_name":"starkware.starknet.common.syscalls.GetCallerAddressRequest","members":{"selector":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetCallerAddressResponse":{"full_name":"starkware.starknet.common.syscalls.GetCallerAddressResponse","members":{"caller_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetContractAddress":{"full_name":"starkware.starknet.common.syscalls.GetContractAddress","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.GetContractAddressRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.GetContractAddressResponse","offset":1}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.GetContractAddressRequest":{"full_name":"starkware.starknet.common.syscalls.GetContractAddressRequest","members":{"selector":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetContractAddressResponse":{"full_name":"starkware.starknet.common.syscalls.GetContractAddressResponse","members":{"contract_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetSequencerAddress":{"full_name":"starkware.starknet.common.syscalls.GetSequencerAddress","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.GetSequencerAddressRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.GetSequencerAddressResponse","offset":1}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.GetSequencerAddressRequest":{"full_name":"starkware.starknet.common.syscalls.GetSequencerAddressRequest","members":{"selector":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetSequencerAddressResponse":{"full_name":"starkware.starknet.common.syscalls.GetSequencerAddressResponse","members":{"sequencer_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetTxSignature":{"full_name":"starkware.starknet.common.syscalls.GetTxSignature","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.GetTxSignatureRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.GetTxSignatureResponse","offset":1}},"size":3,"type":"struct"},"starkware.starknet.common.syscalls.GetTxSignatureRequest":{"full_name":"starkware.starknet.common.syscalls.GetTxSignatureRequest","members":{"selector":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.GetTxSignatureResponse":{"full_name":"starkware.starknet.common.syscalls.GetTxSignatureResponse","members":{"signature":{"cairo_type":"felt*","offset":1},"signature_len":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR":{"type":"const","value":433017908768303439907196859243777073},"starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR":{"type":"const","value":100890693370601760042082660},"starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR":{"type":"const","value":25828017502874050592466629733},"starkware.starknet.common.syscalls.SendMessageToL1SysCall":{"full_name":"starkware.starknet.common.syscalls.SendMessageToL1SysCall","members":{"payload_ptr":{"cairo_type":"felt*","offset":3},"payload_size":{"cairo_type":"felt","offset":2},"selector":{"cairo_type":"felt","offset":0},"to_address":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"starkware.starknet.common.syscalls.StorageRead":{"full_name":"starkware.starknet.common.syscalls.StorageRead","members":{"request":{"cairo_type":"starkware.starknet.common.syscalls.StorageReadRequest","offset":0},"response":{"cairo_type":"starkware.starknet.common.syscalls.StorageReadResponse","offset":2}},"size":3,"type":"struct"},"starkware.starknet.common.syscalls.StorageReadRequest":{"full_name":"starkware.starknet.common.syscalls.StorageReadRequest","members":{"address":{"cairo_type":"felt","offset":1},"selector":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.StorageReadResponse":{"full_name":"starkware.starknet.common.syscalls.StorageReadResponse","members":{"value":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.StorageWrite":{"full_name":"starkware.starknet.common.syscalls.StorageWrite","members":{"address":{"cairo_type":"felt","offset":1},"selector":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":2}},"size":3,"type":"struct"},"starkware.starknet.common.syscalls.call_contract":{"decorators":[],"pc":100,"type":"function"},"starkware.starknet.common.syscalls.call_contract.Args":{"full_name":"starkware.starknet.common.syscalls.call_contract.Args","members":{"calldata":{"cairo_type":"felt*","offset":3},"calldata_size":{"cairo_type":"felt","offset":2},"contract_address":{"cairo_type":"felt","offset":0},"function_selector":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"starkware.starknet.common.syscalls.call_contract.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.call_contract.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.call_contract.Return":{"full_name":"starkware.starknet.common.syscalls.call_contract.Return","members":{"retdata":{"cairo_type":"felt*","offset":1},"retdata_size":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.call_contract.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.call_contract.__temp9":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.call_contract.__temp9","references":[{"ap_tracking_data":{"group":9,"offset":1},"pc":102,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.calldata":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.call_contract.calldata","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.calldata_size":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.call_contract.calldata_size","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.contract_address":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.call_contract.contract_address","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.function_selector":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.call_contract.function_selector","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.response":{"cairo_type":"starkware.starknet.common.syscalls.CallContractResponse","full_name":"starkware.starknet.common.syscalls.call_contract.response","references":[{"ap_tracking_data":{"group":9,"offset":1},"pc":107,"value":"[cast([fp + (-7)] + 5, starkware.starknet.common.syscalls.CallContractResponse*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.syscall":{"cairo_type":"starkware.starknet.common.syscalls.CallContract","full_name":"starkware.starknet.common.syscalls.call_contract.syscall","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast([fp + (-7)], starkware.starknet.common.syscalls.CallContract*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.call_contract.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.call_contract.syscall_ptr","references":[{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":9,"offset":1},"pc":107,"value":"cast([fp + (-7)] + 7, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call":{"decorators":[],"pc":112,"type":"function"},"starkware.starknet.common.syscalls.delegate_call.Args":{"full_name":"starkware.starknet.common.syscalls.delegate_call.Args","members":{"calldata":{"cairo_type":"felt*","offset":3},"calldata_size":{"cairo_type":"felt","offset":2},"contract_address":{"cairo_type":"felt","offset":0},"function_selector":{"cairo_type":"felt","offset":1}},"size":4,"type":"struct"},"starkware.starknet.common.syscalls.delegate_call.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.delegate_call.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.delegate_call.Return":{"full_name":"starkware.starknet.common.syscalls.delegate_call.Return","members":{"retdata":{"cairo_type":"felt*","offset":1},"retdata_size":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.delegate_call.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.delegate_call.__temp10":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.delegate_call.__temp10","references":[{"ap_tracking_data":{"group":10,"offset":1},"pc":114,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.calldata":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.delegate_call.calldata","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-3), felt**)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.calldata_size":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.delegate_call.calldata_size","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.contract_address":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.delegate_call.contract_address","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-6), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.function_selector":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.delegate_call.function_selector","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-5), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.response":{"cairo_type":"starkware.starknet.common.syscalls.CallContractResponse","full_name":"starkware.starknet.common.syscalls.delegate_call.response","references":[{"ap_tracking_data":{"group":10,"offset":1},"pc":119,"value":"[cast([fp + (-7)] + 5, starkware.starknet.common.syscalls.CallContractResponse*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.syscall":{"cairo_type":"starkware.starknet.common.syscalls.CallContract","full_name":"starkware.starknet.common.syscalls.delegate_call.syscall","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast([fp + (-7)], starkware.starknet.common.syscalls.CallContract*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.delegate_call.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.delegate_call.syscall_ptr","references":[{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":10,"offset":1},"pc":119,"value":"cast([fp + (-7)] + 7, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.get_caller_address":{"decorators":[],"pc":124,"type":"function"},"starkware.starknet.common.syscalls.get_caller_address.Args":{"full_name":"starkware.starknet.common.syscalls.get_caller_address.Args","members":{},"size":0,"type":"struct"},"starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.get_caller_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_caller_address.Return":{"full_name":"starkware.starknet.common.syscalls.get_caller_address.Return","members":{"caller_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_caller_address.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.get_caller_address.__temp11":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.get_caller_address.__temp11","references":[{"ap_tracking_data":{"group":11,"offset":1},"pc":126,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_caller_address.syscall":{"cairo_type":"starkware.starknet.common.syscalls.GetCallerAddress","full_name":"starkware.starknet.common.syscalls.get_caller_address.syscall","references":[{"ap_tracking_data":{"group":11,"offset":0},"pc":124,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetCallerAddress*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_caller_address.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.get_caller_address.syscall_ptr","references":[{"ap_tracking_data":{"group":11,"offset":0},"pc":124,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":11,"offset":1},"pc":127,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.get_contract_address":{"decorators":[],"pc":138,"type":"function"},"starkware.starknet.common.syscalls.get_contract_address.Args":{"full_name":"starkware.starknet.common.syscalls.get_contract_address.Args","members":{},"size":0,"type":"struct"},"starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.get_contract_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_contract_address.Return":{"full_name":"starkware.starknet.common.syscalls.get_contract_address.Return","members":{"contract_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_contract_address.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.get_contract_address.__temp13":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.get_contract_address.__temp13","references":[{"ap_tracking_data":{"group":13,"offset":1},"pc":140,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_contract_address.syscall":{"cairo_type":"starkware.starknet.common.syscalls.GetContractAddress","full_name":"starkware.starknet.common.syscalls.get_contract_address.syscall","references":[{"ap_tracking_data":{"group":13,"offset":0},"pc":138,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetContractAddress*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_contract_address.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.get_contract_address.syscall_ptr","references":[{"ap_tracking_data":{"group":13,"offset":0},"pc":138,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":13,"offset":1},"pc":141,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.get_sequencer_address":{"decorators":[],"pc":131,"type":"function"},"starkware.starknet.common.syscalls.get_sequencer_address.Args":{"full_name":"starkware.starknet.common.syscalls.get_sequencer_address.Args","members":{},"size":0,"type":"struct"},"starkware.starknet.common.syscalls.get_sequencer_address.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.get_sequencer_address.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_sequencer_address.Return":{"full_name":"starkware.starknet.common.syscalls.get_sequencer_address.Return","members":{"sequencer_address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_sequencer_address.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.get_sequencer_address.__temp12":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.get_sequencer_address.__temp12","references":[{"ap_tracking_data":{"group":12,"offset":1},"pc":133,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_sequencer_address.syscall":{"cairo_type":"starkware.starknet.common.syscalls.GetSequencerAddress","full_name":"starkware.starknet.common.syscalls.get_sequencer_address.syscall","references":[{"ap_tracking_data":{"group":12,"offset":0},"pc":131,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetSequencerAddress*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_sequencer_address.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.get_sequencer_address.syscall_ptr","references":[{"ap_tracking_data":{"group":12,"offset":0},"pc":131,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":12,"offset":1},"pc":134,"value":"cast([fp + (-3)] + 2, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.get_tx_signature":{"decorators":[],"pc":145,"type":"function"},"starkware.starknet.common.syscalls.get_tx_signature.Args":{"full_name":"starkware.starknet.common.syscalls.get_tx_signature.Args","members":{},"size":0,"type":"struct"},"starkware.starknet.common.syscalls.get_tx_signature.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.get_tx_signature.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.get_tx_signature.Return":{"full_name":"starkware.starknet.common.syscalls.get_tx_signature.Return","members":{"signature":{"cairo_type":"felt*","offset":1},"signature_len":{"cairo_type":"felt","offset":0}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.get_tx_signature.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.get_tx_signature.__temp14":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.get_tx_signature.__temp14","references":[{"ap_tracking_data":{"group":14,"offset":1},"pc":147,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_tx_signature.syscall":{"cairo_type":"starkware.starknet.common.syscalls.GetTxSignature","full_name":"starkware.starknet.common.syscalls.get_tx_signature.syscall","references":[{"ap_tracking_data":{"group":14,"offset":0},"pc":145,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetTxSignature*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.get_tx_signature.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.get_tx_signature.syscall_ptr","references":[{"ap_tracking_data":{"group":14,"offset":0},"pc":145,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":14,"offset":1},"pc":148,"value":"cast([fp + (-3)] + 3, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_read":{"decorators":[],"pc":153,"type":"function"},"starkware.starknet.common.syscalls.storage_read.Args":{"full_name":"starkware.starknet.common.syscalls.storage_read.Args","members":{"address":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.storage_read.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.storage_read.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.storage_read.Return":{"full_name":"starkware.starknet.common.syscalls.storage_read.Return","members":{"value":{"cairo_type":"felt","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.storage_read.__temp15":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.storage_read.__temp15","references":[{"ap_tracking_data":{"group":15,"offset":1},"pc":155,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_read.address":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.storage_read.address","references":[{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_read.response":{"cairo_type":"starkware.starknet.common.syscalls.StorageReadResponse","full_name":"starkware.starknet.common.syscalls.storage_read.response","references":[{"ap_tracking_data":{"group":15,"offset":1},"pc":157,"value":"[cast([fp + (-4)] + 2, starkware.starknet.common.syscalls.StorageReadResponse*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_read.syscall":{"cairo_type":"starkware.starknet.common.syscalls.StorageRead","full_name":"starkware.starknet.common.syscalls.storage_read.syscall","references":[{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast([fp + (-4)], starkware.starknet.common.syscalls.StorageRead*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_read.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.storage_read.syscall_ptr","references":[{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":15,"offset":1},"pc":157,"value":"cast([fp + (-4)] + 3, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_write":{"decorators":[],"pc":161,"type":"function"},"starkware.starknet.common.syscalls.storage_write.Args":{"full_name":"starkware.starknet.common.syscalls.storage_write.Args","members":{"address":{"cairo_type":"felt","offset":0},"value":{"cairo_type":"felt","offset":1}},"size":2,"type":"struct"},"starkware.starknet.common.syscalls.storage_write.ImplicitArgs":{"full_name":"starkware.starknet.common.syscalls.storage_write.ImplicitArgs","members":{"syscall_ptr":{"cairo_type":"felt*","offset":0}},"size":1,"type":"struct"},"starkware.starknet.common.syscalls.storage_write.Return":{"full_name":"starkware.starknet.common.syscalls.storage_write.Return","members":{},"size":0,"type":"struct"},"starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS":{"type":"const","value":0},"starkware.starknet.common.syscalls.storage_write.__temp16":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.storage_write.__temp16","references":[{"ap_tracking_data":{"group":16,"offset":1},"pc":163,"value":"[cast(ap + (-1), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_write.address":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.storage_write.address","references":[{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-4), felt*)]"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_write.syscall_ptr":{"cairo_type":"felt*","full_name":"starkware.starknet.common.syscalls.storage_write.syscall_ptr","references":[{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":16,"offset":1},"pc":166,"value":"cast([fp + (-5)] + 3, felt*)"}],"type":"reference"},"starkware.starknet.common.syscalls.storage_write.value":{"cairo_type":"felt","full_name":"starkware.starknet.common.syscalls.storage_write.value","references":[{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-3), felt*)]"}],"type":"reference"}},"main_scope":"__main__","prime":"0x800000000000011000000000000000000000000000000000000000000000001","reference_manager":{"references":[{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":1,"offset":0},"pc":3,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":1,"offset":0},"pc":5,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":1,"offset":0},"pc":5,"value":"cast([fp + (-5)] + 3, starkware.cairo.common.cairo_builtins.HashBuiltin*)"},{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":2,"offset":0},"pc":9,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":2,"offset":2},"pc":14,"value":"[cast(ap + (-2), starkware.cairo.common.memcpy.memcpy.LoopFrame*)]"},{"ap_tracking_data":{"group":2,"offset":2},"pc":14,"value":"[cast(ap + (-2), starkware.cairo.common.memcpy.memcpy.LoopFrame*)]"},{"ap_tracking_data":{"group":2,"offset":3},"pc":15,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":2,"offset":3},"pc":16,"value":"[cast(ap, felt*)]"},{"ap_tracking_data":{"group":2,"offset":3},"pc":16,"value":"cast(ap + 1, starkware.cairo.common.memcpy.memcpy.LoopFrame*)"},{"ap_tracking_data":{"group":3,"offset":0},"pc":24,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":4,"offset":0},"pc":29,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":4,"offset":0},"pc":29,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":4,"offset":0},"pc":30,"value":"cast([fp + (-4)] + 1, felt)"},{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":5,"offset":0},"pc":33,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":5,"offset":5},"pc":37,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":6,"offset":0},"pc":38,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":6,"offset":5},"pc":42,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":6,"offset":14},"pc":46,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast([fp + (-4)], felt*)]"},{"ap_tracking_data":{"group":7,"offset":0},"pc":47,"value":"[cast([fp + (-4)] + 1, felt*)]"},{"ap_tracking_data":{"group":7,"offset":1},"pc":49,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":2},"pc":50,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":3},"pc":51,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":4},"pc":53,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":5},"pc":55,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":6},"pc":56,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":7,"offset":6},"pc":57,"value":"cast([fp + (-4)] + 3, felt)"},{"ap_tracking_data":{"group":8,"offset":0},"pc":60,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":8,"offset":0},"pc":60,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":8,"offset":1},"pc":62,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":1},"pc":64,"value":"cast([fp + (-3)] + 106710729501573572985208420194530329073740042555888586719489, felt)"},{"ap_tracking_data":{"group":8,"offset":1},"pc":64,"value":"cast((-1) - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":8,"offset":12},"pc":69,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":13},"pc":71,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":75,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":2},"pc":80,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":13},"pc":86,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":90,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":98,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":8,"offset":24},"pc":98,"value":"[cast(ap - 0 + (-1), felt*)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":9,"offset":0},"pc":100,"value":"[cast([fp + (-7)], starkware.starknet.common.syscalls.CallContract*)]"},{"ap_tracking_data":{"group":9,"offset":1},"pc":102,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":9,"offset":1},"pc":107,"value":"[cast([fp + (-7)] + 5, starkware.starknet.common.syscalls.CallContractResponse*)]"},{"ap_tracking_data":{"group":9,"offset":1},"pc":107,"value":"cast([fp + (-7)] + 7, felt*)"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":10,"offset":0},"pc":112,"value":"[cast([fp + (-7)], starkware.starknet.common.syscalls.CallContract*)]"},{"ap_tracking_data":{"group":10,"offset":1},"pc":114,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":10,"offset":1},"pc":119,"value":"[cast([fp + (-7)] + 5, starkware.starknet.common.syscalls.CallContractResponse*)]"},{"ap_tracking_data":{"group":10,"offset":1},"pc":119,"value":"cast([fp + (-7)] + 7, felt*)"},{"ap_tracking_data":{"group":11,"offset":0},"pc":124,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":11,"offset":0},"pc":124,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetCallerAddress*)]"},{"ap_tracking_data":{"group":11,"offset":1},"pc":126,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":11,"offset":1},"pc":127,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":12,"offset":0},"pc":131,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":12,"offset":0},"pc":131,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetSequencerAddress*)]"},{"ap_tracking_data":{"group":12,"offset":1},"pc":133,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":12,"offset":1},"pc":134,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":13,"offset":0},"pc":138,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":13,"offset":0},"pc":138,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetContractAddress*)]"},{"ap_tracking_data":{"group":13,"offset":1},"pc":140,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":13,"offset":1},"pc":141,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":14,"offset":0},"pc":145,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":14,"offset":0},"pc":145,"value":"[cast([fp + (-3)], starkware.starknet.common.syscalls.GetTxSignature*)]"},{"ap_tracking_data":{"group":14,"offset":1},"pc":147,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":14,"offset":1},"pc":148,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":15,"offset":0},"pc":153,"value":"[cast([fp + (-4)], starkware.starknet.common.syscalls.StorageRead*)]"},{"ap_tracking_data":{"group":15,"offset":1},"pc":155,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":15,"offset":1},"pc":157,"value":"[cast([fp + (-4)] + 2, starkware.starknet.common.syscalls.StorageReadResponse*)]"},{"ap_tracking_data":{"group":15,"offset":1},"pc":157,"value":"cast([fp + (-4)] + 3, felt*)"},{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":16,"offset":0},"pc":161,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":16,"offset":1},"pc":163,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":16,"offset":1},"pc":166,"value":"cast([fp + (-5)] + 3, felt*)"},{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":169,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"[cast([fp + (-5)] + 4, felt*)]"},{"ap_tracking_data":{"group":17,"offset":0},"pc":171,"value":"cast([fp + (-5)] + 5, starkware.cairo.common.cairo_builtins.BitwiseBuiltin*)"},{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":19,"offset":0},"pc":176,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":19,"offset":1},"pc":178,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":19,"offset":1},"pc":182,"value":"cast([fp + (-6)] + 4, felt*)"},{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":20,"offset":0},"pc":185,"value":"cast(1090342827190808580885637187050034007524108436288464842432620195147420788107, felt)"},{"ap_tracking_data":{"group":20,"offset":7},"pc":191,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":20,"offset":7},"pc":191,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":20,"offset":36},"pc":195,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":20,"offset":36},"pc":195,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":21,"offset":0},"pc":199,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":21,"offset":44},"pc":204,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":51},"pc":208,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":21,"offset":51},"pc":208,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":58},"pc":213,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":21,"offset":58},"pc":213,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":59},"pc":214,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":21,"offset":60},"pc":215,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":21,"offset":61},"pc":216,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":62},"pc":217,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":21,"offset":63},"pc":218,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-4), (felt, felt)*)]"},{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-7), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":22,"offset":0},"pc":219,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":22,"offset":44},"pc":224,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":22,"offset":51},"pc":229,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":22,"offset":57},"pc":234,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-7), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":23,"offset":0},"pc":237,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":23,"offset":69},"pc":245,"value":"[cast(ap + (-2), (felt, felt)*)]"},{"ap_tracking_data":{"group":23,"offset":70},"pc":246,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":23,"offset":71},"pc":247,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":23,"offset":138},"pc":255,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":24,"offset":0},"pc":256,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":24,"offset":1},"pc":257,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":2},"pc":258,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":2},"pc":259,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":24,"offset":2},"pc":259,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":24,"offset":3},"pc":261,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":4},"pc":262,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":5},"pc":263,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":24,"offset":5},"pc":263,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":24,"offset":6},"pc":265,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":24,"offset":152},"pc":275,"value":"[cast(ap + 0, __main__.advance_counter.Return*)]"},{"ap_tracking_data":{"group":24,"offset":153},"pc":277,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":24,"offset":153},"pc":277,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":25,"offset":0},"pc":285,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":25,"offset":7},"pc":290,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":26,"offset":0},"pc":293,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":26,"offset":1},"pc":295,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":26,"offset":17},"pc":303,"value":"[cast(ap + 0, __main__.constructor.Return*)]"},{"ap_tracking_data":{"group":26,"offset":18},"pc":305,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":26,"offset":18},"pc":305,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-9), felt**)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-8), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":27,"offset":0},"pc":313,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":27,"offset":69},"pc":319,"value":"[cast(ap + (-2), (felt, felt)*)]"},{"ap_tracking_data":{"group":27,"offset":76},"pc":324,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":76},"pc":324,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":27,"offset":83},"pc":329,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":83},"pc":329,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":27,"offset":150},"pc":337,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-5)] + 3, starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"[cast([fp + (-3)], __main__.IndexAndValues*)]"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":28,"offset":0},"pc":339,"value":"cast([fp + (-3)] + 3 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":28,"offset":1},"pc":341,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-4), felt**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.BitwiseBuiltin**)]"},{"ap_tracking_data":{"group":28,"offset":161},"pc":351,"value":"[cast(ap + 0, __main__.xor_counters.Return*)]"},{"ap_tracking_data":{"group":28,"offset":162},"pc":353,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":28,"offset":162},"pc":353,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"},{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":29,"offset":0},"pc":361,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":365,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":29,"offset":4},"pc":366,"value":"cast(fp + (-5), felt*)"},{"ap_tracking_data":{"group":29,"offset":4},"pc":369,"value":"cast([fp] + 3, felt*)"},{"ap_tracking_data":{"group":29,"offset":5},"pc":371,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":29,"offset":16},"pc":379,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-5), __main__.IndexAndValues*)]"},{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":30,"offset":0},"pc":382,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":30,"offset":26},"pc":390,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":30,"offset":26},"pc":390,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"[cast([fp + (-3)] + 1, __main__.IndexAndValues*)]"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 4, felt*)"},{"ap_tracking_data":{"group":31,"offset":0},"pc":391,"value":"cast([fp + (-3)] + 4 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":31,"offset":1},"pc":393,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":31,"offset":35},"pc":402,"value":"[cast(ap + 0, __main__.call_xor_counters.Return*)]"},{"ap_tracking_data":{"group":31,"offset":36},"pc":404,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":31,"offset":36},"pc":404,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-6), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":32,"offset":0},"pc":412,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":32,"offset":7},"pc":415,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-5), felt**)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":32,"offset":76},"pc":423,"value":"[cast(ap + (-2), (felt, felt)*)]"},{"ap_tracking_data":{"group":32,"offset":77},"pc":424,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":32,"offset":78},"pc":425,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":32,"offset":145},"pc":433,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":33,"offset":0},"pc":435,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":33,"offset":1},"pc":437,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":33,"offset":153},"pc":444,"value":"[cast(ap + 0, __main__.add_signature_to_counters.Return*)]"},{"ap_tracking_data":{"group":33,"offset":154},"pc":446,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":33,"offset":154},"pc":446,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":34,"offset":0},"pc":454,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":34,"offset":7},"pc":459,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":35,"offset":0},"pc":460,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":35,"offset":1},"pc":462,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":35,"offset":13},"pc":468,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":35,"offset":13},"pc":468,"value":"[cast(ap + 0, __main__.set_value.Return*)]"},{"ap_tracking_data":{"group":35,"offset":14},"pc":470,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":35,"offset":14},"pc":470,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":36,"offset":0},"pc":478,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":36,"offset":0},"pc":478,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":36,"offset":7},"pc":482,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":36,"offset":7},"pc":482,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":37,"offset":0},"pc":483,"value":"[cast(fp + (-4), __main__.get_value.Return*)]"},{"ap_tracking_data":{"group":37,"offset":0},"pc":483,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":37,"offset":1},"pc":485,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":37,"offset":1},"pc":485,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":37,"offset":1},"pc":486,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":37,"offset":2},"pc":488,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":38,"offset":0},"pc":492,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":38,"offset":1},"pc":494,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":38,"offset":12},"pc":499,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":38,"offset":12},"pc":499,"value":"[cast(ap + (-1), __main__.get_value.Return*)]"},{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":38,"offset":20},"pc":502,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":39,"offset":0},"pc":509,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":39,"offset":0},"pc":509,"value":"[cast(fp + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":39,"offset":7},"pc":514,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":39,"offset":7},"pc":514,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":39,"offset":14},"pc":521,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":39,"offset":20},"pc":525,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":39,"offset":20},"pc":525,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":40,"offset":0},"pc":530,"value":"cast([fp + (-3)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":40,"offset":26},"pc":535,"value":"[cast(ap + 0, __main__.entry_point.Return*)]"},{"ap_tracking_data":{"group":40,"offset":27},"pc":537,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":40,"offset":27},"pc":537,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":41,"offset":0},"pc":545,"value":"[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":41,"offset":0},"pc":545,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":41,"offset":19},"pc":552,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":41,"offset":26},"pc":559,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":41,"offset":26},"pc":559,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":42,"offset":0},"pc":565,"value":"[cast(fp + (-4), __main__.test_builtins.Return*)]"},{"ap_tracking_data":{"group":42,"offset":0},"pc":565,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":42,"offset":1},"pc":567,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":42,"offset":1},"pc":567,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":42,"offset":1},"pc":568,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":42,"offset":2},"pc":570,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)], felt*)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":43,"offset":0},"pc":574,"value":"cast([fp + (-3)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":43,"offset":33},"pc":579,"value":"[cast(ap + (-1), __main__.test_builtins.Return*)]"},{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-3), felt*)]"},{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":43,"offset":41},"pc":582,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":44,"offset":0},"pc":589,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":44,"offset":0},"pc":589,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":44,"offset":2},"pc":595,"value":"[cast(fp, (felt, felt)*)]"},{"ap_tracking_data":{"group":44,"offset":4},"pc":597,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":44,"offset":12},"pc":604,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":45,"offset":0},"pc":605,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":45,"offset":1},"pc":607,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":45,"offset":17},"pc":612,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":45,"offset":17},"pc":612,"value":"[cast(ap + 0, __main__.send_message.Return*)]"},{"ap_tracking_data":{"group":45,"offset":18},"pc":614,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":45,"offset":18},"pc":614,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":46,"offset":0},"pc":622,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":46,"offset":11},"pc":629,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"[cast([fp + (-3)] + 2, felt*)]"},{"ap_tracking_data":{"group":47,"offset":0},"pc":631,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":47,"offset":1},"pc":632,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":47,"offset":2},"pc":633,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":47,"offset":2},"pc":634,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":47,"offset":2},"pc":634,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":47,"offset":3},"pc":636,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":47,"offset":4},"pc":637,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":47,"offset":5},"pc":638,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":47,"offset":5},"pc":638,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":47,"offset":24},"pc":647,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":47,"offset":24},"pc":647,"value":"[cast(ap + 0, __main__.test_call_contract.Return*)]"},{"ap_tracking_data":{"group":47,"offset":25},"pc":649,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":47,"offset":25},"pc":649,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":47,"offset":26},"pc":650,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":48,"offset":0},"pc":659,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":48,"offset":11},"pc":666,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"[cast([fp + (-3)] + 2, felt*)]"},{"ap_tracking_data":{"group":49,"offset":0},"pc":668,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":49,"offset":1},"pc":669,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":49,"offset":2},"pc":670,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":49,"offset":2},"pc":671,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":49,"offset":2},"pc":671,"value":"cast([fp + (-3)] + 3, felt*)"},{"ap_tracking_data":{"group":49,"offset":3},"pc":673,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":49,"offset":4},"pc":674,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":49,"offset":5},"pc":675,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":49,"offset":5},"pc":675,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":49,"offset":24},"pc":684,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":49,"offset":24},"pc":684,"value":"[cast(ap + 0, __main__.test_delegate_call.Return*)]"},{"ap_tracking_data":{"group":49,"offset":25},"pc":686,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":49,"offset":25},"pc":686,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":49,"offset":26},"pc":687,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":50,"offset":0},"pc":696,"value":"[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":50,"offset":3},"pc":698,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":50,"offset":4},"pc":701,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":50,"offset":150},"pc":711,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":51,"offset":0},"pc":715,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":51,"offset":1},"pc":717,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]"},{"ap_tracking_data":{"group":51,"offset":161},"pc":725,"value":"[cast(ap + 0, __main__.deposit.Return*)]"},{"ap_tracking_data":{"group":51,"offset":162},"pc":727,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":51,"offset":162},"pc":727,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":52,"offset":0},"pc":735,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":52,"offset":0},"pc":735,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":52,"offset":6},"pc":738,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":52,"offset":6},"pc":738,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":53,"offset":0},"pc":741,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":53,"offset":1},"pc":743,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":53,"offset":12},"pc":748,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":53,"offset":12},"pc":748,"value":"[cast(ap + 0, __main__.test_get_caller_address.Return*)]"},{"ap_tracking_data":{"group":53,"offset":13},"pc":750,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":53,"offset":13},"pc":750,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":54,"offset":0},"pc":758,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":54,"offset":0},"pc":758,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":54,"offset":6},"pc":761,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":54,"offset":6},"pc":761,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":55,"offset":0},"pc":764,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":55,"offset":1},"pc":766,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":55,"offset":12},"pc":771,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":55,"offset":12},"pc":771,"value":"[cast(ap + 0, __main__.test_get_sequencer_address.Return*)]"},{"ap_tracking_data":{"group":55,"offset":13},"pc":773,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":55,"offset":13},"pc":773,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":56,"offset":0},"pc":781,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":56,"offset":0},"pc":781,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":56,"offset":6},"pc":784,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":56,"offset":6},"pc":784,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":57,"offset":0},"pc":787,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":57,"offset":1},"pc":789,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":57,"offset":12},"pc":794,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":57,"offset":12},"pc":794,"value":"[cast(ap + 0, __main__.test_get_contract_address.Return*)]"},{"ap_tracking_data":{"group":57,"offset":13},"pc":796,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":57,"offset":13},"pc":796,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":58,"offset":0},"pc":804,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":58,"offset":12},"pc":810,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":58,"offset":17},"pc":812,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":58,"offset":17},"pc":812,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":59,"offset":0},"pc":822,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":59,"offset":0},"pc":822,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":59,"offset":11},"pc":826,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":59,"offset":11},"pc":826,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":60,"offset":0},"pc":834,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":61,"offset":0},"pc":839,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":61,"offset":1},"pc":841,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":62,"offset":0},"pc":848,"value":"[cast(ap + 0, __main__.test_call_storage_consistency.Return*)]"},{"ap_tracking_data":{"group":62,"offset":1},"pc":850,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":62,"offset":1},"pc":850,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":63,"offset":0},"pc":858,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":63,"offset":12},"pc":865,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":64,"offset":0},"pc":870,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":64,"offset":0},"pc":870,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":64,"offset":11},"pc":875,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":64,"offset":11},"pc":875,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":65,"offset":0},"pc":884,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":65,"offset":1},"pc":886,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":66,"offset":0},"pc":890,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":66,"offset":1},"pc":892,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":67,"offset":0},"pc":899,"value":"[cast(ap + 0, __main__.test_re_entrance.Return*)]"},{"ap_tracking_data":{"group":67,"offset":1},"pc":901,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":67,"offset":1},"pc":901,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-5), felt**)]"},{"ap_tracking_data":{"group":68,"offset":0},"pc":909,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":68,"offset":6},"pc":912,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":68,"offset":6},"pc":912,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":69,"offset":0},"pc":921,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":69,"offset":0},"pc":921,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":69,"offset":1},"pc":923,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":69,"offset":13},"pc":929,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":70,"offset":0},"pc":931,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":70,"offset":1},"pc":933,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":71,"offset":0},"pc":939,"value":"[cast(ap + 0, __main__.add_value.Return*)]"},{"ap_tracking_data":{"group":71,"offset":1},"pc":941,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":71,"offset":1},"pc":941,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":72,"offset":0},"pc":949,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":73,"offset":0},"pc":959,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":74,"offset":0},"pc":966,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":74,"offset":0},"pc":966,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":74,"offset":16},"pc":970,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":75,"offset":0},"pc":972,"value":"cast([fp + (-3)] + 2 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":75,"offset":1},"pc":974,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":76,"offset":0},"pc":981,"value":"[cast(ap + 0, __main__.recursive_add_value.Return*)]"},{"ap_tracking_data":{"group":76,"offset":1},"pc":983,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":76,"offset":1},"pc":983,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":77,"offset":0},"pc":991,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":77,"offset":0},"pc":991,"value":"[cast(fp + (-4), felt**)]"},{"ap_tracking_data":{"group":77,"offset":7},"pc":995,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":77,"offset":7},"pc":995,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":77,"offset":14},"pc":1001,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":78,"offset":0},"pc":1002,"value":"cast([fp + (-3)] + 1 - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":78,"offset":1},"pc":1004,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":78,"offset":19},"pc":1009,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":78,"offset":19},"pc":1009,"value":"[cast(ap + 0, __main__.increase_value.Return*)]"},{"ap_tracking_data":{"group":78,"offset":20},"pc":1011,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":78,"offset":20},"pc":1011,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":79,"offset":0},"pc":1019,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":80,"offset":0},"pc":1033,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":80,"offset":0},"pc":1033,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)], felt**)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 1, felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 2, felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-5)] + 3, felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-3)], felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"cast([fp + (-3)] + 1, felt*)"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"[cast([fp + (-3)] + 1, felt*)]"},{"ap_tracking_data":{"group":81,"offset":0},"pc":1034,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":81,"offset":1},"pc":1035,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":81,"offset":2},"pc":1036,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":81,"offset":2},"pc":1037,"value":"cast([[fp + (-5)] + 2] + 1, felt)"},{"ap_tracking_data":{"group":81,"offset":2},"pc":1037,"value":"cast([fp + (-3)] + 2, felt*)"},{"ap_tracking_data":{"group":81,"offset":3},"pc":1039,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":81,"offset":4},"pc":1040,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":81,"offset":5},"pc":1041,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":81,"offset":5},"pc":1041,"value":"cast([ap + (-1)] - [fp + (-3)], felt)"},{"ap_tracking_data":{"group":81,"offset":6},"pc":1043,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + (-2), felt**)]"},{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":82,"offset":0},"pc":1052,"value":"[cast(ap + 0, __main__.test_call_with_array.Return*)]"},{"ap_tracking_data":{"group":82,"offset":1},"pc":1054,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":82,"offset":1},"pc":1054,"value":"cast(0, felt)"},{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":83,"offset":0},"pc":1062,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1066,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1067,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1067,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1068,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":83,"offset":4},"pc":1069,"value":"cast([fp] + 2, felt*)"},{"ap_tracking_data":{"group":83,"offset":5},"pc":1071,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":83,"offset":16},"pc":1079,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":84,"offset":0},"pc":1082,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1086,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1087,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1087,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":84,"offset":4},"pc":1088,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":84,"offset":5},"pc":1090,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"[cast([ap + (-1)], felt*)]"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"cast([ap + (-1)] + 1, felt*)"},{"ap_tracking_data":{"group":84,"offset":16},"pc":1098,"value":"cast([ap + (-1)] + 1 - [ap + (-1)], felt)"},{"ap_tracking_data":{"group":84,"offset":17},"pc":1100,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-6), felt**)]"},{"ap_tracking_data":{"group":85,"offset":0},"pc":1105,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1109,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1110,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1110,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":85,"offset":4},"pc":1111,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":85,"offset":5},"pc":1113,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":85,"offset":16},"pc":1121,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-3), felt*)]"},{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-7), felt**)]"},{"ap_tracking_data":{"group":86,"offset":0},"pc":1124,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1128,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1129,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1129,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1130,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":86,"offset":4},"pc":1131,"value":"cast([fp] + 2, felt*)"},{"ap_tracking_data":{"group":86,"offset":5},"pc":1133,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":86,"offset":16},"pc":1141,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-6), felt*)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-5), felt*)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-4), felt*)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-3), felt**)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-8), felt**)]"},{"ap_tracking_data":{"group":87,"offset":0},"pc":1144,"value":"[cast(fp + (-7), felt*)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1148,"value":"[cast(ap + (-1), felt**)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1149,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1149,"value":"[cast(fp, felt**)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1150,"value":"cast([fp] + 1, felt*)"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1151,"value":"cast([fp] + 2, felt*)"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1154,"value":"[cast(fp + 1, felt*)]"},{"ap_tracking_data":{"group":87,"offset":6},"pc":1154,"value":"cast([fp] + 2, felt*)"},{"ap_tracking_data":{"group":87,"offset":7},"pc":1156,"value":"[cast(ap + (-1), felt*)]"},{"ap_tracking_data":{"group":87,"offset":7},"pc":1157,"value":"[cast(fp + 2, felt**)]"},{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-3), felt**)]"},{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-2), felt*)]"},{"ap_tracking_data":{"group":88,"offset":11},"pc":1171,"value":"[cast(ap + (-1), felt**)]"}]}} \ No newline at end of file diff --git a/crates/papyrus_storage/src/base_layer.rs b/crates/papyrus_storage/src/base_layer.rs new file mode 100644 index 00000000000..ea5e844e71a --- /dev/null +++ b/crates/papyrus_storage/src/base_layer.rs @@ -0,0 +1,97 @@ +//! Interface for handling data related to the base layer. +//! +//! The base layer is the blockchain that is used for the final verification of the StarkNet state. +//! +//! The common use case is Ethereum, but it can be other blockchains as well (including another +//! Starknet network). +//! +//! Import [`BaseLayerStorageReader`] and [`BaseLayerStorageWriter`] to read and write data related +//! to the base layer using a [`StorageTxn`]. +//! # Example +//! ``` +//! use papyrus_storage::base_layer::{BaseLayerStorageReader, BaseLayerStorageWriter}; +//! use papyrus_storage::open_storage; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! use starknet_api::block::BlockNumber; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .update_base_layer_block_marker(&BlockNumber(3))? //Update the base layer block marker. +//! .commit()?; // Commit the transaction. +//! let block_number = reader.begin_ro_txn()?.get_base_layer_block_marker()?; +//! assert_eq!(block_number, BlockNumber(3)); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` +#[cfg(test)] +#[path = "base_layer_test.rs"] +mod base_layer_test; + +use starknet_api::block::BlockNumber; + +use crate::db::table_types::Table; +use crate::db::{TransactionKind, RW}; +use crate::{MarkerKind, StorageResult, StorageTxn}; + +/// Interface for reading data related to the base layer. +pub trait BaseLayerStorageReader { + /// The block number marker is the first block number that doesn't exist yet in the base layer. + fn get_base_layer_block_marker(&self) -> StorageResult; +} + +/// Interface for writing data related to the base layer. +pub trait BaseLayerStorageWriter +where + Self: Sized, +{ + /// Updates the block marker of the base layer. + // To enforce that no commit happen after a failure, we consume and return Self on success. + fn update_base_layer_block_marker(self, block_number: &BlockNumber) -> StorageResult; + + /// When reverting a block, if the base layer marker points to the block afterward, revert the + /// marker. + fn try_revert_base_layer_marker( + self, + reverted_block_number: BlockNumber, + ) -> StorageResult; +} + +impl<'env, Mode: TransactionKind> BaseLayerStorageReader for StorageTxn<'env, Mode> { + fn get_base_layer_block_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::BaseLayerBlock)?.unwrap_or_default()) + } +} + +impl<'env> BaseLayerStorageWriter for StorageTxn<'env, RW> { + fn update_base_layer_block_marker(self, block_number: &BlockNumber) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + markers_table.upsert(&self.txn, &MarkerKind::BaseLayerBlock, block_number)?; + Ok(self) + } + + fn try_revert_base_layer_marker( + self, + reverted_block_number: BlockNumber, + ) -> StorageResult { + let cur_marker = self.get_base_layer_block_marker()?; + // Revert only if we revert a block that is the last block in the base layer we know about. + if cur_marker == reverted_block_number.unchecked_next() { + Ok(self.update_base_layer_block_marker(&reverted_block_number)?) + } else { + Ok(self) + } + } +} diff --git a/crates/papyrus_storage/src/base_layer_test.rs b/crates/papyrus_storage/src/base_layer_test.rs new file mode 100644 index 00000000000..9b038fe39d3 --- /dev/null +++ b/crates/papyrus_storage/src/base_layer_test.rs @@ -0,0 +1,52 @@ +use starknet_api::block::BlockNumber; + +use crate::base_layer::{BaseLayerStorageReader, BaseLayerStorageWriter}; +use crate::test_utils::get_test_storage; + +#[tokio::test] +async fn rw_base_layer_tip_marker() { + let (reader, mut writer) = get_test_storage().0; + + // Initial tip. + let initial_tip = reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + assert_eq!(initial_tip, BlockNumber(0)); + + // Update tip. + writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&BlockNumber(5)) + .unwrap() + .commit() + .unwrap(); + let updated_tip = reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + assert_eq!(updated_tip, BlockNumber(5)); +} + +#[test] +fn try_revert_base_layer_marker() { + let (reader, mut writer) = get_test_storage().0; + + writer + .begin_rw_txn() + .unwrap() + .update_base_layer_block_marker(&BlockNumber(2)) + .unwrap() + .try_revert_base_layer_marker(BlockNumber(2)) + .unwrap() + .commit() + .unwrap(); + + let cur_marker = reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + assert_eq!(cur_marker, BlockNumber(2)); + + writer + .begin_rw_txn() + .unwrap() + .try_revert_base_layer_marker(BlockNumber(1)) + .unwrap() + .commit() + .unwrap(); + let cur_marker = reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + assert_eq!(cur_marker, BlockNumber(1)); +} diff --git a/crates/papyrus_storage/src/bin/README.md b/crates/papyrus_storage/src/bin/README.md new file mode 100644 index 00000000000..72496f4d19b --- /dev/null +++ b/crates/papyrus_storage/src/bin/README.md @@ -0,0 +1,41 @@ +# Dump Declared Classes Tool + +This tool allows you to dump the entire `declared_classes` table from Papyrus storage into a file. + +## Instructions + +1. **Run a Docker** + Please refer to the main [README](../../../../README.adoc#running-papyrus-with-docker) for instructions. + + Note: use a released Docker image + +3. **View Running Docker Containers** + + ```bash + docker ps + ``` + You can also view the logs produced by the full node with: + + ```bash + docker logs + ``` + +4. **Sync the Full Node** + + The full node sync could take a few hours/days. Once it's partially or fully synced, you can run the tool to dump the declared classes into a file. + +5. **Access the Docker Container** + + ```bash + docker exec -ti sh + ``` + +6. **Run the Tool** + + ```bash + target/release/dump_declared_classes --start_block --end_block --chain_id [--file_path file_path] + ``` + + The default value for file_path is `dump_declared_classes.json`. + + diff --git a/crates/papyrus_storage/src/bin/dump_declared_classes.rs b/crates/papyrus_storage/src/bin/dump_declared_classes.rs new file mode 100644 index 00000000000..80c43999cee --- /dev/null +++ b/crates/papyrus_storage/src/bin/dump_declared_classes.rs @@ -0,0 +1,79 @@ +use clap::{Arg, Command}; +use papyrus_storage::utils::dump_declared_classes_table_by_block_range; +use starknet_api::core::ChainId; + +/// This executable dumps the declared_classes table from the storage to a file. +fn main() { + let cli_params = get_cli_params(); + match dump_declared_classes_table_by_block_range( + cli_params.start_block, + cli_params.end_block, + &cli_params.file_path, + &cli_params.chain_id, + ) { + Ok(_) => println!("Dumped declared_classes table to file: {} .", cli_params.file_path), + Err(e) => println!("Failed dumping declared_classes table with error: {}", e), + } +} + +struct CliParams { + start_block: u64, + end_block: u64, + file_path: String, + chain_id: ChainId, +} + +/// The start_block and end_block arguments are mandatory and define the block range to dump, +/// start_block is inclusive and end_block is exclusive. The file_path is an optional parameter, +/// otherwise the data will be dumped to "dump_declared_classes.json". +fn get_cli_params() -> CliParams { + let matches = Command::new("Dump declared classes") + .arg( + Arg::new("file_path") + .short('f') + .long("file_path") + .default_value("dump_declared_classes.json") + .help("The file path to dump the declared classes table to."), + ) + .arg( + Arg::new("start_block") + .short('s') + .long("start_block") + .required(true) + .help("The block number to start dumping from."), + ) + .arg( + Arg::new("end_block") + .short('e') + .long("end_block") + .required(true) + .help("The block number to end dumping at."), + ) + .arg( + Arg::new("chain_id") + .short('c') + .long("chain_id") + .required(true) + .help("The chain id SN_MAIN/SN_SEPOLIA, default value is SN_MAIN."), + ) + .get_matches(); + + let file_path = + matches.get_one::("file_path").expect("Failed parsing file_path").to_string(); + let start_block = matches + .get_one::("start_block") + .expect("Failed parsing start_block") + .parse::() + .expect("Failed parsing start_block"); + let end_block = matches + .get_one::("end_block") + .expect("Failed parsing end_block") + .parse::() + .expect("Failed parsing end_block"); + if start_block >= end_block { + panic!("start_block must be smaller than end_block"); + } + let chain_id = + matches.get_one::("chain_id").expect("Failed parsing chain_id").to_string(); + CliParams { start_block, end_block, file_path, chain_id: ChainId::Other(chain_id) } +} diff --git a/crates/papyrus_storage/src/bin/storage_benchmark.rs b/crates/papyrus_storage/src/bin/storage_benchmark.rs new file mode 100644 index 00000000000..61da955958d --- /dev/null +++ b/crates/papyrus_storage/src/bin/storage_benchmark.rs @@ -0,0 +1,213 @@ +use std::fs::{read_to_string, File}; +use std::time::Duration; + +use clap::{Arg, Command}; +use papyrus_common::storage_query::StorageQuery; +use papyrus_storage::db::DbConfig; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::StorageConfig; +use serde::{Deserialize, Serialize}; +use starknet_api::core::ChainId; +use statistical::median; + +// TODO(dvir): consider add logger and use it for the prints. +// TODO(dvir): add this to the readme of the binaries and/or consider reordering the binaries. +// TODO(dvir): consider adding tests. + +pub fn main() { + let cli_params = get_cli_params(); + + // Creates List of queries to be executed. + println!("Creating queries"); + let mut queries: Vec = Vec::new(); + for line in read_to_string(cli_params.queries_file_path) + .expect("Should be able to read the queries file") + .lines() + { + queries + .push(serde_json::from_str(line).expect("Query should be a valid query json object")); + } + + // Open storage to execute the queries. + println!("Opening storage"); + let db_config = DbConfig { + path_prefix: cli_params.db_path.into(), + chain_id: cli_params.chain_id, + ..Default::default() + }; + let config = StorageConfig { db_config, ..Default::default() }; + + let (reader, mut _writer) = + papyrus_storage::open_storage(config).expect("Should be able to open storage"); + let txn = reader.begin_ro_txn().expect("Should be able to begin read only transaction"); + let state_reader = txn.get_state_reader().expect("Should be able to get state reader"); + + let mut times = Times::default(); + + // Execute the queries and measure the time it takes to execute them. + println!("Executing queries"); + for q in queries { + let exec_time; + match q { + StorageQuery::GetClassHashAt(state_number, contract_address) => { + let now = std::time::Instant::now(); + let _class_hash = state_reader.get_class_hash_at(state_number, &contract_address); + exec_time = now.elapsed(); + times.get_class_hash_at.push(exec_time); + } + StorageQuery::GetNonceAt(state_number, contract_address) => { + let now = std::time::Instant::now(); + let _nonce = state_reader.get_nonce_at(state_number, &contract_address); + exec_time = now.elapsed(); + times.get_nonce_at.push(exec_time); + } + StorageQuery::GetStorageAt(state_number, contract_address, storage_key) => { + let now = std::time::Instant::now(); + let _storage = + state_reader.get_storage_at(state_number, &contract_address, &storage_key); + exec_time = now.elapsed(); + times.get_storage_at.push(exec_time); + } + } + println!("{}", serde_json::to_string(&q).expect("Should be able to serialize the query")); + println!("time in microseconds: {}", exec_time.as_micros()); + } + + println!("Writing results to file"); + let results_file = File::create(cli_params.output_file_path) + .expect("Should be able to create the output file"); + let final_results = times.get_final_results(); + serde_json::to_writer(results_file, &final_results) + .expect("Should be able to write to the output file"); +} + +// Records the time it takes to execute the queries. +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +struct Times { + get_class_hash_at: Vec, + get_nonce_at: Vec, + get_storage_at: Vec, +} + +impl Times { + // Returns statics about the executing times of the queries in a format that can be use in + // github action. + fn get_final_results(&self) -> Vec { + let mut results: Vec = vec![]; + + let get_class_hash_at_median = if self.get_class_hash_at.is_empty() { + 0 + } else { + median(&self.get_class_hash_at.iter().map(|x| x.as_micros()).collect::>()) + }; + results.push(Entry { + name: "get_class_hash_at".to_string(), + unit: "Microseconds".to_string(), + value: get_class_hash_at_median as usize, + }); + + let get_nonce_at_median = if self.get_nonce_at.is_empty() { + 0 + } else { + median(&self.get_nonce_at.iter().map(|x| x.as_micros()).collect::>()) + }; + results.push(Entry { + name: "get_nonce_at".to_string(), + unit: "Microseconds".to_string(), + value: get_nonce_at_median as usize, + }); + + let get_storage_at_median = if self.get_storage_at.is_empty() { + 0 + } else { + median(&self.get_storage_at.iter().map(|x| x.as_micros()).collect::>()) + }; + + results.push(Entry { + name: "get_storage_at".to_string(), + unit: "Microseconds".to_string(), + value: get_storage_at_median as usize, + }); + + results + } + + #[allow(dead_code)] + fn print_times(&self) { + let get_class_hash_at_time_sum = self.get_class_hash_at.iter().sum::(); + let get_nonce_at_time_sum = self.get_nonce_at.iter().sum::(); + let get_storage_at_time_sum = self.get_storage_at.iter().sum::(); + + println!("Times:"); + println!(" - GetClassHashAt: {:?}", get_class_hash_at_time_sum.as_nanos()); + println!(" - GetNonceAt: {:?}", get_nonce_at_time_sum.as_nanos()); + println!(" - GetStorageAt: {:?}", get_storage_at_time_sum.as_nanos()); + println!( + " - total time: {:?}", + (get_class_hash_at_time_sum + get_nonce_at_time_sum + get_storage_at_time_sum) + .as_nanos() + ); + } +} + +// Represents a single entry in the results file. +#[derive(Debug, Clone, Default, Serialize)] +struct Entry { + name: String, + unit: String, + value: usize, +} + +struct CliParams { + queries_file_path: String, + db_path: String, + output_file_path: String, + chain_id: ChainId, +} + +fn get_cli_params() -> CliParams { + let matches = Command::new("Storage benchmark") + .arg( + Arg::new("queries_file_path") + .short('q') + .long("queries_file_path") + .required(true) + .help("The path to a file with the queries"), + ) + .arg( + Arg::new("db_path") + .short('d') + .long("db_path") + .required(true) + .help("The path to the database"), + ) + .arg( + Arg::new("output_file_path") + .short('o') + .long("output_file_path") + .required(true) + .help("The path to the output file"), + ) + .arg( + Arg::new("chain_id") + .short('c') + .long("chain_id") + .required(true) + .help("The chain id SN_MAIN/SN_SEPOLIA for example"), + ) + .get_matches(); + + let queries_file_path = matches + .get_one::("queries_file_path") + .expect("Missing queries_file_path") + .to_string(); + let db_path = matches.get_one::("db_path").expect("Missing db_path").to_string(); + let output_file_path = matches + .get_one::("output_file_path") + .expect("Missing output_file_path") + .to_string(); + let chain_id = + matches.get_one::("chain_id").expect("Missing parse chain_id").to_string(); + + CliParams { queries_file_path, db_path, output_file_path, chain_id: chain_id.into() } +} diff --git a/crates/papyrus_storage/src/body/body_test.rs b/crates/papyrus_storage/src/body/body_test.rs new file mode 100644 index 00000000000..fc0b2ac3424 --- /dev/null +++ b/crates/papyrus_storage/src/body/body_test.rs @@ -0,0 +1,413 @@ +use assert_matches::assert_matches; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockBody, BlockNumber}; +use starknet_api::transaction::TransactionOffsetInBlock; +use test_case::test_case; +use test_utils::{get_test_block, get_test_body}; + +use crate::body::{BodyStorageReader, BodyStorageWriter, TransactionIndex}; +use crate::db::table_types::Table; +use crate::db::{DbError, KeyAlreadyExistsError}; +use crate::test_utils::{get_test_storage, get_test_storage_by_scope}; +use crate::{OffsetKind, StorageError, StorageScope, StorageWriter}; + +#[tokio::test] +async fn append_body() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let body = get_test_block(10, None, None, None).body; + let txs = body.transactions; + let tx_outputs = body.transaction_outputs; + let tx_hashes = body.transaction_hashes; + + let body0 = BlockBody { + transactions: vec![txs[0].clone()], + transaction_outputs: vec![tx_outputs[0].clone()], + transaction_hashes: vec![tx_hashes[0]], + }; + let body1 = BlockBody::default(); + let body2 = BlockBody { + transactions: vec![txs[1].clone(), txs[2].clone()], + transaction_outputs: vec![tx_outputs[1].clone(), tx_outputs[2].clone()], + transaction_hashes: vec![tx_hashes[1], tx_hashes[2]], + }; + let body3 = BlockBody { + transactions: vec![txs[3].clone(), txs[0].clone()], + transaction_outputs: vec![tx_outputs[3].clone(), tx_outputs[0].clone()], + transaction_hashes: vec![tx_hashes[3], tx_hashes[0]], + }; + writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), body0) + .unwrap() + .append_body(BlockNumber(1), body1) + .unwrap() + .commit() + .unwrap(); + + // Check for MarkerMismatch error when trying to append the wrong block number. + let Err(err) = writer.begin_rw_txn().unwrap().append_body(BlockNumber(5), body2.clone()) else { + panic!("Unexpected Ok."); + }; + + assert_matches!( + err, + StorageError::MarkerMismatch { expected, found } + if expected == BlockNumber(2) && found == BlockNumber(5)); + + writer.begin_rw_txn().unwrap().append_body(BlockNumber(2), body2).unwrap().commit().unwrap(); + + let Err(err) = writer.begin_rw_txn().unwrap().append_body(BlockNumber(3), body3) else { + panic!("Unexpected Ok."); + }; + + let expected_tx_index = TransactionIndex(BlockNumber(3), TransactionOffsetInBlock(1)); + assert_matches!( + err, + StorageError::InnerError(DbError::KeyAlreadyExists(KeyAlreadyExistsError { + table_name: _, + key, + value + })) if key == format!("{:?}", tx_hashes[0]) && value == format!("{:?}", expected_tx_index) + ); + + let txn = reader.begin_ro_txn().unwrap(); + // Check marker. + assert_eq!(txn.get_body_marker().unwrap(), BlockNumber(3)); + + // Check single transactions, outputs and events. + let tx_cases = vec![ + (BlockNumber(0), TransactionOffsetInBlock(0), Some(0)), + (BlockNumber(0), TransactionOffsetInBlock(1), None), + (BlockNumber(1), TransactionOffsetInBlock(0), None), + (BlockNumber(2), TransactionOffsetInBlock(0), Some(1)), + (BlockNumber(2), TransactionOffsetInBlock(1), Some(2)), + (BlockNumber(2), TransactionOffsetInBlock(2), None), + ]; + + for (block_number, tx_offset, original_index) in tx_cases { + let expected_tx = original_index.map(|i| txs[i].clone()); + assert_eq!( + txn.get_transaction(TransactionIndex(block_number, tx_offset)).unwrap(), + expected_tx + ); + + let expected_tx_output = original_index.map(|i| tx_outputs[i].clone()); + assert_eq!( + txn.get_transaction_output(TransactionIndex(block_number, tx_offset)).unwrap(), + expected_tx_output + ); + } + + // Check transaction index by hash. + assert_eq!( + txn.get_transaction_idx_by_hash(&tx_hashes[0]).unwrap(), + Some(TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0))) + ); + assert_eq!( + txn.get_transaction_idx_by_hash(&tx_hashes[1]).unwrap(), + Some(TransactionIndex(BlockNumber(2), TransactionOffsetInBlock(0))) + ); + assert_eq!( + txn.get_transaction_idx_by_hash(&tx_hashes[2]).unwrap(), + Some(TransactionIndex(BlockNumber(2), TransactionOffsetInBlock(1))) + ); + + // Check transaction hash by index. + assert_eq!( + txn.get_transaction_hash_by_idx(&TransactionIndex( + BlockNumber(0), + TransactionOffsetInBlock(0) + )) + .unwrap(), + Some(tx_hashes[0]) + ); + assert_eq!( + txn.get_transaction_hash_by_idx(&TransactionIndex( + BlockNumber(2), + TransactionOffsetInBlock(0) + )) + .unwrap(), + Some(tx_hashes[1]) + ); + assert_eq!( + txn.get_transaction_hash_by_idx(&TransactionIndex( + BlockNumber(2), + TransactionOffsetInBlock(1) + )) + .unwrap(), + Some(tx_hashes[2]) + ); + + // Check block transactions. + assert_eq!(txn.get_block_transactions(BlockNumber(0)).unwrap(), Some(vec![txs[0].clone()])); + assert_eq!(txn.get_block_transactions(BlockNumber(1)).unwrap(), Some(vec![])); + assert_eq!( + txn.get_block_transactions(BlockNumber(2)).unwrap(), + Some(vec![txs[1].clone(), txs[2].clone(),]) + ); + assert_eq!(txn.get_block_transactions(BlockNumber(3)).unwrap(), None); + + // Check block transaction hashes. + assert_eq!(txn.get_block_transaction_hashes(BlockNumber(0)).unwrap(), Some(vec![tx_hashes[0]])); + assert_eq!(txn.get_block_transaction_hashes(BlockNumber(1)).unwrap(), Some(vec![])); + assert_eq!( + txn.get_block_transaction_hashes(BlockNumber(2)).unwrap(), + Some(vec![tx_hashes[1], tx_hashes[2]]) + ); + assert_eq!(txn.get_block_transaction_hashes(BlockNumber(3)).unwrap(), None); + + // Check block transaction outputs. + assert_eq!( + txn.get_block_transaction_outputs(BlockNumber(0)).unwrap(), + Some(vec![tx_outputs[0].clone()]) + ); + assert_eq!(txn.get_block_transaction_outputs(BlockNumber(1)).unwrap(), Some(vec![])); + assert_eq!( + txn.get_block_transaction_outputs(BlockNumber(2)).unwrap(), + Some(vec![tx_outputs[1].clone(), tx_outputs[2].clone(),]) + ); + assert_eq!(txn.get_block_transaction_outputs(BlockNumber(3)).unwrap(), None); + + // Check block transactions count. + assert_eq!(txn.get_block_transactions_count(BlockNumber(0)).unwrap(), Some(1)); + assert_eq!(txn.get_block_transactions_count(BlockNumber(1)).unwrap(), Some(0)); + assert_eq!(txn.get_block_transactions_count(BlockNumber(2)).unwrap(), Some(2)); + assert_eq!(txn.get_block_transactions_count(BlockNumber(3)).unwrap(), None); +} + +#[tokio::test] +async fn append_body_state_only() { + let ((reader, mut writer), _temp_dir) = get_test_storage_by_scope(StorageScope::StateOnly); + let block_body = get_test_block(1, Some(1), None, None).body; + + writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), block_body) + .unwrap() + .commit() + .unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + // Check marker. + assert_eq!(txn.get_body_marker().unwrap(), BlockNumber(1)); +} + +#[test_case(StorageScope::FullArchive; "revert non existing body fails full archive")] +#[test_case(StorageScope::StateOnly; "revert non existing body fails state only")] +#[tokio::test] +async fn revert_non_existing_body_fails(storage_scope: StorageScope) { + let ((_, mut writer), _temp_dir) = get_test_storage_by_scope(storage_scope); + let (_, deleted_data) = writer.begin_rw_txn().unwrap().revert_body(BlockNumber(5)).unwrap(); + assert!(deleted_data.is_none()); +} + +#[test_case(StorageScope::FullArchive; "revert last body success full archive")] +#[test_case(StorageScope::StateOnly; "revert last body success state only")] +#[tokio::test] +async fn revert_body_state_only(storage_scope: StorageScope) { + let ((_, mut writer), _temp_dir) = get_test_storage_by_scope(storage_scope); + writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .commit() + .unwrap(); + writer.begin_rw_txn().unwrap().revert_body(BlockNumber(0)).unwrap().0.commit().unwrap(); +} + +#[tokio::test] +async fn revert_old_body_fails() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + append_2_bodies(&mut writer); + let (_, deleted_data) = writer.begin_rw_txn().unwrap().revert_body(BlockNumber(0)).unwrap(); + assert!(deleted_data.is_none()); +} + +#[test_case(StorageScope::FullArchive; "revert body updates marker full archive")] +#[test_case(StorageScope::StateOnly; "revert body updates marker state only")] +#[tokio::test] +async fn revert_body_updates_marker(storage_scope: StorageScope) { + let ((reader, mut writer), _temp_dir) = get_test_storage_by_scope(storage_scope); + append_2_bodies(&mut writer); + + // Verify that the body marker before revert is 2. + assert_eq!(reader.begin_ro_txn().unwrap().get_body_marker().unwrap(), BlockNumber(2)); + + writer.begin_rw_txn().unwrap().revert_body(BlockNumber(1)).unwrap().0.commit().unwrap(); + assert_eq!(reader.begin_ro_txn().unwrap().get_body_marker().unwrap(), BlockNumber(1)); +} + +#[tokio::test] +async fn get_reverted_body_returns_none() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_bodies(&mut writer); + + // Verify that we can get block 1's transactions before the revert. + assert!( + reader.begin_ro_txn().unwrap().get_block_transactions(BlockNumber(1)).unwrap().is_some() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_hashes(BlockNumber(1)) + .unwrap() + .is_some() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_outputs(BlockNumber(1)) + .unwrap() + .is_some() + ); + + writer.begin_rw_txn().unwrap().revert_body(BlockNumber(1)).unwrap().0.commit().unwrap(); + assert!( + reader.begin_ro_txn().unwrap().get_block_transactions(BlockNumber(1)).unwrap().is_none() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_hashes(BlockNumber(1)) + .unwrap() + .is_none() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_outputs(BlockNumber(1)) + .unwrap() + .is_none() + ); +} + +#[tokio::test] +async fn revert_transactions() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let body = get_test_body(10, None, None, None); + writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), body.clone()) + .unwrap() + .commit() + .unwrap(); + + // Verify the data exists before revert. + for (offset, tx_hash) in body.transaction_hashes.clone().into_iter().enumerate() { + let tx_index = TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(offset)); + + assert!(reader.begin_ro_txn().unwrap().get_transaction(tx_index).unwrap().is_some()); + assert!(reader.begin_ro_txn().unwrap().get_transaction_output(tx_index).unwrap().is_some()); + assert_eq!( + reader.begin_ro_txn().unwrap().get_transaction_idx_by_hash(&tx_hash).unwrap().unwrap(), + tx_index + ); + assert_eq!( + reader.begin_ro_txn().unwrap().get_transaction_hash_by_idx(&tx_index).unwrap().unwrap(), + tx_hash + ); + } + assert!( + reader.begin_ro_txn().unwrap().get_block_transactions(BlockNumber(0)).unwrap().is_some() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_hashes(BlockNumber(0)) + .unwrap() + .is_some() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_outputs(BlockNumber(0)) + .unwrap() + .is_some() + ); + + writer.begin_rw_txn().unwrap().revert_body(BlockNumber(0)).unwrap().0.commit().unwrap(); + + // Check that all the transactions were deleted. + for (offset, tx_hash) in body.transaction_hashes.into_iter().enumerate() { + let tx_index = TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(offset)); + + assert!(reader.begin_ro_txn().unwrap().get_transaction(tx_index).unwrap().is_none()); + assert!(reader.begin_ro_txn().unwrap().get_transaction_output(tx_index).unwrap().is_none()); + assert!( + reader.begin_ro_txn().unwrap().get_transaction_idx_by_hash(&tx_hash).unwrap().is_none() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_transaction_hash_by_idx(&tx_index) + .unwrap() + .is_none() + ); + } + assert!( + reader.begin_ro_txn().unwrap().get_block_transactions(BlockNumber(0)).unwrap().is_none() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_hashes(BlockNumber(0)) + .unwrap() + .is_none() + ); + assert!( + reader + .begin_ro_txn() + .unwrap() + .get_block_transaction_outputs(BlockNumber(0)) + .unwrap() + .is_none() + ); +} + +fn append_2_bodies(writer: &mut StorageWriter) { + writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), BlockBody::default()) + .unwrap() + .append_body(BlockNumber(1), BlockBody::default()) + .unwrap() + .commit() + .unwrap(); +} + +#[test] +fn update_offset_table() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let body = get_test_block(3, None, None, None).body; + writer.begin_rw_txn().unwrap().append_body(BlockNumber(0), body).unwrap().commit().unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + let file_offset_table = txn.txn.open_table(&txn.tables.file_offsets).unwrap(); + let transaction_metadata_table = txn.txn.open_table(&txn.tables.transaction_metadata).unwrap(); + let last_tx_metadata = transaction_metadata_table + .get(&txn.txn, &TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(2))) + .unwrap() + .unwrap(); + + assert_eq!( + last_tx_metadata.tx_location.next_offset(), + file_offset_table.get(&txn.txn, &OffsetKind::Transaction).unwrap().unwrap() + ); + assert_eq!( + last_tx_metadata.tx_output_location.next_offset(), + file_offset_table.get(&txn.txn, &OffsetKind::TransactionOutput).unwrap().unwrap() + ); +} diff --git a/crates/papyrus_storage/src/body/events.rs b/crates/papyrus_storage/src/body/events.rs new file mode 100644 index 00000000000..ca45f35de73 --- /dev/null +++ b/crates/papyrus_storage/src/body/events.rs @@ -0,0 +1,365 @@ +//! Interface for iterating over events from the storage. +//! +//! Events are part of the transaction output. Each transaction output holds an array of events. +//! Import [`EventsReader`] to iterate over events using a read-only [`StorageTxn`]. +//! +//! # Example +//! ``` +//! use papyrus_storage::open_storage; +//! use papyrus_storage::body::TransactionIndex; +//! use papyrus_storage::body::events::{EventIndex, EventsReader}; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! # use starknet_api::block::BlockNumber; +//! use starknet_api::core::ContractAddress; +//! use starknet_api::transaction::TransactionOffsetInBlock; +//! use starknet_api::transaction::EventIndexInTransactionOutput; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! // The API allows read-only interactions with the events. To write events, use the body writer. +//! let (reader, mut writer) = open_storage(storage_config)?; +//! // iterate events from all contracts, starting from the first event in the first transaction. +//! let event_index = EventIndex( +//! TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)), +//! EventIndexInTransactionOutput(0), +//! ); +//! let txn = reader.begin_ro_txn()?; // The transaction must live longer than the iterator. +//! let events_iterator = txn.iter_events(None, event_index, BlockNumber(0))?; +//! for ((contract_address, event_index), event_content) in events_iterator { +//! // Do something with the event. +//! } +//! // iterate events from a specific contract. +//! let contract_events_iterator = txn.iter_events(Some(ContractAddress::default()), event_index, BlockNumber(0))?; +//! for ((contract_address, event_index), event_content) in contract_events_iterator { +//! // Do something with the event. +//! } +//! # Ok::<(), papyrus_storage::StorageError>(()) +#[cfg(test)] +#[path = "events_test.rs"] +mod events_test; + +use std::collections::VecDeque; + +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockNumber; +use starknet_api::core::ContractAddress; +use starknet_api::transaction::{ + Event, + EventContent, + EventIndexInTransactionOutput, + TransactionOutput, +}; + +use super::TransactionMetadataTable; +use crate::body::{EventsTableKey, TransactionIndex}; +use crate::db::serialization::{NoVersionValueWrapper, VersionZeroWrapper}; +use crate::db::table_types::{CommonPrefix, DbCursor, DbCursorTrait, NoValue, SimpleTable, Table}; +use crate::db::{DbTransaction, RO}; +use crate::{FileHandlers, StorageResult, StorageTxn, TransactionMetadata}; + +/// An identifier of an event. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +#[cfg_attr(any(test, feature = "testing"), derive(Hash))] +pub struct EventIndex(pub TransactionIndex, pub EventIndexInTransactionOutput); + +/// An interface for reading events. +pub trait EventsReader<'txn, 'env> { + /// Returns an iterator over events, which is a wrapper of two iterators. + /// If the address is none it iterates the events by the order of the event index, + /// else, it iterated the events by the order of the contract addresses. + /// + /// # Arguments + /// * address - contract address to iterate over events was emitted by it. + /// * event_index - event index to start iterate from it. + /// * to_block_number - block number to stop iterate at it. + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn iter_events( + &'env self, + address: Option, + event_index: EventIndex, + to_block_number: BlockNumber, + ) -> StorageResult>; +} + +// TODO: support all read transactions (including RW). +impl<'txn, 'env> EventsReader<'txn, 'env> for StorageTxn<'env, RO> { + fn iter_events( + &'env self, + optional_address: Option, + event_index: EventIndex, + to_block_number: BlockNumber, + ) -> StorageResult> { + if let Some(address) = optional_address { + return Ok(EventIter::ByContractAddress( + self.iter_events_by_contract_address((address, event_index))?, + )); + } + + Ok(EventIter::ByEventIndex(self.iter_events_by_event_index(event_index, to_block_number)?)) + } +} + +// TODO(dvir): add transaction hash to the return value. In the RPC when returning events this is +// with the transaction hash. We can do it efficiently here because we anyway read the relevant +// entry in the transaction_metadata table.. +#[allow(missing_docs)] +/// A wrapper of two iterators [`EventIterByContractAddress`] and [`EventIterByEventIndex`]. +pub enum EventIter<'txn, 'env> { + ByContractAddress(EventIterByContractAddress<'env, 'txn>), + ByEventIndex(EventIterByEventIndex<'txn>), +} + +/// This iterator is a wrapper of two iterators [`EventIterByContractAddress`] +/// and [`EventIterByEventIndex`]. +/// With this wrapper we can execute the same code, regardless the +/// type of iteration used. +impl Iterator for EventIter<'_, '_> { + type Item = ((ContractAddress, EventIndex), EventContent); + + fn next(&mut self) -> Option { + match self { + EventIter::ByContractAddress(it) => it.next(), + EventIter::ByEventIndex(it) => it.next(), + } + .unwrap_or(None) + } +} + +/// This iterator goes over the events in the order of the events table key. +/// That is, the events iterated first by the contract address and then by the event index. +pub struct EventIterByContractAddress<'env, 'txn> { + txn: &'txn DbTransaction<'env, RO>, + file_handles: &'txn FileHandlers, + // This value is the next entry in the events table to search for relevant events. If it is + // None there are no more events. + next_entry_in_event_table: Option, + // Queue of events to return from the iterator. When this queue is empty, we need to fetch more + // events. + events_queue: VecDeque<((ContractAddress, EventIndex), EventContent)>, + cursor: EventsTableCursor<'txn>, + transaction_metadata_table: TransactionMetadataTable<'env>, +} + +impl<'env, 'txn> EventIterByContractAddress<'env, 'txn> { + /// Returns the next event. If there are no more events, returns None. + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn next(&mut self) -> StorageResult> { + // Here we make sure that the events_queue is not empty. If it does we fill it with new + // relevant events. + if self.events_queue.is_empty() { + let Some((contract_address, tx_index)) = self.next_entry_in_event_table.take() else { + return Ok(None); + }; + let tx_metadata = + self.transaction_metadata_table.get(self.txn, &tx_index)?.unwrap_or_else(|| { + panic!("Transaction metadata not found for transaction index: {tx_index:?}") + }); + let tx_output = self + .file_handles + .get_transaction_output_unchecked(tx_metadata.tx_output_location)?; + // TODO(dvir): don't clone the events here. + self.events_queue = + get_events_from_tx(tx_output.events().into(), tx_index, contract_address, 0); + self.next_entry_in_event_table = self.cursor.next()?.map(|(key, _)| key); + } + + Ok(Some(self.events_queue.pop_front().expect("events_queue should not be empty."))) + } +} + +/// This iterator goes over the events in the order of the event index. +/// That is, the events are iterated by the order they are emitted. +/// First by the block number, then by the transaction offset in the block, +/// and finally, by the event index in the transaction output. +pub struct EventIterByEventIndex<'txn> { + file_handlers: &'txn FileHandlers, + tx_current: Option<(TransactionIndex, TransactionOutput)>, + tx_cursor: TransactionMetadataTableCursor<'txn>, + event_index_in_tx_current: EventIndexInTransactionOutput, + to_block_number: BlockNumber, +} + +impl EventIterByEventIndex<'_> { + /// Returns the next event. If there are no more events, returns None. + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn next(&mut self) -> StorageResult> { + let Some((tx_index, tx_output)) = &self.tx_current else { return Ok(None) }; + let Some(Event { from_address, content }) = + tx_output.events().get(self.event_index_in_tx_current.0) + else { + return Ok(None); + }; + let key = (*from_address, EventIndex(*tx_index, self.event_index_in_tx_current)); + // TODO(dvir): don't clone here the event content. + let content = content.clone(); + self.event_index_in_tx_current.0 += 1; + self.find_next_event_by_event_index()?; + Ok(Some((key, content.clone()))) + } + + /// Finds the event that corresponds to the first event index greater than or equals to the + /// current event index. The current event index is composed of the transaction index of the + /// current transaction (tx_current) and the event index in current transaction output + /// (event_index_in_tx_current). + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn find_next_event_by_event_index(&mut self) -> StorageResult<()> { + while let Some((tx_index, tx_output)) = &self.tx_current { + if tx_index.0 > self.to_block_number { + self.tx_current = None; + break; + } + // Checks if there's an event in the current event index. + if tx_output.events().len() > self.event_index_in_tx_current.0 { + break; + } + + // There are no more events in the current transaction, so we go over the rest of the + // transactions until we find an event. + let Some((tx_index, tx_metadata)) = self.tx_cursor.next()? else { + self.tx_current = None; + return Ok(()); + }; + self.tx_current = Some(( + tx_index, + self.file_handlers + .get_transaction_output_unchecked(tx_metadata.tx_output_location)?, + )); + self.event_index_in_tx_current = EventIndexInTransactionOutput(0); + } + + Ok(()) + } +} + +impl<'txn, 'env> StorageTxn<'env, RO> +where + 'env: 'txn, +{ + /// Returns an events iterator that iterates events by the events table key from the given key. + /// + /// # Arguments + /// * key - key to start from the first event with a key greater or equals to the given key. + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn iter_events_by_contract_address( + &'env self, + key: (ContractAddress, EventIndex), + ) -> StorageResult> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let events_table = self.open_table(&self.tables.events)?; + let mut cursor = events_table.cursor(&self.txn)?; + let events_queue = if let Some((contract_address, tx_index)) = + cursor.lower_bound(&(key.0, key.1.0))?.map(|(key, _)| key) + { + let tx_metadata = + transaction_metadata_table.get(&self.txn, &tx_index)?.unwrap_or_else(|| { + panic!("Transaction metadata not found for transaction index: {tx_index:?}") + }); + let tx_output = self + .file_handlers + .get_transaction_output_unchecked(tx_metadata.tx_output_location)?; + + // In case of we get tx_index different from the key, it means we need to start a new + // transaction which means the first event. + let start_event_index = if tx_index == key.1.0 { key.1.1.0 } else { 0 }; + // TODO(dvir): don't clone the events here. + get_events_from_tx( + tx_output.events().into(), + tx_index, + contract_address, + start_event_index, + ) + } else { + VecDeque::new() + }; + let next_entry_in_event_table = cursor.next()?.map(|(key, _)| key); + + Ok(EventIterByContractAddress { + txn: &self.txn, + file_handles: &self.file_handlers, + next_entry_in_event_table, + events_queue, + cursor, + transaction_metadata_table, + }) + } + + /// Returns an events iterator that iterates events by event index from the given event index. + /// + /// # Arguments + /// * event_index - event index to start from the first event with an index greater or equals + /// to. + /// * to_block_number - block number to stop iterate at it. + /// + /// # Errors + /// Returns [`StorageError`](crate::StorageError) if there was an error. + fn iter_events_by_event_index( + &'env self, + event_index: EventIndex, + to_block_number: BlockNumber, + ) -> StorageResult> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let mut tx_cursor = transaction_metadata_table.cursor(&self.txn)?; + let first_txn_location = tx_cursor.lower_bound(&event_index.0)?; + let first_relevant_transaction = match first_txn_location { + None => None, + Some((tx_index, tx_metadata)) => Some(( + tx_index, + self.file_handlers + .get_transaction_output_unchecked(tx_metadata.tx_output_location)?, + )), + }; + + let mut it = EventIterByEventIndex { + file_handlers: &self.file_handlers, + tx_current: first_relevant_transaction, + tx_cursor, + event_index_in_tx_current: event_index.1, + to_block_number, + }; + it.find_next_event_by_event_index()?; + Ok(it) + } +} + +fn get_events_from_tx( + events_list: Vec, + tx_index: TransactionIndex, + contract_address: ContractAddress, + start_index: usize, +) -> VecDeque<((ContractAddress, EventIndex), EventContent)> { + let mut events = VecDeque::new(); + for (i, event) in events_list.into_iter().enumerate().skip(start_index) { + if event.from_address == contract_address { + let key = (contract_address, EventIndex(tx_index, EventIndexInTransactionOutput(i))); + events.push_back((key, event.content)); + } + } + events +} + +/// A cursor of the events table. +type EventsTableCursor<'txn> = + DbCursor<'txn, RO, EventsTableKey, NoVersionValueWrapper, CommonPrefix>; +/// A cursor of the transaction outputs table. +type TransactionMetadataTableCursor<'txn> = + DbCursor<'txn, RO, TransactionIndex, VersionZeroWrapper, SimpleTable>; diff --git a/crates/papyrus_storage/src/body/events_test.rs b/crates/papyrus_storage/src/body/events_test.rs new file mode 100644 index 00000000000..d3f6f22c38d --- /dev/null +++ b/crates/papyrus_storage/src/body/events_test.rs @@ -0,0 +1,255 @@ +use std::vec; + +use assert_matches::assert_matches; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockNumber; +use starknet_api::transaction::{ + Event, + EventContent, + EventData, + EventIndexInTransactionOutput, + TransactionOffsetInBlock, +}; +use test_utils::get_test_block; + +use crate::body::events::{get_events_from_tx, EventIndex, EventsReader}; +use crate::body::{BodyStorageWriter, TransactionIndex}; +use crate::db::table_types::Table; +use crate::header::HeaderStorageWriter; +use crate::test_utils::get_test_storage; + +#[test] +fn iter_events_by_key() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let ca1 = 1u32.into(); + let ca2 = 2u32.into(); + let from_addresses = vec![ca1, ca2]; + let block = get_test_block(4, Some(3), Some(from_addresses), None); + let block_number = block.header.block_number; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + // Create the events emitted, starting from contract address ca1 onwards. + // In our case, after the events emitted from address ca1, come the events + // emitted from address ca2, which are all the remaining events. + let mut events_ca1 = vec![]; + let mut events_ca2 = vec![]; + for (tx_i, tx_output) in block.body.transaction_outputs.iter().enumerate() { + for (event_i, event) in tx_output.events().iter().enumerate() { + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(tx_i)), + EventIndexInTransactionOutput(event_i), + ); + if event.from_address == ca1 { + events_ca1.push(((event.from_address, event_index), event.content.clone())) + } else { + events_ca2.push(((event.from_address, event_index), event.content.clone())) + } + } + } + let all_events = + events_ca1.iter().cloned().chain(events_ca2.iter().cloned()).collect::>(); + + let txn = storage_reader.begin_ro_txn().unwrap(); + + // Iterate over all the events from the first to the last. + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ); + let event_iter = txn.iter_events(Some(ca1), event_index, block_number).unwrap(); + assert_eq!(event_iter.into_iter().collect::>(), all_events); + + // Start from not existing event index. + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(5)), + EventIndexInTransactionOutput(0), + ); + let event_iter = txn.iter_events(Some(ca2), event_index, block_number).unwrap(); + assert_eq!(event_iter.into_iter().collect::>(), vec![]); + + // TODO(dvir): add non random test that checks the iterator when there are no more relevant + // events in the start transaction index. Start from event index in a middle of transaction. + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(1), + ); + let expected_events = if block.body.transaction_outputs[0].events()[0].from_address == ca1 { + events_ca1.iter().skip(1).cloned().chain(events_ca2.iter().cloned()).collect::>() + } else { + events_ca1.iter().cloned().chain(events_ca2.iter().cloned()).collect::>() + }; + let event_iter = txn.iter_events(Some(ca1), event_index, block_number).unwrap(); + assert_eq!(event_iter.into_iter().collect::>(), expected_events); +} + +#[test] +fn iter_events_by_index() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let block = get_test_block(2, Some(5), None, None); + let block_number = block.header.block_number; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + // Create the events emitted starting from event index ((0,0),2). + let mut emitted_events = vec![]; + for (tx_i, tx_output) in block.body.transaction_outputs.iter().enumerate() { + for (event_i, event) in tx_output.events().iter().enumerate() { + if tx_i == 0 && event_i < 2 { + continue; + } + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(tx_i)), + EventIndexInTransactionOutput(event_i), + ); + emitted_events.push(((event.from_address, event_index), event.content.clone())) + } + } + + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(2), + ); + let txn = storage_reader.begin_ro_txn().unwrap(); + let event_iter = txn.iter_events(None, event_index, block_number).unwrap(); + assert_eq!(event_iter.into_iter().collect::>(), emitted_events); +} + +#[test] +fn revert_events() { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let block = get_test_block(2, Some(5), None, None); + let block_number = block.header.block_number; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let event_index = EventIndex( + TransactionIndex(block_number, TransactionOffsetInBlock(0)), + EventIndexInTransactionOutput(0), + ); + + // Test iter events using the storage reader. + assert!( + storage_reader + .begin_ro_txn() + .unwrap() + .iter_events(None, event_index, block_number) + .unwrap() + .last() + .is_some() + ); + + // Test events raw table. + let txn = storage_reader.begin_ro_txn().unwrap(); + let events_table = txn.txn.open_table(&txn.tables.events).unwrap(); + for (tx_idx, tx_output) in block.body.transaction_outputs.iter().enumerate() { + let transaction_index = TransactionIndex(block_number, TransactionOffsetInBlock(tx_idx)); + for event in tx_output.events().iter() { + assert_matches!( + events_table.get(&txn.txn, &(event.from_address, transaction_index)), + Ok(Some(_)) + ); + } + } + + storage_writer + .begin_rw_txn() + .unwrap() + .revert_header(block_number) + .unwrap() + .0 + .revert_body(block_number) + .unwrap() + .0 + .commit() + .unwrap(); + assert!( + storage_reader + .begin_ro_txn() + .unwrap() + .iter_events(None, event_index, block_number) + .unwrap() + .last() + .is_none() + ); + + let txn = storage_reader.begin_ro_txn().unwrap(); + let events_table = txn.txn.open_table(&txn.tables.events).unwrap(); + for (tx_idx, tx_output) in block.body.transaction_outputs.iter().enumerate() { + let transaction_index = TransactionIndex(block_number, TransactionOffsetInBlock(tx_idx)); + for event in tx_output.events().iter() { + assert_matches!( + events_table.get(&txn.txn, &(event.from_address, transaction_index)), + Ok(None) + ); + } + } +} + +#[test] +fn get_events_from_tx_test() { + let tx_index = TransactionIndex(BlockNumber(0), TransactionOffsetInBlock(0)); + let ca1 = 1u32.into(); + let ca2 = 2u32.into(); + + let e1 = Event { + from_address: ca1, + content: EventContent { data: EventData(vec![1u32.into()]), ..Default::default() }, + }; + let e2 = Event { + from_address: ca2, + content: EventContent { data: EventData(vec![1u32.into()]), ..Default::default() }, + }; + let e3 = Event { + from_address: ca1, + content: EventContent { data: EventData(vec![2u32.into()]), ..Default::default() }, + }; + + let events = vec![e1.clone(), e2.clone(), e3.clone()]; + let e1_output = + ((ca1, EventIndex(tx_index, EventIndexInTransactionOutput(0))), e1.content.clone()); + let e2_output = + ((ca2, EventIndex(tx_index, EventIndexInTransactionOutput(1))), e2.content.clone()); + let e3_output = + ((ca1, EventIndex(tx_index, EventIndexInTransactionOutput(2))), e3.content.clone()); + + // All events. + assert_eq!( + get_events_from_tx(events.clone(), tx_index, ca1, 0), + vec![e1_output.clone(), e3_output.clone()] + ); + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca2, 0), vec![e2_output.clone()]); + + // All events of starting from the second event. + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca1, 1), vec![e3_output.clone()]); + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca2, 1), vec![e2_output.clone()]); + + // All events of starting from the third event. + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca1, 2), vec![e3_output.clone()]); + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca2, 2), vec![]); + + // All events of starting from the not existing index. + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca1, 3), vec![]); + assert_eq!(get_events_from_tx(events.clone(), tx_index, ca2, 3), vec![]); +} diff --git a/crates/papyrus_storage/src/body/mod.rs b/crates/papyrus_storage/src/body/mod.rs new file mode 100644 index 00000000000..066be012aa1 --- /dev/null +++ b/crates/papyrus_storage/src/body/mod.rs @@ -0,0 +1,520 @@ +//! Interface for handling data related to Starknet [block bodies](https://docs.rs/starknet_api/latest/starknet_api/block/struct.BlockBody.html). +//! +//! The block body is the part of the block that contains the transactions and the transaction +//! outputs. +//! Import [`BodyStorageReader`] and [`BodyStorageWriter`] to read and write data related +//! to the block bodies using a [`StorageTxn`]. +//! +//! See [`events`] module for the interface for handling events. +//! +//! # Example +//! ``` +//! use papyrus_storage::open_storage; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! use starknet_api::block::{Block, BlockNumber}; +//! use papyrus_storage::body::{BodyStorageReader, BodyStorageWriter}; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! let block = Block::default(); +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_body(BlockNumber(0), block.body)? // Append the block body (consumes the body at the current version). +//! .commit()?; +//! +//! let stored_body_transactions = reader.begin_ro_txn()?.get_block_transactions(BlockNumber(0))?; +//! assert_eq!(stored_body_transactions, Some(Block::default().body.transactions)); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` + +#[cfg(test)] +mod body_test; +pub mod events; + +use std::collections::HashSet; +use std::fmt::Debug; + +use papyrus_proc_macros::latency_histogram; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockBody, BlockNumber}; +use starknet_api::core::ContractAddress; +use starknet_api::transaction::{ + Transaction, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput, +}; +use tracing::debug; + +use crate::db::serialization::{NoVersionValueWrapper, VersionZeroWrapper}; +use crate::db::table_types::{CommonPrefix, DbCursorTrait, NoValue, SimpleTable, Table}; +use crate::db::{DbTransaction, TableHandle, TransactionKind, RW}; +use crate::{ + FileHandlers, + MarkerKind, + MarkersTable, + OffsetKind, + StorageError, + StorageResult, + StorageScope, + StorageTxn, + TransactionMetadata, +}; + +type FileOffsetsTable<'env> = + TableHandle<'env, OffsetKind, NoVersionValueWrapper, SimpleTable>; +type TransactionMetadataTable<'env> = + TableHandle<'env, TransactionIndex, VersionZeroWrapper, SimpleTable>; +type TransactionHashToIdxTable<'env> = + TableHandle<'env, TransactionHash, NoVersionValueWrapper, SimpleTable>; +type EventsTableKey = (ContractAddress, TransactionIndex); +type EventsTable<'env> = + TableHandle<'env, EventsTableKey, NoVersionValueWrapper, CommonPrefix>; + +/// The index of a transaction in a block. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] +#[cfg_attr(any(test, feature = "testing"), derive(Hash))] +pub struct TransactionIndex(pub BlockNumber, pub TransactionOffsetInBlock); + +/// Interface for reading data related to the block body. +pub trait BodyStorageReader { + /// The body marker is the first block number that doesn't exist yet. + fn get_body_marker(&self) -> StorageResult; + + /// Returns the transaction and its execution status at the given index. + fn get_transaction( + &self, + transaction_index: TransactionIndex, + ) -> StorageResult>; + + /// Returns the transaction output at the given index. + fn get_transaction_output( + &self, + transaction_index: TransactionIndex, + ) -> StorageResult>; + + /// Returns the index of the transaction with the given hash. + fn get_transaction_idx_by_hash( + &self, + tx_hash: &TransactionHash, + ) -> StorageResult>; + + /// Returns the transaction hash with the given transaction index. + fn get_transaction_hash_by_idx( + &self, + tx_index: &TransactionIndex, + ) -> StorageResult>; + + /// Returns the transactions and their execution status of the block with the given number. + fn get_block_transactions( + &self, + block_number: BlockNumber, + ) -> StorageResult>>; + + /// Returns the transaction hashes of the block with the given number. + fn get_block_transaction_hashes( + &self, + block_number: BlockNumber, + ) -> StorageResult>>; + + /// Returns the transaction outputs of the block with the given number. + fn get_block_transaction_outputs( + &self, + block_number: BlockNumber, + ) -> StorageResult>>; + + /// Returns the number of transactions in the block with the given number. + fn get_block_transactions_count( + &self, + block_number: BlockNumber, + ) -> StorageResult>; +} + +type RevertedBlockBody = (Vec, Vec, Vec); + +/// Interface for updating data related to the block body. +pub trait BodyStorageWriter +where + Self: Sized, +{ + /// Appends a block body to the storage. + // To enforce that no commit happen after a failure, we consume and return Self on success. + // The body is consumed to avoid unnecessary copying while converting transaction outputs into + // thin transaction outputs. + // TODO(yair): make this work without consuming the body. + fn append_body(self, block_number: BlockNumber, block_body: BlockBody) -> StorageResult; + + /// Removes a block body from the storage and returns the removed data. + fn revert_body( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option)>; +} + +impl<'env, Mode: TransactionKind> BodyStorageReader for StorageTxn<'env, Mode> { + fn get_body_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::Body)?.unwrap_or_default()) + } + + // TODO(dvir): add option to get transaction with its hash. + fn get_transaction( + &self, + transaction_index: TransactionIndex, + ) -> StorageResult> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let Some(tx_metadata) = transaction_metadata_table.get(&self.txn, &transaction_index)? + else { + return Ok(None); + }; + let transaction = self.file_handlers.get_transaction_unchecked(tx_metadata.tx_location)?; + Ok(Some(transaction)) + } + + fn get_transaction_output( + &self, + transaction_index: TransactionIndex, + ) -> StorageResult> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let Some(tx_metadata) = transaction_metadata_table.get(&self.txn, &transaction_index)? + else { + return Ok(None); + }; + let transaction_output = + self.file_handlers.get_transaction_output_unchecked(tx_metadata.tx_output_location)?; + Ok(Some(transaction_output)) + } + + fn get_transaction_idx_by_hash( + &self, + tx_hash: &TransactionHash, + ) -> StorageResult> { + let transaction_hash_to_idx_table = + self.open_table(&self.tables.transaction_hash_to_idx)?; + let idx = transaction_hash_to_idx_table.get(&self.txn, tx_hash)?; + Ok(idx) + } + + fn get_transaction_hash_by_idx( + &self, + tx_index: &TransactionIndex, + ) -> StorageResult> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let Some(tx_metadata) = transaction_metadata_table.get(&self.txn, tx_index)? else { + return Ok(None); + }; + Ok(Some(tx_metadata.tx_hash)) + } + + fn get_block_transactions( + &self, + block_number: BlockNumber, + ) -> StorageResult>> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + self.get_transactions_in_block(block_number, transaction_metadata_table) + } + + fn get_block_transaction_hashes( + &self, + block_number: BlockNumber, + ) -> StorageResult>> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + self.get_transaction_hashes_in_block(block_number, transaction_metadata_table) + } + + fn get_block_transaction_outputs( + &self, + block_number: BlockNumber, + ) -> StorageResult>> { + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + self.get_transaction_outputs_in_block(block_number, transaction_metadata_table) + } + + fn get_block_transactions_count( + &self, + block_number: BlockNumber, + ) -> StorageResult> { + // After this condition, we know that the block exists, so if something goes wrong is only + // because there are no transactions in it. + if self.get_body_marker()? <= block_number { + return Ok(None); + } + + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let mut cursor = transaction_metadata_table.cursor(&self.txn)?; + let Some(next_block_number) = block_number.next() else { + return Ok(None); + }; + + cursor.lower_bound(&TransactionIndex(next_block_number, TransactionOffsetInBlock(0)))?; + let Some((TransactionIndex(received_block_number, last_tx_index), _tx_hash)) = + cursor.prev()? + else { + return Ok(Some(0)); + }; + if received_block_number != block_number { + return Ok(Some(0)); + } + + Ok(Some(last_tx_index.0 + 1)) + } +} + +impl<'env, Mode: TransactionKind> StorageTxn<'env, Mode> { + // Returns a vector with transaction objects (can be tx hash for example). + fn get_vector_of_transaction_objects( + &self, + block_number: BlockNumber, + transaction_metadata_table: TransactionMetadataTable<'env>, + tx_metadata_to_tx_object: fn(TransactionMetadata, &FileHandlers) -> StorageResult, + ) -> StorageResult>> { + if self.get_body_marker()? <= block_number { + return Ok(None); + } + let mut cursor = transaction_metadata_table.cursor(&self.txn)?; + let mut current = + cursor.lower_bound(&TransactionIndex(block_number, TransactionOffsetInBlock(0)))?; + + // TODO(dvir): consider initializing with capacity based on the get_block_transactions_count + // function. + let mut res = Vec::new(); + while let Some((TransactionIndex(current_block_number, _), tx_metadata)) = current { + if current_block_number != block_number { + break; + } + let tx_output = tx_metadata_to_tx_object(tx_metadata, &self.file_handlers)?; + res.push(tx_output); + current = cursor.next()?; + } + Ok(Some(res)) + } + + fn get_transaction_outputs_in_block( + &self, + block_number: BlockNumber, + transaction_metadata_table: TransactionMetadataTable<'env>, + ) -> StorageResult>> { + self.get_vector_of_transaction_objects( + block_number, + transaction_metadata_table, + |tx_metadata, file_handlers| { + file_handlers.get_transaction_output_unchecked(tx_metadata.tx_output_location) + }, + ) + } + + fn get_transactions_in_block( + &self, + block_number: BlockNumber, + transaction_metadata_table: TransactionMetadataTable<'env>, + ) -> StorageResult>> { + self.get_vector_of_transaction_objects( + block_number, + transaction_metadata_table, + |tx_metadata, file_handlers| { + file_handlers.get_transaction_unchecked(tx_metadata.tx_location) + }, + ) + } + + fn get_transaction_hashes_in_block( + &self, + block_number: BlockNumber, + transaction_metadata_table: TransactionMetadataTable<'env>, + ) -> StorageResult>> { + self.get_vector_of_transaction_objects( + block_number, + transaction_metadata_table, + |tx_metadata, _file_handlers| Ok(tx_metadata.tx_hash), + ) + } +} + +impl<'env> BodyStorageWriter for StorageTxn<'env, RW> { + #[latency_histogram("storage_append_body_latency_seconds", false)] + fn append_body(self, block_number: BlockNumber, block_body: BlockBody) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + update_marker(&self.txn, &markers_table, block_number)?; + + if self.scope != StorageScope::StateOnly { + let events_table = self.open_table(&self.tables.events)?; + let transaction_hash_to_idx_table = + self.open_table(&self.tables.transaction_hash_to_idx)?; + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let file_offset_table = self.txn.open_table(&self.tables.file_offsets)?; + + write_transactions( + &block_body, + &self.txn, + &self.file_handlers, + &file_offset_table, + &transaction_hash_to_idx_table, + &transaction_metadata_table, + &events_table, + block_number, + )?; + } + + Ok(self) + } + + fn revert_body( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option)> { + let markers_table = self.open_table(&self.tables.markers)?; + + // Assert that body marker equals the reverted block number + 1 + let current_header_marker = self.get_body_marker()?; + if block_number + .next() + .filter(|next_block_number| current_header_marker == *next_block_number) + .is_none() + { + debug!( + "Attempt to revert a non-existing / old block {}. Returning without an action.", + block_number + ); + return Ok((self, None)); + } + + let reverted_block_body = 'reverted_block_body: { + if self.scope == StorageScope::StateOnly { + break 'reverted_block_body None; + } + + let transaction_metadata_table = self.open_table(&self.tables.transaction_metadata)?; + let transaction_hash_to_idx_table = + self.open_table(&self.tables.transaction_hash_to_idx)?; + let events_table = self.open_table(&self.tables.events)?; + + let transactions = self + .get_block_transactions(block_number)? + .unwrap_or_else(|| panic!("Missing transactions for block {block_number}.")); + let transaction_outputs = self + .get_block_transaction_outputs(block_number)? + .unwrap_or_else(|| panic!("Missing transaction outputs for block {block_number}.")); + let transaction_hashes = self + .get_block_transaction_hashes(block_number)? + .unwrap_or_else(|| panic!("Missing transaction hashes for block {block_number}.")); + + // Delete the transactions data. + for (offset, (tx_hash, tx_output)) in + transaction_hashes.iter().zip(transaction_outputs.iter()).enumerate() + { + let tx_index = TransactionIndex(block_number, TransactionOffsetInBlock(offset)); + + for event in tx_output.events().iter() { + events_table.delete(&self.txn, &(event.from_address, tx_index))?; + } + transaction_hash_to_idx_table.delete(&self.txn, tx_hash)?; + transaction_metadata_table.delete(&self.txn, &tx_index)?; + } + Some((transactions, transaction_outputs, transaction_hashes)) + }; + + markers_table.upsert(&self.txn, &MarkerKind::Body, &block_number)?; + markers_table.upsert(&self.txn, &MarkerKind::Event, &block_number)?; + Ok((self, reverted_block_body)) + } +} + +// TODO(dvir): consider enforcing that the block_body transactions, transaction_outputs and +// transaction_hashes to be the same size. +#[allow(clippy::too_many_arguments)] +fn write_transactions<'env>( + block_body: &BlockBody, + txn: &DbTransaction<'env, RW>, + file_handlers: &FileHandlers, + file_offset_table: &'env FileOffsetsTable<'env>, + transaction_hash_to_idx_table: &'env TransactionHashToIdxTable<'env>, + transaction_metadata_table: &'env TransactionMetadataTable<'env>, + events_table: &'env EventsTable<'env>, + block_number: BlockNumber, +) -> StorageResult<()> { + for (index, ((tx, tx_output), tx_hash)) in block_body + .transactions + .iter() + .zip(block_body.transaction_outputs.iter()) + .zip(block_body.transaction_hashes.iter()) + .enumerate() + { + let tx_offset_in_block = TransactionOffsetInBlock(index); + let transaction_index = TransactionIndex(block_number, tx_offset_in_block); + let tx_location = file_handlers.append_transaction(tx); + let tx_output_location = file_handlers.append_transaction_output(tx_output); + write_events(tx_output, txn, events_table, transaction_index)?; + transaction_hash_to_idx_table.insert(txn, tx_hash, &transaction_index)?; + transaction_metadata_table.append( + txn, + &transaction_index, + &TransactionMetadata { tx_location, tx_output_location, tx_hash: *tx_hash }, + )?; + + // If this is the last iteration, update the file offset table. + if index == block_body.transactions.len() - 1 { + file_offset_table.upsert(txn, &OffsetKind::Transaction, &tx_location.next_offset())?; + file_offset_table.upsert( + txn, + &OffsetKind::TransactionOutput, + &tx_output_location.next_offset(), + )?; + } + } + + Ok(()) +} + +// This function assumes that the `transaction_index` is the last index used to call it. +fn write_events<'env>( + tx_output: &TransactionOutput, + txn: &DbTransaction<'env, RW>, + events_table: &'env EventsTable<'env>, + transaction_index: TransactionIndex, +) -> StorageResult<()> { + let mut contract_addresses_set = HashSet::new(); + + for event in tx_output.events().iter() { + contract_addresses_set.insert(event.from_address); + } + + for contract_address in contract_addresses_set { + let key = (contract_address, transaction_index); + // Here, we use the function assumption; the append will fail if an older transaction_index + // is a table. + events_table.append_greater_sub_key(txn, &key, &NoValue)?; + } + Ok(()) +} + +fn update_marker<'env>( + txn: &DbTransaction<'env, RW>, + markers_table: &'env MarkersTable<'env>, + block_number: BlockNumber, +) -> StorageResult<()> { + // Make sure marker is consistent. + let body_marker = markers_table.get(txn, &MarkerKind::Body)?.unwrap_or_default(); + if body_marker != block_number { + return Err(StorageError::MarkerMismatch { expected: body_marker, found: block_number }); + }; + let event_marker = markers_table.get(txn, &MarkerKind::Event)?.unwrap_or_default(); + if event_marker != block_number { + return Err(StorageError::MarkerMismatch { expected: event_marker, found: block_number }); + }; + + // Advance marker. + markers_table.upsert(txn, &MarkerKind::Body, &block_number.unchecked_next())?; + markers_table.upsert(txn, &MarkerKind::Event, &block_number.unchecked_next())?; + Ok(()) +} diff --git a/crates/papyrus_storage/src/class.rs b/crates/papyrus_storage/src/class.rs new file mode 100644 index 00000000000..ceede70b943 --- /dev/null +++ b/crates/papyrus_storage/src/class.rs @@ -0,0 +1,240 @@ +//! Interface for handling data related to Starknet [classes (Cairo 1)](https://docs.rs/starknet_api/latest/starknet_api/state/struct.ContractClass.html) and [deprecated classes (Cairo 0)](https://docs.rs/starknet_api/latest/starknet_api/deprecated_contract_class/struct.ContractClass.html). +//! +//! Import [`ClassStorageReader`] and [`ClassStorageWriter`] to read and write data related to +//! classes using a [`StorageTxn`]. +//! +//! Note that the written classes' hashes should be the same as those declared in the block's state +//! diff and deploy transactions (now depreacted). This is not validated but breaking this will +//! cause the DB to be inconsistent. +//! +//! # Example +//! ``` +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! use indexmap::indexmap; +//! use papyrus_storage::class::{ClassStorageReader, ClassStorageWriter}; +//! use papyrus_storage::open_storage; +//! use papyrus_storage::state::StateStorageWriter; +//! use starknet_api::block::BlockNumber; +//! use starknet_api::core::{ClassHash, CompiledClassHash}; +//! use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +//! use starknet_api::hash::StarkHash; +//! use starknet_api::state::{ContractClass, ThinStateDiff}; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let class_hash = ClassHash::default(); +//! let class = ContractClass::default(); +//! let deprecated_class_hash = ClassHash(StarkHash::ONE); +//! let deprecated_class = DeprecatedContractClass::default(); +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_state_diff( +//! BlockNumber(0), +//! ThinStateDiff { +//! declared_classes: indexmap! { class_hash => CompiledClassHash::default() }, +//! deprecated_declared_classes: vec![deprecated_class_hash], +//! ..Default::default() +//! }, +//! )? // Append a state diff. +//! .append_classes( +//! BlockNumber(0), +//! &vec![(class_hash, &class)], +//! &vec![(deprecated_class_hash, &deprecated_class)], +//! )? // Append all classes of block no. 0. +//! .commit()?; // Commit the transaction. +//! +//! let written_class = reader.begin_ro_txn()?.get_class(&class_hash)?; +//! assert_eq!(written_class, Some(class)); +//! +//! let written_deprecated_class = +//! reader.begin_ro_txn()?.get_deprecated_class(&ClassHash(StarkHash::ONE))?; +//! assert_eq!(written_deprecated_class, Some(deprecated_class)); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` + +#[cfg(test)] +#[path = "class_test.rs"] +mod class_test; + +use papyrus_proc_macros::latency_histogram; +use starknet_api::block::BlockNumber; +use starknet_api::core::ClassHash; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::ContractClass; + +use crate::db::table_types::Table; +use crate::db::{TransactionKind, RW}; +use crate::state::{DeclaredClassesTable, DeprecatedDeclaredClassesTable, FileOffsetTable}; +use crate::{ + DbTransaction, + FileHandlers, + IndexedDeprecatedContractClass, + MarkerKind, + OffsetKind, + StorageError, + StorageResult, + StorageTxn, +}; + +/// Interface for reading data related to classes or deprecated classes. +pub trait ClassStorageReader { + /// Returns the Cairo 1 class with the given hash. + fn get_class(&self, class_hash: &ClassHash) -> StorageResult>; + + /// Returns the Cairo 0 class with the given hash. + fn get_deprecated_class( + &self, + class_hash: &ClassHash, + ) -> StorageResult>; + + /// The block marker is the first block number that we don't have all of its classes. + fn get_class_marker(&self) -> StorageResult; +} + +/// Interface for writing data related to classes or deprecated classes. +pub trait ClassStorageWriter +where + Self: Sized, +{ + /// Stores the classes declared in a block. + /// + /// It is assumed that the classes and deprecated classes fit the declared classes in the + /// block's state diff and in deploy transactions. Breaking this assumption will cause the DB to + /// be inconsistent. + /// + /// Note: This function needs to be called for each block, even if there are no classes or + /// deprecated classes declared in that block + // To enforce that no commit happen after a failure, we consume and return Self on success. + fn append_classes( + self, + block_number: BlockNumber, + classes: &[(ClassHash, &ContractClass)], + deprecated_classes: &[(ClassHash, &DeprecatedContractClass)], + ) -> StorageResult; +} + +impl<'env, Mode: TransactionKind> ClassStorageReader for StorageTxn<'env, Mode> { + fn get_class(&self, class_hash: &ClassHash) -> StorageResult> { + let declared_classes_table = self.open_table(&self.tables.declared_classes)?; + let contract_class_location = declared_classes_table.get(&self.txn, class_hash)?; + contract_class_location + .map(|location| self.file_handlers.get_contract_class_unchecked(location)) + .transpose() + } + + fn get_deprecated_class( + &self, + class_hash: &ClassHash, + ) -> StorageResult> { + let deprecated_declared_classes_table = + self.open_table(&self.tables.deprecated_declared_classes)?; + let deprecated_contract_class_location = + deprecated_declared_classes_table.get(&self.txn, class_hash)?; + deprecated_contract_class_location + .map(|value| { + self.file_handlers.get_deprecated_contract_class_unchecked(value.location_in_file) + }) + .transpose() + } + + fn get_class_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::Class)?.unwrap_or_default()) + } +} + +impl<'env> ClassStorageWriter for StorageTxn<'env, RW> { + #[latency_histogram("storage_append_classes_latency_seconds", false)] + fn append_classes( + self, + block_number: BlockNumber, + classes: &[(ClassHash, &ContractClass)], + deprecated_classes: &[(ClassHash, &DeprecatedContractClass)], + ) -> StorageResult { + let declared_classes_table = self.open_table(&self.tables.declared_classes)?; + let deprecated_declared_classes_table = + self.open_table(&self.tables.deprecated_declared_classes)?; + let file_offset_table = self.txn.open_table(&self.tables.file_offsets)?; + let markers_table = self.open_table(&self.tables.markers)?; + + let marker_block_number = + markers_table.get(&self.txn, &MarkerKind::Class)?.unwrap_or_default(); + if block_number != marker_block_number { + return Err(StorageError::MarkerMismatch { + expected: marker_block_number, + found: block_number, + }); + } + + write_classes( + classes, + &self.txn, + &declared_classes_table, + &self.file_handlers, + &file_offset_table, + )?; + + write_deprecated_classes( + deprecated_classes, + &self.txn, + block_number, + &deprecated_declared_classes_table, + &self.file_handlers, + &file_offset_table, + )?; + + markers_table.upsert(&self.txn, &MarkerKind::Class, &block_number.unchecked_next())?; + + Ok(self) + } +} + +fn write_classes<'env>( + classes: &[(ClassHash, &ContractClass)], + txn: &DbTransaction<'env, RW>, + declared_classes_table: &'env DeclaredClassesTable<'env>, + file_handlers: &FileHandlers, + file_offset_table: &'env FileOffsetTable<'env>, +) -> StorageResult<()> { + for (class_hash, contract_class) in classes { + let location = file_handlers.append_contract_class(contract_class); + declared_classes_table.insert(txn, class_hash, &location)?; + file_offset_table.upsert(txn, &OffsetKind::ContractClass, &location.next_offset())?; + } + Ok(()) +} + +fn write_deprecated_classes<'env>( + deprecated_classes: &[(ClassHash, &DeprecatedContractClass)], + txn: &DbTransaction<'env, RW>, + block_number: BlockNumber, + deprecated_declared_classes_table: &'env DeprecatedDeclaredClassesTable<'env>, + file_handlers: &FileHandlers, + file_offset_table: &'env FileOffsetTable<'env>, +) -> StorageResult<()> { + for (class_hash, deprecated_contract_class) in deprecated_classes { + if deprecated_declared_classes_table.get(txn, class_hash)?.is_some() { + continue; + } + let location = file_handlers.append_deprecated_contract_class(deprecated_contract_class); + let value = IndexedDeprecatedContractClass { block_number, location_in_file: location }; + file_offset_table.upsert( + txn, + &OffsetKind::DeprecatedContractClass, + &location.next_offset(), + )?; + deprecated_declared_classes_table.insert(txn, class_hash, &value)?; + } + Ok(()) +} diff --git a/crates/papyrus_storage/src/class_test.rs b/crates/papyrus_storage/src/class_test.rs new file mode 100644 index 00000000000..5ba2c19468f --- /dev/null +++ b/crates/papyrus_storage/src/class_test.rs @@ -0,0 +1,123 @@ +use assert_matches::assert_matches; +use indexmap::indexmap; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass, StateNumber, ThinStateDiff}; +use test_utils::read_json_file; + +use super::{ClassStorageReader, ClassStorageWriter}; +use crate::state::{StateStorageReader, StateStorageWriter}; +use crate::test_utils::get_test_storage; +use crate::StorageError; + +#[test] +fn append_classes_writes_correct_data() { + let class_json = read_json_file("class.json"); + let expected_class: ContractClass = serde_json::from_value(class_json).unwrap(); + let deprecated_class_json = read_json_file("deprecated_class.json"); + let expected_deprecated_class: DeprecatedContractClass = + serde_json::from_value(deprecated_class_json).unwrap(); + let class_hash = ClassHash::default(); + let deprecated_class_hash = ClassHash(StarkHash::ONE); + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + writer + .begin_rw_txn() + .unwrap() + .append_state_diff( + BlockNumber(0), + ThinStateDiff { + declared_classes: indexmap! { class_hash => CompiledClassHash::default() }, + deprecated_declared_classes: vec![deprecated_class_hash], + ..Default::default() + }, + ) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash, &expected_class)], + &[(deprecated_class_hash, &expected_deprecated_class)], + ) + .unwrap() + .commit() + .unwrap(); + + let class = reader.begin_ro_txn().unwrap().get_class(&ClassHash::default()).unwrap().unwrap(); + assert_eq!(class, expected_class); + + let deprecated_class = reader + .begin_ro_txn() + .unwrap() + .get_deprecated_class(&deprecated_class_hash) + .unwrap() + .unwrap(); + assert_eq!(deprecated_class, expected_deprecated_class); +} + +#[test] +fn append_classes_marker_mismatch() { + let ((_reader, mut writer), _temp_dir) = get_test_storage(); + + let Err(err) = writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(1), &Vec::new(), &Vec::new()) + else { + panic!("Unexpected Ok."); + }; + + assert_matches!( + err, + StorageError::MarkerMismatch { expected, found } if expected.0 == 0 && found.0 == 1 + ); +} + +#[test] +fn append_deprecated_class_not_in_state_diff() { + let deprecated_class_json = read_json_file("deprecated_class.json"); + let expected_deprecated_class: DeprecatedContractClass = + serde_json::from_value(deprecated_class_json).unwrap(); + let deprecated_class_hash = ClassHash::default(); + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(0), &[], &[]) + .unwrap() + .append_state_diff(BlockNumber(1), ThinStateDiff::default()) + .unwrap() + .append_classes(BlockNumber(1), &[], &[(deprecated_class_hash, &expected_deprecated_class)]) + .unwrap() + .commit() + .unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + let statetxn = txn.get_state_reader().unwrap(); + + let state0 = StateNumber::right_after_block(BlockNumber(0)).unwrap(); + assert!( + statetxn + .get_deprecated_class_definition_at(state0, &deprecated_class_hash) + .unwrap() + .is_none() + ); + + let state1 = StateNumber::right_after_block(BlockNumber(1)).unwrap(); + assert_eq!( + statetxn + .get_deprecated_class_definition_at(state1, &deprecated_class_hash) + .unwrap() + .unwrap(), + expected_deprecated_class + ); +} diff --git a/crates/papyrus_storage/src/compiled_class.rs b/crates/papyrus_storage/src/compiled_class.rs new file mode 100644 index 00000000000..be55c0a1dd6 --- /dev/null +++ b/crates/papyrus_storage/src/compiled_class.rs @@ -0,0 +1,140 @@ +//! Interface for handling data related to Starknet [compiled classes (Cairo assembly, or CASM)](https://docs.rs/cairo-lang-starknet/latest/cairo_lang_starknet/casm_contract_class/struct.CasmContractClass.html). +//! +//! The compiled class is the result of compiling a Cairo program. +//! Import [`CasmStorageReader`] and [`CasmStorageWriter`] to read and write data related to the +//! compiled classes using a [`StorageTxn`]. +//! # Example +//! ``` +//! use papyrus_storage::open_storage; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +//! use papyrus_storage::compiled_class::{CasmStorageReader, CasmStorageWriter}; +//! use starknet_api::core::ClassHash; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_casm(&ClassHash::default(), &CasmContractClass::default())? // Append a compiled class. +//! .commit()?; // Commit the transaction. +//! let casm = reader.begin_ro_txn()?.get_casm(&ClassHash::default())?; +//! assert_eq!(casm, Some(CasmContractClass::default())); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` + +#[cfg(test)] +#[path = "compiled_class_test.rs"] +mod casm_test; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use papyrus_proc_macros::latency_histogram; +use starknet_api::block::BlockNumber; +use starknet_api::core::ClassHash; + +use crate::db::serialization::VersionZeroWrapper; +use crate::db::table_types::{SimpleTable, Table}; +use crate::db::{DbTransaction, TableHandle, TransactionKind, RW}; +use crate::mmap_file::LocationInFile; +use crate::{FileHandlers, MarkerKind, MarkersTable, OffsetKind, StorageResult, StorageTxn}; + +/// Interface for reading data related to the compiled classes. +pub trait CasmStorageReader { + /// Returns the Cairo assembly of a class given its Sierra class hash. + fn get_casm(&self, class_hash: &ClassHash) -> StorageResult>; + /// The block marker is the first block number that doesn't exist yet. + /// + /// Note: If the last blocks don't contain any declared classes, the marker will point at the + /// block after the last block that had declared classes. + fn get_compiled_class_marker(&self) -> StorageResult; +} + +/// Interface for writing data related to the compiled classes. +pub trait CasmStorageWriter +where + Self: Sized, +{ + /// Stores the Cairo assembly of a class, mapped to its class hash. + // To enforce that no commit happen after a failure, we consume and return Self on success. + fn append_casm(self, class_hash: &ClassHash, casm: &CasmContractClass) -> StorageResult; +} + +impl<'env, Mode: TransactionKind> CasmStorageReader for StorageTxn<'env, Mode> { + fn get_casm(&self, class_hash: &ClassHash) -> StorageResult> { + let casm_table = self.open_table(&self.tables.casms)?; + let casm_location = casm_table.get(&self.txn, class_hash)?; + casm_location.map(|location| self.file_handlers.get_casm_unchecked(location)).transpose() + } + + fn get_compiled_class_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::CompiledClass)?.unwrap_or_default()) + } +} + +impl<'env> CasmStorageWriter for StorageTxn<'env, RW> { + #[latency_histogram("storage_append_casm_latency_seconds", false)] + fn append_casm(self, class_hash: &ClassHash, casm: &CasmContractClass) -> StorageResult { + let casm_table = self.open_table(&self.tables.casms)?; + let markers_table = self.open_table(&self.tables.markers)?; + let state_diff_table = self.open_table(&self.tables.state_diffs)?; + let file_offset_table = self.txn.open_table(&self.tables.file_offsets)?; + + let location = self.file_handlers.append_casm(casm); + casm_table.insert(&self.txn, class_hash, &location)?; + file_offset_table.upsert(&self.txn, &OffsetKind::Casm, &location.next_offset())?; + update_marker( + &self.txn, + &markers_table, + &state_diff_table, + self.file_handlers.clone(), + class_hash, + )?; + Ok(self) + } +} + +fn update_marker<'env>( + txn: &DbTransaction<'env, RW>, + markers_table: &'env MarkersTable<'env>, + state_diffs_table: &'env TableHandle< + '_, + BlockNumber, + VersionZeroWrapper, + SimpleTable, + >, + file_handlers: FileHandlers, + class_hash: &ClassHash, +) -> StorageResult<()> { + // The marker needs to update if we reached the last class from the state diff. We can continue + // advancing it if the next blocks don't have declared classes. + let mut block_number = markers_table.get(txn, &MarkerKind::CompiledClass)?.unwrap_or_default(); + loop { + let Some(state_diff_location) = state_diffs_table.get(txn, &block_number)? else { + break; + }; + if let Some((last_class_hash, _)) = file_handlers + .get_thin_state_diff_unchecked(state_diff_location)? + .declared_classes + .last() + { + // Not the last class in the state diff, keep the current marker. + if last_class_hash != class_hash { + break; + } + } + block_number = block_number.unchecked_next(); + markers_table.upsert(txn, &MarkerKind::CompiledClass, &block_number)?; + } + Ok(()) +} diff --git a/crates/papyrus_storage/src/compiled_class_test.rs b/crates/papyrus_storage/src/compiled_class_test.rs new file mode 100644 index 00000000000..6ca0439402a --- /dev/null +++ b/crates/papyrus_storage/src/compiled_class_test.rs @@ -0,0 +1,55 @@ +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use pretty_assertions::assert_eq; +use starknet_api::core::ClassHash; +use test_utils::read_json_file; + +use crate::compiled_class::{CasmStorageReader, CasmStorageWriter}; +use crate::db::{DbError, KeyAlreadyExistsError}; +use crate::test_utils::get_test_storage; +use crate::StorageError; + +#[test] +fn append_casm() { + let casm_json = read_json_file("compiled_class.json"); + let expected_casm: CasmContractClass = serde_json::from_value(casm_json).unwrap(); + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + writer + .begin_rw_txn() + .unwrap() + .append_casm(&ClassHash::default(), &expected_casm) + .unwrap() + .commit() + .unwrap(); + + let casm = reader.begin_ro_txn().unwrap().get_casm(&ClassHash::default()).unwrap().unwrap(); + assert_eq!(casm, expected_casm); +} + +#[test] +fn casm_rewrite() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + + writer + .begin_rw_txn() + .unwrap() + .append_casm(&ClassHash::default(), &CasmContractClass::default()) + .unwrap() + .commit() + .unwrap(); + + let Err(err) = writer + .begin_rw_txn() + .unwrap() + .append_casm(&ClassHash::default(), &CasmContractClass::default()) + else { + panic!("Unexpected Ok."); + }; + + assert_matches!(err, StorageError::InnerError(DbError::KeyAlreadyExists(KeyAlreadyExistsError { + table_name: _, + key, + value: _ + })) if key == format!("{:?}", ClassHash::default())); +} diff --git a/crates/papyrus_storage/src/compression_utils.rs b/crates/papyrus_storage/src/compression_utils.rs new file mode 100644 index 00000000000..fd9c0de4b36 --- /dev/null +++ b/crates/papyrus_storage/src/compression_utils.rs @@ -0,0 +1,67 @@ +#[cfg(test)] +#[path = "compression_utils_test.rs"] +mod compression_utils_test; + +use crate::db::serialization::{StorageSerde, StorageSerdeError}; + +// TODO(dvir): create one compressor/decompressor only once (maybe only once per thread) to prevent +// buffer reallocation. +// TODO: fine tune the compression hyperparameters (and maybe even the compression algorithm). + +// The maximum size of the decompressed data. +// TODO(Dvir): consider defining this for each type separately and pass it as an argument to the +// decompress function. +pub(crate) const MAX_DECOMPRESSED_SIZE: usize = 1 << 28; // 256 MB +// The compression level to use. Higher levels are slower but compress better. +const COMPRESSION_LEVEL: i32 = zstd::DEFAULT_COMPRESSION_LEVEL; + +/// Returns the compressed data in a vector. +/// +/// # Arguments +/// * data - bytes to compress. +/// +/// # Errors +/// Returns [`std::io::Error`] if any read error is encountered. +pub fn compress(data: &[u8]) -> Result, std::io::Error> { + zstd::bulk::compress(data, COMPRESSION_LEVEL) +} + +/// Serialized and then compress object. +/// +/// # Arguments +/// * object - the object to serialize and compress. +/// +/// # Errors +/// Returns [`StorageSerdeError`] if any error is encountered in the serialization or compression. +pub fn serialize_and_compress(object: &impl StorageSerde) -> Result, StorageSerdeError> { + let mut buf = Vec::new(); + object.serialize_into(&mut buf)?; + Ok(compress(buf.as_slice())?) +} + +/// Decompress data and returns it as bytes in a vector. +/// +/// # Arguments +/// * data - bytes to decompress. + +/// # Errors +/// Returns [`std::io::Error`] if any read error is encountered. +pub fn decompress(data: &[u8]) -> Result, std::io::Error> { + zstd::bulk::decompress(data, MAX_DECOMPRESSED_SIZE) +} + +/// Decompress a vector directly from a reader. +/// In case of successful decompression, the vector will be returned; otherwise, None. +/// +/// # Arguments +/// * bytes - bytes to read. +pub fn decompress_from_reader(bytes: &mut impl std::io::Read) -> Option> { + let compressed_data = Vec::::deserialize_from(bytes)?; + decompress(compressed_data.as_slice()).ok() +} + +#[derive(Debug, Eq, PartialEq)] +pub(crate) enum IsCompressed { + No = 0, + Yes = 1, +} diff --git a/crates/papyrus_storage/src/compression_utils_test.rs b/crates/papyrus_storage/src/compression_utils_test.rs new file mode 100644 index 00000000000..7951cdcc97b --- /dev/null +++ b/crates/papyrus_storage/src/compression_utils_test.rs @@ -0,0 +1,25 @@ +use pretty_assertions::assert_eq; +use starknet_api::deprecated_contract_class::Program; +use test_utils::read_json_file; + +use super::{compress, decompress, decompress_from_reader, serialize_and_compress}; +use crate::db::serialization::StorageSerde; + +#[test] +fn bytes_compression() { + let bytes = vec![30, 5, 23, 12, 47]; + let x = decompress(compress(bytes.as_slice()).unwrap().as_slice()).unwrap(); + assert_eq!(bytes, x); +} + +#[test] +fn object_compression() { + let program_json = read_json_file("program.json"); + let program = serde_json::from_value::(program_json).unwrap(); + let compressed = serialize_and_compress(&program).unwrap(); + let mut buf = Vec::new(); + compressed.serialize_into(&mut buf).unwrap(); + let decompressed = decompress_from_reader(&mut buf.as_slice()).unwrap(); + let restored_program = Program::deserialize_from(&mut decompressed.as_slice()).unwrap(); + assert_eq!(program, restored_program); +} diff --git a/crates/papyrus_storage/src/db/db_stats.rs b/crates/papyrus_storage/src/db/db_stats.rs new file mode 100644 index 00000000000..a5649b56e54 --- /dev/null +++ b/crates/papyrus_storage/src/db/db_stats.rs @@ -0,0 +1,112 @@ +use human_bytes::human_bytes; +use libmdbx::Info; +use serde::{Deserialize, Serialize}; + +use super::{DbReader, DbResult}; + +/// A single table statistics. +#[derive(Serialize, Deserialize, Debug)] +pub struct DbTableStats { + /// Number of entries in the table. + pub entries: usize, + /// Number of branch pages in the table. + pub branch_pages: usize, + /// Depth of the table. + pub depth: u32, + /// Number of leaf pages in the table. + pub leaf_pages: usize, + /// Number of overflow pages in the table. + pub overflow_pages: usize, + /// Total size of the table. + #[serde(serialize_with = "readable_bytes")] + pub total_size: u64, + /// The table size as a portion of the whole database size. + #[serde(serialize_with = "float_precision")] + pub db_portion: f64, +} + +#[derive(Serialize, Deserialize, Debug)] +/// Statics about the whole database. +pub struct DbWholeStats { + /// Number of entries in the database. + pub entries: usize, + /// Number of branch pages in the database. + pub branch_pages: usize, + /// Number of leaf pages in the database. + pub leaf_pages: usize, + /// Number of overflow pages in the database. + pub overflow_pages: usize, + /// Total size of the database. + #[serde(serialize_with = "readable_bytes")] + pub total_size: u64, + /// Page size of the database. + #[serde(serialize_with = "readable_bytes")] + pub page_size: u64, + /// The number of pages in the free list. + pub freelist_size: usize, +} + +impl DbReader { + // Returns statistics about a specific table in the database. + pub(crate) fn get_table_stats(&self, name: &str) -> DbResult { + let db_txn = self.begin_ro_txn()?; + let table = db_txn.txn.open_table(Some(name))?; + let stat = db_txn.txn.table_stat(&table)?; + Ok(DbTableStats { + branch_pages: stat.branch_pages(), + depth: stat.depth(), + entries: stat.entries(), + leaf_pages: stat.leaf_pages(), + overflow_pages: stat.overflow_pages(), + total_size: stat.total_size(), + db_portion: stat.total_size() as f64 / self.env.stat()?.total_size() as f64, + }) + } + + // Returns statistics about the whole database. + pub(crate) fn get_db_stats(&self) -> DbResult { + let stat = self.env.stat()?; + Ok(DbWholeStats { + entries: stat.entries(), + branch_pages: stat.branch_pages(), + leaf_pages: stat.leaf_pages(), + overflow_pages: stat.overflow_pages(), + total_size: stat.total_size(), + page_size: stat.page_size().into(), + freelist_size: self.env.freelist()?, + }) + } + + // Returns information about the database. + pub(crate) fn get_db_info(&self) -> DbResult { + Ok(self.env.info()?) + } + + // Returns the the number of free pages in the database. + // NOTICE: currently, this function will return a garbage value due to a bug in the binding + // freelist function. + // TODO(dvir): bump libmdbx version when the bug is fixed. + pub(crate) fn get_free_pages(&self) -> DbResult { + Ok(self.env.freelist()?) + } +} + +// Serialize bytes as a human readable string. +// For example 1024*1024 bytes will be serialized as "1 MiB". +fn readable_bytes(bytes_num: &u64, s: S) -> Result +where + S: serde::Serializer, +{ + s.serialize_str(&human_bytes(*bytes_num as f64)) +} + +// Serialize float with 4 decimal points. +// For example 0.123456 will be serialized to 0.1234. +fn float_precision(float: &f64, s: S) -> Result +where + S: serde::Serializer, +{ + const PRECISION: u32 = 4; + let power = u32::pow(10, PRECISION) as f64; + s.serialize_f64((*float * power).round() / power) +} diff --git a/crates/papyrus_storage/src/db/db_test.rs b/crates/papyrus_storage/src/db/db_test.rs new file mode 100644 index 00000000000..747d88f4581 --- /dev/null +++ b/crates/papyrus_storage/src/db/db_test.rs @@ -0,0 +1,381 @@ +use assert_matches::assert_matches; +use libmdbx::PageSize; +use pretty_assertions::assert_eq; +use tempfile::TempDir; + +use crate::db::serialization::{NoVersionValueWrapper, ValueSerde, VersionZeroWrapper}; +use crate::db::table_types::Table; +use crate::db::{get_page_size, open_env, DbError, DbIter, DbReader, DbResult, DbWriter}; +use crate::test_utils::get_test_config; + +pub(crate) fn get_test_env() -> ((DbReader, DbWriter), TempDir) { + let (config, temp_dir) = get_test_config(None); + (open_env(&config.db_config).expect("Failed to open environment."), temp_dir) +} + +#[test] +fn open_env_scenario() { + get_test_env(); +} + +#[test] +fn open_env_with_enforce_file_exists() { + let (config, _temp_dir) = get_test_config(None); + let mut db_config = config.db_config; + db_config.enforce_file_exists = true; + + // First call to `open_env` with `enforce_file_exists` set to `true` should fail because + // the file does not exist yet. This equals to starting a new chain, where this flag must be + // off. + let result = open_env(&db_config); + assert_matches!(result, Err(DbError::FileDoesNotExist(_))); + + // Make sure that file in the expected file indeed does not exist. + let mut mdbx_file_exists = db_config.path().join("mdbx.dat").exists(); + assert_eq!(mdbx_file_exists, false); + + // Set `enforce_file_exists` to `false` and try again. + // This equals to opening a new chain, where this flag is off. + db_config.enforce_file_exists = false; + + // Second call to `open_env` should succeed and create the mdbx.dat file in the new env. + // Called inside a block to drop the db handlers before the next call. + { + let result: DbResult<(DbReader, DbWriter)> = open_env(&db_config); + assert_matches!(result, Ok(_)); + } + + // Ensure that mdbx.dat file exists in the expected location. + // Third call with `enforce_file_exists` flag set to `true` should succeed. + mdbx_file_exists = db_config.path().join("mdbx.dat").exists(); + assert_eq!(mdbx_file_exists, true); + + db_config.enforce_file_exists = true; + let result: DbResult<(DbReader, DbWriter)> = open_env(&db_config); + assert_matches!(result, Ok(_)); + + // Add some charachter to the path to make it invalid. + // Fourth and final call to `open_env` with path enforcement should fail because the path is + // invalid. + db_config.path_prefix = db_config.path_prefix.join("2"); + let result = open_env(&db_config); + assert_matches!(result, Err(DbError::FileDoesNotExist(_))); +} + +#[test] +fn txns_scenarios() { + // Create an environment and a table. + let ((reader, mut writer), _temp_dir) = get_test_env(); + let table_id = + writer.create_simple_table::<[u8; 3], NoVersionValueWrapper<[u8; 5]>>("table").unwrap(); + + // Snapshot state by creating a read txn. + let txn0 = reader.begin_ro_txn().unwrap(); + let table = txn0.open_table(&table_id).unwrap(); + + // Insert a value. + let wtxn = writer.begin_rw_txn().unwrap(); + table.insert(&wtxn, b"key", b"data0").unwrap(); + wtxn.commit().unwrap(); + + // Snapshot state by creating a read txn. + let txn1 = reader.begin_ro_txn().unwrap(); + + // Update the value. + let wtxn = writer.begin_rw_txn().unwrap(); + table.upsert(&wtxn, b"key", b"data1").unwrap(); + wtxn.commit().unwrap(); + + // Snapshot state by creating a read txn. + let txn2 = reader.begin_ro_txn().unwrap(); + + // Delete the value. + let wtxn2 = writer.begin_rw_txn().unwrap(); + table.delete(&wtxn2, b"key").unwrap(); + wtxn2.commit().unwrap(); + + // Snapshot state by creating a read txn. + let txn3 = reader.begin_ro_txn().unwrap(); + + // Validate data in snapshots. + assert_eq!(table.get(&txn0, b"key").unwrap(), None); + assert_eq!(table.get(&txn1, b"key").unwrap(), Some(*b"data0")); + assert_eq!(table.get(&txn2, b"key").unwrap(), Some(*b"data1")); + assert_eq!(table.get(&txn3, b"key").unwrap(), None); +} + +#[test] + +fn table_stats() { + // Create an environment and a table. + let ((reader, mut writer), _temp_dir) = get_test_env(); + let table_id = + writer.create_simple_table::<[u8; 3], NoVersionValueWrapper<[u8; 5]>>("table").unwrap(); + + // Empty table stats. + let empty_stat = reader.get_table_stats("table").unwrap(); + assert_eq!(empty_stat.branch_pages, 0); + assert_eq!(empty_stat.depth, 0); + assert_eq!(empty_stat.entries, 0); + assert_eq!(empty_stat.overflow_pages, 0); + assert_eq!(empty_stat.leaf_pages, 0); + + // Insert a value. + let wtxn = writer.begin_rw_txn().unwrap(); + let table = wtxn.open_table(&table_id).unwrap(); + table.insert(&wtxn, b"key", b"data0").unwrap(); + wtxn.commit().unwrap(); + + // Non-empty table stats. + let empty_stat = reader.get_table_stats("table").unwrap(); + assert_eq!(empty_stat.branch_pages, 0); + assert_eq!(empty_stat.depth, 1); + assert_eq!(empty_stat.entries, 1); + assert_eq!(empty_stat.overflow_pages, 0); + assert_eq!(empty_stat.leaf_pages, 1); + + // Delete the value. + let wtxn = writer.begin_rw_txn().unwrap(); + let table = wtxn.open_table(&table_id).unwrap(); + table.delete(&wtxn, b"key").unwrap(); + wtxn.commit().unwrap(); + + // Empty table stats. + let empty_stat = reader.get_table_stats("table").unwrap(); + assert_eq!(empty_stat.branch_pages, 0); + assert_eq!(empty_stat.depth, 0); + assert_eq!(empty_stat.entries, 0); + assert_eq!(empty_stat.overflow_pages, 0); + assert_eq!(empty_stat.leaf_pages, 0); +} + +use super::serialization::{Migratable, StorageSerde, StorageSerdeError, VersionWrapper}; +use super::{MDBX_MAX_PAGESIZE, MDBX_MIN_PAGESIZE}; +#[test] +fn get_page_size_test() { + // Good values. + assert_eq!(get_page_size(MDBX_MIN_PAGESIZE), PageSize::Set(MDBX_MIN_PAGESIZE)); + assert_eq!(get_page_size(4096), PageSize::Set(4096)); + assert_eq!(get_page_size(MDBX_MAX_PAGESIZE), PageSize::Set(MDBX_MAX_PAGESIZE)); + + // Range fix. + assert_eq!(get_page_size(MDBX_MIN_PAGESIZE - 1), PageSize::Set(MDBX_MIN_PAGESIZE)); + assert_eq!(get_page_size(MDBX_MAX_PAGESIZE + 1), PageSize::Set(MDBX_MAX_PAGESIZE)); + + // Power of two fix. + assert_eq!(get_page_size(1025), PageSize::Set(1024)); + assert_eq!(get_page_size(2047), PageSize::Set(1024)); +} + +#[test] +fn test_iter() { + // Create an environment and a table. + let ((reader, mut writer), _temp_dir) = get_test_env(); + let table_id = + writer.create_simple_table::<[u8; 4], NoVersionValueWrapper<[u8; 4]>>("table").unwrap(); + + // Insert some values. + let items = vec![ + (*b"key1", *b"val1"), + (*b"key2", *b"val2"), + (*b"key3", *b"val3"), + (*b"key5", *b"val5"), + ]; + let wtxn = writer.begin_rw_txn().unwrap(); + let table = wtxn.open_table(&table_id).unwrap(); + for (k, v) in &items { + table.insert(&wtxn, k, v).unwrap(); + } + wtxn.commit().unwrap(); + + // Use the iterator. + let txn = reader.begin_ro_txn().unwrap(); + let mut cursor = txn.open_table(&table_id).unwrap().cursor(&txn).unwrap(); + let iter = DbIter::new(&mut cursor); + assert_eq!(items, iter.collect::>>().unwrap()); + + let mut cursor = txn.open_table(&table_id).unwrap().cursor(&txn).unwrap(); + let mut iter = DbIter::new(&mut cursor); + let mut index = 0; + while let Some(Ok((k, v))) = iter.next() { + assert_eq!(items[index], (k, v)); + index += 1; + } +} + +#[test] +fn with_version_zero_serialization() { + let ((reader, mut writer), _temp_dir) = get_test_env(); + let table_id = + writer.create_simple_table::<[u8; 4], VersionZeroWrapper<[u8; 4]>>("table").unwrap(); + + let items = vec![ + (*b"key1", *b"val1"), + (*b"key2", *b"val2"), + (*b"key3", *b"val3"), + (*b"key5", *b"val5"), + ]; + let wtxn = writer.begin_rw_txn().unwrap(); + let table = wtxn.open_table(&table_id).unwrap(); + for (k, v) in &items { + table.insert(&wtxn, k, v).unwrap(); + } + wtxn.commit().unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + let mut cursor = txn.open_table(&table_id).unwrap().cursor(&txn).unwrap(); + let iter = DbIter::new(&mut cursor); + assert_eq!(items, iter.collect::>>().unwrap()); + + // TODO: move to serialization tests. + const A_RANDOM_U8: u8 = 123; + let with_zero_version_serialization = + VersionZeroWrapper::::serialize(&A_RANDOM_U8).unwrap(); + assert_eq!(with_zero_version_serialization, vec![0, 123]); + assert_eq!( + VersionZeroWrapper::::deserialize(&mut with_zero_version_serialization.as_slice()), + Some(A_RANDOM_U8) + ); + + let with_no_version_serialization = + NoVersionValueWrapper::::serialize(&A_RANDOM_U8).unwrap(); + assert_eq!(with_no_version_serialization, vec![123]); + assert_eq!( + NoVersionValueWrapper::::deserialize(&mut with_no_version_serialization.as_slice()), + Some(A_RANDOM_U8) + ); +} + +#[derive(Clone, Debug, Default, Ord, Eq, PartialEq, PartialOrd)] +struct Key { + pub k: u8, +} + +impl StorageSerde for Key { + fn serialize_into(&self, writer: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.k.serialize_into(writer) + } + + fn deserialize_from(reader: &mut impl std::io::Read) -> Option { + Some(Self { k: u8::deserialize_from(reader)? }) + } +} + +#[derive(Clone, Debug, Default, Ord, Eq, PartialEq, PartialOrd)] +struct V0 { + pub x: u8, + pub y: u8, +} + +impl StorageSerde for V0 { + fn serialize_into(&self, writer: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.x.serialize_into(writer)?; + self.y.serialize_into(writer) + } + + fn deserialize_from(reader: &mut impl std::io::Read) -> Option { + Some(Self { x: u8::deserialize_from(reader)?, y: u8::deserialize_from(reader)? }) + } +} + +#[derive(Clone, Debug, Default, Ord, Eq, PartialEq, PartialOrd)] +struct V1 { + pub x: u8, + pub y: u8, + pub z: u8, +} + +impl StorageSerde for V1 { + fn serialize_into(&self, writer: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.x.serialize_into(writer)?; + self.y.serialize_into(writer)?; + self.z.serialize_into(writer) + } + + fn deserialize_from(reader: &mut impl std::io::Read) -> Option { + Some(Self { + x: u8::deserialize_from(reader)?, + y: u8::deserialize_from(reader)?, + z: u8::deserialize_from(reader)?, + }) + } +} + +impl Migratable for V1 { + fn try_from_older_version( + bytes: &mut impl std::io::Read, + older_version: u8, + ) -> Result { + if older_version != 0 { + println!("Unexpected older version: {}", older_version); + return Err(StorageSerdeError::Migration); + } + V0::deserialize_from(bytes) + .map(|v0| V1 { x: v0.x, y: v0.y, z: 0 }) + .ok_or(StorageSerdeError::Migration) + } +} + +#[test] +fn version_migration() { + let ((reader, mut writer), _temp_dir) = get_test_env(); + let table_name = "table"; + + let v0_table_id = + writer.create_simple_table::>(table_name).unwrap(); + let key0 = Key { k: 0 }; + let expected_v0 = V0::default(); + // Insert a V0 entry into a table. + { + let txn = writer.begin_rw_txn().unwrap(); + let v0_table = txn.open_table(&v0_table_id).unwrap(); + v0_table.insert(&txn, &key0, &expected_v0).unwrap(); + txn.commit().unwrap(); + } + // Verify that the entry is present in the table. + { + let txn = reader.begin_ro_txn().unwrap(); + let v0_table = txn.open_table(&v0_table_id).unwrap(); + let v0 = v0_table.get(&txn, &key0).unwrap().unwrap(); + assert_eq!(v0, expected_v0); + } + // Open the same table as a V1 table. + let v1_table_id = writer.create_simple_table::>(table_name).unwrap(); + + // Insert a V1 entry into the V1 table. + let key1 = Key { k: 1 }; + let expected_v1 = V1::default(); + { + let txn = writer.begin_rw_txn().unwrap(); + let v1_table = txn.open_table(&v1_table_id).unwrap(); + v1_table.insert(&txn, &key1, &expected_v1).unwrap(); + txn.commit().unwrap(); + } + + // Verify that the V1 entry is present in the V1 table. + { + let txn = reader.begin_ro_txn().unwrap(); + let v1_table = txn.open_table(&v1_table_id).unwrap(); + let v1 = v1_table.get(&txn, &key1).unwrap().unwrap(); + assert_eq!(v1, expected_v1); + } + + // Try to get the V0 entry as a V1 entry. + { + let txn = reader.begin_ro_txn().unwrap(); + let v1_table = txn.open_table(&v1_table_id).unwrap(); + let v0_as_v1 = v1_table.get(&txn, &key0).unwrap(); + assert!(v0_as_v1.is_some()); + let v0_as_v1 = v0_as_v1.unwrap(); + let expected_v1 = V1 { x: expected_v0.x, y: expected_v0.y, z: 0 }; + assert_eq!(v0_as_v1, expected_v1); + } + + // Try to get the V1 entry as a V0 entry. + { + let txn = reader.begin_ro_txn().unwrap(); + let v0_table = txn.open_table(&v0_table_id).unwrap(); + let v1_as_v0 = v0_table.get(&txn, &key1).unwrap_err(); + assert_matches!(v1_as_v0, DbError::InnerDeserialization); + } +} diff --git a/crates/papyrus_storage/src/db/mod.rs b/crates/papyrus_storage/src/db/mod.rs new file mode 100644 index 00000000000..725f3f7517a --- /dev/null +++ b/crates/papyrus_storage/src/db/mod.rs @@ -0,0 +1,354 @@ +//! Basic structs for interacting with the db. +//! +//! Low database layer for interaction with libmdbx. The API is supposedly generic enough to easily +//! replace the database library with other Berkley-like database implementations. +//! +//! Assumptions: +//! - The database is transactional with full ACID semantics. +//! - The keys are always sorted and range lookups are supported. +//! +//! Guarantees: +//! - The serialization is consistent across code versions (though, not necessarily across +//! machines). + +#[cfg(test)] +mod db_test; + +/// Statistics and information about the database. +pub mod db_stats; +// TODO(yair): Make the serialization module pub(crate). +#[doc(hidden)] +pub mod serialization; +pub(crate) mod table_types; + +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::fmt::Debug; +use std::marker::PhantomData; +use std::path::PathBuf; +use std::result; +use std::sync::Arc; + +use libmdbx::{DatabaseFlags, Geometry, PageSize, WriteMap}; +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::validators::{validate_ascii, validate_path_exists}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_api::core::ChainId; +use validator::Validate; + +use self::serialization::{Key, ValueSerde}; +use self::table_types::{DbCursor, DbCursorTrait}; +use crate::db::table_types::TableType; + +// Maximum number of Sub-Databases. +const MAX_DBS: usize = 18; + +// Note that NO_TLS mode is used by default. +type EnvironmentKind = WriteMap; +type Environment = libmdbx::Database; + +type DbKeyType<'env> = Cow<'env, [u8]>; +type DbValueType<'env> = Cow<'env, [u8]>; + +/// The configuration of the database. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Validate)] +pub struct DbConfig { + /// The path prefix of the database files. The final path is the path prefix followed by the + /// chain id. + #[validate(custom = "validate_path_exists")] + pub path_prefix: PathBuf, + /// The [chain id](https://docs.rs/starknet_api/latest/starknet_api/core/struct.ChainId.html) of the Starknet network. + #[validate(custom = "validate_ascii")] + pub chain_id: ChainId, + /// Whether to enforce that the path exists. If true, `open_env` fails when the mdbx.dat file + /// does not exist. + pub enforce_file_exists: bool, + /// The minimum size of the database. + pub min_size: usize, + /// The maximum size of the database. + pub max_size: usize, + /// The growth step of the database. + pub growth_step: isize, +} + +impl Default for DbConfig { + fn default() -> Self { + DbConfig { + path_prefix: PathBuf::from("./data"), + chain_id: ChainId::Mainnet, + enforce_file_exists: false, + min_size: 1 << 20, // 1MB + max_size: 1 << 40, // 1TB + growth_step: 1 << 32, // 4GB + } + } +} + +impl SerializeConfig for DbConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "path_prefix", + &self.path_prefix, + "Prefix of the path of the node's storage directory, the storage file path \ + will be /. The path is not created automatically.", + ParamPrivacyInput::Public, + ), + ser_param( + "chain_id", + &self.chain_id, + "The chain to follow. For more details see https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#chain-id.", + ParamPrivacyInput::Public, + ), + ser_param( + "enforce_file_exists", + &self.enforce_file_exists, + "Whether to enforce that the path exists. If true, `open_env` fails when the \ + mdbx.dat file does not exist.", + ParamPrivacyInput::Public, + ), + ser_param( + "min_size", + &self.min_size, + "The minimum size of the node's storage in bytes.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_size", + &self.max_size, + "The maximum size of the node's storage in bytes.", + ParamPrivacyInput::Public, + ), + ser_param( + "growth_step", + &self.growth_step, + "The growth step in bytes, must be greater than zero to allow the database to \ + grow.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl DbConfig { + /// Returns the path of the database (path prefix, followed by the chain id). + pub fn path(&self) -> PathBuf { + self.path_prefix.join(self.chain_id.to_string().as_str()) + } +} + +/// An error that can occur when interacting with the database. +#[derive(thiserror::Error, Debug)] +pub enum DbError { + /// An error that occurred in the database library. + #[error(transparent)] + Inner(#[from] libmdbx::Error), + /// An error that occurred when tried to insert a key that already exists in a table. + #[error( + "Key '{}' already exists in table '{}'. Error when tried to insert value '{}'", .0.key, + .0.table_name, .0.value + )] + KeyAlreadyExists(KeyAlreadyExistsError), + #[error("Deserialization failed.")] + /// An error that occurred during deserialization. + InnerDeserialization, + /// An error that occurred during serialization. + #[error("Serialization failed.")] + Serialization, + /// An error that occurred when trying to open a db file that does not exist. + #[error("The file '{0}' does not exist.")] + FileDoesNotExist(PathBuf), + // TODO(dvir): consider adding more details about the error, table name, key, value and last + // key in the tree. + /// An error that occurred when trying to append a key when it is not the last. + #[error("Append error. The key is not the last in the table.")] + Append, +} + +type DbResult = result::Result; + +/// A helper struct for DbError::KeyAlreadyExists. +#[derive(Debug)] +pub struct KeyAlreadyExistsError { + /// The name of the table. + pub table_name: &'static str, + /// The key that already exists in the table. + pub key: String, + /// The value that was tried to be inserted. + pub value: String, +} + +impl KeyAlreadyExistsError { + /// Creates a new KeyAlreadyExistsError. + pub fn new(table_name: &'static str, key: &impl Debug, value: &impl Debug) -> Self { + Self { table_name, key: format!("{:?}", key), value: format!("{:?}", value) } + } +} + +/// Tries to open an MDBX environment and returns a reader and a writer to it. +/// There is a single non clonable writer instance, to make sure there is only one write transaction +/// at any given moment. +pub(crate) fn open_env(config: &DbConfig) -> DbResult<(DbReader, DbWriter)> { + let db_file_path = config.path().join("mdbx.dat"); + // Checks if path exists if enforce_file_exists is true. + if config.enforce_file_exists && !db_file_path.exists() { + return Err(DbError::FileDoesNotExist(db_file_path)); + } + const MAX_READERS: u32 = 1 << 13; // 8K readers + let env = Arc::new( + Environment::new() + .set_geometry(Geometry { + size: Some(config.min_size..config.max_size), + growth_step: Some(config.growth_step), + page_size: Some(get_page_size(page_size::get())), + ..Default::default() + }) + .set_max_tables(MAX_DBS) + .set_max_readers(MAX_READERS) + .set_flags(DatabaseFlags { + // There is no locality of pages in the database almost at all, so readahead will + // fill the RAM with garbage. + no_rdahead: true, + // LIFO policy for recycling a Garbage Collection items should be faster. + liforeclaim: true, + ..Default::default() + }) + .open(&config.path())?, + ); + Ok((DbReader { env: env.clone() }, DbWriter { env })) +} + +// Size in bytes. +const MDBX_MIN_PAGESIZE: usize = 256; +const MDBX_MAX_PAGESIZE: usize = 65536; // 64KB + +fn get_page_size(os_page_size: usize) -> PageSize { + let mut page_size = os_page_size.clamp(MDBX_MIN_PAGESIZE, MDBX_MAX_PAGESIZE); + + // Page size must be power of two. + if !page_size.is_power_of_two() { + page_size = page_size.next_power_of_two() / 2; + } + + PageSize::Set(page_size) +} + +#[derive(Clone, Debug)] +pub(crate) struct DbReader { + env: Arc, +} + +#[derive(Debug)] +pub(crate) struct DbWriter { + env: Arc, +} + +impl DbReader { + pub(crate) fn begin_ro_txn(&self) -> DbResult> { + Ok(DbReadTransaction { txn: self.env.begin_ro_txn()? }) + } +} + +type DbReadTransaction<'env> = DbTransaction<'env, RO>; + +impl DbWriter { + pub(crate) fn begin_rw_txn(&mut self) -> DbResult> { + Ok(DbWriteTransaction { txn: self.env.begin_rw_txn()? }) + } +} + +type DbWriteTransaction<'env> = DbTransaction<'env, RW>; + +impl<'a> DbWriteTransaction<'a> { + pub(crate) fn commit(self) -> DbResult<()> { + self.txn.commit()?; + Ok(()) + } +} + +#[doc(hidden)] +// Transaction wrappers. +pub trait TransactionKind { + type Internal: libmdbx::TransactionKind; +} + +pub(crate) struct DbTransaction<'env, Mode: TransactionKind> { + txn: libmdbx::Transaction<'env, Mode::Internal, EnvironmentKind>, +} + +impl<'a, Mode: TransactionKind> DbTransaction<'a, Mode> { + pub fn open_table<'env, K: Key + Debug, V: ValueSerde + Debug, T: TableType>( + &'env self, + table_id: &TableIdentifier, + ) -> DbResult> { + let database = self.txn.open_table(Some(table_id.name))?; + Ok(TableHandle { + database, + name: table_id.name, + _key_type: PhantomData {}, + _value_type: PhantomData {}, + _table_type: PhantomData {}, + }) + } +} +pub(crate) struct TableIdentifier { + pub(crate) name: &'static str, + _key_type: PhantomData, + _value_type: PhantomData, + _table_type: PhantomData, +} + +pub(crate) struct TableHandle<'env, K: Key + Debug, V: ValueSerde + Debug, T: TableType> { + database: libmdbx::Table<'env>, + name: &'static str, + _key_type: PhantomData, + _value_type: PhantomData, + _table_type: PhantomData, +} + +/// Iterator for iterating over a DB table +pub(crate) struct DbIter<'cursor, 'txn, Mode: TransactionKind, K: Key, V: ValueSerde, T: TableType> +{ + cursor: &'cursor mut DbCursor<'txn, Mode, K, V, T>, + _key_type: PhantomData, + _value_type: PhantomData, +} + +impl<'cursor, 'txn, Mode: TransactionKind, K: Key, V: ValueSerde, T: TableType> + DbIter<'cursor, 'txn, Mode, K, V, T> +{ + #[allow(dead_code)] + pub(crate) fn new(cursor: &'cursor mut DbCursor<'txn, Mode, K, V, T>) -> Self { + Self { cursor, _key_type: PhantomData {}, _value_type: PhantomData {} } + } +} + +impl<'cursor, 'txn, Mode: TransactionKind, K: Key, V: ValueSerde, T: TableType> Iterator + for DbIter<'cursor, 'txn, Mode, K, V, T> +where + DbCursor<'txn, Mode, K, V, T>: DbCursorTrait, +{ + type Item = DbResult<(K, V::Value)>; + + fn next(&mut self) -> Option { + let prev_cursor_res = self.cursor.next().transpose()?; + Some(prev_cursor_res) + } +} + +#[doc(hidden)] +#[derive(Clone, Copy, Debug)] +pub struct RO {} + +impl TransactionKind for RO { + type Internal = libmdbx::RO; +} + +#[doc(hidden)] +#[derive(Clone, Copy, Debug)] +pub struct RW {} + +impl TransactionKind for RW { + type Internal = libmdbx::RW; +} diff --git a/crates/papyrus_storage/src/db/serialization.rs b/crates/papyrus_storage/src/db/serialization.rs new file mode 100644 index 00000000000..0ff9f28ae3c --- /dev/null +++ b/crates/papyrus_storage/src/db/serialization.rs @@ -0,0 +1,179 @@ +use std::fmt::Debug; +use std::io::Write; +use std::marker::PhantomData; + +use tracing::{debug, error}; + +use crate::db::DbError; + +/// Trait for serializing and deserializing values. +pub(crate) trait StorageSerdeEx: StorageSerde { + fn serialize(&self) -> Result, DbError>; + + fn deserialize(bytes: &mut impl std::io::Read) -> Option; +} + +impl StorageSerdeEx for T { + fn serialize(&self) -> Result, DbError> { + let mut res: Vec = Vec::new(); + self.serialize_into(&mut res).map_err(|_| DbError::Serialization)?; + Ok(res) + } + + fn deserialize(bytes: &mut impl std::io::Read) -> Option { + let res = Self::deserialize_from(bytes)?; + if !is_all_bytes_read(bytes) { + return None; + } + Some(res) + } +} + +/// Trait for deserializing and serializing values into buffers. +pub trait StorageSerde: Sized { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError>; + + // TODO(dan): consider returning a result here. We probably transform this into + // InnerDeserialization error, so having more context might be useful. + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option; +} + +/// Trait that enforces a database key to implement `StorageSerdeEx`, `Ord` and `Clone`. +pub(crate) trait Key: StorageSerdeEx + Ord + Clone {} +impl Key for T where T: StorageSerdeEx + Ord + Clone {} + +/// Trait for serializing and deserializing values from the database. +pub(crate) trait ValueSerde { + type Value: StorageSerde + Debug; + + fn serialize(obj: &Self::Value) -> Result, DbError>; + // TODO(yair): Return a result here. + fn deserialize(bytes: &mut impl std::io::Read) -> Option; +} + +#[derive(Clone, Debug)] +/// A generic wrapper for values that do not have a version. +pub(crate) struct NoVersionValueWrapper { + _value_type: PhantomData, +} + +impl ValueSerde for NoVersionValueWrapper { + type Value = T; + + fn serialize(obj: &Self::Value) -> Result, DbError> { + StorageSerdeEx::serialize(obj) + } + + fn deserialize(bytes: &mut impl std::io::Read) -> Option { + StorageSerdeEx::deserialize(bytes) + } +} + +// TODO(Eitan): Implement this wrapper struct as VersionWrapper with version 0. +#[derive(Clone, Debug)] +/// A generic wrapper for values with version zero. These values are serialized with a leading byte +/// that is set to zero. +pub(crate) struct VersionZeroWrapper { + _value_type: PhantomData, +} + +const VERSION_ZERO: u8 = 0; + +impl ValueSerde for VersionZeroWrapper { + type Value = T; + + fn serialize(obj: &Self::Value) -> Result, DbError> { + let mut res = Vec::new(); + res.write_all(&[VERSION_ZERO]).expect("Failed to write version"); + obj.serialize_into(&mut res).map_err(|_| DbError::Serialization)?; + Ok(res) + } + + fn deserialize(bytes: &mut impl std::io::Read) -> Option { + let mut version = [0u8; 1]; + bytes.read_exact(&mut version[..]).ok()?; + if version[0] != VERSION_ZERO { + return None; + } + let res = Self::Value::deserialize_from(bytes)?; + + if !is_all_bytes_read(bytes) { + return None; + } + Some(res) + } +} + +/// Trait for migrating values from older versions. +pub(crate) trait Migratable { + /// Tries to migrate the value from an older version. + fn try_from_older_version( + bytes: &mut impl std::io::Read, + older_version: u8, + ) -> Result + where + Self: std::marker::Sized; +} + +/// A generic wrapper for values with version. These values are serialized with a leading byte +/// that is set to the version. When deserializing, the version is checked and the value is migrated +/// if the serialization is of an older version. +#[derive(Clone, Debug)] +pub(crate) struct VersionWrapper { + _value_type: PhantomData, +} + +impl ValueSerde + for VersionWrapper +{ + type Value = T; + + fn serialize(obj: &Self::Value) -> Result, DbError> { + let mut res = Vec::new(); + res.write_all(&[VERSION]).expect("Failed to write version"); + obj.serialize_into(&mut res).map_err(|_| DbError::Serialization)?; + Ok(res) + } + + fn deserialize(bytes: &mut impl std::io::Read) -> Option { + let mut version = [0u8; 1]; + bytes.read_exact(&mut version[..]).ok()?; + if version[0] > VERSION { + error!( + "Unable to deserialize value with version {} into version {}", + version[0], VERSION + ); + return None; + } + let res = if version[0] < VERSION { + debug!("Migrating value with version {} to version {}", version[0], VERSION); + T::try_from_older_version(bytes, version[0]).ok()? + } else { + Self::Value::deserialize_from(bytes)? + }; + + if !is_all_bytes_read(bytes) { + return None; + } + Some(res) + } +} + +/// Error type for serialization and deserialization. +#[derive(thiserror::Error, Debug)] +pub enum StorageSerdeError { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + Serde(#[from] serde_json::Error), + /// An error occurred during migration. + #[error("Failed to migrate value")] + Migration, +} + +// Make sure we are at EOF. +fn is_all_bytes_read(bytes: &mut impl std::io::Read) -> bool { + let mut buf = [0u8, 1]; + // TODO: return an error instead of false. + bytes.read(&mut buf[..]).ok() == Some(0) +} diff --git a/crates/papyrus_storage/src/db/table_types/dup_sort_tables.rs b/crates/papyrus_storage/src/db/table_types/dup_sort_tables.rs new file mode 100644 index 00000000000..7c607b6b9d3 --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/dup_sort_tables.rs @@ -0,0 +1,470 @@ +#[cfg(test)] +#[path = "dup_sort_tables_test.rs"] +mod dup_sort_tables_test; + +use std::borrow::Cow; +use std::fmt::Debug; +use std::marker::PhantomData; + +use libmdbx::{TableFlags, WriteFlags}; + +use super::{DbResult, Table, TableType}; +use crate::db::serialization::{Key as KeyTrait, StorageSerde, StorageSerdeEx, ValueSerde}; +use crate::db::{ + DbCursor, + DbCursorTrait, + DbError, + DbKeyType, + DbTransaction, + DbValueType, + DbWriter, + KeyAlreadyExistsError, + TableHandle, + TableIdentifier, + TransactionKind, + RW, +}; + +// NOTICE: If a write operation fails (insert, upsert, append, delete, append_greater_sub_key), the +// transaction should not be committed. Doing so can cause a corrupt database. +// TODO(dvir): enforce this in code. + +// TODO(dvir): add the following table types: 1. key suffix and value with fixed size. 2. key and +// value with a fixed size. This is not done because of a bug in the libmdbx `DUP_FIXED` feature. We +// should be careful when using this feature. + +// All tables types that use libmdbx `DUP_SORT` feature +trait DupSortTableType {} +impl TableType for T {} + +// A table with keys with common prefix. The same common prefix will be saved only once. +// NOTICE: the size of the serialized sub-key and value must be no more than half of page size. +pub(crate) struct CommonPrefix; + +impl DupSortTableType for CommonPrefix {} + +// TODO(dvir): consider move this to the end of the file. +// This trait represents the required functionality for table types using libmdbx `DUP_SORT` +// feature, ensuring their automatic implementation of the Table trait (along with the cursor +// trait). +trait DupSortUtils { + // Returns the main-key bytes. + fn get_main_key(key: &K) -> DbResult>; + + // Returns the sub-key bytes. + fn get_sub_key(key: &K) -> DbResult>; + + // Returns the sub-key and value bytes. + fn get_sub_key_and_value(key: &K, value: &V::Value) -> DbResult>; + + // Returns the first sub-key (bytes) that is greater than or equal to sub-key of the given key. + fn get_sub_key_lower_bound(key: &K) -> DbResult>; + + // Changes main_key_bytes to the next greater one. + fn next_main_key(main_key_bytes: &mut Vec); + + // Returns a key value pair from main_key bytes and sub_key_value bytes. None will return in + // case of a failure. + fn get_key_value_pair(main_key: &[u8], sub_key_and_value: &[u8]) -> Option<(K, V::Value)>; +} + +// TODO(dvir): consider add test for the implementation. +impl DupSortUtils<(MainKey, SubKey), V> + for CommonPrefix +where + (MainKey, SubKey): KeyTrait, +{ + fn get_main_key(key: &(MainKey, SubKey)) -> DbResult> { + key.0.serialize() + } + + fn get_sub_key(key: &(MainKey, SubKey)) -> DbResult> { + key.1.serialize() + } + + fn get_sub_key_and_value<'a>(key: &(MainKey, SubKey), value: &V::Value) -> DbResult> { + let mut res = Vec::new(); + key.1.serialize_into(&mut res).map_err(|_| DbError::Serialization)?; + value.serialize_into(&mut res).map_err(|_| DbError::Serialization)?; + Ok(res) + } + + fn get_sub_key_lower_bound(key: &(MainKey, SubKey)) -> DbResult> { + key.1.serialize() + } + + fn next_main_key(main_key_bytes: &mut Vec) { + add_one(main_key_bytes); + } + + fn get_key_value_pair( + mut main_key: &[u8], + mut sub_key_and_value: &[u8], + ) -> Option<((MainKey, SubKey), V::Value)> { + // The SubKey::deserialize_from and not SubKey::deserialize is because the deserialize + // function also checks all the bytes were used, which is not the case before + // deserialize also the value from sub_key_value. + Some(( + ( + MainKey::deserialize(&mut main_key)?, + SubKey::deserialize_from(&mut sub_key_and_value)?, + ), + V::Value::deserialize(&mut sub_key_and_value)?, + )) + } +} + +// Adds one to the number represented by the bytes. +fn add_one(bytes: &mut Vec) { + for byte in bytes.iter_mut().rev() { + if *byte == u8::MAX { + *byte = 0; + } else { + *byte += 1; + return; // No need to continue if there is no carry. + } + } + + // If we reach this point, it means there was a carry into the most significant byte. + bytes.insert(0, 1); +} + +impl DbWriter { + #[allow(dead_code)] + pub(crate) fn create_common_prefix_table< + MainKey: KeyTrait + Debug, + SubKey: KeyTrait + Debug, + V: ValueSerde + Debug, + >( + &mut self, + name: &'static str, + ) -> DbResult> + where + (MainKey, SubKey): KeyTrait + Debug, + { + let txn = self.env.begin_rw_txn()?; + txn.create_table(Some(name), TableFlags::DUP_SORT)?; + txn.commit()?; + Ok(TableIdentifier { + name, + _key_type: PhantomData {}, + _value_type: PhantomData {}, + _table_type: PhantomData {}, + }) + } +} + +impl<'env, K: KeyTrait + Debug, V: ValueSerde + Debug, T: DupSortTableType + DupSortUtils> + Table<'env> for TableHandle<'env, K, V, T> +{ + type Key = K; + type Value = V; + type TableVariant = T; + + fn cursor<'txn, Mode: TransactionKind>( + &'env self, + txn: &'txn DbTransaction<'env, Mode>, + ) -> DbResult> { + let cursor = txn.txn.cursor(&self.database)?; + Ok(DbCursor { + cursor, + _key_type: PhantomData {}, + _value_type: PhantomData {}, + _table_type: PhantomData {}, + }) + } + + fn get( + &'env self, + txn: &'env DbTransaction<'env, Mode>, + key: &Self::Key, + ) -> DbResult::Value>> { + let main_key = T::get_main_key(key)?; + let first_sub_key = T::get_sub_key_lower_bound(key)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + let Some(bytes) = cursor.get_both_range::>(&main_key, &first_sub_key)? else { + return Ok(None); + }; + + let sub_key = T::get_sub_key(key)?; + if let Some(mut bytes) = bytes.strip_prefix(sub_key.as_slice()) { + let value = V::deserialize(&mut bytes).ok_or(DbError::InnerDeserialization)?; + return Ok(Some(value)); + } + Ok(None) + } + + // NOTICE: if this returns an error, the transaction should not be committed. Doing so can cause + // a corrupt database. + // TODO(dvir): consider first checking if the key exists, if so delete it and only than insert + // it (instead of upsert and fix if there is a problem). + fn upsert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()> { + let main_key = T::get_main_key(key)?; + let sub_key_value = T::get_sub_key_and_value(key, value)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + cursor.put(&main_key, &sub_key_value, WriteFlags::UPSERT)?; + + let sub_key = T::get_sub_key(key)?; + // TODO(dvir): consider return the cursor to the original position using prev instead of + // cloning. + let mut cloned_cursor = cursor.clone(); + if let Some((_key_prefix, sub_key_value)) = + cloned_cursor.next_dup::, DbValueType<'_>>()? + { + if sub_key_value.starts_with(&sub_key) { + cloned_cursor.del(WriteFlags::empty())?; + return Ok(()); + } + }; + + if let Some((_key_prefix, sub_key_value)) = + cursor.prev_dup::, DbValueType<'_>>()? + { + if sub_key_value.starts_with(&sub_key) { + cursor.del(WriteFlags::empty())?; + return Ok(()); + } + }; + Ok(()) + } + + // NOTICE: if this returns an error, the transaction should not be committed. Doing so can cause + // a corrupt database. + // TODO(dvir): consider first checking if the key exists and only then insert it (instead of + // insert and fix if there is a problem). + fn insert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()> { + let main_key = T::get_main_key(key)?; + let sub_key_value = T::get_sub_key_and_value(key, value)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + cursor.put(&main_key, &sub_key_value, WriteFlags::NO_DUP_DATA).map_err( + |err| match err { + libmdbx::Error::KeyExist => { + DbError::KeyAlreadyExists(KeyAlreadyExistsError::new(self.name, key, value)) + } + _ => err.into(), + }, + )?; + + // In the case of existing main-key and sub-key but different values, because the bytes + // array of the key suffix and value is not present in the table, the put will + // succeed, although the key exists. The next two checks come to find those cases + // and delete the new value from the DB. + + let sub_key = T::get_sub_key(key)?; + + if let Some((_key_prefix, sub_key_value)) = + cursor.clone().next_dup::, DbValueType<'_>>()? + { + if sub_key_value.starts_with(&sub_key) { + cursor.del(WriteFlags::empty())?; + return Err(DbError::KeyAlreadyExists(KeyAlreadyExistsError::new( + self.name, key, value, + ))); + } + }; + + if let Some((_key_prefix, sub_key_value)) = + cursor.clone().prev_dup::, DbValueType<'_>>()? + { + if sub_key_value.starts_with(&sub_key) { + cursor.del(WriteFlags::empty())?; + return Err(DbError::KeyAlreadyExists(KeyAlreadyExistsError::new( + self.name, key, value, + ))); + } + }; + Ok(()) + } + + // NOTICE: if this returns an error, the transaction should not be committed. Doing so can cause + // a corrupt database. + // TODO(dvir): consider first checking if the key is equal to the last key, delete the last key, + // and then append instead of optimistically append. + fn append( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &K, + value: &::Value, + ) -> DbResult<()> { + let main_key = T::get_main_key(key)?; + let sub_key_and_value = T::get_sub_key_and_value(key, value)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + match cursor.put(&main_key, &sub_key_and_value, WriteFlags::APPEND_DUP | WriteFlags::APPEND) + { + Err(libmdbx::Error::KeyMismatch) => { + // This case can happen if the appended sub_key_and_value is smaller than the last + // entry value, but the sub-key itself is equal. + // For example: append (0,0) -> 1, old last entry: (0,0) -> 2. + let (last_main_key_bytes, last_key_suffix_and_value_bytes) = + cursor.last::, DbValueType<'_>>()?.expect( + "Should have a last key. otherwise the previous put operation would \ + succeed.", + ); + + // If the appended key is equal to the last key in the table, we can append it. To + // do that we first need to delete the old entry. + if last_main_key_bytes == main_key.as_slice() + && last_key_suffix_and_value_bytes.starts_with(&T::get_sub_key(key)?) + { + cursor.del(WriteFlags::empty())?; + cursor.put( + &main_key, + &sub_key_and_value, + WriteFlags::APPEND_DUP | WriteFlags::APPEND, + )?; + + Ok(()) + } else { + Err(DbError::Append) + } + } + Ok(()) => { + // In the case of overriding the last key with a bigger value, we need to delete the + // old entry. + if let Some(prev) = cursor.prev_dup::, DbValueType<'_>>()? { + if prev.1.starts_with(&T::get_sub_key(key)?) { + cursor.del(WriteFlags::empty())?; + } + } + Ok(()) + } + Err(err) => Err(err.into()), + } + } + + // NOTICE: if this returns an error, the transaction should not be committed. Doing so can cause + // a corrupt database. + fn delete(&'env self, txn: &DbTransaction<'env, RW>, key: &Self::Key) -> DbResult<()> { + let main_key = T::get_main_key(key)?; + let first_sub_key = T::get_sub_key_lower_bound(key)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + let Some(bytes) = cursor.get_both_range::>(&main_key, &first_sub_key)? else { + return Ok(()); + }; + + let sub_key = T::get_sub_key(key)?; + if bytes.starts_with(&sub_key) { + cursor.del(WriteFlags::empty())?; + } + Ok(()) + } +} + +// TODO(dvir): consider adding unchecked version of the append function. +#[allow(private_bounds)] +impl<'env, K: KeyTrait + Debug, V: ValueSerde + Debug, T: DupSortTableType + DupSortUtils> + TableHandle<'env, K, V, T> +{ + // Append a new value to the given key. The sub-key must be bigger than the last sub-key for the + // given main-key, otherwise an error will be returned. + // In contrast to the append function in the Table trait, this function will return an error if + // The sub-key is equal to the last sub-key of the given main-key. + // NOTICE: if this returns an error, the transaction should not be committed. Doing so can cause + // a corrupt database. + #[allow(dead_code)] + pub(crate) fn append_greater_sub_key( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &K, + value: &::Value, + ) -> DbResult<()> { + let main_key = T::get_main_key(key)?; + let sub_key_and_value = T::get_sub_key_and_value(key, value)?; + + let mut cursor = txn.txn.cursor(&self.database)?; + cursor.put(&main_key, &sub_key_and_value, WriteFlags::APPEND_DUP).map_err( + |err| match err { + libmdbx::Error::KeyMismatch => DbError::Append, + _ => err.into(), + }, + )?; + + // This checks the case where the the sub-key is already the last in the sub tree; in this + // case, we revert the last put and return an error. + if let Some(prev) = cursor.prev_dup::, DbValueType<'_>>()? { + if prev.1.starts_with(&T::get_sub_key(key)?) { + cursor.next_dup::, DbValueType<'_>>()?; + cursor.del(WriteFlags::empty())?; + return Err(DbError::Append); + } + } + + Ok(()) + } +} + +impl< + 'txn, + Mode: TransactionKind, + K: KeyTrait + Debug, + V: ValueSerde + Debug, + T: DupSortTableType + DupSortUtils, +> DbCursorTrait for DbCursor<'txn, Mode, K, V, T> +{ + type Key = K; + type Value = V; + + fn prev(&mut self) -> DbResult::Value)>> { + let prev_cursor_res = self.cursor.prev::, DbValueType<'_>>()?; + match prev_cursor_res { + None => Ok(None), + Some((main_key_bytes, sub_key_value_bytes)) => { + Ok(T::get_key_value_pair(&main_key_bytes, &sub_key_value_bytes)) + } + } + } + + fn next(&mut self) -> DbResult::Value)>> { + let prev_cursor_res = self.cursor.next::, DbValueType<'_>>()?; + match prev_cursor_res { + None => Ok(None), + Some((main_key_bytes, sub_key_value_bytes)) => { + Ok(T::get_key_value_pair(&main_key_bytes, &sub_key_value_bytes)) + } + } + } + + // TODO(dvir): make this function walk only once on the table and not twice. This will + // require to add functionality of libmdbx to the binding. + // Functionality adding PR: https://github.com/vorot93/libmdbx-rs/commit/0f3823b7e510147903bc19255f61345f7bf7bf69 + fn lower_bound( + &mut self, + key: &Self::Key, + ) -> DbResult::Value)>> { + let mut main_key = T::get_main_key(key)?; + let first_sub_key = T::get_sub_key_lower_bound(key)?; + + // First try to find a match for the main-key. + if let Some(value_bytes) = + self.cursor.get_both_range::>(&main_key, &first_sub_key)? + { + return Ok(T::get_key_value_pair(&main_key, &value_bytes)); + } + + // The next main-key bytes. + T::next_main_key(&mut main_key); + + let Some((main_key_bytes, sub_key_value_bytes)) = + self.cursor.set_range::, DbValueType<'_>>(&main_key)? + else { + return Ok(None); + }; + + Ok(T::get_key_value_pair(&main_key_bytes, &sub_key_value_bytes)) + } +} diff --git a/crates/papyrus_storage/src/db/table_types/dup_sort_tables_test.rs b/crates/papyrus_storage/src/db/table_types/dup_sort_tables_test.rs new file mode 100644 index 00000000000..c8c01a9275e --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/dup_sort_tables_test.rs @@ -0,0 +1,94 @@ +use assert_matches::assert_matches; + +use super::{DupSortTableType, DupSortUtils}; +use crate::db::db_test::get_test_env; +use crate::db::serialization::NoVersionValueWrapper; +use crate::db::table_types::dup_sort_tables::add_one; +use crate::db::table_types::test_utils::{random_table_test, table_test, TableKey, TableValue}; +use crate::db::table_types::Table; +use crate::db::{DbError, DbResult, DbWriter, TableIdentifier}; + +#[test] +fn common_prefix_table() { + table_test(DbWriter::create_common_prefix_table); +} + +// Ignore because this test takes few seconds to run. +#[ignore] +#[test] +fn common_prefix_compare_with_simple_table_random() { + let ((reader, mut writer), _temp_dir) = get_test_env(); + let simple_table = writer.create_simple_table("simple_table").unwrap(); + let common_prefix_table = writer.create_common_prefix_table("common_prefix_table").unwrap(); + random_table_test(simple_table, common_prefix_table, &reader, &mut writer); +} + +#[test] +fn common_prefix_append_greater_sub_key() { + append_greater_sub_key_test(DbWriter::create_common_prefix_table); +} + +#[allow(clippy::type_complexity)] +fn append_greater_sub_key_test( + create_table: fn( + &mut DbWriter, + &'static str, + ) -> DbResult>, +) where + T: DupSortTableType + DupSortUtils<(u32, u32), NoVersionValueWrapper>, +{ + let ((_reader, mut writer), _temp_dir) = get_test_env(); + let table_id = create_table(&mut writer, "table").unwrap(); + + let txn = writer.begin_rw_txn().unwrap(); + + let handle = txn.open_table(&table_id).unwrap(); + handle.append_greater_sub_key(&txn, &(2, 2), &22).unwrap(); + handle.append_greater_sub_key(&txn, &(2, 3), &23).unwrap(); + handle.append_greater_sub_key(&txn, &(1, 1), &11).unwrap(); + handle.append_greater_sub_key(&txn, &(3, 0), &30).unwrap(); + + // For DupSort tables append with key that already exists should fail. Try append with smaller + // bigger and equal values. + let result = handle.append_greater_sub_key(&txn, &(2, 2), &0); + assert_matches!(result, Err(DbError::Append)); + + let result = handle.append_greater_sub_key(&txn, &(2, 2), &22); + assert_matches!(result, Err(DbError::Append)); + + let result = handle.append_greater_sub_key(&txn, &(2, 2), &100); + assert_matches!(result, Err(DbError::Append)); + + // As before, but for the last main key. + let result = handle.append_greater_sub_key(&txn, &(3, 0), &0); + assert_matches!(result, Err(DbError::Append)); + + let result = handle.append_greater_sub_key(&txn, &(3, 0), &30); + assert_matches!(result, Err(DbError::Append)); + + let result = handle.append_greater_sub_key(&txn, &(3, 0), &100); + assert_matches!(result, Err(DbError::Append)); + + // Check the final database. + assert_eq!(handle.get(&txn, &(2, 2)).unwrap(), Some(22)); + assert_eq!(handle.get(&txn, &(2, 3)).unwrap(), Some(23)); + assert_eq!(handle.get(&txn, &(1, 1)).unwrap(), Some(11)); + assert_eq!(handle.get(&txn, &(3, 0)).unwrap(), Some(30)); +} + +#[test] +fn add_one_test() { + let mut bytes; + + bytes = vec![0]; + add_one(&mut bytes); + assert_eq!(bytes, vec![1]); + + bytes = vec![u8::MAX]; + add_one(&mut bytes); + assert_eq!(bytes, vec![1, 0]); + + bytes = vec![1, 0, u8::MAX]; + add_one(&mut bytes); + assert_eq!(bytes, vec![1, 1, 0]); +} diff --git a/crates/papyrus_storage/src/db/table_types/mod.rs b/crates/papyrus_storage/src/db/table_types/mod.rs new file mode 100644 index 00000000000..78113259dad --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/mod.rs @@ -0,0 +1,104 @@ +use std::fmt::Debug; +use std::marker::PhantomData; + +use libmdbx::Cursor; + +use super::serialization::{Key as KeyTrait, ValueSerde}; +use super::{DbResult, DbTransaction, TransactionKind, RW}; + +mod dup_sort_tables; +mod simple_table; +#[allow(unused_imports)] +pub(crate) use dup_sort_tables::CommonPrefix; +pub(crate) use simple_table::SimpleTable; +#[cfg(test)] +pub(crate) mod test_utils; + +// TODO(dvir): consider adding the create_table method to the Table trait. +// TODO(dvir): consider adding unchecked version of the those functions. + +pub(crate) trait Table<'env> { + type Key: KeyTrait + Debug; + type Value: ValueSerde + Debug; + type TableVariant: TableType; + + // TODO(dvir): consider move this to the cursor trait and get rid of the TableVariant type. + // Create a cursor for the table. + #[allow(clippy::type_complexity)] + fn cursor<'txn, Mode: TransactionKind>( + &'env self, + txn: &'txn DbTransaction<'env, Mode>, + ) -> DbResult>; + + // Get a key value pair from the table. + fn get( + &'env self, + txn: &'env DbTransaction<'env, Mode>, + key: &Self::Key, + ) -> DbResult::Value>>; + + // Insert or update a key value pair in the table. If the key already exists, the value will be + // updated. + fn upsert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()>; + + // Insert a key value pair in the table. If the key already exists, an error will be returned. + fn insert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()>; + + // Append a key value pair to the end of the table. The key must be bigger than or equal to + // the last key in the table; otherwise, an error will be returned. + #[allow(dead_code)] + fn append( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()>; + + // Delete a key value pair from the table. + fn delete(&'env self, txn: &DbTransaction<'env, RW>, key: &Self::Key) -> DbResult<()>; +} + +// TODO(dvir): consider adding append functionality using a cursor. It should be more efficient for +// more than a single append operation (also for other table types). +pub(crate) trait DbCursorTrait { + type Key: KeyTrait + Debug; + type Value: ValueSerde + Debug; + + // Position at the previous key. + #[allow(clippy::type_complexity)] + fn prev(&mut self) -> DbResult::Value)>>; + + // Position at the next key. + #[allow(clippy::type_complexity)] + fn next(&mut self) -> DbResult::Value)>>; + + // Position at first key greater than or equal to specified key. + #[allow(clippy::type_complexity)] + fn lower_bound( + &mut self, + key: &Self::Key, + ) -> DbResult::Value)>>; +} + +pub(crate) struct DbCursor<'txn, Mode: TransactionKind, K: KeyTrait, V: ValueSerde, T: TableType> { + cursor: Cursor<'txn, Mode::Internal>, + _key_type: PhantomData, + _value_type: PhantomData, + _table_type: PhantomData, +} + +pub(crate) trait TableType {} + +// A value place holder for tables where we don't need a value. +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub(crate) struct NoValue; diff --git a/crates/papyrus_storage/src/db/table_types/simple_table.rs b/crates/papyrus_storage/src/db/table_types/simple_table.rs new file mode 100644 index 00000000000..37208145444 --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/simple_table.rs @@ -0,0 +1,192 @@ +#[cfg(test)] +#[path = "simple_table_test.rs"] +mod simple_table_test; + +use std::borrow::Cow; +use std::fmt::Debug; +use std::marker::PhantomData; + +use libmdbx::{TableFlags, WriteFlags}; + +use super::{DbResult, Table, TableType}; +use crate::db::serialization::{Key as KeyTrait, ValueSerde}; +use crate::db::table_types::DbCursorTrait; +use crate::db::{ + DbCursor, + DbError, + DbKeyType, + DbTransaction, + DbValueType, + DbWriter, + KeyAlreadyExistsError, + TableHandle, + TableIdentifier, + TransactionKind, + RW, +}; + +// A simple mapping between key and value. +pub(crate) struct SimpleTable; + +impl TableType for SimpleTable {} + +impl DbWriter { + pub(crate) fn create_simple_table( + &mut self, + name: &'static str, + ) -> DbResult> { + let txn = self.env.begin_rw_txn()?; + txn.create_table(Some(name), TableFlags::empty())?; + txn.commit()?; + Ok(TableIdentifier { + name, + _key_type: PhantomData {}, + _value_type: PhantomData {}, + _table_type: PhantomData {}, + }) + } +} + +impl<'env, K: KeyTrait + Debug, V: ValueSerde + Debug> Table<'env> + for TableHandle<'env, K, V, SimpleTable> +{ + type Key = K; + type Value = V; + type TableVariant = SimpleTable; + + fn cursor<'txn, Mode: TransactionKind>( + &'env self, + txn: &'txn DbTransaction<'env, Mode>, + ) -> DbResult> { + let cursor = txn.txn.cursor(&self.database)?; + Ok(DbCursor { + cursor, + _key_type: PhantomData {}, + _value_type: PhantomData {}, + _table_type: PhantomData {}, + }) + } + + fn get( + &'env self, + txn: &'env DbTransaction<'env, Mode>, + key: &Self::Key, + ) -> DbResult::Value>> { + let bin_key = key.serialize()?; + let Some(bytes) = txn.txn.get::>(&self.database, &bin_key)? else { + return Ok(None); + }; + let value = + ::deserialize(&mut bytes.as_ref()).ok_or(DbError::InnerDeserialization)?; + Ok(Some(value)) + } + + fn upsert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()> { + let data = ::serialize(value)?; + let bin_key = key.serialize()?; + txn.txn.put(&self.database, bin_key, data, WriteFlags::UPSERT)?; + Ok(()) + } + + fn insert( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &Self::Key, + value: &::Value, + ) -> DbResult<()> { + let data = ::serialize(value)?; + let bin_key = key.serialize()?; + txn.txn.put(&self.database, bin_key, data, WriteFlags::NO_OVERWRITE).map_err(|err| { + match err { + libmdbx::Error::KeyExist => { + DbError::KeyAlreadyExists(KeyAlreadyExistsError::new(self.name, key, value)) + } + _ => err.into(), + } + })?; + Ok(()) + } + + #[allow(dead_code)] + fn append( + &'env self, + txn: &DbTransaction<'env, RW>, + key: &K, + value: &::Value, + ) -> DbResult<()> { + let data = V::serialize(value)?; + let bin_key = key.serialize()?; + txn.txn.put(&self.database, bin_key, data, WriteFlags::APPEND).map_err( + |err| match err { + libmdbx::Error::KeyMismatch => DbError::Append, + _ => err.into(), + }, + )?; + Ok(()) + } + + fn delete(&'env self, txn: &DbTransaction<'env, RW>, key: &Self::Key) -> DbResult<()> { + let bin_key = key.serialize()?; + txn.txn.del(&self.database, bin_key, None)?; + Ok(()) + } +} + +impl<'txn, Mode: TransactionKind, K: KeyTrait + Debug, V: ValueSerde + Debug> DbCursorTrait + for DbCursor<'txn, Mode, K, V, SimpleTable> +{ + type Key = K; + type Value = V; + + fn prev(&mut self) -> DbResult::Value)>> { + let prev_cursor_res = self.cursor.prev::, DbValueType<'_>>()?; + match prev_cursor_res { + None => Ok(None), + Some((key_bytes, value_bytes)) => { + let key = + K::deserialize(&mut key_bytes.as_ref()).ok_or(DbError::InnerDeserialization)?; + let value = V::deserialize(&mut value_bytes.as_ref()) + .ok_or(DbError::InnerDeserialization)?; + Ok(Some((key, value))) + } + } + } + + fn next(&mut self) -> DbResult::Value)>> { + let prev_cursor_res = self.cursor.next::, DbValueType<'_>>()?; + match prev_cursor_res { + None => Ok(None), + Some((key_bytes, value_bytes)) => { + let key = + K::deserialize(&mut key_bytes.as_ref()).ok_or(DbError::InnerDeserialization)?; + let value = V::deserialize(&mut value_bytes.as_ref()) + .ok_or(DbError::InnerDeserialization)?; + Ok(Some((key, value))) + } + } + } + + fn lower_bound( + &mut self, + key: &K, + ) -> DbResult::Value)>> { + let key_bytes = key.serialize()?; + let prev_cursor_res = + self.cursor.set_range::, DbValueType<'_>>(&key_bytes)?; + match prev_cursor_res { + None => Ok(None), + Some((key_bytes, value_bytes)) => { + let key = + K::deserialize(&mut key_bytes.as_ref()).ok_or(DbError::InnerDeserialization)?; + let value = V::deserialize(&mut value_bytes.as_ref()) + .ok_or(DbError::InnerDeserialization)?; + Ok(Some((key, value))) + } + } + } +} diff --git a/crates/papyrus_storage/src/db/table_types/simple_table_test.rs b/crates/papyrus_storage/src/db/table_types/simple_table_test.rs new file mode 100644 index 00000000000..855c70dcc6c --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/simple_table_test.rs @@ -0,0 +1,7 @@ +use crate::db::table_types::test_utils::table_test; +use crate::db::DbWriter; + +#[test] +fn simple_table_test() { + table_test(DbWriter::create_simple_table); +} diff --git a/crates/papyrus_storage/src/db/table_types/test_utils.rs b/crates/papyrus_storage/src/db/table_types/test_utils.rs new file mode 100644 index 00000000000..579f405b973 --- /dev/null +++ b/crates/papyrus_storage/src/db/table_types/test_utils.rs @@ -0,0 +1,418 @@ +use assert_matches::assert_matches; +use rand::rngs::ThreadRng; +use rand::Rng; +use tracing::debug; + +use super::{Table, TableType}; +use crate::db::db_test::get_test_env; +use crate::db::serialization::{NoVersionValueWrapper, StorageSerde, StorageSerdeError}; +use crate::db::table_types::{DbCursor, DbCursorTrait}; +use crate::db::{DbReader, DbResult, DbWriter, TableHandle, TableIdentifier, RO, RW}; +use crate::serialization::serializers::auto_storage_serde; +use crate::DbError; + +// TODO(dvir): consider adding tests with keys and values in different sizes. + +pub(crate) type TableKey = (u32, u32); +pub(crate) type TableValue = NoVersionValueWrapper; + +auto_storage_serde! { + (u32, u32); +} + +// A generic test for all table types. +#[allow(clippy::type_complexity)] +pub(crate) fn table_test( + create_table: fn( + &mut DbWriter, + &'static str, + ) -> DbResult>, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue, TableVariant = T>, + for<'txn> DbCursor<'txn, RW, TableKey, TableValue, T>: + DbCursorTrait, +{ + let ((_reader, mut writer), _temp_dir) = get_test_env(); + + let get_test_table = create_table(&mut writer, "get_test").unwrap(); + get_test(get_test_table, &mut writer); + + let insert_test_table = create_table(&mut writer, "insert_test").unwrap(); + insert_test(insert_test_table, &mut writer); + + let upsert_test_table = create_table(&mut writer, "upsert_test").unwrap(); + upsert_test(upsert_test_table, &mut writer); + + let append_test_table = create_table(&mut writer, "append_test").unwrap(); + append_test(append_test_table, &mut writer); + + let delete_test_table = create_table(&mut writer, "delete_test").unwrap(); + delete_test(delete_test_table, &mut writer); + + let cursor_test_table = create_table(&mut writer, "cursor_test").unwrap(); + table_cursor_test(cursor_test_table, &mut writer); +} + +fn get_test(table_id: TableIdentifier, writer: &mut DbWriter) +where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue>, +{ + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + // Read does not exist value. + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), None); + + // Insert and read a value. + table.insert(&txn, &(1, 1), &11).unwrap(); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); +} + +fn insert_test( + table_id: TableIdentifier, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue>, +{ + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + // Insert values. + table.insert(&txn, &(1, 2), &12).unwrap(); + table.insert(&txn, &(2, 1), &21).unwrap(); + table.insert(&txn, &(1, 1), &11).unwrap(); + + assert_eq!(table.get(&txn, &(1, 2)).unwrap(), Some(12)); + assert_eq!(table.get(&txn, &(2, 1)).unwrap(), Some(21)); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); + + // Insert duplicate key. + assert_eq!( + table.insert(&txn, &(1, 1), &0).expect_err("Expected KeyAlreadyExistsError").to_string(), + format!( + "Key '{key:?}' already exists in table '{table_name}'. Error when tried to insert \ + value '0'", + key = (1, 1), + table_name = table_id.name + ), + ); + + // Check the final database. + assert_eq!(table.get(&txn, &(1, 2)).unwrap(), Some(12)); + assert_eq!(table.get(&txn, &(2, 1)).unwrap(), Some(21)); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); +} + +fn upsert_test( + table_id: TableIdentifier, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue>, +{ + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + // Upsert not existing key. + table.upsert(&txn, &(1, 1), &11).unwrap(); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); + + // (1,1) was already inserted, so this is an update. + table.upsert(&txn, &(1, 1), &0).unwrap(); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(0)); +} + +fn append_test( + table_id: TableIdentifier, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue>, +{ + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + // Append to an empty table. + table.append(&txn, &(1, 1), &11).unwrap(); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); + + // Successful appends. + table.append(&txn, &(1, 1), &0).unwrap(); + table.append(&txn, &(1, 2), &12).unwrap(); + table.append(&txn, &(2, 0), &20).unwrap(); + table.append(&txn, &(2, 2), &22).unwrap(); + + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(0)); + assert_eq!(table.get(&txn, &(1, 2)).unwrap(), Some(12)); + assert_eq!(table.get(&txn, &(2, 0)).unwrap(), Some(20)); + assert_eq!(table.get(&txn, &(2, 2)).unwrap(), Some(22)); + + // Override the last key with a smaller value. + table.append(&txn, &(2, 2), &0).unwrap(); + assert_eq!(table.get(&txn, &(2, 2)).unwrap(), Some(0)); + + // Override the last key with a bigger value. + table.append(&txn, &(2, 2), &100).unwrap(); + assert_eq!(table.get(&txn, &(2, 2)).unwrap(), Some(100)); + + // Append key that is not the last, should fail. + assert_matches!(table.append(&txn, &(0, 0), &0), Err(DbError::Append)); + assert_matches!(table.append(&txn, &(1, 3), &0), Err(DbError::Append)); + assert_matches!(table.append(&txn, &(2, 1), &0), Err(DbError::Append)); + + // Check the final database. + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(0)); + assert_eq!(table.get(&txn, &(1, 2)).unwrap(), Some(12)); + assert_eq!(table.get(&txn, &(2, 0)).unwrap(), Some(20)); + assert_eq!(table.get(&txn, &(2, 2)).unwrap(), Some(100)); +} + +fn delete_test( + table_id: TableIdentifier, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue>, +{ + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + table.insert(&txn, &(1, 1), &11).unwrap(); + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), Some(11)); + + table.delete(&txn, &(1, 1)).unwrap(); + // Delete non-existent value. + table.delete(&txn, &(2, 2)).unwrap(); + + assert_eq!(table.get(&txn, &(1, 1)).unwrap(), None); + assert_eq!(table.get(&txn, &(2, 2)).unwrap(), None); +} + +fn table_cursor_test( + table_id: TableIdentifier, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T>: + Table<'env, Key = TableKey, Value = TableValue, TableVariant = T>, + for<'txn> DbCursor<'txn, RW, TableKey, TableValue, T>: + DbCursorTrait, +{ + const VALUES: [((u32, u32), u32); 9] = [ + ((2, 2), 2), + ((1, 1), 7), + ((3, 3), 4), + ((3, 1), 8), + ((1, 2), 9), + ((2, 3), 5), + ((1, 3), 1), + ((3, 2), 1), + ((2, 1), 5), + ]; + + const SORTED_VALUES: [((u32, u32), u32); 9] = [ + ((1, 1), 7), + ((1, 2), 9), + ((1, 3), 1), + ((2, 1), 5), + ((2, 2), 2), + ((2, 3), 5), + ((3, 1), 8), + ((3, 2), 1), + ((3, 3), 4), + ]; + + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + + // Insert the values to the table. + for (k, v) in &VALUES { + table.insert(&txn, k, v).unwrap(); + } + + // Test lower_bound(). + let mut cursor = table.cursor(&txn).unwrap(); + let current = cursor.lower_bound(&(0, 0)).unwrap(); + assert_eq!(current, Some(((1, 1), 7))); + let current = cursor.lower_bound(&(2, 2)).unwrap(); + assert_eq!(current, Some(((2, 2), 2))); + let current = cursor.lower_bound(&(2, 4)).unwrap(); + assert_eq!(current, Some(((3, 1), 8))); + let current = cursor.lower_bound(&(4, 4)).unwrap(); + assert_eq!(current, None); + + // Iterate using next(). + let mut cursor = table.cursor(&txn).unwrap(); + let mut current = cursor.lower_bound(&(0, 0)).unwrap(); + for kv_pair in SORTED_VALUES { + assert_eq!(current, Some(kv_pair)); + current = cursor.next().unwrap(); + } + current = cursor.next().unwrap(); + assert_eq!(current, None); + // In the end still return None. + current = cursor.next().unwrap(); + assert_eq!(current, None); + + // Iterate using prev(). + let mut cursor = table.cursor(&txn).unwrap(); + let mut current = cursor.lower_bound(&(4, 4)).unwrap(); + assert_eq!(current, None); + for kv_pair in SORTED_VALUES.iter().rev().cloned() { + current = cursor.prev().unwrap(); + assert_eq!(current, Some(kv_pair)); + } + current = cursor.prev().unwrap(); + assert_eq!(current, None); + // In the end still return None. + current = cursor.prev().unwrap(); + assert_eq!(current, None); +} + +// Constants for random_table_test. +// Use 300 as the maximum value to make the values spread over more than one byte but small enough +// to make collisions. +const MAX_VALUE: u32 = 300; +const MAIN_KEY_MAX_VALUE: u32 = 300; +const SUB_KEY_MAX_VALUE: u32 = 300; +// Number of iterations to run the test. +const ITERS: usize = 1000; +// Number of get calls to make in each iteration. +const GET_CALLS: usize = 10; +// Number of cursor test iterations to make in each main iteration. +const CURSOR_ITERS: usize = 2; +// Number of cursor operations to make in each cursor iteration. +const CURSOR_OPS_NUM: usize = 7; + +pub(crate) fn random_table_test( + first_table_id: TableIdentifier, + second_table_id: TableIdentifier, + reader: &DbReader, + writer: &mut DbWriter, +) where + for<'env> TableHandle<'env, TableKey, TableValue, T0>: + Table<'env, Key = TableKey, Value = TableValue, TableVariant = T0>, + for<'env> TableHandle<'env, TableKey, TableValue, T1>: + Table<'env, Key = TableKey, Value = TableValue, TableVariant = T1>, + for<'txn> DbCursor<'txn, RO, TableKey, TableValue, T0>: + DbCursorTrait, + for<'txn> DbCursor<'txn, RO, TableKey, TableValue, T1>: + DbCursorTrait, +{ + let _ = simple_logger::init_with_env(); + let rtxn = reader.begin_ro_txn().unwrap(); + let first_table = rtxn.open_table(&first_table_id).unwrap(); + let second_table = rtxn.open_table(&second_table_id).unwrap(); + let mut rng = rand::thread_rng(); + + for iter in 0..ITERS { + debug!("iteration: {iter:?}"); + let wtxn = writer.begin_rw_txn().unwrap(); + let random_op = rng.gen_range(0..4); + let key = get_random_key(&mut rng); + let value = rng.gen_range(0..MAX_VALUE); + + // Insert, upsert, or delete a random key. + if random_op == 0 { + // Insert + debug!("insert: {key:?}, {value:?}"); + let first_res = first_table.insert(&wtxn, &key, &value); + let second_res = second_table.insert(&wtxn, &key, &value); + assert!( + (first_res.is_ok() && second_res.is_ok()) + || (matches!(first_res.unwrap_err(), DbError::KeyAlreadyExists(..)) + && matches!(second_res.unwrap_err(), DbError::KeyAlreadyExists(..))) + ); + } else if random_op == 1 { + // Upsert + debug!("upsert: {key:?}, {value:?}"); + first_table.upsert(&wtxn, &key, &value).unwrap(); + second_table.upsert(&wtxn, &key, &value).unwrap(); + } else if random_op == 2 { + // Append + // TODO(dvir): consider increasing the number of successful appends (append of not the + // last entry will fail). + debug!("append: {key:?}, {value:?}"); + let first_res = first_table.append(&wtxn, &key, &value); + let second_res = second_table.append(&wtxn, &key, &value); + assert!( + (first_res.is_ok() && second_res.is_ok()) + || (matches!(first_res.unwrap_err(), DbError::Append) + && matches!(second_res.unwrap_err(), DbError::Append)) + ); + } else if random_op == 3 { + // Delete + debug!("delete: {key:?}"); + first_table.delete(&wtxn, &key).unwrap(); + second_table.delete(&wtxn, &key).unwrap(); + } + + wtxn.commit().unwrap(); + let rtxn = reader.begin_ro_txn().unwrap(); + + // Compare get calls. + let mut keys_list = vec![key]; + for _ in 0..GET_CALLS { + keys_list.push(get_random_key(&mut rng)); + } + + for key in keys_list { + let first_value = first_table.get(&rtxn, &key).unwrap(); + let second_value = second_table.get(&rtxn, &key).unwrap(); + assert_eq!( + first_value, second_value, + "Mismatch for key {key:?}\n first key: {first_value:?}\n second key: \ + {second_value:?}" + ); + } + + // Compare cursor calls. + let mut keys_list = vec![key]; + for _ in 0..CURSOR_ITERS { + keys_list.push(get_random_key(&mut rng)); + } + + for key in keys_list { + debug!("lower_bound: {key:?}"); + let mut first_cursor = first_table.cursor(&rtxn).unwrap(); + let first_res = first_cursor.lower_bound(&key).unwrap(); + let mut second_cursor = second_table.cursor(&rtxn).unwrap(); + let second_res = second_cursor.lower_bound(&key).unwrap(); + assert_eq!( + first_res, second_res, + "Mismatch for key {key:?}\n first key: {first_res:?}\n second key: {second_res:?}" + ); + + for _ in 0..CURSOR_OPS_NUM { + let random_op = rng.gen_range(0..2); + if random_op == 0 { + // Next + debug!("next: {key:?}"); + let first_res = first_cursor.next().unwrap(); + let second_res = second_cursor.next().unwrap(); + assert_eq!( + first_res, second_res, + "Mismatch for key {key:?}\n first key: {first_res:?}\n second key: \ + {second_res:?}" + ); + } else if random_op == 1 { + // Prev + debug!("prev: {key:?}"); + let first_res = first_cursor.prev().unwrap(); + let second_res = second_cursor.prev().unwrap(); + assert_eq!( + first_res, second_res, + "Mismatch for key {key:?}\n first key: {first_res:?}\n second key: \ + {second_res:?}" + ); + } + } + } + } +} + +fn get_random_key(rng: &mut ThreadRng) -> TableKey { + (rng.gen_range(0..MAIN_KEY_MAX_VALUE), rng.gen_range(0..SUB_KEY_MAX_VALUE)) +} diff --git a/crates/papyrus_storage/src/deprecated/migrations.rs b/crates/papyrus_storage/src/deprecated/migrations.rs new file mode 100644 index 00000000000..8235098eb34 --- /dev/null +++ b/crates/papyrus_storage/src/deprecated/migrations.rs @@ -0,0 +1,2 @@ +// This file should contain the deprecated structs and the corresponding migration logic. +// Check file history for examples. diff --git a/crates/papyrus_storage/src/deprecated/mod.rs b/crates/papyrus_storage/src/deprecated/mod.rs new file mode 100644 index 00000000000..11a8e418dd5 --- /dev/null +++ b/crates/papyrus_storage/src/deprecated/mod.rs @@ -0,0 +1,4 @@ +mod migrations; +mod serializers; +#[cfg(test)] +mod test_instances; diff --git a/crates/papyrus_storage/src/deprecated/serializers.rs b/crates/papyrus_storage/src/deprecated/serializers.rs new file mode 100644 index 00000000000..74655664c25 --- /dev/null +++ b/crates/papyrus_storage/src/deprecated/serializers.rs @@ -0,0 +1,2 @@ +// This file should contain the serialization logic for the deprecated structs. Usually, using the +// auto_storage_serde macro. diff --git a/crates/papyrus_storage/src/deprecated/test_instances.rs b/crates/papyrus_storage/src/deprecated/test_instances.rs new file mode 100644 index 00000000000..7aec292e7e7 --- /dev/null +++ b/crates/papyrus_storage/src/deprecated/test_instances.rs @@ -0,0 +1,2 @@ +// This file should contain the test instances for the deprecated structs. Usually, using the +// auto_impl_get_test_instance macro. diff --git a/crates/papyrus_storage/src/document_calls.rs b/crates/papyrus_storage/src/document_calls.rs new file mode 100644 index 00000000000..656b2994775 --- /dev/null +++ b/crates/papyrus_storage/src/document_calls.rs @@ -0,0 +1,29 @@ +//! This module is used to log calls to the storage system. This is useful for benchmarking +//! and used in the storage_benchmark tool. + +// TODO(dvir): add a link to the storage_benchmark tool after its publishing. + +use std::fs::File; +use std::io::Write; +use std::sync::Mutex; + +use lazy_static::lazy_static; +pub use papyrus_common::storage_query::StorageQuery; + +// TODO(dvir): consider enabling the user to choose the file path using an environment variable. +const QUERY_FILE_PATH: &str = "./document_calls.txt"; + +lazy_static! { + pub(crate) static ref QUERY_FILE: Mutex = Mutex::new( + File::create(QUERY_FILE_PATH).expect("Should be able to create document_calls.txt file") + ); +} + +// Adds a query to the document_calls file. +pub(crate) fn add_query(query: StorageQuery) { + let query_string = serde_json::to_string(&query).expect("Should be able to serialize query"); + let mut file = QUERY_FILE.lock().expect("Should be able to lock the queries file"); + file.write_all(query_string.as_bytes()).expect("Should be able to write to the queries file"); + file.write_all(b"\n").expect("Should be able to write to the queries file"); + file.flush().expect("Should be able to flush the queries file"); +} diff --git a/crates/papyrus_storage/src/header.rs b/crates/papyrus_storage/src/header.rs new file mode 100644 index 00000000000..6944c333426 --- /dev/null +++ b/crates/papyrus_storage/src/header.rs @@ -0,0 +1,416 @@ +//! Interface for handling data related to Starknet [block headers](https://docs.rs/starknet_api/latest/starknet_api/block/struct.BlockHeader.html). +//! +//! The block header is the part of the block that contains metadata about the block. +//! Import [`HeaderStorageReader`] and [`HeaderStorageWriter`] to read and write data related +//! to the block headers using a [`StorageTxn`]. +//! # Example +//! ``` +//! use papyrus_storage::open_storage; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::core::ChainId; +//! use starknet_api::block::{Block, BlockNumber}; +//! use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! let block = Block::default(); +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_header(BlockNumber(0), &block.header)? // Appending a block body will fail without matching header. +//! .commit()?; +//! +//! let header = reader.begin_ro_txn()?.get_block_header(BlockNumber(0))?; +//! assert_eq!(header, Some(block.header)); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` + +#[cfg(test)] +#[path = "header_test.rs"] +mod header_test; + +use serde::{Deserialize, Serialize}; +use starknet_api::block::{ + BlockHash, + BlockHeader, + BlockNumber, + BlockSignature, + BlockTimestamp, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + EventCommitment, + GlobalRoot, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use tracing::debug; + +use crate::db::serialization::NoVersionValueWrapper; +use crate::db::table_types::{DbCursorTrait, SimpleTable, Table}; +use crate::db::{DbTransaction, TableHandle, TransactionKind, RW}; +use crate::{MarkerKind, MarkersTable, StorageError, StorageResult, StorageTxn}; + +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub(crate) struct StorageBlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, + pub n_transactions: usize, + pub n_events: usize, +} + +type BlockHashToNumberTable<'env> = + TableHandle<'env, BlockHash, NoVersionValueWrapper, SimpleTable>; + +/// Interface for reading data related to the block headers. +pub trait HeaderStorageReader { + /// The block marker is the first block number that doesn't exist yet. + fn get_header_marker(&self) -> StorageResult; + /// Returns the header of the block with the given number. + fn get_block_header(&self, block_number: BlockNumber) -> StorageResult>; + + /// Returns the block number of the block with the given hash. + fn get_block_number_by_hash( + &self, + block_hash: &BlockHash, + ) -> StorageResult>; + + /// Returns the Starknet version at the given block number. + fn get_starknet_version( + &self, + block_number: BlockNumber, + ) -> StorageResult>; + + /// Returns the signature of the block with the given number. + fn get_block_signature( + &self, + block_number: BlockNumber, + ) -> StorageResult>; +} + +/// Interface for writing data related to the block headers. +pub trait HeaderStorageWriter +where + Self: Sized, +{ + /// Appends a header to the storage. + // To enforce that no commit happen after a failure, we consume and return Self on success. + fn append_header( + self, + block_number: BlockNumber, + block_header: &BlockHeader, + ) -> StorageResult; + + /// Update the starknet version if needed. + fn update_starknet_version( + self, + block_number: &BlockNumber, + starknet_version: &StarknetVersion, + ) -> StorageResult; + + /// Removes a block header and its signature (if exists) from the storage and returns the + /// removed data. + fn revert_header( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option, Option)>; + + /// Appends a block signature to the storage. + /// Written separately from the header to allow skipping the signature when creating a block. + fn append_block_signature( + self, + block_number: BlockNumber, + block_signature: &BlockSignature, + ) -> StorageResult; +} + +impl<'env, Mode: TransactionKind> HeaderStorageReader for StorageTxn<'env, Mode> { + fn get_header_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::Header)?.unwrap_or_default()) + } + + fn get_block_header(&self, block_number: BlockNumber) -> StorageResult> { + let headers_table = self.open_table(&self.tables.headers)?; + let Some(block_header) = headers_table.get(&self.txn, &block_number)? else { + return Ok(None); + }; + let Some(starknet_version) = self.get_starknet_version(block_number)? else { + return Ok(None); + }; + Ok(Some(BlockHeader { + block_hash: block_header.block_hash, + parent_hash: block_header.parent_hash, + block_number: block_header.block_number, + l1_gas_price: block_header.l1_gas_price, + l1_data_gas_price: block_header.l1_data_gas_price, + state_root: block_header.state_root, + sequencer: block_header.sequencer, + timestamp: block_header.timestamp, + l1_da_mode: block_header.l1_da_mode, + state_diff_commitment: block_header.state_diff_commitment, + transaction_commitment: block_header.transaction_commitment, + event_commitment: block_header.event_commitment, + receipt_commitment: block_header.receipt_commitment, + state_diff_length: block_header.state_diff_length, + n_transactions: block_header.n_transactions, + n_events: block_header.n_events, + starknet_version, + })) + } + + fn get_block_number_by_hash( + &self, + block_hash: &BlockHash, + ) -> StorageResult> { + let block_hash_to_number_table = self.open_table(&self.tables.block_hash_to_number)?; + let block_number = block_hash_to_number_table.get(&self.txn, block_hash)?; + Ok(block_number) + } + + // TODO(shahak): Internalize this function. + fn get_starknet_version( + &self, + block_number: BlockNumber, + ) -> StorageResult> { + if block_number >= self.get_header_marker()? { + return Ok(None); + } + + let starknet_version_table = self.open_table(&self.tables.starknet_version)?; + let mut cursor = starknet_version_table.cursor(&self.txn)?; + let Some(next_block_number) = block_number.next() else { + return Ok(None); + }; + cursor.lower_bound(&next_block_number)?; + let res = cursor.prev()?; + + match res { + Some((_block_number, starknet_version)) => Ok(Some(starknet_version)), + None => unreachable!( + "Since block_number >= self.get_header_marker(), starknet_version_table should \ + have at least a single mapping." + ), + } + } + + fn get_block_signature( + &self, + block_number: BlockNumber, + ) -> StorageResult> { + let block_signatures_table = self.open_table(&self.tables.block_signatures)?; + let block_signature = block_signatures_table.get(&self.txn, &block_number)?; + Ok(block_signature) + } +} + +impl<'env> HeaderStorageWriter for StorageTxn<'env, RW> { + fn append_header( + self, + block_number: BlockNumber, + block_header: &BlockHeader, + ) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + let headers_table = self.open_table(&self.tables.headers)?; + let block_hash_to_number_table = self.open_table(&self.tables.block_hash_to_number)?; + + update_marker(&self.txn, &markers_table, block_number)?; + + let storage_block_header = StorageBlockHeader { + block_hash: block_header.block_hash, + parent_hash: block_header.parent_hash, + block_number: block_header.block_number, + l1_gas_price: block_header.l1_gas_price, + l1_data_gas_price: block_header.l1_data_gas_price, + state_root: block_header.state_root, + sequencer: block_header.sequencer, + timestamp: block_header.timestamp, + l1_da_mode: block_header.l1_da_mode, + state_diff_commitment: block_header.state_diff_commitment.clone(), + transaction_commitment: block_header.transaction_commitment, + event_commitment: block_header.event_commitment, + receipt_commitment: block_header.receipt_commitment, + state_diff_length: block_header.state_diff_length, + n_transactions: block_header.n_transactions, + n_events: block_header.n_events, + }; + + headers_table.append(&self.txn, &block_number, &storage_block_header)?; + + update_hash_mapping( + &self.txn, + &block_hash_to_number_table, + &storage_block_header, + block_number, + )?; + + self.update_starknet_version(&block_number, &block_header.starknet_version) + } + + // TODO(shahak): Internalize this function. + fn update_starknet_version( + self, + block_number: &BlockNumber, + starknet_version: &StarknetVersion, + ) -> StorageResult { + let starknet_version_table = self.open_table(&self.tables.starknet_version)?; + let mut cursor = starknet_version_table.cursor(&self.txn)?; + cursor.lower_bound(block_number)?; + let res = cursor.prev()?; + + match res { + Some((_block_number, last_starknet_version)) + if last_starknet_version == *starknet_version => {} + _ => starknet_version_table.insert(&self.txn, block_number, starknet_version)?, + } + Ok(self) + } + + fn revert_header( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option, Option)> { + let markers_table = self.open_table(&self.tables.markers)?; + let headers_table = self.open_table(&self.tables.headers)?; + let block_hash_to_number_table = self.open_table(&self.tables.block_hash_to_number)?; + let starknet_version_table = self.open_table(&self.tables.starknet_version)?; + let block_signatures_table = self.open_table(&self.tables.block_signatures)?; + + // Assert that header marker equals the reverted block number + 1 + let current_header_marker = self.get_header_marker()?; + + // Reverts only the last header. + let Some(next_block_number) = block_number + .next() + .filter(|next_block_number| *next_block_number == current_header_marker) + else { + debug!( + "Attempt to revert a non-existing / old header of block {}. Returning without an \ + action.", + block_number + ); + return Ok((self, None, None)); + }; + + let reverted_header = headers_table + .get(&self.txn, &block_number)? + .expect("Missing header for block {block_number}."); + markers_table.upsert(&self.txn, &MarkerKind::Header, &block_number)?; + headers_table.delete(&self.txn, &block_number)?; + block_hash_to_number_table.delete(&self.txn, &reverted_header.block_hash)?; + + // Revert starknet version and get the version. + // TODO(shahak): Fix code duplication with get_starknet_version. + let mut cursor = starknet_version_table.cursor(&self.txn)?; + cursor.lower_bound(&next_block_number)?; + let res = cursor.prev()?; + + let starknet_version = match res { + Some((_block_number, starknet_version)) => starknet_version, + None => unreachable!( + "Since block_number >= self.get_header_marker(), starknet_version_table should \ + have at least a single mapping." + ), + }; + starknet_version_table.delete(&self.txn, &block_number)?; + + // Revert block signature. + let reverted_block_signature = block_signatures_table.get(&self.txn, &block_number)?; + if reverted_block_signature.is_some() { + block_signatures_table.delete(&self.txn, &block_number)?; + } + + Ok(( + self, + Some(BlockHeader { + block_hash: reverted_header.block_hash, + parent_hash: reverted_header.parent_hash, + block_number: reverted_header.block_number, + l1_gas_price: reverted_header.l1_gas_price, + l1_data_gas_price: reverted_header.l1_data_gas_price, + state_root: reverted_header.state_root, + sequencer: reverted_header.sequencer, + timestamp: reverted_header.timestamp, + l1_da_mode: reverted_header.l1_da_mode, + state_diff_commitment: reverted_header.state_diff_commitment, + transaction_commitment: reverted_header.transaction_commitment, + event_commitment: reverted_header.event_commitment, + receipt_commitment: reverted_header.receipt_commitment, + state_diff_length: reverted_header.state_diff_length, + n_transactions: reverted_header.n_transactions, + n_events: reverted_header.n_events, + starknet_version, + }), + reverted_block_signature, + )) + } + + fn append_block_signature( + self, + block_number: BlockNumber, + block_signature: &BlockSignature, + ) -> StorageResult { + let current_header_marker = self.get_header_marker()?; + if block_number >= current_header_marker { + return Err(StorageError::BlockSignatureForNonExistingBlock { + block_number, + block_signature: *block_signature, + }); + } + + let block_signatures_table = self.open_table(&self.tables.block_signatures)?; + block_signatures_table.insert(&self.txn, &block_number, block_signature)?; + Ok(self) + } +} + +fn update_hash_mapping<'env>( + txn: &DbTransaction<'env, RW>, + block_hash_to_number_table: &'env BlockHashToNumberTable<'env>, + block_header: &StorageBlockHeader, + block_number: BlockNumber, +) -> Result<(), StorageError> { + block_hash_to_number_table.insert(txn, &block_header.block_hash, &block_number)?; + Ok(()) +} + +fn update_marker<'env>( + txn: &DbTransaction<'env, RW>, + markers_table: &'env MarkersTable<'env>, + block_number: BlockNumber, +) -> StorageResult<()> { + // Make sure marker is consistent. + let header_marker = markers_table.get(txn, &MarkerKind::Header)?.unwrap_or_default(); + if header_marker != block_number { + return Err(StorageError::MarkerMismatch { expected: header_marker, found: block_number }); + }; + + // Advance marker. + markers_table.upsert(txn, &MarkerKind::Header, &block_number.unchecked_next())?; + Ok(()) +} diff --git a/crates/papyrus_storage/src/header_test.rs b/crates/papyrus_storage/src/header_test.rs new file mode 100644 index 00000000000..d5342cfad4c --- /dev/null +++ b/crates/papyrus_storage/src/header_test.rs @@ -0,0 +1,295 @@ +use assert_matches::assert_matches; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockHash, BlockHeader, BlockNumber, BlockSignature}; +use starknet_api::felt; + +use crate::header::{HeaderStorageReader, HeaderStorageWriter, StarknetVersion}; +use crate::test_utils::get_test_storage; +use crate::{StorageError, StorageWriter}; + +#[tokio::test] +async fn append_header() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + // Check for MarkerMismatch error when trying to append the wrong block number. + let Err(err) = + writer.begin_rw_txn().unwrap().append_header(BlockNumber(5), &BlockHeader::default()) + else { + panic!("Unexpected Ok."); + }; + + assert_matches!( + err, + StorageError::MarkerMismatch { expected, found } + if expected == BlockNumber(0) && found == BlockNumber(5) + ); + + // Check block hash. + assert_eq!( + reader.begin_ro_txn().unwrap().get_block_number_by_hash(&BlockHash::default()).unwrap(), + None + ); + + // Append with the right block number. + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .commit() + .unwrap(); + + // Check block and marker. + let txn = reader.begin_ro_txn().unwrap(); + let marker = txn.get_header_marker().unwrap(); + assert_eq!(marker, BlockNumber(1)); + let header = txn.get_block_header(BlockNumber(0)).unwrap(); + assert_eq!(header, Some(BlockHeader::default())); + + // Check block hash. + assert_eq!(txn.get_block_number_by_hash(&BlockHash::default()).unwrap(), Some(BlockNumber(0))); +} + +#[tokio::test] +async fn revert_non_existing_header_fails() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + let (_, deleted_data, _) = + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(5)).unwrap(); + assert!(deleted_data.is_none()); +} + +#[tokio::test] +async fn revert_last_header_success() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .commit() + .unwrap(); + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(0)).unwrap().0.commit().unwrap(); +} + +#[tokio::test] +async fn revert_old_header_fails() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + append_2_headers(&mut writer); + let (_, deleted_data, _) = + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(0)).unwrap(); + assert!(deleted_data.is_none()); +} + +#[tokio::test] +async fn revert_header_updates_marker() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_headers(&mut writer); + + // Verify that the header marker before revert is 2. + assert_eq!(reader.begin_ro_txn().unwrap().get_header_marker().unwrap(), BlockNumber(2)); + + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(1)).unwrap().0.commit().unwrap(); + assert_eq!(reader.begin_ro_txn().unwrap().get_header_marker().unwrap(), BlockNumber(1)); +} + +#[tokio::test] +async fn get_reverted_header_returns_none() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_headers(&mut writer); + + // Verify that we can get block 1's header before the revert. + assert!(reader.begin_ro_txn().unwrap().get_block_header(BlockNumber(1)).unwrap().is_some()); + + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(1)).unwrap().0.commit().unwrap(); + assert!(reader.begin_ro_txn().unwrap().get_block_header(BlockNumber(1)).unwrap().is_none()); +} + +#[tokio::test] +async fn get_reverted_block_number_by_hash_returns_none() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_headers(&mut writer); + + let block_hash = BlockHash(felt!("0x1")); + + // Verify that we can get block 1 by hash before the revert. + assert!( + reader.begin_ro_txn().unwrap().get_block_number_by_hash(&block_hash).unwrap().is_some() + ); + + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(1)).unwrap().0.commit().unwrap(); + assert!( + reader.begin_ro_txn().unwrap().get_block_number_by_hash(&block_hash).unwrap().is_none() + ); +} + +fn append_2_headers(writer: &mut StorageWriter) { + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { block_hash: BlockHash(felt!("0x0")), ..BlockHeader::default() }, + ) + .unwrap() + .append_header( + BlockNumber(1), + &BlockHeader { block_hash: BlockHash(felt!("0x1")), ..BlockHeader::default() }, + ) + .unwrap() + .commit() + .unwrap(); +} + +#[tokio::test] +async fn starknet_version() { + fn block_header(hash: u8, starknet_version: StarknetVersion) -> BlockHeader { + BlockHeader { + block_hash: BlockHash(felt!(hash)), + starknet_version, + ..BlockHeader::default() + } + } + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + let initial_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap(); + assert!(initial_starknet_version.is_none()); + + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &block_header(0, StarknetVersion::default())) + .unwrap() + .commit() + .unwrap(); + + let block_0_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap(); + assert_eq!(block_0_starknet_version.unwrap(), StarknetVersion::default()); + + let non_existing_block_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(1)).unwrap(); + assert!(non_existing_block_starknet_version.is_none()); + + let second_version = StarknetVersion("second_version".to_string()); + let yet_another_version = StarknetVersion("yet_another_version".to_string()); + + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(1), &block_header(1, StarknetVersion::default())) + .unwrap() + .append_header(BlockNumber(2), &block_header(2, second_version.clone())) + .unwrap() + .append_header(BlockNumber(3), &block_header(3, second_version.clone())) + .unwrap() + .append_header(BlockNumber(4), &block_header(4, yet_another_version.clone())) + .unwrap() + .append_header(BlockNumber(5), &block_header(5, yet_another_version.clone())) + .unwrap() + .commit() + .unwrap(); + + let block_0_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap(); + assert_eq!(block_0_starknet_version.unwrap(), StarknetVersion::default()); + + let block_1_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(1)).unwrap(); + assert_eq!(block_1_starknet_version.unwrap(), StarknetVersion::default()); + + let block_2_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(2)).unwrap(); + assert_eq!(block_2_starknet_version.unwrap(), second_version); + + let block_3_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(3)).unwrap(); + assert_eq!(block_3_starknet_version.unwrap(), second_version); + + let block_4_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(4)).unwrap(); + assert_eq!(block_4_starknet_version.unwrap(), yet_another_version); + + let block_5_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(5)).unwrap(); + assert_eq!(block_5_starknet_version.unwrap(), yet_another_version); + + let block_6_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(6)).unwrap(); + assert!(block_6_starknet_version.is_none()); + + // Revert block 5. + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(5)).unwrap().0.commit().unwrap(); + let block_5_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(5)).unwrap(); + assert!(block_5_starknet_version.is_none()); + + let block_4_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(4)).unwrap(); + assert_eq!(block_4_starknet_version.unwrap(), yet_another_version); + + // Revert block 4. + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(4)).unwrap().0.commit().unwrap(); + let block_4_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(4)).unwrap(); + assert!(block_4_starknet_version.is_none()); + + let block_3_starknet_version = + reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(3)).unwrap(); + assert_eq!(block_3_starknet_version.unwrap(), second_version); +} + +#[test] +fn block_signature() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + assert!(reader.begin_ro_txn().unwrap().get_block_signature(BlockNumber(0)).unwrap().is_none()); + let signature = BlockSignature::default(); + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_block_signature(BlockNumber(0), &signature) + .unwrap() + .commit() + .unwrap(); + assert_eq!( + reader.begin_ro_txn().unwrap().get_block_signature(BlockNumber(0)).unwrap(), + Some(signature) + ); +} + +#[test] +fn get_reverted_block_signature_returns_none() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let signature = BlockSignature::default(); + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &BlockHeader::default()) + .unwrap() + .append_block_signature(BlockNumber(0), &signature) + .unwrap() + .commit() + .unwrap(); + assert_eq!( + reader.begin_ro_txn().unwrap().get_block_signature(BlockNumber(0)).unwrap(), + Some(signature) + ); + let (txn, maybe_header, maybe_signature) = + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(0)).unwrap(); + txn.commit().unwrap(); + assert!(maybe_header.is_some()); + assert!(maybe_signature.is_some()); + assert!(reader.begin_ro_txn().unwrap().get_block_signature(BlockNumber(0)).unwrap().is_none()); +} + +#[test] +fn revert_overflowing_block_number() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + let (_, header, signature) = + writer.begin_rw_txn().unwrap().revert_header(BlockNumber(u64::MAX)).unwrap(); + assert!(header.is_none()); + assert!(signature.is_none()); +} diff --git a/crates/papyrus_storage/src/lib.rs b/crates/papyrus_storage/src/lib.rs new file mode 100644 index 00000000000..e02e825006b --- /dev/null +++ b/crates/papyrus_storage/src/lib.rs @@ -0,0 +1,894 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] +#![warn(missing_docs)] + +//! A storage implementation for a [`Starknet`] node. +//! +//! This crate provides a writing and reading interface for various Starknet data structures to a +//! database. Enables at most one writing operation and multiple reading operations concurrently. +//! The underlying storage is implemented using the [`libmdbx`] crate. +//! +//! # Disclaimer +//! This crate is still under development and is not keeping backwards compatibility with previous +//! versions. Breaking changes are expected to happen in the near future. +//! +//! # Quick Start +//! To use this crate, open a storage by calling [`open_storage`] to get a [`StorageWriter`] and a +//! [`StorageReader`] and use them to create [`StorageTxn`] instances. The actual +//! functionality is implemented on the transaction in multiple traits. +//! +//! ``` +//! use papyrus_storage::open_storage; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; // Import the header API. +//! use starknet_api::block::{BlockHeader, BlockNumber, StarknetVersion}; +//! use starknet_api::core::ChainId; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! let db_config = DbConfig { +//! path_prefix: dir, +//! chain_id: ChainId::Mainnet, +//! enforce_file_exists: false, +//! min_size: 1 << 20, // 1MB +//! max_size: 1 << 35, // 32GB +//! growth_step: 1 << 26, // 64MB +//! }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_header(BlockNumber(0), &BlockHeader::default())? // Append a header. +//! .commit()?; // Commit the changes. +//! +//! let header = reader.begin_ro_txn()?.get_block_header(BlockNumber(0))?; // Read the header. +//! assert_eq!(header, Some(BlockHeader::default())); +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` +//! # Storage Version +//! +//! Attempting to open an existing database using a crate version with a mismatching storage version +//! will result in an error. +//! +//! The storage version is composed of two components: [`STORAGE_VERSION_STATE`] for the state and +//! [`STORAGE_VERSION_BLOCKS`] for blocks. Each version consists of a major and a minor version. A +//! higher major version indicates that a re-sync is necessary, while a higher minor version +//! indicates a change that is migratable. +//! +//! When a storage is opened with [`StorageScope::StateOnly`], only the state version must match. +//! For storage opened with [`StorageScope::FullArchive`], both versions must match the crate's +//! versions. +//! +//! Incompatibility occurs when the code and the database have differing major versions. However, +//! if the code has the same major version but a higher minor version compared to the database, it +//! will still function properly. +//! +//! Example cases: +//! - Code: {major: 0, minor: 0}, Database: {major: 1, minor: 0} will fail due to major version +//! inequality. +//! - Code: {major: 0, minor: 0}, Database: {major: 0, minor: 1} will fail due to the smaller code's +//! minor version. +//! - Code: {major: 0, minor: 1}, Database: {major: 0, minor: 0} will succeed since the major +//! versions match and the code's minor version is higher. +//! +//! [`Starknet`]: https://starknet.io/ +//! [`libmdbx`]: https://docs.rs/libmdbx/latest/libmdbx/ + +pub mod base_layer; +pub mod body; +pub mod class; +pub mod compiled_class; +#[cfg(feature = "document_calls")] +pub mod document_calls; +pub mod utils; +// TODO(yair): Make the compression_utils module pub(crate) or extract it from the crate. +#[doc(hidden)] +pub mod compression_utils; +pub mod db; +pub mod header; +pub mod mmap_file; +mod serialization; +pub mod state; +mod version; + +mod deprecated; + +#[cfg(test)] +mod test_instances; + +#[cfg(any(feature = "testing", test))] +pub mod test_utils; + +use std::collections::{BTreeMap, HashMap}; +use std::fmt::Debug; +use std::sync::Arc; + +use body::events::EventIndex; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use db::db_stats::{DbTableStats, DbWholeStats}; +use db::serialization::{Key, NoVersionValueWrapper, ValueSerde, VersionZeroWrapper}; +use db::table_types::{CommonPrefix, NoValue, Table, TableType}; +use mmap_file::{ + open_file, + FileHandler, + LocationInFile, + MMapFileError, + MmapFileConfig, + Reader, + Writer, +}; +use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_proc_macros::latency_histogram; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber, BlockSignature, StarknetVersion}; +use starknet_api::core::{ClassHash, ContractAddress, Nonce}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::{ContractClass, StateNumber, StorageKey, ThinStateDiff}; +use starknet_api::transaction::{Transaction, TransactionHash, TransactionOutput}; +use starknet_types_core::felt::Felt; +use tracing::{debug, warn}; +use validator::Validate; +use version::{StorageVersionError, Version}; + +use crate::body::TransactionIndex; +use crate::db::table_types::SimpleTable; +use crate::db::{ + open_env, + DbConfig, + DbError, + DbReader, + DbTransaction, + DbWriter, + TableHandle, + TableIdentifier, + TransactionKind, + RO, + RW, +}; +use crate::header::StorageBlockHeader; +use crate::mmap_file::MMapFileStats; +use crate::state::data::IndexedDeprecatedContractClass; +pub use crate::utils::update_storage_metrics; +use crate::version::{VersionStorageReader, VersionStorageWriter}; + +// For more details on the storage version, see the module documentation. +/// The current version of the storage state code. +pub const STORAGE_VERSION_STATE: Version = Version { major: 1, minor: 1 }; +/// The current version of the storage blocks code. +pub const STORAGE_VERSION_BLOCKS: Version = Version { major: 2, minor: 0 }; + +/// Opens a storage and returns a [`StorageReader`] and a [`StorageWriter`]. +pub fn open_storage( + storage_config: StorageConfig, +) -> StorageResult<(StorageReader, StorageWriter)> { + let (db_reader, mut db_writer) = open_env(&storage_config.db_config)?; + let tables = Arc::new(Tables { + block_hash_to_number: db_writer.create_simple_table("block_hash_to_number")?, + block_signatures: db_writer.create_simple_table("block_signatures")?, + casms: db_writer.create_simple_table("casms")?, + contract_storage: db_writer.create_common_prefix_table("contract_storage")?, + declared_classes: db_writer.create_simple_table("declared_classes")?, + declared_classes_block: db_writer.create_simple_table("declared_classes_block")?, + deprecated_declared_classes: db_writer + .create_simple_table("deprecated_declared_classes")?, + deployed_contracts: db_writer.create_simple_table("deployed_contracts")?, + events: db_writer.create_common_prefix_table("events")?, + headers: db_writer.create_simple_table("headers")?, + markers: db_writer.create_simple_table("markers")?, + nonces: db_writer.create_common_prefix_table("nonces")?, + file_offsets: db_writer.create_simple_table("file_offsets")?, + state_diffs: db_writer.create_simple_table("state_diffs")?, + transaction_hash_to_idx: db_writer.create_simple_table("transaction_hash_to_idx")?, + transaction_metadata: db_writer.create_simple_table("transaction_metadata")?, + + // Version tables + starknet_version: db_writer.create_simple_table("starknet_version")?, + storage_version: db_writer.create_simple_table("storage_version")?, + }); + let (file_writers, file_readers) = open_storage_files( + &storage_config.db_config, + storage_config.mmap_file_config, + db_reader.clone(), + &tables.file_offsets, + )?; + + let reader = StorageReader { + db_reader, + tables: tables.clone(), + scope: storage_config.scope, + file_readers, + }; + let writer = StorageWriter { db_writer, tables, scope: storage_config.scope, file_writers }; + + let writer = set_version_if_needed(reader.clone(), writer)?; + verify_storage_version(reader.clone())?; + Ok((reader, writer)) +} + +// In case storage version does not exist, set it to the crate version. +// Expected to happen once - when the node is launched for the first time. +// If the storage scope has changed, update accordingly. +fn set_version_if_needed( + reader: StorageReader, + mut writer: StorageWriter, +) -> StorageResult { + let Some(existing_storage_version) = get_storage_version(reader)? else { + // Initialize the storage version. + writer.begin_rw_txn()?.set_state_version(&STORAGE_VERSION_STATE)?.commit()?; + // If in full-archive mode, also set the block version. + if writer.scope == StorageScope::FullArchive { + writer.begin_rw_txn()?.set_blocks_version(&STORAGE_VERSION_BLOCKS)?.commit()?; + } + debug!( + "Storage was initialized with state_version: {:?}, scope: {:?}, blocks_version: {:?}", + STORAGE_VERSION_STATE, writer.scope, STORAGE_VERSION_BLOCKS + ); + return Ok(writer); + }; + debug!("Existing storage state: {:?}", existing_storage_version); + // Handle the case where the storage scope has changed. + match existing_storage_version { + StorageVersion::FullArchive(FullArchiveVersion { state_version: _, blocks_version: _ }) => { + // TODO(yael): consider optimizing by deleting the block's data if the scope has changed + // to StateOnly + if writer.scope == StorageScope::StateOnly { + // Deletion of the block's version is required here. It ensures that the node knows + // that the storage operates in StateOnly mode and prevents the operator from + // running it in FullArchive mode again. + debug!("Changing the storage scope from FullArchive to StateOnly."); + writer.begin_rw_txn()?.delete_blocks_version()?.commit()?; + } + } + StorageVersion::StateOnly(StateOnlyVersion { state_version: _ }) => { + // The storage cannot change from state-only to full-archive mode. + if writer.scope == StorageScope::FullArchive { + return Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageScope, + )); + } + } + } + // Update the version if it's lower than the crate version. + let mut wtxn = writer.begin_rw_txn()?; + match existing_storage_version { + StorageVersion::FullArchive(FullArchiveVersion { state_version, blocks_version }) => { + // This allow is for when STORAGE_VERSION_STATE.minor = 0. + #[allow(clippy::absurd_extreme_comparisons)] + if STORAGE_VERSION_STATE.major == state_version.major + && STORAGE_VERSION_STATE.minor > state_version.minor + { + debug!( + "Updating the storage state version from {:?} to {:?}", + state_version, STORAGE_VERSION_STATE + ); + wtxn = wtxn.set_state_version(&STORAGE_VERSION_STATE)?; + } + // This allow is for when STORAGE_VERSION_BLOCKS.minor = 0. + #[allow(clippy::absurd_extreme_comparisons)] + if STORAGE_VERSION_BLOCKS.major == blocks_version.major + && STORAGE_VERSION_BLOCKS.minor > blocks_version.minor + { + debug!( + "Updating the storage blocks version from {:?} to {:?}", + blocks_version, STORAGE_VERSION_BLOCKS + ); + wtxn = wtxn.set_blocks_version(&STORAGE_VERSION_BLOCKS)?; + } + } + StorageVersion::StateOnly(StateOnlyVersion { state_version }) => { + // This allow is for when STORAGE_VERSION_STATE.minor = 0. + #[allow(clippy::absurd_extreme_comparisons)] + if STORAGE_VERSION_STATE.major == state_version.major + && STORAGE_VERSION_STATE.minor > state_version.minor + { + debug!( + "Updating the storage state version from {:?} to {:?}", + state_version, STORAGE_VERSION_STATE + ); + wtxn = wtxn.set_state_version(&STORAGE_VERSION_STATE)?; + } + } + } + wtxn.commit()?; + Ok(writer) +} + +#[derive(Debug)] +struct FullArchiveVersion { + state_version: Version, + blocks_version: Version, +} + +#[derive(Debug)] +struct StateOnlyVersion { + state_version: Version, +} + +#[derive(Debug)] +enum StorageVersion { + FullArchive(FullArchiveVersion), + StateOnly(StateOnlyVersion), +} + +fn get_storage_version(reader: StorageReader) -> StorageResult> { + let current_storage_version_state = + reader.begin_ro_txn()?.get_state_version().map_err(|err| { + if matches!(err, StorageError::InnerError(DbError::InnerDeserialization)) { + tracing::error!( + "Cannot deserialize storage version. Storage major version has been changed, \ + re-sync is needed." + ); + } + err + })?; + let current_storage_version_blocks = reader.begin_ro_txn()?.get_blocks_version()?; + let Some(current_storage_version_state) = current_storage_version_state else { + return Ok(None); + }; + match current_storage_version_blocks { + Some(current_storage_version_blocks) => { + Ok(Some(StorageVersion::FullArchive(FullArchiveVersion { + state_version: current_storage_version_state, + blocks_version: current_storage_version_blocks, + }))) + } + None => Ok(Some(StorageVersion::StateOnly(StateOnlyVersion { + state_version: current_storage_version_state, + }))), + } +} + +// Assumes the storage has a version. +fn verify_storage_version(reader: StorageReader) -> StorageResult<()> { + let existing_storage_version = get_storage_version(reader)?; + debug!( + "Crate storage version: State = {STORAGE_VERSION_STATE:} Blocks = \ + {STORAGE_VERSION_BLOCKS:}. Existing storage state: {existing_storage_version:?} " + ); + + match existing_storage_version { + None => panic!("Storage should be initialized."), + Some(StorageVersion::FullArchive(FullArchiveVersion { + state_version: existing_state_version, + blocks_version: _, + })) if STORAGE_VERSION_STATE != existing_state_version => { + Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageVersion { + crate_version: STORAGE_VERSION_STATE, + storage_version: existing_state_version, + }, + )) + } + + Some(StorageVersion::FullArchive(FullArchiveVersion { + state_version: _, + blocks_version: existing_blocks_version, + })) if STORAGE_VERSION_BLOCKS != existing_blocks_version => { + Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageVersion { + crate_version: STORAGE_VERSION_BLOCKS, + storage_version: existing_blocks_version, + }, + )) + } + + Some(StorageVersion::StateOnly(StateOnlyVersion { + state_version: existing_state_version, + })) if STORAGE_VERSION_STATE != existing_state_version => { + Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageVersion { + crate_version: STORAGE_VERSION_STATE, + storage_version: existing_state_version, + }, + )) + } + Some(_) => Ok(()), + } +} + +/// The categories of data to save in the storage. +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq)] +pub enum StorageScope { + /// Stores all types of data. + #[default] + FullArchive, + /// Stores the data describing the current state. In this mode the transaction, events and + /// state-diffs are not stored. + StateOnly, +} + +/// A struct for starting RO transactions ([`StorageTxn`]) to the storage. +#[derive(Clone)] +pub struct StorageReader { + db_reader: DbReader, + file_readers: FileHandlers, + tables: Arc, + scope: StorageScope, +} + +impl StorageReader { + /// Takes a snapshot of the current state of the storage and returns a [`StorageTxn`] for + /// reading data from the storage. + pub fn begin_ro_txn(&self) -> StorageResult> { + Ok(StorageTxn { + txn: self.db_reader.begin_ro_txn()?, + file_handlers: self.file_readers.clone(), + tables: self.tables.clone(), + scope: self.scope, + }) + } + + /// Returns metadata about the tables in the storage. + pub fn db_tables_stats(&self) -> StorageResult { + let mut tables_stats = BTreeMap::new(); + for name in Tables::field_names() { + tables_stats.insert(name.to_string(), self.db_reader.get_table_stats(name)?); + } + Ok(DbStats { db_stats: self.db_reader.get_db_stats()?, tables_stats }) + } + + /// Returns metadata about the memory mapped files in the storage. + pub fn mmap_files_stats(&self) -> HashMap { + self.file_readers.stats() + } + + /// Returns the scope of the storage. + pub fn get_scope(&self) -> StorageScope { + self.scope + } +} + +/// A struct for starting RW transactions ([`StorageTxn`]) to the storage. +/// There is a single non clonable writer instance, to make sure there is only one write transaction +/// at any given moment. +pub struct StorageWriter { + db_writer: DbWriter, + file_writers: FileHandlers, + tables: Arc, + scope: StorageScope, +} + +impl StorageWriter { + /// Takes a snapshot of the current state of the storage and returns a [`StorageTxn`] for + /// reading and modifying data in the storage. + pub fn begin_rw_txn(&mut self) -> StorageResult> { + Ok(StorageTxn { + txn: self.db_writer.begin_rw_txn()?, + file_handlers: self.file_writers.clone(), + tables: self.tables.clone(), + scope: self.scope, + }) + } +} + +/// A struct for interacting with the storage. +/// The actually functionality is implemented on the transaction in multiple traits. +pub struct StorageTxn<'env, Mode: TransactionKind> { + txn: DbTransaction<'env, Mode>, + file_handlers: FileHandlers, + tables: Arc, + scope: StorageScope, +} + +impl<'env> StorageTxn<'env, RW> { + /// Commits the changes made in the transaction to the storage. + #[latency_histogram("storage_commit_latency_seconds", false)] + pub fn commit(self) -> StorageResult<()> { + self.file_handlers.flush(); + Ok(self.txn.commit()?) + } +} + +impl<'env, Mode: TransactionKind> StorageTxn<'env, Mode> { + pub(crate) fn open_table( + &self, + table_id: &TableIdentifier, + ) -> StorageResult> { + if self.scope == StorageScope::StateOnly { + let unused_tables = [ + self.tables.events.name, + self.tables.transaction_hash_to_idx.name, + self.tables.transaction_metadata.name, + ]; + if unused_tables.contains(&table_id.name) { + return Err(StorageError::ScopeError { + table_name: table_id.name.to_owned(), + storage_scope: self.scope, + }); + } + } + Ok(self.txn.open_table(table_id)?) + } +} + +/// Returns the names of the tables in the storage. +pub fn table_names() -> &'static [&'static str] { + Tables::field_names() +} + +struct_field_names! { + struct Tables { + block_hash_to_number: TableIdentifier, SimpleTable>, + block_signatures: TableIdentifier, SimpleTable>, + casms: TableIdentifier, SimpleTable>, + // Empirically, defining the common prefix as (ContractAddress, StorageKey) is better space-wise than defining the + // common prefix only as ContractAddress. + contract_storage: TableIdentifier<((ContractAddress, StorageKey), BlockNumber), NoVersionValueWrapper, CommonPrefix>, + declared_classes: TableIdentifier, SimpleTable>, + declared_classes_block: TableIdentifier, SimpleTable>, + deprecated_declared_classes: TableIdentifier, SimpleTable>, + // TODO(dvir): consider use here also the CommonPrefix table type. + deployed_contracts: TableIdentifier<(ContractAddress, BlockNumber), VersionZeroWrapper, SimpleTable>, + events: TableIdentifier<(ContractAddress, TransactionIndex), NoVersionValueWrapper, CommonPrefix>, + headers: TableIdentifier, SimpleTable>, + markers: TableIdentifier, SimpleTable>, + nonces: TableIdentifier<(ContractAddress, BlockNumber), VersionZeroWrapper, CommonPrefix>, + file_offsets: TableIdentifier, SimpleTable>, + state_diffs: TableIdentifier, SimpleTable>, + transaction_hash_to_idx: TableIdentifier, SimpleTable>, + // TODO(dvir): consider not saving transaction hash and calculating it from the transaction on demand. + transaction_metadata: TableIdentifier, SimpleTable>, + + // Version tables + starknet_version: TableIdentifier, SimpleTable>, + storage_version: TableIdentifier, SimpleTable> + } +} + +macro_rules! struct_field_names { + (struct $name:ident { $($fname:ident : $ftype:ty),* }) => { + pub(crate) struct $name { + $($fname : $ftype),* + } + + impl $name { + fn field_names() -> &'static [&'static str] { + static NAMES: &'static [&'static str] = &[$(stringify!($fname)),*]; + NAMES + } + } + } +} +use struct_field_names; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct TransactionMetadata { + tx_hash: TransactionHash, + tx_location: LocationInFile, + tx_output_location: LocationInFile, +} + +// TODO: sort the variants alphabetically. +/// Error type for the storage crate. +#[allow(missing_docs)] +#[derive(thiserror::Error, Debug)] +pub enum StorageError { + /// Errors related to the underlying database. + #[error(transparent)] + InnerError(#[from] DbError), + #[error("Marker mismatch (expected {expected}, found {found}).")] + MarkerMismatch { expected: BlockNumber, found: BlockNumber }, + #[error( + "State diff redefined a nonce {nonce:?} for contract {contract_address:?} at block \ + {block_number}." + )] + NonceReWrite { nonce: Nonce, block_number: BlockNumber, contract_address: ContractAddress }, + #[error( + "Event with index {event_index:?} emitted from contract address {from_address:?} was not \ + found." + )] + EventNotFound { event_index: EventIndex, from_address: ContractAddress }, + #[error("DB in inconsistent state: {msg:?}.")] + DBInconsistency { msg: String }, + /// Errors related to the underlying files. + #[error(transparent)] + MMapFileError(#[from] MMapFileError), + #[error(transparent)] + StorageVersionInconsistency(#[from] StorageVersionError), + #[error("The table {table_name} is unused under the {storage_scope:?} storage scope.")] + ScopeError { table_name: String, storage_scope: StorageScope }, + #[error(transparent)] + IOError(#[from] std::io::Error), + #[error(transparent)] + SerdeError(#[from] serde_json::Error), + #[error( + "The block number {block} should be smaller than the compiled_class_marker \ + {compiled_class_marker}." + )] + InvalidBlockNumber { block: BlockNumber, compiled_class_marker: BlockNumber }, + #[error( + "Attempt to write block signature {block_signature:?} of non-existing block \ + {block_number}." + )] + BlockSignatureForNonExistingBlock { block_number: BlockNumber, block_signature: BlockSignature }, +} + +/// A type alias that maps to std::result::Result. +pub type StorageResult = std::result::Result; + +/// A struct for the configuration of the storage. +#[allow(missing_docs)] +#[derive(Serialize, Debug, Default, Deserialize, Clone, PartialEq, Validate)] +pub struct StorageConfig { + #[validate] + pub db_config: DbConfig, + #[validate] + pub mmap_file_config: MmapFileConfig, + pub scope: StorageScope, +} + +impl SerializeConfig for StorageConfig { + fn dump(&self) -> BTreeMap { + let mut dumped_config = BTreeMap::from_iter([ser_param( + "scope", + &self.scope, + "The categories of data saved in storage.", + ParamPrivacyInput::Public, + )]); + dumped_config + .extend(append_sub_config_name(self.mmap_file_config.dump(), "mmap_file_config")); + dumped_config.extend(append_sub_config_name(self.db_config.dump(), "db_config")); + dumped_config + } +} + +/// A struct for the statistics of the tables in the database. +#[derive(Serialize, Deserialize, Debug)] +pub struct DbStats { + /// Stats about the whole database. + pub db_stats: DbWholeStats, + /// A mapping from a table name in the database to its statistics. + pub tables_stats: BTreeMap, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +// A marker is the first block number for which the corresponding data doesn't exist yet. +// Invariants: +// - CompiledClass <= Class <= State <= Header +// - Body <= Header +// - BaseLayerBlock <= Header +// Event is currently unsupported. +pub(crate) enum MarkerKind { + Header, + Body, + Event, + State, + Class, + CompiledClass, + BaseLayerBlock, +} + +pub(crate) type MarkersTable<'env> = + TableHandle<'env, MarkerKind, VersionZeroWrapper, SimpleTable>; + +#[derive(Clone, Debug)] +struct FileHandlers { + thin_state_diff: FileHandler, Mode>, + contract_class: FileHandler, Mode>, + casm: FileHandler, Mode>, + deprecated_contract_class: FileHandler, Mode>, + transaction_output: FileHandler, Mode>, + transaction: FileHandler, Mode>, +} + +impl FileHandlers { + // Appends a thin state diff to the corresponding file and returns its location. + #[latency_histogram("storage_file_handler_append_state_diff_latency_seconds", true)] + fn append_state_diff(&self, thin_state_diff: &ThinStateDiff) -> LocationInFile { + self.clone().thin_state_diff.append(thin_state_diff) + } + + // Appends a contract class to the corresponding file and returns its location. + fn append_contract_class(&self, contract_class: &ContractClass) -> LocationInFile { + self.clone().contract_class.append(contract_class) + } + + // Appends a CASM to the corresponding file and returns its location. + fn append_casm(&self, casm: &CasmContractClass) -> LocationInFile { + self.clone().casm.append(casm) + } + + // Appends a deprecated contract class to the corresponding file and returns its location. + fn append_deprecated_contract_class( + &self, + deprecated_contract_class: &DeprecatedContractClass, + ) -> LocationInFile { + self.clone().deprecated_contract_class.append(deprecated_contract_class) + } + + // Appends a thin transaction output to the corresponding file and returns its location. + fn append_transaction_output(&self, transaction_output: &TransactionOutput) -> LocationInFile { + self.clone().transaction_output.append(transaction_output) + } + + // Appends a transaction to the corresponding file and returns its location. + fn append_transaction(&self, transaction: &Transaction) -> LocationInFile { + self.clone().transaction.append(transaction) + } + + // TODO(dan): Consider 1. flushing only the relevant files, 2. flushing concurrently. + #[latency_histogram("storage_file_handler_flush_latency_seconds", false)] + fn flush(&self) { + debug!("Flushing the mmap files."); + self.thin_state_diff.flush(); + self.contract_class.flush(); + self.casm.flush(); + self.deprecated_contract_class.flush(); + self.transaction_output.flush(); + self.transaction.flush(); + } +} + +impl FileHandlers { + pub fn stats(&self) -> HashMap { + // TODO: use consts for the file names. + HashMap::from_iter([ + ("thin_state_diff".to_string(), self.thin_state_diff.stats()), + ("contract_class".to_string(), self.contract_class.stats()), + ("casm".to_string(), self.casm.stats()), + ("deprecated_contract_class".to_string(), self.deprecated_contract_class.stats()), + ("transaction_output".to_string(), self.transaction_output.stats()), + ("transaction".to_string(), self.transaction.stats()), + ]) + } + + // Returns the thin state diff at the given location or an error in case it doesn't exist. + fn get_thin_state_diff_unchecked( + &self, + location: LocationInFile, + ) -> StorageResult { + self.thin_state_diff.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("ThinStateDiff at location {:?} not found.", location), + }) + } + + // Returns the contract class at the given location or an error in case it doesn't exist. + fn get_contract_class_unchecked( + &self, + location: LocationInFile, + ) -> StorageResult { + self.contract_class.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("ContractClass at location {:?} not found.", location), + }) + } + + // Returns the CASM at the given location or an error in case it doesn't exist. + fn get_casm_unchecked(&self, location: LocationInFile) -> StorageResult { + self.casm.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("CasmContractClass at location {:?} not found.", location), + }) + } + + // Returns the deprecated contract class at the given location or an error in case it doesn't + // exist. + fn get_deprecated_contract_class_unchecked( + &self, + location: LocationInFile, + ) -> StorageResult { + self.deprecated_contract_class.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("DeprecatedContractClass at location {:?} not found.", location), + }) + } + + // Returns the transaction output at the given location or an error in case it doesn't + // exist. + fn get_transaction_output_unchecked( + &self, + location: LocationInFile, + ) -> StorageResult { + self.transaction_output.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("TransactionOutput at location {:?} not found.", location), + }) + } + + // Returns the transaction at the given location or an error in case it doesn't exist. + fn get_transaction_unchecked(&self, location: LocationInFile) -> StorageResult { + self.transaction.get(location)?.ok_or(StorageError::DBInconsistency { + msg: format!("Transaction at location {:?} not found.", location), + }) + } +} + +fn open_storage_files( + db_config: &DbConfig, + mmap_file_config: MmapFileConfig, + db_reader: DbReader, + file_offsets_table: &TableIdentifier, SimpleTable>, +) -> StorageResult<(FileHandlers, FileHandlers)> { + let db_transaction = db_reader.begin_ro_txn()?; + let table = db_transaction.open_table(file_offsets_table)?; + + // TODO(dvir): consider using a loop here to avoid code duplication. + let thin_state_diff_offset = + table.get(&db_transaction, &OffsetKind::ThinStateDiff)?.unwrap_or_default(); + let (thin_state_diff_writer, thin_state_diff_reader) = open_file( + mmap_file_config.clone(), + db_config.path().join("thin_state_diff.dat"), + thin_state_diff_offset, + )?; + + let contract_class_offset = + table.get(&db_transaction, &OffsetKind::ContractClass)?.unwrap_or_default(); + let (contract_class_writer, contract_class_reader) = open_file( + mmap_file_config.clone(), + db_config.path().join("contract_class.dat"), + contract_class_offset, + )?; + + let casm_offset = table.get(&db_transaction, &OffsetKind::Casm)?.unwrap_or_default(); + let (casm_writer, casm_reader) = + open_file(mmap_file_config.clone(), db_config.path().join("casm.dat"), casm_offset)?; + + let deprecated_contract_class_offset = + table.get(&db_transaction, &OffsetKind::DeprecatedContractClass)?.unwrap_or_default(); + let (deprecated_contract_class_writer, deprecated_contract_class_reader) = open_file( + mmap_file_config.clone(), + db_config.path().join("deprecated_contract_class.dat"), + deprecated_contract_class_offset, + )?; + + let transaction_output_offset = + table.get(&db_transaction, &OffsetKind::TransactionOutput)?.unwrap_or_default(); + let (transaction_output_writer, transaction_output_reader) = open_file( + mmap_file_config.clone(), + db_config.path().join("transaction_output.dat"), + transaction_output_offset, + )?; + + let transaction_offset = + table.get(&db_transaction, &OffsetKind::Transaction)?.unwrap_or_default(); + let (transaction_writer, transaction_reader) = + open_file(mmap_file_config, db_config.path().join("transaction.dat"), transaction_offset)?; + + Ok(( + FileHandlers { + thin_state_diff: thin_state_diff_writer, + contract_class: contract_class_writer, + casm: casm_writer, + deprecated_contract_class: deprecated_contract_class_writer, + transaction_output: transaction_output_writer, + transaction: transaction_writer, + }, + FileHandlers { + thin_state_diff: thin_state_diff_reader, + contract_class: contract_class_reader, + casm: casm_reader, + deprecated_contract_class: deprecated_contract_class_reader, + transaction_output: transaction_output_reader, + transaction: transaction_reader, + }, + )) +} + +/// Represents a kind of mmap file. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum OffsetKind { + /// A thin state diff file. + ThinStateDiff, + /// A contract class file. + ContractClass, + /// A CASM file. + Casm, + /// A deprecated contract class file. + DeprecatedContractClass, + /// A transaction output file. + TransactionOutput, + /// A transaction file. + Transaction, +} + +/// A storage query. Used for benchmarking in the storage_benchmark binary. +// TODO(dvir): add more queries (especially get casm). +// TODO(dvir): consider move this, maybe to test_utils. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum StorageQuery { + /// Get the class hash at a given state number. + GetClassHashAt(StateNumber, ContractAddress), + /// Get the nonce at a given state number. + GetNonceAt(StateNumber, ContractAddress), + /// Get the storage at a given state number. + GetStorageAt(StateNumber, ContractAddress, StorageKey), +} diff --git a/crates/papyrus_storage/src/mmap_file/mmap_file_test.rs b/crates/papyrus_storage/src/mmap_file/mmap_file_test.rs new file mode 100644 index 00000000000..cae470419da --- /dev/null +++ b/crates/papyrus_storage/src/mmap_file/mmap_file_test.rs @@ -0,0 +1,304 @@ +use std::sync::Arc; + +use pretty_assertions::assert_eq; +use rand::Rng; +use tempfile::tempdir; +use test_utils::get_rng; +use tokio::sync::{Barrier, RwLock}; + +use super::*; +use crate::db::serialization::NoVersionValueWrapper; +use crate::test_utils::get_mmap_file_test_config; + +#[test] +fn config_validation() { + let mut config = get_mmap_file_test_config(); + config.max_size = config.growth_step - 1; + assert!(config.validate().is_err()); + config.max_size = 1 << 27; + assert!(config.validate().is_ok()); + + config.growth_step = config.max_object_size - 1; + assert!(config.validate().is_err()); + config.growth_step = 1 << 20; + assert!(config.validate().is_ok()); +} + +#[test] +fn write_read() { + let dir = tempdir().unwrap(); + let offset = 0; + let (mut writer, reader) = open_file::>>( + get_mmap_file_test_config(), + dir.path().to_path_buf().join("test_write_read"), + offset, + ) + .unwrap(); + let data = vec![1, 2, 3]; + + let location_in_file = writer.append(&data); + let res_writer = writer.get(location_in_file).unwrap().unwrap(); + assert_eq!(res_writer, data); + + let res = reader.get(location_in_file).unwrap().unwrap(); + assert_eq!(res, data); + + dir.close().unwrap(); +} + +#[test] +fn concurrent_reads() { + let dir = tempdir().unwrap(); + let offset = 0; + let (mut writer, reader) = open_file::>>( + get_mmap_file_test_config(), + dir.path().to_path_buf().join("test_concurrent_reads"), + offset, + ) + .unwrap(); + let data = vec![1, 2, 3]; + + let location_in_file = writer.append(&data); + + let num_threads = 50; + let mut handles = vec![]; + + for _ in 0..num_threads { + let reader = reader.clone(); + let handle = std::thread::spawn(move || reader.get(location_in_file).unwrap()); + handles.push(handle); + } + + for handle in handles { + let res = handle.join().unwrap().unwrap(); + assert_eq!(res, data); + } + + dir.close().unwrap(); +} + +#[test] +fn concurrent_reads_single_write() { + let dir = tempdir().unwrap(); + let offset = 0; + let (mut writer, reader) = open_file::>>( + get_mmap_file_test_config(), + dir.path().to_path_buf().join("test_concurrent_reads_single_write"), + offset, + ) + .unwrap(); + let first_data = vec![1, 2, 3]; + let second_data = vec![3, 2, 1]; + let first_location = writer.append(&first_data); + writer.flush(); + let second_location = + LocationInFile { offset: first_location.next_offset(), len: first_location.len }; + + let n = 10; + let barrier = Arc::new(std::sync::Barrier::new(n + 1)); + let mut handles = Vec::with_capacity(n); + + for _ in 0..n { + let reader = reader.clone(); + let reader_barrier = barrier.clone(); + let first_data = first_data.clone(); + handles.push(std::thread::spawn(move || { + assert_eq!(reader.get(first_location).unwrap().unwrap(), first_data); + reader_barrier.wait(); + // readers wait for the writer to write the value. + reader_barrier.wait(); + reader.get(second_location).unwrap() + })); + } + // Writer waits for all readers to read the first value. + barrier.wait(); + writer.append(&second_data); + writer.flush(); + // Allow readers to proceed reading the second value. + barrier.wait(); + + for handle in handles { + let res = handle.join().unwrap().unwrap(); + assert_eq!(res, second_data); + } +} + +#[test] +fn grow_file() { + let data = vec![1, 2]; + let serialization_size = NoVersionValueWrapper::serialize(&data).unwrap().len(); + let dir = tempdir().unwrap(); + let config = MmapFileConfig { + max_size: 10 * serialization_size, + max_object_size: serialization_size, // 3 (len + data) + growth_step: serialization_size + 1, // 4 + }; + + let file_path = dir.path().to_path_buf().join("test_grow_file"); + let mut offset = 0; + { + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .open(file_path.clone()) + .unwrap(); + // file_size = 0, offset = 0 + assert_eq!(file.metadata().unwrap().len(), 0); + + let (mut writer, _) = + open_file::>>(config.clone(), file_path.clone(), offset) + .unwrap(); + // file_size = 4 (growth_step), offset = 0 + let mut file_size = file.metadata().unwrap().len(); + assert_eq!(file_size, config.growth_step as u64); + assert_eq!(offset, 0); + + offset += writer.append(&data).len; + // file_size = 8 (2 * growth_step), offset = 3 (serialization_size) + file_size = file.metadata().unwrap().len(); + assert_eq!(file_size, 2 * config.growth_step as u64); + assert_eq!(offset, serialization_size); + + offset += writer.append(&data).len; + // file_size = 12 (3 * growth_step), offset = 6 (2 * serialization_size) + file_size = file.metadata().unwrap().len(); + assert_eq!(file_size, 3 * config.growth_step as u64); + assert_eq!(offset, 2 * serialization_size); + + offset += writer.append(&data).len; + // file_size = 12 (3 * growth_step), offset = 9 (3 * serialization_size) + file_size = file.metadata().unwrap().len(); + assert_eq!(file_size, 3 * config.growth_step as u64); + assert_eq!(offset, 3 * serialization_size); + + offset += writer.append(&data).len; + // file_size = 16 (4 * growth_step), offset = 12 (4 * serialization_size) + file_size = file.metadata().unwrap().len(); + assert_eq!(file_size, 4 * config.growth_step as u64); + assert_eq!(offset, 4 * serialization_size); + } + + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .open(file_path.clone()) + .unwrap(); + assert_eq!(file.metadata().unwrap().len(), 4 * config.growth_step as u64); + let _ = open_file::>>(config.clone(), file_path, offset).unwrap(); + assert_eq!(file.metadata().unwrap().len(), 4 * config.growth_step as u64); + + dir.close().unwrap(); +} + +#[tokio::test] +async fn write_read_different_locations() { + let dir = tempdir().unwrap(); + let offset = 0; + let (mut writer, reader) = open_file( + get_mmap_file_test_config(), + dir.path().to_path_buf().join("test_write_read_different_locations"), + offset, + ) + .unwrap(); + let mut data = vec![0, 1]; + + const ROUNDS: u8 = 10; + const LEN: usize = 3; + let n_readers_per_phase = 10; + let barrier = Arc::new(Barrier::new(n_readers_per_phase + 1)); + let lock = Arc::new(RwLock::new(0)); + + async fn reader_task( + reader: FileHandler>, RO>, + lock: Arc>, + barrier: Arc, + ) { + barrier.wait().await; + let round: usize; + { + round = *lock.read().await; + } + let read_offset = 3 * rand::thread_rng().gen_range(0..round + 1); + let read_location = LocationInFile { offset: read_offset, len: LEN }; + let read_value = reader.get(read_location).unwrap().unwrap(); + let first_expected_value: u8 = (read_offset / 3 * 2).try_into().unwrap(); + let expected_value = vec![first_expected_value, first_expected_value + 1]; + assert_eq!(read_value, expected_value); + } + + let mut handles = Vec::new(); + for round in 0..ROUNDS { + for _ in 0..n_readers_per_phase { + let reader = reader.clone(); + handles.push(tokio::spawn(reader_task(reader, lock.clone(), barrier.clone()))); + } + + writer.append(&data); + writer.flush(); + { + *lock.write().await = round as usize; + } + barrier.wait().await; + data = data.into_iter().map(|x| x + 2).collect(); + } + + for handle in handles { + handle.await.unwrap(); + } +} + +#[test] +fn reader_when_writer_is_out_of_scope() { + let dir = tempdir().unwrap(); + let offset = 0; + let (mut writer, reader) = open_file::>>( + get_mmap_file_test_config(), + dir.path().to_path_buf().join("test_reader_when_writer_is_out_of_scope"), + offset, + ) + .unwrap(); + let data = vec![1, 2, 3]; + + let location_in_file = writer.append(&data); + let res = reader.get(location_in_file).unwrap().unwrap(); + assert_eq!(res, data); + + drop(writer); + let res = reader.get(location_in_file).unwrap().unwrap(); + assert_eq!(res, data); + + dir.close().unwrap(); +} + +#[test] +fn storage_serde_test_location_in_file() { + let item = LocationInFile::get_test_instance(&mut get_rng()); + let mut buf = Vec::new(); + item.serialize_into(&mut buf).unwrap(); + let res = LocationInFile::deserialize_from(&mut buf.as_slice()).unwrap(); + assert_eq!(res, item); +} + +#[test] +fn location_in_file_serialization_max_value() { + let item = LocationInFile { offset: (1 << 48) - 1, len: (1 << 32) - 1 }; + let mut buf = Vec::new(); + item.serialize_into(&mut buf).unwrap(); + let res = LocationInFile::deserialize_from(&mut buf.as_slice()).unwrap(); + assert_eq!(res, item); +} + +#[test] +fn location_in_file_serialization_order() { + let location_1 = LocationInFile { offset: 1, len: 1 }; + let location_256 = LocationInFile { offset: 256, len: 1 }; + let mut serialized_1 = Vec::new(); + location_1.serialize_into(&mut serialized_1).unwrap(); + let mut serialized_256 = Vec::new(); + location_256.serialize_into(&mut serialized_256).unwrap(); + assert!(serialized_256 > serialized_1); +} diff --git a/crates/papyrus_storage/src/mmap_file/mod.rs b/crates/papyrus_storage/src/mmap_file/mod.rs new file mode 100644 index 00000000000..568dd3827b4 --- /dev/null +++ b/crates/papyrus_storage/src/mmap_file/mod.rs @@ -0,0 +1,315 @@ +//! Interface for handling append only data that is backed up by mmap file directly. +//! Data is serialized directly into the mmap file. +//! The caller **must** ensure that: +//! * The serialized data is not larger than the maximum object size. +//! * New data is appended to the file (i.e, at the offset returned by the previous write). + +#[cfg(test)] +mod mmap_file_test; + +use std::collections::BTreeMap; +use std::fmt::Debug; +use std::fs::{File, OpenOptions}; +use std::marker::PhantomData; +use std::path::PathBuf; +use std::result; +use std::sync::{Arc, Mutex}; + +use memmap2::{MmapMut, MmapOptions}; +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +#[cfg(test)] +use rand_chacha::ChaCha8Rng; +use serde::{Deserialize, Serialize}; +#[cfg(test)] +use test_utils::GetTestInstance; +use thiserror::Error; +use tracing::{debug, instrument, trace}; +use validator::{Validate, ValidationError}; + +use crate::db::serialization::{StorageSerde, StorageSerdeError, ValueSerde}; +use crate::db::{TransactionKind, RO, RW}; + +type MmapFileResult = result::Result; + +/// Configuration for a memory mapped file. +#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] +#[validate(schema(function = "validate_config"))] +pub struct MmapFileConfig { + /// The maximum size of the memory map in bytes. + pub max_size: usize, + /// The growth step of the corresponding file in bytes. + pub growth_step: usize, + /// The maximum size of an object in bytes. + pub max_object_size: usize, +} + +impl SerializeConfig for MmapFileConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "max_size", + &self.max_size, + "The maximum size of a memory mapped file in bytes. Must be greater than \ + growth_step.", + ParamPrivacyInput::Public, + ), + ser_param( + "growth_step", + &self.growth_step, + "The growth step in bytes, must be greater than max_object_size.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_object_size", + &self.max_object_size, + "The maximum size of a single object in the file in bytes", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl Default for MmapFileConfig { + fn default() -> Self { + Self { + max_size: 1 << 40, // 1TB + growth_step: 1 << 30, // 1GB + max_object_size: 1 << 28, // 256MB + } + } +} + +fn validate_config(config: &MmapFileConfig) -> result::Result<(), ValidationError> { + if config.max_size < config.growth_step { + return Err(ValidationError::new("max_size should be larger than growth_step")); + } + if config.growth_step < config.max_object_size { + return Err(ValidationError::new("growth_step should be larger than max_object_size")); + } + Ok(()) +} + +/// Errors associated with memory mapped files. +#[derive(Debug, Error)] +pub enum MMapFileError { + /// IO error. + #[error(transparent)] + IO(#[from] std::io::Error), + + /// Number conversion error. + #[error(transparent)] + TryFromInt(#[from] std::num::TryFromIntError), +} + +/// A trait for writing to a memory mapped file. +pub(crate) trait Writer { + /// Inserts an object to the file, returns the [`LocationInFile`] of the object. + fn append(&mut self, val: &V::Value) -> LocationInFile; + + /// Flushes the mmap to the file. + fn flush(&self); +} + +/// A trait for reading from a memory mapped file. +pub(crate) trait Reader { + /// Returns an object from the file. + fn get(&self, location: LocationInFile) -> MmapFileResult>; +} + +/// Represents a location in the file. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct LocationInFile { + /// Offset in the file. + offset: usize, + /// Length of the object. + len: usize, +} + +impl LocationInFile { + /// returns the next offset in the file. + pub fn next_offset(&self) -> usize { + self.offset + self.len + } +} + +/// Represents a memory mapped append only file. +#[derive(Debug)] +struct MMapFile { + config: MmapFileConfig, + file: File, + size: usize, + mmap: MmapMut, + offset: usize, + should_flush: bool, + _value_type: PhantomData, +} + +impl MMapFile { + /// Grows the file by the growth step. + fn grow(&mut self) { + self.flush(); + let new_size = self.size + self.config.growth_step; + debug!("Growing file to size: {}", new_size); + self.file.set_len(new_size as u64).expect("Failed to set the file size"); + self.size = new_size; + } + + /// Flushes the mmap to the file. + fn flush(&mut self) { + trace!("Flushing mmap to file"); + self.mmap.flush().expect("Failed to flush the mmap"); + self.should_flush = false; + } +} + +/// Open a memory mapped file, create it if it doesn't exist. +#[instrument(level = "debug", err)] +pub(crate) fn open_file( + config: MmapFileConfig, + path: PathBuf, + offset: usize, +) -> MmapFileResult<(FileHandler, FileHandler)> { + let file = OpenOptions::new().read(true).write(true).create(true).truncate(false).open(path)?; + let size = file.metadata()?.len(); + let mmap = unsafe { MmapOptions::new().len(config.max_size).map_mut(&file)? }; + let mmap_ptr = mmap.as_ptr(); + let mmap_file = MMapFile { + config, + file, + mmap, + size: size.try_into().expect("size should fit in usize"), + offset, + should_flush: false, + _value_type: PhantomData {}, + }; + let shared_mmap_file = Arc::new(Mutex::new(mmap_file)); + + let mut write_file_handler: FileHandler = FileHandler { + memory_ptr: mmap_ptr, + mmap_file: shared_mmap_file.clone(), + _mode: PhantomData, + }; + write_file_handler.grow_file_if_needed(0); + + let read_file_handler: FileHandler = + FileHandler { memory_ptr: mmap_ptr, mmap_file: shared_mmap_file, _mode: PhantomData }; + + Ok((write_file_handler, read_file_handler)) +} + +/// A wrapper around `MMapFile` that provides both write and read interfaces. +#[derive(Clone, Debug)] +pub(crate) struct FileHandler { + memory_ptr: *const u8, + mmap_file: Arc>>, + _mode: PhantomData, +} + +unsafe impl Send for FileHandler {} +unsafe impl Sync for FileHandler {} + +impl FileHandler { + fn grow_file_if_needed(&mut self, offset: usize) { + let mut mmap_file = self.mmap_file.lock().expect("Lock should not be poisoned"); + if mmap_file.size < offset + mmap_file.config.max_object_size { + debug!( + "Attempting to grow file. File size: {}, offset: {}, max_object_size: {}", + mmap_file.size, offset, mmap_file.config.max_object_size + ); + mmap_file.grow(); + } + } +} + +impl Writer for FileHandler { + fn append(&mut self, val: &V::Value) -> LocationInFile { + trace!("Inserting object: {:?}", val); + let serialized = V::serialize(val).expect("Should be able to serialize"); + let len = serialized.len(); + let offset; + { + let mut mmap_file = self.mmap_file.lock().expect("Lock should not be poisoned"); + offset = mmap_file.offset; + trace!("Inserting object at offset: {}", offset); + let mmap_slice = &mut mmap_file.mmap[offset..]; + mmap_slice[..len].copy_from_slice(&serialized); + mmap_file + .mmap + .flush_async_range(offset, len) + .expect("Failed to asynchronously flush the mmap after inserting"); + mmap_file.offset += len; + mmap_file.should_flush = true; + } + let location = LocationInFile { offset, len }; + self.grow_file_if_needed(location.next_offset()); + location + } + + fn flush(&self) { + let mut mmap_file = self.mmap_file.lock().expect("Lock should not be poisoned"); + if mmap_file.should_flush { + mmap_file.flush(); + } + } +} + +impl Reader for FileHandler { + /// Returns an object from the file. + fn get(&self, location: LocationInFile) -> MmapFileResult> { + trace!("Reading object at location: {:?}", location); + let mut bytes = unsafe { + std::slice::from_raw_parts( + self.memory_ptr.offset(location.offset.try_into()?), + location.len, + ) + }; + trace!("Deserializing object: {:?}", bytes); + Ok(V::deserialize(&mut bytes)) + } +} + +/// Stats for a memory mapped file. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct MMapFileStats { + // The current size of the file. + size: usize, + // The amount of data that has been written to the file. + offset: usize, +} + +impl FileHandler { + pub fn stats(&self) -> MMapFileStats { + let mmap_file = self.mmap_file.lock().expect("Lock should not be poisoned"); + MMapFileStats { size: mmap_file.size, offset: mmap_file.offset } + } +} + +// This serialization writes the offset as 6 bytes and the length as 4 bytes. +// This means the size of the file is limited to 256TB (1<<48 bits) and the length of the data +// is limited to 4GB (1<<32 bits). +impl StorageSerde for LocationInFile { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + let bytes = &self.len.to_be_bytes(); + res.write_all(&bytes[4..])?; + let bytes = &self.offset.to_be_bytes(); + res.write_all(&bytes[2..])?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let mut arr = [0u8; 8]; + bytes.read_exact(&mut arr[4..]).ok()?; + let len = usize::from_be_bytes(arr); + bytes.read_exact(&mut arr[2..]).ok()?; + let offset = usize::from_be_bytes(arr); + Some(Self { offset, len }) + } +} + +#[cfg(test)] +impl GetTestInstance for LocationInFile { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + Self { offset: usize::get_test_instance(rng), len: usize::get_test_instance(rng) } + } +} diff --git a/crates/papyrus_storage/src/serialization/mod.rs b/crates/papyrus_storage/src/serialization/mod.rs new file mode 100644 index 00000000000..a071991813f --- /dev/null +++ b/crates/papyrus_storage/src/serialization/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod serializers; +#[cfg(test)] +pub(crate) mod serializers_test; diff --git a/crates/papyrus_storage/src/serialization/serializers.rs b/crates/papyrus_storage/src/serialization/serializers.rs new file mode 100644 index 00000000000..c259ee3426c --- /dev/null +++ b/crates/papyrus_storage/src/serialization/serializers.rs @@ -0,0 +1,1263 @@ +use std::collections::{BTreeMap, HashMap}; +use std::convert::TryFrom; +use std::hash::Hash; +use std::ops::Deref; +use std::sync::Arc; + +use byteorder::BigEndian; +use cairo_lang_casm::hints::Hint; +use cairo_lang_starknet_classes::casm_contract_class::{ + CasmContractClass, + CasmContractEntryPoint, + CasmContractEntryPoints, +}; +use cairo_lang_starknet_classes::NestedIntList; +use cairo_lang_utils::bigint::BigUintAsHex; +use indexmap::IndexMap; +use integer_encoding::*; +use num_bigint::BigUint; +use parity_scale_codec::{Decode, Encode}; +use primitive_types::H160; +use starknet_api::block::{ + BlockHash, + BlockNumber, + BlockSignature, + BlockStatus, + BlockTimestamp, + GasPrice, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + EventCommitment, + GlobalRoot, + Nonce, + PatriciaKey, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::crypto::utils::Signature; +use starknet_api::data_availability::{DataAvailabilityMode, L1DataAvailabilityMode}; +use starknet_api::deprecated_contract_class::{ + ConstructorType, + ContractClass as DeprecatedContractClass, + ContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointOffset, + EntryPointType as DeprecatedEntryPointType, + EventAbiEntry, + EventType, + FunctionAbiEntry, + FunctionStateMutability, + FunctionType, + L1HandlerType, + Program, + StructAbiEntry, + StructMember, + StructType, + TypedParameter, +}; +use starknet_api::hash::{PoseidonHash, StarkHash}; +use starknet_api::state::{ + ContractClass, + EntryPoint, + EntryPointType, + FunctionIndex, + StorageKey, + ThinStateDiff, +}; +use starknet_api::transaction::{ + AccountDeploymentData, + Builtin, + Calldata, + ContractAddressSalt, + DeclareTransaction, + DeclareTransactionOutput, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeclareTransactionV3, + DeployAccountTransaction, + DeployAccountTransactionOutput, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + DeployTransaction, + DeployTransactionOutput, + Event, + EventContent, + EventData, + EventIndexInTransactionOutput, + EventKey, + ExecutionResources, + Fee, + GasVector, + InvokeTransaction, + InvokeTransactionOutput, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + L1HandlerTransaction, + L1HandlerTransactionOutput, + L1ToL2Payload, + L2ToL1Payload, + MessageToL1, + MessageToL2, + PaymasterData, + Resource, + ResourceBounds, + ResourceBoundsMapping, + RevertedTransactionExecutionStatus, + Tip, + Transaction, + TransactionExecutionStatus, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput, + TransactionSignature, + TransactionVersion, +}; +use starknet_types_core::felt::Felt; +use tracing::warn; + +use crate::body::events::EventIndex; +use crate::body::TransactionIndex; +use crate::compression_utils::{ + compress, + decompress, + decompress_from_reader, + serialize_and_compress, + IsCompressed, +}; +use crate::db::serialization::{StorageSerde, StorageSerdeError}; +use crate::db::table_types::NoValue; +use crate::header::StorageBlockHeader; +use crate::mmap_file::LocationInFile; +#[cfg(test)] +use crate::serialization::serializers_test::{create_storage_serde_test, StorageSerdeTest}; +use crate::state::data::IndexedDeprecatedContractClass; +use crate::version::Version; +use crate::{MarkerKind, OffsetKind, TransactionMetadata}; + +// The threshold for compressing transactions. +const COMPRESSION_THRESHOLD_BYTES: usize = 384; + +auto_storage_serde! { + pub struct AccountDeploymentData(pub Vec); + pub struct BlockHash(pub StarkHash); + pub struct StorageBlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, + pub n_transactions: usize, + pub n_events: usize, + } + pub struct BlockSignature(pub Signature); + pub enum BlockStatus { + Pending = 0, + AcceptedOnL2 = 1, + AcceptedOnL1 = 2, + Rejected = 3, + } + pub struct BlockTimestamp(pub u64); + pub struct Calldata(pub Arc>); + pub struct CompiledClassHash(pub StarkHash); + pub struct ClassHash(pub StarkHash); + pub struct ContractAddressSalt(pub StarkHash); + pub enum ContractClassAbiEntry { + Event(EventAbiEntry) = 0, + Function(FunctionAbiEntry) = 1, + Constructor(FunctionAbiEntry) = 2, + L1Handler(FunctionAbiEntry) = 3, + Struct(StructAbiEntry) = 4, + } + pub enum DataAvailabilityMode { + L1 = 0, + L2 = 1, + } + pub enum DeclareTransaction { + V0(DeclareTransactionV0V1) = 0, + V1(DeclareTransactionV0V1) = 1, + V2(DeclareTransactionV2) = 2, + V3(DeclareTransactionV3) = 3, + } + pub struct DeclareTransactionV0V1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + } + pub struct DeclareTransactionV2 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + } + pub struct DeclareTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + } + pub enum DeployAccountTransaction { + V1(DeployAccountTransactionV1) = 0, + V3(DeployAccountTransactionV3) = 1, + } + pub struct DeprecatedEntryPoint { + pub selector: EntryPointSelector, + pub offset: EntryPointOffset, + } + pub enum DeprecatedEntryPointType { + Constructor = 0, + External = 1, + L1Handler = 2, + } + pub struct EntryPoint { + pub function_idx: FunctionIndex, + pub selector: EntryPointSelector, + } + pub struct FunctionIndex(pub usize); + pub struct EntryPointOffset(pub usize); + pub struct EntryPointSelector(pub StarkHash); + pub enum EntryPointType { + Constructor = 0, + External = 1, + L1Handler = 2, + } + // TODO(dan): consider implementing directly with no H160 dependency. + pub struct EthAddress(pub H160); + pub struct EventAbiEntry { + pub data: Vec, + pub keys: Vec, + pub name: String, + pub r#type: EventType, + } + pub struct Event { + pub from_address: ContractAddress, + pub content: EventContent, + } + pub struct EventContent { + pub keys: Vec, + pub data: EventData, + } + pub struct EventCommitment(pub StarkHash); + pub struct EventData(pub Vec); + struct EventIndex(pub TransactionIndex, pub EventIndexInTransactionOutput); + pub struct EventIndexInTransactionOutput(pub usize); + pub struct EventKey(pub Felt); + pub enum EventType { + Event = 0, + } + pub struct Fee(pub u128); + pub enum FunctionStateMutability { + View = 0, + } + pub struct GasPrice(pub u128); + pub struct GasPricePerToken { + pub price_in_fri: GasPrice, + pub price_in_wei: GasPrice, + } + pub struct GasVector { + pub l1_gas: u64, + pub l1_data_gas: u64, + } + pub struct GlobalRoot(pub StarkHash); + pub struct H160(pub [u8; 20]); + pub struct IndexedDeprecatedContractClass { + pub block_number: BlockNumber, + pub location_in_file: LocationInFile, + } + pub enum InvokeTransaction { + V0(InvokeTransactionV0) = 0, + V1(InvokeTransactionV1) = 1, + V3(InvokeTransactionV3) = 2, + } + pub enum IsCompressed { + No = 0, + Yes = 1, + } + pub enum L1DataAvailabilityMode { + Calldata = 0, + Blob = 1, + } + pub struct L1ToL2Payload(pub Vec); + pub struct L2ToL1Payload(pub Vec); + enum MarkerKind { + Header = 0, + Body = 1, + Event = 2, + State = 3, + Class = 4, + CompiledClass = 5, + BaseLayerBlock = 6, + } + pub struct MessageToL1 { + pub to_address: EthAddress, + pub payload: L2ToL1Payload, + pub from_address: ContractAddress, + } + pub struct MessageToL2 { + pub from_address: EthAddress, + pub payload: L1ToL2Payload, + } + pub enum NestedIntList { + Leaf(usize) = 0, + Node(Vec) = 1, + } + pub struct Nonce(pub Felt); + pub enum OffsetKind { + ThinStateDiff = 0, + ContractClass = 1, + Casm = 2, + DeprecatedContractClass = 3, + TransactionOutput = 4, + Transaction = 5, + } + pub struct PaymasterData(pub Vec); + pub struct PoseidonHash(pub Felt); + pub struct Program { + pub attributes: serde_json::Value, + pub builtins: serde_json::Value, + pub compiler_version: serde_json::Value, + pub data: serde_json::Value, + pub debug_info: serde_json::Value, + pub hints: serde_json::Value, + pub identifiers: serde_json::Value, + pub main_scope: serde_json::Value, + pub prime: serde_json::Value, + pub reference_manager: serde_json::Value, + } + pub struct ReceiptCommitment(pub StarkHash); + pub enum Resource { + L1Gas = 0, + L2Gas = 1, + } + pub struct ResourceBounds { + pub max_amount: u64, + pub max_price_per_unit: u128, + } + pub struct ResourceBoundsMapping(pub BTreeMap); + pub struct SequencerContractAddress(pub ContractAddress); + pub struct Signature { + pub r: Felt, + pub s: Felt, + } + pub struct StructAbiEntry { + pub members: Vec, + pub name: String, + pub size: usize, + pub r#type: StructType, + } + pub struct StructMember { + pub name: String, + pub offset: usize, + pub r#type: String, + } + pub enum StructType { + Struct = 0, + } + pub struct StarknetVersion(pub String); + pub struct StateDiffCommitment(pub PoseidonHash); + pub struct Tip(pub u64); + pub struct TransactionCommitment(pub StarkHash); + pub struct TypedParameter { + pub name: String, + pub r#type: String, + } + pub struct TransactionMetadata { + pub tx_hash: TransactionHash, + pub tx_location: LocationInFile, + pub tx_output_location: LocationInFile, + } + pub enum Transaction { + Declare(DeclareTransaction) = 0, + Deploy(DeployTransaction) = 1, + DeployAccount(DeployAccountTransaction) = 2, + Invoke(InvokeTransaction) = 3, + L1Handler(L1HandlerTransaction) = 4, + } + pub enum TransactionExecutionStatus { + Succeeded = 0, + Reverted(RevertedTransactionExecutionStatus) = 1, + } + pub struct RevertedTransactionExecutionStatus { + pub revert_reason: String, + } + pub struct TransactionHash(pub StarkHash); + struct TransactionIndex(pub BlockNumber, pub TransactionOffsetInBlock); + pub enum TransactionOutput { + Declare(DeclareTransactionOutput) = 0, + Deploy(DeployTransactionOutput) = 1, + DeployAccount(DeployAccountTransactionOutput) = 2, + Invoke(InvokeTransactionOutput) = 3, + L1Handler(L1HandlerTransactionOutput) = 4, + } + pub struct TransactionSignature(pub Vec); + pub struct TransactionVersion(pub Felt); + pub struct Version{ + pub major: u32, + pub minor: u32, + } + + pub struct CasmContractEntryPoints { + pub external: Vec, + pub l1_handler: Vec, + pub constructor: Vec, + } + + pub struct CasmContractEntryPoint { + pub selector: BigUint, + pub offset: usize, + pub builtins: Vec, + } + + pub struct BigUintAsHex { + pub value: BigUint, + } + + pub struct ExecutionResources { + pub steps: u64, + pub builtin_instance_counter: HashMap, + pub memory_holes: u64, + pub da_gas_consumed: GasVector, + pub gas_consumed: GasVector, + } + + pub enum Builtin { + RangeCheck = 0, + Pedersen = 1, + Poseidon = 2, + EcOp = 3, + Ecdsa = 4, + Bitwise = 5, + Keccak = 6, + SegmentArena = 7, + AddMod = 8, + MulMod = 9, + RangeCheck96 = 10, + } + + binary(u32, read_u32, write_u32); + binary(u64, read_u64, write_u64); + binary(u128, read_u128, write_u128); + + + (BlockNumber, TransactionOffsetInBlock); + (BlockHash, ClassHash); + (ContractAddress, BlockHash); + (ContractAddress, BlockNumber); + (ContractAddress, Nonce); + (ContractAddress, StorageKey); + (ContractAddress, TransactionIndex); + ((ContractAddress, StorageKey), BlockNumber); + (usize, Vec); + (usize, Vec); +} + +//////////////////////////////////////////////////////////////////////// +// impl StorageSerde macro. +//////////////////////////////////////////////////////////////////////// +#[allow(unused_macro_rules)] +macro_rules! auto_storage_serde { + () => {}; + // Tuple structs (no names associated with fields) - one field. + ($(pub)? struct $name:ident($(pub)? $ty:ty); $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(Self (<$ty>::deserialize_from(bytes)?)) + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde!($($rest)*); + }; + // Tuple structs (no names associated with fields) - two fields. + ($(pub)? struct $name:ident($(pub)? $ty0:ty, $(pub)? $ty1:ty) ; $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res)?; + self.1.serialize_into(res) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some($name(<$ty0>::deserialize_from(bytes)?, <$ty1>::deserialize_from(bytes)?)) + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde!($($rest)*); + }; + // Structs with public fields. + ($(pub)? struct $name:ident { $(pub $field:ident : $ty:ty ,)* } $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + $( + self.$field.serialize_into(res)?; + )* + Ok(()) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(Self { + $( + $field: <$ty>::deserialize_from(bytes)?, + )* + }) + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde!($($rest)*); + }; + // Tuples - two elements. + (($ty0:ty, $ty1:ty) ; $($rest:tt)*) => { + impl StorageSerde for ($ty0, $ty1) { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res)?; + self.1.serialize_into(res) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(( + <$ty0>::deserialize_from(bytes)?, + <$ty1>::deserialize_from(bytes)?, + )) + } + } + auto_storage_serde!($($rest)*); + }; + // Tuples - three elements. + (($ty0:ty, $ty1:ty, $ty2:ty) ; $($rest:tt)*) => { + impl StorageSerde for ($ty0, $ty1, $ty2) { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res)?; + self.1.serialize_into(res)?; + self.2.serialize_into(res) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(( + <$ty0>::deserialize_from(bytes)?, + <$ty1>::deserialize_from(bytes)?, + <$ty2>::deserialize_from(bytes)?, + )) + } + } + auto_storage_serde!($($rest)*); + }; + // enums. + ($(pub)? enum $name:ident { $($variant:ident $( ($ty:ty) )? = $num:expr ,)* } $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + match self { + $( + variant!( value, $variant $( ($ty) )?) => { + res.write_all(&[$num as u8])?; + $( + (value as &$ty).serialize_into(res)?; + )? + Ok(()) + } + )* + } + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let mut kind = [0u8; 1]; + bytes.read_exact(&mut kind).ok()?; + match kind[0] { + $( + $num => { + Some(Self::$variant $( (<$ty>::deserialize_from(bytes)?) )? ) + }, + )* + _ => None,} + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde!($($rest)*); + }; + // Binary. + (binary($name:ident, $read:ident, $write:ident); $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + Ok(byteorder::WriteBytesExt::$write::(res, *self)?) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + byteorder::ReadBytesExt::$read::(bytes).ok() + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde!($($rest)*); + } +} +pub(crate) use auto_storage_serde; + +// Helper macro. +macro_rules! variant { + ($value:ident, $variant:ident) => { + Self::$variant + }; + ($value:ident, $variant:ident($ty:ty)) => { + Self::$variant($value) + }; +} +pub(crate) use variant; + +//////////////////////////////////////////////////////////////////////// +// Starknet API structs. +//////////////////////////////////////////////////////////////////////// +impl StorageSerde for ContractAddress { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + ContractAddress::try_from(StarkHash::deserialize(bytes)?).ok() + } +} + +impl StorageSerde for PatriciaKey { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.key().serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Self::try_from(StarkHash::deserialize(bytes)?).ok() + } +} + +impl StorageSerde for StarkHash { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + Ok(self.serialize(res)?) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Self::deserialize(bytes) + } +} + +impl StorageSerde for StorageKey { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.0.serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + StorageKey::try_from(StarkHash::deserialize(bytes)?).ok() + } +} + +//////////////////////////////////////////////////////////////////////// +// Primitive types. +//////////////////////////////////////////////////////////////////////// +impl StorageSerde for bool { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + u8::from(*self).serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some((u8::deserialize_from(bytes)?) != 0) + } +} + +// TODO(spapini): Perhaps compress this textual data. +impl StorageSerde for serde_json::Value { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + let bytes = serde_json::to_vec(self)?; + bytes.serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let buf = Vec::deserialize_from(bytes)?; + serde_json::from_slice(buf.as_slice()).ok() + } +} + +impl StorageSerde for String { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + (self.as_bytes().to_vec()).serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Self::from_utf8(Vec::deserialize_from(bytes)?).ok() + } +} + +impl StorageSerde for Option { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + match self { + Some(value) => { + res.write_all(&[1])?; + value.serialize_into(res) + } + None => Ok(res.write_all(&[0])?), + } + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let mut exists = [0u8; 1]; + bytes.read_exact(&mut exists).ok()?; + match exists[0] { + 0 => Some(None), + 1 => Some(Some(T::deserialize_from(bytes)?)), + _ => None, + } + } +} + +impl StorageSerde for u8 { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + Ok(byteorder::WriteBytesExt::write_u8(res, *self)?) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + byteorder::ReadBytesExt::read_u8(bytes).ok() + } +} + +// TODO(dan): get rid of usize. +impl StorageSerde for usize { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + (*self as u64).serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + usize::try_from(u64::deserialize_from(bytes)?).ok() + } +} + +impl StorageSerde for Vec { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + res.write_varint(self.len())?; + for x in self { + x.serialize_into(res)? + } + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let n: usize = bytes.read_varint().ok()?; + let mut res = Vec::with_capacity(n); + for _i in 0..n { + res.push(T::deserialize_from(bytes)?); + } + Some(res) + } +} +impl StorageSerde for HashMap { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + res.write_varint(self.len())?; + for (k, v) in self.iter() { + k.serialize_into(res)?; + v.serialize_into(res)?; + } + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let n: usize = bytes.read_varint().ok()?; + let mut res = HashMap::with_capacity(n); + for _i in 0..n { + let k = K::deserialize_from(bytes)?; + let v = V::deserialize_from(bytes)?; + if res.insert(k, v).is_some() { + return None; + } + } + Some(res) + } +} +// TODO(anatg): Find a way to share code with StorageSerde for HashMap. +impl StorageSerde for IndexMap { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + res.write_varint(self.len())?; + for (k, v) in self.iter() { + k.serialize_into(res)?; + v.serialize_into(res)?; + } + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let n: usize = bytes.read_varint().ok()?; + let mut res = IndexMap::with_capacity(n); + for _i in 0..n { + let k = K::deserialize_from(bytes)?; + let v = V::deserialize_from(bytes)?; + if res.insert(k, v).is_some() { + return None; + } + } + Some(res) + } +} +impl StorageSerde for BTreeMap { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + res.write_varint(self.len())?; + for (k, v) in self.iter() { + k.serialize_into(res)?; + v.serialize_into(res)?; + } + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let n: usize = bytes.read_varint().ok()?; + let mut res = BTreeMap::new(); + for _i in 0..n { + let k = K::deserialize_from(bytes)?; + let v = V::deserialize_from(bytes)?; + if res.insert(k, v).is_some() { + return None; + } + } + Some(res) + } +} +impl StorageSerde for [T; N] { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + for x in self { + x.serialize_into(res)?; + } + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let mut res = [T::default(); N]; + for elm in res.iter_mut() { + *elm = T::deserialize_from(bytes)?; + } + Some(res) + } +} +impl StorageSerde for Arc { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.deref().serialize_into(res)?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let res = T::deserialize_from(bytes)?; + Some(Arc::new(res)) + } +} + +impl StorageSerde for Hint { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.encode().serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Self::decode(&mut Vec::::deserialize_from(bytes)?.as_slice()).ok() + } +} + +impl StorageSerde for BigUint { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.to_bytes_be().serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let bytes_be = Vec::::deserialize_from(bytes)?; + Some(BigUint::from_bytes_be(bytes_be.as_slice())) + } +} + +impl StorageSerde for NoValue { + fn serialize_into(&self, _res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + Ok(()) + } + + fn deserialize_from(_bytes: &mut impl std::io::Read) -> Option { + Some(Self) + } +} + +//////////////////////////////////////////////////////////////////////// +// Custom serialization for storage reduction. +//////////////////////////////////////////////////////////////////////// +// TODO(dvir): remove this when BlockNumber will be u32. +impl StorageSerde for BlockNumber { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + u32::try_from(self.0).expect("BlockNumber should fit into 32 bits.").serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(BlockNumber(u32::deserialize_from(bytes)? as u64)) + } +} + +// This serialization write the offset as 3 bytes, which means that the maximum offset is ~16 +// million (1<<24 bytes). +impl StorageSerde for TransactionOffsetInBlock { + fn serialize_into( + &self, + res: &mut impl std::io::Write, + ) -> Result<(), crate::db::serialization::StorageSerdeError> { + let bytes = &self.0.to_be_bytes(); + res.write_all(&bytes[5..])?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let mut arr = [0u8; 8]; + bytes.read_exact(&mut arr[5..]).ok()?; + let index = usize::from_be_bytes(arr); + Some(Self(index)) + } +} + +//////////////////////////////////////////////////////////////////////// +// Custom serialization with compression. +//////////////////////////////////////////////////////////////////////// +impl StorageSerde for ContractClass { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + serialize_and_compress(&self.sierra_program)?.serialize_into(res)?; + self.entry_points_by_type.serialize_into(res)?; + serialize_and_compress(&self.abi)?.serialize_into(res)?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(Self { + sierra_program: Vec::::deserialize_from( + &mut decompress_from_reader(bytes)?.as_slice(), + )?, + entry_points_by_type: HashMap::>::deserialize_from( + bytes, + )?, + abi: String::deserialize_from(&mut decompress_from_reader(bytes)?.as_slice())?, + }) + } +} +#[cfg(test)] +create_storage_serde_test!(ContractClass); + +impl StorageSerde for DeprecatedContractClass { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + // Compress together the program and abi for better compression results. + let mut to_compress: Vec = Vec::new(); + self.abi.serialize_into(&mut to_compress)?; + self.program.serialize_into(&mut to_compress)?; + if to_compress.len() > crate::compression_utils::MAX_DECOMPRESSED_SIZE { + warn!( + "DeprecatedContractClass serialization size is too large and will lead to \ + deserialization error: {}", + to_compress.len() + ); + } + let compressed = compress(to_compress.as_slice())?; + compressed.serialize_into(res)?; + self.entry_points_by_type.serialize_into(res)?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let compressed_data = Vec::::deserialize_from(bytes)?; + let data = decompress(compressed_data.as_slice()) + .expect("destination buffer should be large enough"); + let data = &mut data.as_slice(); + Some(Self { + abi: Option::>::deserialize_from(data)?, + program: Program::deserialize_from(data)?, + entry_points_by_type: + HashMap::>::deserialize_from( + bytes, + )?, + }) + } +} +#[cfg(test)] +create_storage_serde_test!(DeprecatedContractClass); + +impl StorageSerde for FunctionAbiEntry { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + self.name.serialize_into(res)?; + self.inputs.serialize_into(res)?; + self.outputs.serialize_into(res)?; + self.state_mutability.serialize_into(res)?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + Some(Self { + name: String::deserialize_from(bytes)?, + inputs: Vec::::deserialize_from(bytes)?, + outputs: Vec::::deserialize_from(bytes)?, + state_mutability: Option::::deserialize_from(bytes)?, + r#type: TYPE::default(), + }) + } +} + +impl StorageSerde for CasmContractClass { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + let mut to_compress: Vec = Vec::new(); + self.prime.serialize_into(&mut to_compress)?; + self.compiler_version.serialize_into(&mut to_compress)?; + self.bytecode.serialize_into(&mut to_compress)?; + self.bytecode_segment_lengths.serialize_into(&mut to_compress)?; + self.hints.serialize_into(&mut to_compress)?; + self.pythonic_hints.serialize_into(&mut to_compress)?; + self.entry_points_by_type.serialize_into(&mut to_compress)?; + if to_compress.len() > crate::compression_utils::MAX_DECOMPRESSED_SIZE { + warn!( + "CasmContractClass serialization size is too large and will lead to \ + deserialization error: {}", + to_compress.len() + ); + } + let compressed = compress(to_compress.as_slice())?; + compressed.serialize_into(res)?; + + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let compressed_data = Vec::::deserialize_from(bytes)?; + let data = decompress(compressed_data.as_slice()) + .expect("destination buffer should be large enough"); + let data = &mut data.as_slice(); + Some(Self { + prime: BigUint::deserialize_from(data)?, + compiler_version: String::deserialize_from(data)?, + bytecode: Vec::::deserialize_from(data)?, + bytecode_segment_lengths: Option::::deserialize_from(data)?, + hints: Vec::<(usize, Vec)>::deserialize_from(data)?, + pythonic_hints: Option::)>>::deserialize_from(data)?, + entry_points_by_type: CasmContractEntryPoints::deserialize_from(data)?, + }) + } +} + +#[cfg(test)] +create_storage_serde_test!(CasmContractClass); + +impl StorageSerde for ThinStateDiff { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + let mut to_compress: Vec = Vec::new(); + self.deployed_contracts.serialize_into(&mut to_compress)?; + self.storage_diffs.serialize_into(&mut to_compress)?; + self.declared_classes.serialize_into(&mut to_compress)?; + self.deprecated_declared_classes.serialize_into(&mut to_compress)?; + self.nonces.serialize_into(&mut to_compress)?; + self.replaced_classes.serialize_into(&mut to_compress)?; + if to_compress.len() > crate::compression_utils::MAX_DECOMPRESSED_SIZE { + warn!( + "ThinStateDiff serialization size is too large and will lead to deserialization \ + error: {}", + to_compress.len() + ); + } + let compressed = compress(to_compress.as_slice())?; + compressed.serialize_into(res)?; + Ok(()) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let compressed_data = Vec::::deserialize_from(bytes)?; + let data = decompress(compressed_data.as_slice()) + .expect("destination buffer should be large enough"); + let data = &mut data.as_slice(); + Some(Self { + deployed_contracts: IndexMap::deserialize_from(data)?, + storage_diffs: IndexMap::deserialize_from(data)?, + declared_classes: IndexMap::deserialize_from(data)?, + deprecated_declared_classes: Vec::deserialize_from(data)?, + nonces: IndexMap::deserialize_from(data)?, + replaced_classes: IndexMap::deserialize_from(data)?, + }) + } +} + +#[cfg(test)] +create_storage_serde_test!(ThinStateDiff); + +// The following structs are conditionally compressed based on their serialized size. +macro_rules! auto_storage_serde_conditionally_compressed { + () => {}; + ($(pub)? struct $name:ident { $(pub $field:ident : $ty:ty ,)* } $($rest:tt)*) => { + impl StorageSerde for $name { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + let mut to_compress: Vec = Vec::new(); + $( + self.$field.serialize_into(&mut to_compress)?; + )* + if to_compress.len() > COMPRESSION_THRESHOLD_BYTES { + IsCompressed::Yes.serialize_into(res)?; + if to_compress.len() > crate::compression_utils::MAX_DECOMPRESSED_SIZE { + warn!( + "{} serialization size is too large and will lead to deserialization \ + error: {}", + stringify!($name), + to_compress.len() + ); + } + let compressed = compress(to_compress.as_slice())?; + compressed.serialize_into(res)?; + } else { + IsCompressed::No.serialize_into(res)?; + to_compress.serialize_into(res)?; + } + Ok(()) + } + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + let is_compressed = IsCompressed::deserialize_from(bytes)?; + let maybe_compressed_data = Vec::::deserialize_from(bytes)?; + let data = match is_compressed { + IsCompressed::No => maybe_compressed_data, + IsCompressed::Yes => decompress( + maybe_compressed_data.as_slice()) + .expect("destination buffer should be large enough"), + }; + let data = &mut data.as_slice(); + Some(Self { + $( + $field: <$ty>::deserialize_from(data)?, + )* + }) + } + } + #[cfg(test)] + create_storage_serde_test!($name); + auto_storage_serde_conditionally_compressed!($($rest)*); + }; +} + +// The following transactions have variable length Calldata and are conditionally compressed. +auto_storage_serde_conditionally_compressed! { + pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + } + + pub struct DeployAccountTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + } + + pub struct DeployTransaction { + pub version: TransactionVersion, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + } + + pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + + pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + } + + pub struct InvokeTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + } + + pub struct L1HandlerTransaction { + pub version: TransactionVersion, + pub nonce: Nonce, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + + pub struct DeclareTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + + pub struct DeployAccountTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + + pub struct DeployTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + + pub struct InvokeTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + + pub struct L1HandlerTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } +} diff --git a/crates/papyrus_storage/src/serialization/serializers_test.rs b/crates/papyrus_storage/src/serialization/serializers_test.rs new file mode 100644 index 00000000000..82804dda60f --- /dev/null +++ b/crates/papyrus_storage/src/serialization/serializers_test.rs @@ -0,0 +1,133 @@ +use std::fmt::Debug; + +use cairo_lang_casm::hints::CoreHintBase; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockNumber; +use starknet_api::core::ContractAddress; +use starknet_api::hash::StarkHash; +use starknet_api::state::StorageKey; +use starknet_api::transaction::TransactionOffsetInBlock; +use test_utils::{get_rng, read_json_file, GetTestInstance}; + +use crate::db::serialization::StorageSerde; + +pub trait StorageSerdeTest: StorageSerde { + fn storage_serde_test(); +} + +// Implements the [`storage_serde_test`] function for every type that +// implements the [`StorageSerde`] and [`GetTestInstance`] traits. +impl StorageSerdeTest for T { + fn storage_serde_test() { + let mut rng = get_rng(); + let item = T::get_test_instance(&mut rng); + let mut serialized: Vec = Vec::new(); + item.serialize_into(&mut serialized).unwrap(); + let bytes = serialized.into_boxed_slice(); + let deserialized = T::deserialize_from(&mut bytes.as_ref()); + assert_eq!(item, deserialized.unwrap()); + } +} + +// Tests all types that implement the [`StorageSerde`] trait +// via the [`auto_storage_serde`] macro. +macro_rules! create_storage_serde_test { + ($name:ident) => { + paste::paste! { + #[test] + fn [<"storage_serde_test" _$name:snake>]() { + $name::storage_serde_test() + } + } + }; +} +pub(crate) use create_storage_serde_test; + +//////////////////////////////////////////////////////////////////////// +// Implements the [`GetTestInstance`] trait for types not supported +// by the macro [`impl_get_test_instance`] and calls the [`create_test`] +// macro to create the tests for them. +//////////////////////////////////////////////////////////////////////// +create_storage_serde_test!(bool); +create_storage_serde_test!(ContractAddress); +create_storage_serde_test!(StarkHash); +create_storage_serde_test!(StorageKey); +create_storage_serde_test!(u8); +create_storage_serde_test!(usize); +create_storage_serde_test!(BlockNumber); +create_storage_serde_test!(TransactionOffsetInBlock); + +#[test] +fn transaction_offset_in_block_serialization_order() { + let offset_1 = TransactionOffsetInBlock(1); + let offset_256 = TransactionOffsetInBlock(256); + let mut serialized_1 = Vec::new(); + offset_1.serialize_into(&mut serialized_1).unwrap(); + let mut serialized_256 = Vec::new(); + offset_256.serialize_into(&mut serialized_256).unwrap(); + assert!(serialized_256 > serialized_1); +} + +#[test] +fn transaction_offset_in_block_serialization_max_value() { + let item = TransactionOffsetInBlock((1 << 24) - 1); + let mut buf = Vec::new(); + item.serialize_into(&mut buf).unwrap(); + let res = TransactionOffsetInBlock::deserialize_from(&mut buf.as_slice()).unwrap(); + assert_eq!(res, item); +} + +#[test] +fn block_number_endianness() { + let bn_255 = BlockNumber(255); + let mut serialized: Vec = Vec::new(); + bn_255.serialize_into(&mut serialized).unwrap(); + let bytes_255 = serialized.into_boxed_slice(); + let deserialized = BlockNumber::deserialize_from(&mut bytes_255.as_ref()); + assert_eq!(bn_255, deserialized.unwrap()); + + let bn_256 = BlockNumber(256); + let mut serialized: Vec = Vec::new(); + bn_256.serialize_into(&mut serialized).unwrap(); + let bytes_256 = serialized.into_boxed_slice(); + let deserialized = BlockNumber::deserialize_from(&mut bytes_256.as_ref()); + assert_eq!(bn_256, deserialized.unwrap()); + + assert!(bytes_255 < bytes_256); +} + +// Make sure that the [`Hint`] schema is not modified. If it is, its encoding might change and a +// storage migration is needed. +#[test] +fn hint_modified() { + // Only CoreHintBase is being used in programs (StarknetHint is for tests). + let hint_schema = schemars::schema_for!(CoreHintBase); + insta::assert_yaml_snapshot!(hint_schema); +} + +// Tests the persistent encoding of the hints of an ERC20 contract. +// Each snapshot filename contains the hint's index in the origin casm file, so that a failure in +// the assertion of a file can lead to the hint that caused it. +#[test] +fn hints_regression() { + let casm = serde_json::from_value::(read_json_file( + "erc20_compiled_contract_class.json", + )) + .unwrap(); + for hint in casm.hints.iter() { + let mut encoded_hint: Vec = Vec::new(); + hint.serialize_into(&mut encoded_hint) + .unwrap_or_else(|_| panic!("Failed to serialize hint {hint:?}")); + insta::assert_yaml_snapshot!(format!("hints_regression_hint_{}", hint.0), encoded_hint); + } +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/papyrus_storage/src/serialization/snapshots/papyrus_storage__serialization__serializers_test__hint_modified.snap b/crates/papyrus_storage/src/serialization/snapshots/papyrus_storage__serialization__serializers_test__hint_modified.snap new file mode 100644 index 00000000000..065902d3774 --- /dev/null +++ b/crates/papyrus_storage/src/serialization/snapshots/papyrus_storage__serialization__serializers_test__hint_modified.snap @@ -0,0 +1,792 @@ +--- +source: crates/papyrus_storage/src/serialization/serializers_test.rs +expression: hint_schema +--- +$schema: "http://json-schema.org/draft-07/schema#" +title: CoreHintBase +anyOf: + - $ref: "#/definitions/CoreHint" + - $ref: "#/definitions/DeprecatedHint" +definitions: + CoreHint: + oneOf: + - type: object + required: + - AllocSegment + properties: + AllocSegment: + type: object + required: + - dst + properties: + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - TestLessThan + properties: + TestLessThan: + type: object + required: + - dst + - lhs + - rhs + properties: + lhs: + $ref: "#/definitions/ResOperand" + rhs: + $ref: "#/definitions/ResOperand" + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - TestLessThanOrEqual + properties: + TestLessThanOrEqual: + type: object + required: + - dst + - lhs + - rhs + properties: + lhs: + $ref: "#/definitions/ResOperand" + rhs: + $ref: "#/definitions/ResOperand" + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Variant of TestLessThanOrEqual that compares addresses. + type: object + required: + - TestLessThanOrEqualAddress + properties: + TestLessThanOrEqualAddress: + type: object + required: + - dst + - lhs + - rhs + properties: + lhs: + $ref: "#/definitions/ResOperand" + rhs: + $ref: "#/definitions/ResOperand" + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Multiplies two 128-bit integers and returns two 128-bit integers: the high and low parts of the product." + type: object + required: + - WideMul128 + properties: + WideMul128: + type: object + required: + - high + - lhs + - low + - rhs + properties: + lhs: + $ref: "#/definitions/ResOperand" + rhs: + $ref: "#/definitions/ResOperand" + high: + $ref: "#/definitions/CellRef" + low: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Computes lhs/rhs and returns the quotient and remainder.\n\nNote: the hint may be used to write an already assigned memory cell." + type: object + required: + - DivMod + properties: + DivMod: + type: object + required: + - lhs + - quotient + - remainder + - rhs + properties: + lhs: + $ref: "#/definitions/ResOperand" + rhs: + $ref: "#/definitions/ResOperand" + quotient: + $ref: "#/definitions/CellRef" + remainder: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Divides dividend (represented by 2 128bit limbs) by divisor (represented by 2 128bit limbs). Returns the quotient (represented by 2 128bit limbs) and remainder (represented by 2 128bit limbs). In all cases - `name`0 is the least significant limb." + type: object + required: + - Uint256DivMod + properties: + Uint256DivMod: + type: object + required: + - dividend0 + - dividend1 + - divisor0 + - divisor1 + - quotient0 + - quotient1 + - remainder0 + - remainder1 + properties: + dividend0: + $ref: "#/definitions/ResOperand" + dividend1: + $ref: "#/definitions/ResOperand" + divisor0: + $ref: "#/definitions/ResOperand" + divisor1: + $ref: "#/definitions/ResOperand" + quotient0: + $ref: "#/definitions/CellRef" + quotient1: + $ref: "#/definitions/CellRef" + remainder0: + $ref: "#/definitions/CellRef" + remainder1: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Divides dividend (represented by 4 128bit limbs) by divisor (represented by 2 128bit limbs). Returns the quotient (represented by 4 128bit limbs) and remainder (represented by 2 128bit limbs). In all cases - `name`0 is the least significant limb." + type: object + required: + - Uint512DivModByUint256 + properties: + Uint512DivModByUint256: + type: object + required: + - dividend0 + - dividend1 + - dividend2 + - dividend3 + - divisor0 + - divisor1 + - quotient0 + - quotient1 + - quotient2 + - quotient3 + - remainder0 + - remainder1 + properties: + dividend0: + $ref: "#/definitions/ResOperand" + dividend1: + $ref: "#/definitions/ResOperand" + dividend2: + $ref: "#/definitions/ResOperand" + dividend3: + $ref: "#/definitions/ResOperand" + divisor0: + $ref: "#/definitions/ResOperand" + divisor1: + $ref: "#/definitions/ResOperand" + quotient0: + $ref: "#/definitions/CellRef" + quotient1: + $ref: "#/definitions/CellRef" + quotient2: + $ref: "#/definitions/CellRef" + quotient3: + $ref: "#/definitions/CellRef" + remainder0: + $ref: "#/definitions/CellRef" + remainder1: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - SquareRoot + properties: + SquareRoot: + type: object + required: + - dst + - value + properties: + value: + $ref: "#/definitions/ResOperand" + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Computes the square root of value_low<<128+value_high, stores the 64bit limbs of the result in sqrt0 and sqrt1 as well as the 128bit limbs of the remainder in remainder_low and remainder_high. The remainder is defined as `value - sqrt**2`. Lastly it checks weather `2*sqrt - remainder >= 2**128`." + type: object + required: + - Uint256SquareRoot + properties: + Uint256SquareRoot: + type: object + required: + - remainder_high + - remainder_low + - sqrt0 + - sqrt1 + - sqrt_mul_2_minus_remainder_ge_u128 + - value_high + - value_low + properties: + value_low: + $ref: "#/definitions/ResOperand" + value_high: + $ref: "#/definitions/ResOperand" + sqrt0: + $ref: "#/definitions/CellRef" + sqrt1: + $ref: "#/definitions/CellRef" + remainder_low: + $ref: "#/definitions/CellRef" + remainder_high: + $ref: "#/definitions/CellRef" + sqrt_mul_2_minus_remainder_ge_u128: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Finds some `x` and `y` such that `x * scalar + y = value` and `x <= max_x`." + type: object + required: + - LinearSplit + properties: + LinearSplit: + type: object + required: + - max_x + - scalar + - value + - x + - y + properties: + value: + $ref: "#/definitions/ResOperand" + scalar: + $ref: "#/definitions/ResOperand" + max_x: + $ref: "#/definitions/ResOperand" + x: + $ref: "#/definitions/CellRef" + y: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Allocates a new dict segment, and write its start address into the dict_infos segment." + type: object + required: + - AllocFelt252Dict + properties: + AllocFelt252Dict: + type: object + required: + - segment_arena_ptr + properties: + segment_arena_ptr: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: "Fetch the previous value of a key in a dict, and write it in a new dict access." + type: object + required: + - Felt252DictEntryInit + properties: + Felt252DictEntryInit: + type: object + required: + - dict_ptr + - key + properties: + dict_ptr: + $ref: "#/definitions/ResOperand" + key: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: "Similar to Felt252DictWrite, but updates an existing entry and does not write the previous value to the stack." + type: object + required: + - Felt252DictEntryUpdate + properties: + Felt252DictEntryUpdate: + type: object + required: + - dict_ptr + - value + properties: + dict_ptr: + $ref: "#/definitions/ResOperand" + value: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: Retrieves the index of the given dict in the dict_infos segment. + type: object + required: + - GetSegmentArenaIndex + properties: + GetSegmentArenaIndex: + type: object + required: + - dict_end_ptr + - dict_index + properties: + dict_end_ptr: + $ref: "#/definitions/ResOperand" + dict_index: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Initialized the lists of accesses of each key of a dict as a preparation of squash_dict. + type: object + required: + - InitSquashData + properties: + InitSquashData: + type: object + required: + - big_keys + - dict_accesses + - first_key + - n_accesses + - ptr_diff + properties: + dict_accesses: + $ref: "#/definitions/ResOperand" + ptr_diff: + $ref: "#/definitions/ResOperand" + n_accesses: + $ref: "#/definitions/ResOperand" + big_keys: + $ref: "#/definitions/CellRef" + first_key: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Retrieves the current index of a dict access to process. + type: object + required: + - GetCurrentAccessIndex + properties: + GetCurrentAccessIndex: + type: object + required: + - range_check_ptr + properties: + range_check_ptr: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: Writes if the squash_dict loop should be skipped. + type: object + required: + - ShouldSkipSquashLoop + properties: + ShouldSkipSquashLoop: + type: object + required: + - should_skip_loop + properties: + should_skip_loop: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Writes the delta from the current access index to the next one. + type: object + required: + - GetCurrentAccessDelta + properties: + GetCurrentAccessDelta: + type: object + required: + - index_delta_minus1 + properties: + index_delta_minus1: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Writes if the squash_dict loop should be continued. + type: object + required: + - ShouldContinueSquashLoop + properties: + ShouldContinueSquashLoop: + type: object + required: + - should_continue + properties: + should_continue: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Writes the next dict key to process. + type: object + required: + - GetNextDictKey + properties: + GetNextDictKey: + type: object + required: + - next_key + properties: + next_key: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Finds the two small arcs from within [(0,a),(a,b),(b,PRIME)] and writes it to the range_check segment." + type: object + required: + - AssertLeFindSmallArcs + properties: + AssertLeFindSmallArcs: + type: object + required: + - a + - b + - range_check_ptr + properties: + range_check_ptr: + $ref: "#/definitions/ResOperand" + a: + $ref: "#/definitions/ResOperand" + b: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: "Writes if the arc (0,a) was excluded." + type: object + required: + - AssertLeIsFirstArcExcluded + properties: + AssertLeIsFirstArcExcluded: + type: object + required: + - skip_exclude_a_flag + properties: + skip_exclude_a_flag: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Writes if the arc (a,b) was excluded." + type: object + required: + - AssertLeIsSecondArcExcluded + properties: + AssertLeIsSecondArcExcluded: + type: object + required: + - skip_exclude_b_minus_a + properties: + skip_exclude_b_minus_a: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Samples a random point on the EC. + type: object + required: + - RandomEcPoint + properties: + RandomEcPoint: + type: object + required: + - x + - y + properties: + x: + $ref: "#/definitions/CellRef" + y: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Computes the square root of `val`, if `val` is a quadratic residue, and of `3 * val` otherwise.\n\nSince 3 is not a quadratic residue, exactly one of `val` and `3 * val` is a quadratic residue (unless `val` is 0). This allows proving that `val` is not a quadratic residue." + type: object + required: + - FieldSqrt + properties: + FieldSqrt: + type: object + required: + - sqrt + - val + properties: + val: + $ref: "#/definitions/ResOperand" + sqrt: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Prints the values from start to end. Both must be pointers. + type: object + required: + - DebugPrint + properties: + DebugPrint: + type: object + required: + - end + - start + properties: + start: + $ref: "#/definitions/ResOperand" + end: + $ref: "#/definitions/ResOperand" + additionalProperties: false + - description: "Returns an address with `size` free locations afterwards." + type: object + required: + - AllocConstantSize + properties: + AllocConstantSize: + type: object + required: + - dst + - size + properties: + size: + $ref: "#/definitions/ResOperand" + dst: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: "Provides the inverse of b (represented by 2 128-bit limbs) modulo n (represented by 2 128-bit limbs), or a proof that b has no inverse.\n\nIn case b has an inverse: Returns `r` and `k` such that: * `r = 1 / b (mod n)` * `k = (r * b - 1) / n` * `g0_or_no_inv = 0`\n\nIn case b has no inverse: Returns `g`, `s`, and `t`, such that: `g > 1` `g == 2 || g % 2 == 1` (in particular, `g0_or_no_inv = g0 != 0`) `g * s = b` `g * t = n`\n\nThe case `n == 1` is considered \"no-inverse\" (special case). In this case: Returns `g == 1`, `s == b` and `t == 1`. All no-inverse requirements are satisfied, except for `g > 1`.\n\nIn all cases - `name`0 is the least significant limb." + type: object + required: + - U256InvModN + properties: + U256InvModN: + type: object + required: + - b0 + - b1 + - g0_or_no_inv + - g1_option + - n0 + - n1 + - s_or_r0 + - s_or_r1 + - t_or_k0 + - t_or_k1 + properties: + b0: + $ref: "#/definitions/ResOperand" + b1: + $ref: "#/definitions/ResOperand" + n0: + $ref: "#/definitions/ResOperand" + n1: + $ref: "#/definitions/ResOperand" + g0_or_no_inv: + $ref: "#/definitions/CellRef" + g1_option: + $ref: "#/definitions/CellRef" + s_or_r0: + $ref: "#/definitions/CellRef" + s_or_r1: + $ref: "#/definitions/CellRef" + t_or_k0: + $ref: "#/definitions/CellRef" + t_or_k1: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - EvalCircuit + properties: + EvalCircuit: + type: object + required: + - add_mod_builtin + - mul_mod_builtin + - n_add_mods + - n_mul_mods + properties: + n_add_mods: + $ref: "#/definitions/ResOperand" + add_mod_builtin: + $ref: "#/definitions/ResOperand" + n_mul_mods: + $ref: "#/definitions/ResOperand" + mul_mod_builtin: + $ref: "#/definitions/ResOperand" + additionalProperties: false + CellRef: + description: "Represents an operand of the form [reg + offset]." + type: object + required: + - offset + - register + properties: + register: + $ref: "#/definitions/Register" + offset: + type: integer + format: int16 + Register: + type: string + enum: + - AP + - FP + ResOperand: + oneOf: + - type: object + required: + - Deref + properties: + Deref: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - DoubleDeref + properties: + DoubleDeref: + type: array + items: + - $ref: "#/definitions/CellRef" + - type: integer + format: int16 + maxItems: 2 + minItems: 2 + additionalProperties: false + - type: object + required: + - Immediate + properties: + Immediate: + $ref: "#/definitions/BigInt" + additionalProperties: false + - type: object + required: + - BinOp + properties: + BinOp: + $ref: "#/definitions/BinOpOperand" + additionalProperties: false + BigInt: + type: object + required: + - data + - sign + properties: + sign: + $ref: "#/definitions/Sign" + data: + $ref: "#/definitions/BigUint" + Sign: + type: string + enum: + - Minus + - NoSign + - Plus + BigUint: + type: object + required: + - data + properties: + data: + type: array + items: + type: integer + format: uint64 + minimum: 0 + BinOpOperand: + type: object + required: + - a + - b + - op + properties: + op: + $ref: "#/definitions/Operation" + a: + $ref: "#/definitions/CellRef" + b: + $ref: "#/definitions/DerefOrImmediate" + Operation: + type: string + enum: + - Add + - Mul + DerefOrImmediate: + oneOf: + - type: object + required: + - Deref + properties: + Deref: + $ref: "#/definitions/CellRef" + additionalProperties: false + - type: object + required: + - Immediate + properties: + Immediate: + $ref: "#/definitions/BigInt" + additionalProperties: false + DeprecatedHint: + description: Represents a deprecated hint which is kept for backward compatibility of previously deployed contracts. + oneOf: + - description: Asserts that the current access indices list is empty (after the loop). + type: string + enum: + - AssertCurrentAccessIndicesIsEmpty + - description: Asserts that the number of used accesses is equal to the length of the original accesses list. + type: object + required: + - AssertAllAccessesUsed + properties: + AssertAllAccessesUsed: + type: object + required: + - n_used_accesses + properties: + n_used_accesses: + $ref: "#/definitions/CellRef" + additionalProperties: false + - description: Asserts that the keys list is empty. + type: string + enum: + - AssertAllKeysUsed + - description: "Asserts that the arc (b, PRIME) was excluded." + type: string + enum: + - AssertLeAssertThirdArcExcluded + - description: Asserts that the input represents integers and that a; +pub type DeprecatedDeclaredClasses = IndexMap; + +/// Data structs that are serialized into the database. + +#[derive(Debug, Clone, Eq, PartialEq)] +pub(crate) struct IndexedDeprecatedContractClass { + pub block_number: BlockNumber, + pub location_in_file: LocationInFile, +} diff --git a/crates/papyrus_storage/src/state/mod.rs b/crates/papyrus_storage/src/state/mod.rs new file mode 100644 index 00000000000..ddbbcc1c4d7 --- /dev/null +++ b/crates/papyrus_storage/src/state/mod.rs @@ -0,0 +1,838 @@ +//! Interface for handling data related to Starknet [state](https://docs.rs/starknet_api/latest/starknet_api/state/index.html). +//! +//! Import [`StateStorageReader`] and [`StateStorageWriter`] to read and write data related to state +//! diffs using a [`StorageTxn`]. +//! +//! See [`StateReader`] struct for querying specific data from the state. +//! +//! # Example +//! ``` +//! use papyrus_storage::open_storage; +//! use papyrus_storage::state::{StateStorageReader, StateStorageWriter}; +//! # use indexmap::IndexMap; +//! # use papyrus_storage::{db::DbConfig, StorageConfig}; +//! # use starknet_api::block::BlockNumber; +//! # use starknet_api::core::{ChainId, ContractAddress}; +//! use starknet_api::state::{StateNumber, ThinStateDiff}; +//! +//! # let dir_handle = tempfile::tempdir().unwrap(); +//! # let dir = dir_handle.path().to_path_buf(); +//! # let db_config = DbConfig { +//! # path_prefix: dir, +//! # chain_id: ChainId::Mainnet, +//! # enforce_file_exists: false, +//! # min_size: 1 << 20, // 1MB +//! # max_size: 1 << 35, // 32GB +//! # growth_step: 1 << 26, // 64MB +//! # }; +//! # let storage_config = StorageConfig{db_config, ..Default::default()}; +//! let state_diff = ThinStateDiff::default(); +//! let (reader, mut writer) = open_storage(storage_config)?; +//! writer +//! .begin_rw_txn()? // Start a RW transaction. +//! .append_state_diff(BlockNumber(0), state_diff.clone())? // Append a state diff. +//! .commit()?; +//! +//! // Get the state diff. +//! let read_state_diff = reader.begin_ro_txn()?.get_state_diff(BlockNumber(0))?; +//! assert_eq!(read_state_diff, Some(state_diff)); +//! +//! # let contract_address = ContractAddress::default(); +//! // Get the class hash of a contract at a given state number. +//! // The transaction must live at least as long as the state reader. +//! let txn = reader.begin_ro_txn()?; +//! let state_reader = txn.get_state_reader()?; +//! let class_hash = state_reader.get_class_hash_at( +//! StateNumber::unchecked_right_after_block(BlockNumber(0)), +//! &contract_address, +//! )?; +//! # Ok::<(), papyrus_storage::StorageError>(()) +//! ``` + +#[doc(hidden)] +pub mod data; +#[cfg(test)] +mod state_test; + +use std::collections::HashSet; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::IndexMap; +use papyrus_proc_macros::latency_histogram; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, ContractAddress, Nonce}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::{ContractClass, StateNumber, StorageKey, ThinStateDiff}; +use starknet_types_core::felt::Felt; +use tracing::debug; + +use crate::db::serialization::{NoVersionValueWrapper, VersionZeroWrapper}; +use crate::db::table_types::{CommonPrefix, DbCursorTrait, SimpleTable, Table}; +use crate::db::{DbTransaction, TableHandle, TransactionKind, RW}; +#[cfg(feature = "document_calls")] +use crate::document_calls::{add_query, StorageQuery}; +use crate::mmap_file::LocationInFile; +use crate::state::data::IndexedDeprecatedContractClass; +use crate::{ + FileHandlers, + MarkerKind, + MarkersTable, + OffsetKind, + StorageError, + StorageResult, + StorageTxn, +}; + +// TODO(shahak): Move the table aliases to the crate level. +pub(crate) type FileOffsetTable<'env> = + TableHandle<'env, OffsetKind, NoVersionValueWrapper, SimpleTable>; +pub(crate) type DeclaredClassesTable<'env> = + TableHandle<'env, ClassHash, VersionZeroWrapper, SimpleTable>; +pub(crate) type DeclaredClassesBlockTable<'env> = + TableHandle<'env, ClassHash, NoVersionValueWrapper, SimpleTable>; +pub(crate) type DeprecatedDeclaredClassesTable<'env> = + TableHandle<'env, ClassHash, VersionZeroWrapper, SimpleTable>; +pub(crate) type CompiledClassesTable<'env> = + TableHandle<'env, ClassHash, VersionZeroWrapper, SimpleTable>; +pub(crate) type DeployedContractsTable<'env> = + TableHandle<'env, (ContractAddress, BlockNumber), VersionZeroWrapper, SimpleTable>; +pub(crate) type ContractStorageTable<'env> = TableHandle< + 'env, + ((ContractAddress, StorageKey), BlockNumber), + NoVersionValueWrapper, + CommonPrefix, +>; +pub(crate) type NoncesTable<'env> = + TableHandle<'env, (ContractAddress, BlockNumber), VersionZeroWrapper, CommonPrefix>; + +/// Interface for reading data related to the state. +// Structure of state data: +// * declared_classes_table: (class_hash) -> (block_num, contract_class). Each entry specifies at +// which block was this class declared and with what class definition. For Cairo 1 class +// definitions. +// * deprecated_declared_classes_table: (class_hash) -> (block_num, deprecated_contract_class). Each +// entry specifies at which block was this class declared and with what class definition. For +// Cairo 0 class definitions. +// * deployed_contracts_table: (contract_address, block_num) -> (class_hash). Each entry specifies +// at which block was this contract deployed (or its class got replaced) and with what class hash. +// * storage_table: (contract_address, key, block_num) -> (value). Specifies that at `block_num`, +// the `key` at `contract_address` was changed to `value`. This structure let's us do quick +// lookup, since the database supports "Get the closet element from the left". Thus, to lookup +// the value at a specific block_number, we can search (contract_address, key, block_num), and +// retrieve the closest from left, which should be the latest update to the value before that +// block_num. +// * nonces_table: (contract_address, block_num) -> (nonce). Specifies that at `block_num`, the +// nonce of `contract_address` was changed to `nonce`. + +pub trait StateStorageReader { + /// The state marker is the first block number that doesn't exist yet. + fn get_state_marker(&self) -> StorageResult; + /// Returns the state diff at a given block number. + fn get_state_diff(&self, block_number: BlockNumber) -> StorageResult>; + /// Returns a state reader. + fn get_state_reader(&self) -> StorageResult>; +} + +type RevertedStateDiff = ( + ThinStateDiff, + IndexMap, + IndexMap, + IndexMap, +); + +/// Interface for writing data related to the state. +pub trait StateStorageWriter +where + Self: Sized, +{ + /// Appends a state diff without classes to the storage. + fn append_state_diff( + self, + block_number: BlockNumber, + thin_state_diff: ThinStateDiff, + ) -> StorageResult; + + /// Removes a state diff from the storage and returns the removed data. + fn revert_state_diff( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option)>; +} + +impl<'env, Mode: TransactionKind> StateStorageReader for StorageTxn<'env, Mode> { + // The block number marker is the first block number that doesn't exist yet. + fn get_state_marker(&self) -> StorageResult { + let markers_table = self.open_table(&self.tables.markers)?; + Ok(markers_table.get(&self.txn, &MarkerKind::State)?.unwrap_or_default()) + } + fn get_state_diff(&self, block_number: BlockNumber) -> StorageResult> { + let state_diffs_table = self.open_table(&self.tables.state_diffs)?; + let state_diff_location = state_diffs_table.get(&self.txn, &block_number)?; + match state_diff_location { + None => Ok(None), + Some(state_diff_location) => { + let state_diff = + self.file_handlers.get_thin_state_diff_unchecked(state_diff_location)?; + Ok(Some(state_diff)) + } + } + } + + fn get_state_reader(&self) -> StorageResult> { + StateReader::new(self) + } +} + +/// A single coherent state at a single point in time, +pub struct StateReader<'env, Mode: TransactionKind> { + txn: &'env DbTransaction<'env, Mode>, + declared_classes_table: DeclaredClassesTable<'env>, + declared_classes_block_table: DeclaredClassesBlockTable<'env>, + deprecated_declared_classes_table: DeprecatedDeclaredClassesTable<'env>, + deployed_contracts_table: DeployedContractsTable<'env>, + nonces_table: NoncesTable<'env>, + storage_table: ContractStorageTable<'env>, + markers_table: MarkersTable<'env>, + file_handlers: &'env FileHandlers, +} + +impl<'env, Mode: TransactionKind> StateReader<'env, Mode> { + /// Creates a new state reader from a storage transaction. + /// + /// Opens a handle to each table to be used when reading. + /// + /// # Arguments + /// * txn - A storage transaction object. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error opening the tables. + fn new(txn: &'env StorageTxn<'env, Mode>) -> StorageResult { + let declared_classes_table = txn.txn.open_table(&txn.tables.declared_classes)?; + let declared_classes_block_table = + txn.txn.open_table(&txn.tables.declared_classes_block)?; + let deprecated_declared_classes_table = + txn.txn.open_table(&txn.tables.deprecated_declared_classes)?; + let deployed_contracts_table = txn.txn.open_table(&txn.tables.deployed_contracts)?; + let nonces_table = txn.txn.open_table(&txn.tables.nonces)?; + let storage_table = txn.txn.open_table(&txn.tables.contract_storage)?; + let markers_table = txn.txn.open_table(&txn.tables.markers)?; + Ok(StateReader { + txn: &txn.txn, + declared_classes_table, + declared_classes_block_table, + deprecated_declared_classes_table, + deployed_contracts_table, + nonces_table, + storage_table, + markers_table, + file_handlers: &txn.file_handlers, + }) + } + + /// Returns the class hash at a given state number. + /// If class hash is not found, returns `None`. + /// + /// # Arguments + /// * state_number - state number to search before. + /// * address - contract addrest to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + pub fn get_class_hash_at( + &self, + state_number: StateNumber, + address: &ContractAddress, + ) -> StorageResult> { + // TODO(dvir): create an attribute instead of this. + #[cfg(feature = "document_calls")] + add_query(StorageQuery::GetClassHashAt(state_number, *address)); + + let first_irrelevant_block: BlockNumber = state_number.block_after(); + let db_key = (*address, first_irrelevant_block); + let mut cursor = self.deployed_contracts_table.cursor(self.txn)?; + cursor.lower_bound(&db_key)?; + let res = cursor.prev()?; + + match res { + None => Ok(None), + Some(((got_address, _), _)) if got_address != *address => Ok(None), + Some((_, class_hash)) => Ok(Some(class_hash)), + } + } + + /// Returns the nonce at a given state number. + /// If there is no nonce at the given state number, returns `None`. + /// + /// # Arguments + /// * state_number - state number to search before. + /// * address - contract addrest to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + pub fn get_nonce_at( + &self, + state_number: StateNumber, + address: &ContractAddress, + ) -> StorageResult> { + #[cfg(feature = "document_calls")] + add_query(StorageQuery::GetNonceAt(state_number, *address)); + + // State diff updates are indexed by the block_number at which they occurred. + let first_irrelevant_block: BlockNumber = state_number.block_after(); + // The relevant update is the last update strictly before `first_irrelevant_block`. + let db_key = (*address, first_irrelevant_block); + // Find the previous db item. + let mut cursor = self.nonces_table.cursor(self.txn)?; + cursor.lower_bound(&db_key)?; + let res = cursor.prev()?; + match res { + None => Ok(None), + Some(((got_address, _got_block_number), value)) => { + if got_address != *address { + // The previous item belongs to different address, which means there is no + // previous state diff for this item. + return Ok(None); + }; + // The previous db item indeed belongs to this address and key. + Ok(Some(value)) + } + } + } + + /// Returns the storage value at a given state number for a given contract and key. + /// If no value is stored at the given state number, returns [`Felt`]::default. + /// + /// # Arguments + /// * state_number - state number to search before. + /// * address - contract addrest to search for. + /// * key - key to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + pub fn get_storage_at( + &self, + state_number: StateNumber, + address: &ContractAddress, + key: &StorageKey, + ) -> StorageResult { + #[cfg(feature = "document_calls")] + add_query(StorageQuery::GetStorageAt(state_number, *address, *key)); + + // The updates to the storage key are indexed by the block_number at which they occurred. + let first_irrelevant_block: BlockNumber = state_number.block_after(); + // The relevant update is the last update strictly before `first_irrelevant_block`. + let db_key = ((*address, *key), first_irrelevant_block); + // Find the previous db item. + let mut cursor = self.storage_table.cursor(self.txn)?; + cursor.lower_bound(&db_key)?; + let res = cursor.prev()?; + match res { + None => Ok(Felt::default()), + Some((((got_address, got_key), _got_block_number), value)) => { + if got_address != *address || got_key != *key { + // The previous item belongs to different key, which means there is no + // previous state diff for this item. + return Ok(Felt::default()); + }; + // The previous db item indeed belongs to this address and key. + Ok(value) + } + } + } + + /// Returns the class definition at a given state number. + /// + /// If class_hash is not found, returns `None`. + /// If class_hash is found but given state is before the block it's defined at, returns `None`. + /// + /// # Arguments + /// * state_number - state number to search before. + /// * class_hash - class hash to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + /// + /// Returns [`StorageError`]::DBInconsistency if the block number found for the class hash but + /// the contract class was not found. + pub fn get_class_definition_at( + &self, + state_number: StateNumber, + class_hash: &ClassHash, + ) -> StorageResult> { + let Some(block_number) = self.declared_classes_block_table.get(self.txn, class_hash)? + else { + return Ok(None); + }; + if state_number.is_before(block_number) { + return Ok(None); + } + // TODO(shahak): Fix code duplication with ClassStorageReader. + let Some(contract_class_location) = + self.declared_classes_table.get(self.txn, class_hash)? + else { + if state_number + .is_after(self.markers_table.get(self.txn, &MarkerKind::Class)?.unwrap_or_default()) + { + return Ok(None); + } + return Err(StorageError::DBInconsistency { + msg: "Couldn't find class for a block that is before the class marker.".to_string(), + }); + }; + Ok(Some(self.file_handlers.get_contract_class_unchecked(contract_class_location)?)) + } + + /// Returns the block number for a given class hash (the block in which it was defined). + /// If class is not defined, returns `None`. + /// + /// # Arguments + /// * class_hash - class hash to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + pub fn get_class_definition_block_number( + &self, + class_hash: &ClassHash, + ) -> StorageResult> { + Ok(self.declared_classes_block_table.get(self.txn, class_hash)?) + } + + /// Returns the deprecated contract class at a given state number for a given class hash. + /// If class is not found, returns `None`. + /// If class is defined but in a block after given state number, returns `None`. + /// + /// # Arguments + /// * state_number - state number to search before. + /// * class_hash - class hash to search for. + /// + /// # Errors + /// Returns [`StorageError`] if there was an error searching the table. + pub fn get_deprecated_class_definition_at( + &self, + state_number: StateNumber, + class_hash: &ClassHash, + ) -> StorageResult> { + let Some(value) = self.deprecated_declared_classes_table.get(self.txn, class_hash)? else { + return Ok(None); + }; + if state_number.is_before(value.block_number) { + return Ok(None); + } + // TODO(shahak): Fix code duplication with ClassStorageReader. + Ok(Some( + self.file_handlers.get_deprecated_contract_class_unchecked(value.location_in_file)?, + )) + } +} + +impl<'env> StateStorageWriter for StorageTxn<'env, RW> { + #[latency_histogram("storage_append_thin_state_diff_latency_seconds", false)] + fn append_state_diff( + self, + block_number: BlockNumber, + thin_state_diff: ThinStateDiff, + ) -> StorageResult { + let file_offset_table = self.txn.open_table(&self.tables.file_offsets)?; + let markers_table = self.open_table(&self.tables.markers)?; + let state_diffs_table = self.open_table(&self.tables.state_diffs)?; + let nonces_table = self.open_table(&self.tables.nonces)?; + let deployed_contracts_table = self.open_table(&self.tables.deployed_contracts)?; + let storage_table = self.open_table(&self.tables.contract_storage)?; + let declared_classes_block_table = self.open_table(&self.tables.declared_classes_block)?; + + // Write state. + write_deployed_contracts( + &thin_state_diff.deployed_contracts, + &self.txn, + block_number, + &deployed_contracts_table, + &nonces_table, + &thin_state_diff.nonces, + )?; + write_storage_diffs( + &thin_state_diff.storage_diffs, + &self.txn, + block_number, + &storage_table, + )?; + write_nonces(&thin_state_diff.nonces, &self.txn, block_number, &nonces_table)?; + write_replaced_classes( + &thin_state_diff.replaced_classes, + &self.txn, + block_number, + &deployed_contracts_table, + )?; + + // We don't store the deprecated declared classes' block number. + for (class_hash, _) in &thin_state_diff.declared_classes { + declared_classes_block_table.insert(&self.txn, class_hash, &block_number)?; + } + + // Write state diff. + let location = self.file_handlers.append_state_diff(&thin_state_diff); + state_diffs_table.append(&self.txn, &block_number, &location)?; + file_offset_table.upsert(&self.txn, &OffsetKind::ThinStateDiff, &location.next_offset())?; + + update_marker_to_next_block(&self.txn, &markers_table, MarkerKind::State, block_number)?; + + advance_compiled_class_marker_over_blocks_without_classes( + &self.txn, + &markers_table, + &state_diffs_table, + &self.file_handlers, + )?; + + Ok(self) + } + + fn revert_state_diff( + self, + block_number: BlockNumber, + ) -> StorageResult<(Self, Option)> { + let markers_table = self.open_table(&self.tables.markers)?; + let declared_classes_table = self.open_table(&self.tables.declared_classes)?; + let declared_classes_block_table = self.open_table(&self.tables.declared_classes_block)?; + let deprecated_declared_classes_table = + self.open_table(&self.tables.deprecated_declared_classes)?; + // TODO(yair): Consider reverting the compiled classes in their own module. + let compiled_classes_table = self.open_table(&self.tables.casms)?; + let deployed_contracts_table = self.open_table(&self.tables.deployed_contracts)?; + let nonces_table = self.open_table(&self.tables.nonces)?; + let storage_table = self.open_table(&self.tables.contract_storage)?; + let state_diffs_table = self.open_table(&self.tables.state_diffs)?; + + let current_state_marker = self.get_state_marker()?; + + // Reverts only the last state diff. + let Some(next_block_number) = block_number + .next() + .filter(|next_block_number| *next_block_number == current_state_marker) + else { + debug!( + "Attempt to revert a non-existing / old state diff of block {}. Returning without \ + an action.", + block_number + ); + return Ok((self, None)); + }; + + let thin_state_diff = self + .get_state_diff(block_number)? + .unwrap_or_else(|| panic!("Missing state diff for block {block_number}.")); + markers_table.upsert(&self.txn, &MarkerKind::State, &block_number)?; + let classes_marker = markers_table.get(&self.txn, &MarkerKind::Class)?.unwrap_or_default(); + if classes_marker == next_block_number { + markers_table.upsert(&self.txn, &MarkerKind::Class, &block_number)?; + } + let compiled_classes_marker = + markers_table.get(&self.txn, &MarkerKind::CompiledClass)?.unwrap_or_default(); + if compiled_classes_marker == next_block_number { + markers_table.upsert(&self.txn, &MarkerKind::CompiledClass, &block_number)?; + } + let deleted_classes = delete_declared_classes( + &self.txn, + &thin_state_diff, + &declared_classes_table, + &declared_classes_block_table, + &self.file_handlers, + )?; + let deleted_deprecated_classes = delete_deprecated_declared_classes( + &self.txn, + block_number, + &thin_state_diff, + &deprecated_declared_classes_table, + &self.file_handlers, + )?; + let deleted_compiled_classes = delete_compiled_classes( + &self.txn, + thin_state_diff.declared_classes.keys(), + &compiled_classes_table, + &self.file_handlers, + )?; + delete_deployed_contracts( + &self.txn, + block_number, + &thin_state_diff, + &deployed_contracts_table, + &nonces_table, + )?; + delete_storage_diffs(&self.txn, block_number, &thin_state_diff, &storage_table)?; + delete_nonces(&self.txn, block_number, &thin_state_diff, &nonces_table)?; + state_diffs_table.delete(&self.txn, &block_number)?; + delete_replaced_classes( + &self.txn, + block_number, + &thin_state_diff, + &deployed_contracts_table, + )?; + + Ok(( + self, + Some(( + thin_state_diff, + deleted_classes, + deleted_deprecated_classes, + deleted_compiled_classes, + )), + )) + } +} + +#[latency_histogram("storage_update_marker_to_next_block_latency_seconds", true)] +fn update_marker_to_next_block<'env>( + txn: &DbTransaction<'env, RW>, + markers_table: &'env MarkersTable<'env>, + marker_kind: MarkerKind, + block_number: BlockNumber, +) -> StorageResult<()> { + // Make sure marker is consistent. + let marker = markers_table.get(txn, &marker_kind)?.unwrap_or_default(); + if marker != block_number { + return Err(StorageError::MarkerMismatch { expected: marker, found: block_number }); + }; + + // Advance marker. + markers_table.upsert(txn, &marker_kind, &block_number.unchecked_next())?; + Ok(()) +} + +#[latency_histogram( + "storage_advance_compiled_class_marker_over_blocks_without_classes_latency_seconds", + true +)] +fn advance_compiled_class_marker_over_blocks_without_classes<'env>( + txn: &DbTransaction<'env, RW>, + markers_table: &'env MarkersTable<'env>, + state_diffs_table: &'env TableHandle< + '_, + BlockNumber, + VersionZeroWrapper, + SimpleTable, + >, + file_handlers: &FileHandlers, +) -> StorageResult<()> { + let state_marker = markers_table.get(txn, &MarkerKind::State)?.unwrap_or_default(); + let mut compiled_class_marker = + markers_table.get(txn, &MarkerKind::CompiledClass)?.unwrap_or_default(); + while compiled_class_marker < state_marker { + let state_diff_location = state_diffs_table + .get(txn, &compiled_class_marker)? + .unwrap_or_else(|| panic!("Missing state diff for block {compiled_class_marker}")); + if !file_handlers + .get_thin_state_diff_unchecked(state_diff_location)? + .declared_classes + .is_empty() + { + break; + } + compiled_class_marker = compiled_class_marker.unchecked_next(); + markers_table.upsert(txn, &MarkerKind::CompiledClass, &compiled_class_marker)?; + } + Ok(()) +} + +#[latency_histogram("storage_write_deployed_contracts_latency_seconds", true)] +fn write_deployed_contracts<'env>( + deployed_contracts: &IndexMap, + txn: &DbTransaction<'env, RW>, + block_number: BlockNumber, + deployed_contracts_table: &'env DeployedContractsTable<'env>, + nonces_table: &'env NoncesTable<'env>, + nonces_diffs: &IndexMap, +) -> StorageResult<()> { + for (address, class_hash) in deployed_contracts { + deployed_contracts_table.insert(txn, &(*address, block_number), class_hash)?; + + // In old blocks, there is no nonce diff, so we must add the default value if the diff is + // not specified. + // TODO: check what happens in case of a contract that was deployed and its nonce is still + // zero (does it in the nonce diff?). + if !nonces_diffs.contains_key(address) { + nonces_table.append_greater_sub_key( + txn, + &(*address, block_number), + &Nonce::default(), + )?; + } + } + Ok(()) +} + +#[latency_histogram("storage_write_nonce_latency_seconds", true)] +fn write_nonces<'env>( + nonces: &IndexMap, + txn: &DbTransaction<'env, RW>, + block_number: BlockNumber, + contracts_table: &'env NoncesTable<'env>, +) -> StorageResult<()> { + for (contract_address, nonce) in nonces { + contracts_table.upsert(txn, &(*contract_address, block_number), nonce)?; + } + Ok(()) +} + +#[latency_histogram("storage_write_replaced_classes_latency_seconds", true)] +fn write_replaced_classes<'env>( + replaced_classes: &IndexMap, + txn: &DbTransaction<'env, RW>, + block_number: BlockNumber, + deployed_contracts_table: &'env DeployedContractsTable<'env>, +) -> StorageResult<()> { + for (contract_address, class_hash) in replaced_classes { + deployed_contracts_table.insert(txn, &(*contract_address, block_number), class_hash)?; + } + Ok(()) +} + +#[latency_histogram("storage_write_storage_diffs_latency_seconds", false)] +fn write_storage_diffs<'env>( + storage_diffs: &IndexMap>, + txn: &DbTransaction<'env, RW>, + block_number: BlockNumber, + storage_table: &'env ContractStorageTable<'env>, +) -> StorageResult<()> { + for (address, storage_entries) in storage_diffs { + for (key, value) in storage_entries { + storage_table.append_greater_sub_key(txn, &((*address, *key), block_number), value)?; + } + } + Ok(()) +} + +fn delete_declared_classes<'env>( + txn: &'env DbTransaction<'env, RW>, + thin_state_diff: &ThinStateDiff, + declared_classes_table: &'env DeclaredClassesTable<'env>, + declared_classes_block_table: &'env DeclaredClassesBlockTable<'env>, + file_handlers: &FileHandlers, +) -> StorageResult> { + let mut deleted_data = IndexMap::new(); + for class_hash in thin_state_diff.declared_classes.keys() { + let Some(contract_class_location) = declared_classes_table.get(txn, class_hash)? else { + continue; + }; + deleted_data.insert( + *class_hash, + file_handlers.get_contract_class_unchecked(contract_class_location)?, + ); + declared_classes_table.delete(txn, class_hash)?; + declared_classes_block_table.delete(txn, class_hash)?; + } + + Ok(deleted_data) +} + +fn delete_deprecated_declared_classes<'env>( + txn: &'env DbTransaction<'env, RW>, + block_number: BlockNumber, + thin_state_diff: &ThinStateDiff, + deprecated_declared_classes_table: &'env DeprecatedDeclaredClassesTable<'env>, + file_handlers: &FileHandlers, +) -> StorageResult> { + // Class hashes of the contracts that were deployed in this block. + let deployed_contracts_class_hashes = thin_state_diff.deployed_contracts.values(); + + // Merge the class hashes from the state diff and from the deployed contracts into a single + // unique set. + let class_hashes: HashSet<&ClassHash> = thin_state_diff + .deprecated_declared_classes + .iter() + .chain(deployed_contracts_class_hashes) + .collect(); + + let mut deleted_data = IndexMap::new(); + for class_hash in class_hashes { + // If the class is not in the deprecated classes table, it means that either we didn't + // download it yet or the hash is of a deployed contract of a new class type. We've decided + // to avoid deleting these classes because they're from at most 0.11. + if let Some(IndexedDeprecatedContractClass { + block_number: declared_block_number, + location_in_file, + }) = deprecated_declared_classes_table.get(txn, class_hash)? + { + // If the class was declared in a different block then we should'nt delete it. + if block_number == declared_block_number { + deleted_data.insert( + *class_hash, + file_handlers.get_deprecated_contract_class_unchecked(location_in_file)?, + ); + deprecated_declared_classes_table.delete(txn, class_hash)?; + } + } + } + + Ok(deleted_data) +} + +fn delete_compiled_classes<'a, 'env>( + txn: &'env DbTransaction<'env, RW>, + class_hashes: impl Iterator, + compiled_classes_table: &'env CompiledClassesTable<'env>, + file_handlers: &FileHandlers, +) -> StorageResult> { + let mut deleted_data = IndexMap::new(); + for class_hash in class_hashes { + let Some(compiled_class_location) = compiled_classes_table.get(txn, class_hash)? + // No compiled class means the rest of the compiled classes weren't downloaded yet. + else { + break; + }; + compiled_classes_table.delete(txn, class_hash)?; + deleted_data + .insert(*class_hash, file_handlers.get_casm_unchecked(compiled_class_location)?); + } + + Ok(deleted_data) +} + +fn delete_deployed_contracts<'env>( + txn: &'env DbTransaction<'env, RW>, + block_number: BlockNumber, + thin_state_diff: &ThinStateDiff, + deployed_contracts_table: &'env DeployedContractsTable<'env>, + nonces_table: &'env NoncesTable<'env>, +) -> StorageResult<()> { + for contract_address in thin_state_diff.deployed_contracts.keys() { + deployed_contracts_table.delete(txn, &(*contract_address, block_number))?; + nonces_table.delete(txn, &(*contract_address, block_number))?; + } + Ok(()) +} + +fn delete_storage_diffs<'env>( + txn: &'env DbTransaction<'env, RW>, + block_number: BlockNumber, + thin_state_diff: &ThinStateDiff, + storage_table: &'env ContractStorageTable<'env>, +) -> StorageResult<()> { + for (address, storage_entries) in &thin_state_diff.storage_diffs { + for (key, _) in storage_entries { + storage_table.delete(txn, &((*address, *key), block_number))?; + } + } + Ok(()) +} + +fn delete_nonces<'env>( + txn: &'env DbTransaction<'env, RW>, + block_number: BlockNumber, + thin_state_diff: &ThinStateDiff, + contracts_table: &'env NoncesTable<'env>, +) -> StorageResult<()> { + for contract_address in thin_state_diff.nonces.keys() { + contracts_table.delete(txn, &(*contract_address, block_number))?; + } + Ok(()) +} + +fn delete_replaced_classes<'env>( + txn: &'env DbTransaction<'env, RW>, + block_number: BlockNumber, + thin_state_diff: &ThinStateDiff, + deployed_contracts_table: &'env DeployedContractsTable<'env>, +) -> StorageResult<()> { + for contract_address in thin_state_diff.replaced_classes.keys() { + deployed_contracts_table.delete(txn, &(*contract_address, block_number))?; + } + Ok(()) +} diff --git a/crates/papyrus_storage/src/state/state_test.rs b/crates/papyrus_storage/src/state/state_test.rs new file mode 100644 index 00000000000..90a5208a777 --- /dev/null +++ b/crates/papyrus_storage/src/state/state_test.rs @@ -0,0 +1,773 @@ +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::{indexmap, IndexMap}; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass, StateNumber, StorageKey, ThinStateDiff}; +use starknet_api::{felt, patricia_key}; +use starknet_types_core::felt::Felt; +use test_utils::get_test_state_diff; + +use crate::class::{ClassStorageReader, ClassStorageWriter}; +use crate::compiled_class::{CasmStorageReader, CasmStorageWriter}; +use crate::state::{StateStorageReader, StateStorageWriter}; +use crate::test_utils::get_test_storage; +use crate::StorageWriter; + +#[test] +fn get_class_definition_at() { + // Deprecated classes. + let dc0 = ClassHash(felt!("0x00")); + let dc1 = ClassHash(felt!("0x01")); + let dep_class = DeprecatedContractClass::default(); + // New classes. + let nc0 = ClassHash(felt!("0x10")); + let nc1 = ClassHash(felt!("0x11")); + let new_class = ContractClass::default(); + let compiled_class_hash = CompiledClassHash::default(); + let diff0 = ThinStateDiff { + deprecated_declared_classes: vec![dc0, dc1], + declared_classes: IndexMap::from([(nc0, compiled_class_hash)]), + ..Default::default() + }; + let diff1 = ThinStateDiff { + deprecated_declared_classes: vec![dc0], + declared_classes: IndexMap::from([(nc1, compiled_class_hash)]), + ..Default::default() + }; + + let ((_, mut writer), _temp_dir) = get_test_storage(); + let mut txn = writer.begin_rw_txn().unwrap(); + txn = txn.append_state_diff(BlockNumber(0), diff0).unwrap(); + txn = txn.append_state_diff(BlockNumber(1), diff1).unwrap(); + txn = txn + .append_classes( + BlockNumber(0), + &[(nc0, &new_class)], + &[(dc0, &dep_class), (dc1, &dep_class)], + ) + .unwrap(); + txn = txn.append_classes(BlockNumber(1), &[(nc1, &new_class)], &[(dc0, &dep_class)]).unwrap(); + txn.commit().unwrap(); + + // State numbers. + let state0 = StateNumber::right_before_block(BlockNumber(0)); + let state1 = StateNumber::right_before_block(BlockNumber(1)); + let state2 = StateNumber::right_before_block(BlockNumber(2)); + + // Deprecated Classes Test + + let txn = writer.begin_rw_txn().unwrap(); + let statetxn = txn.get_state_reader().unwrap(); + + // Class0. + assert!(statetxn.get_deprecated_class_definition_at(state0, &dc0).unwrap().is_none()); + assert!(statetxn.get_deprecated_class_definition_at(state1, &dc0).unwrap().is_some()); + assert!(statetxn.get_deprecated_class_definition_at(state2, &dc0).unwrap().is_some()); + + // Class1. + assert!(statetxn.get_deprecated_class_definition_at(state0, &dc1).unwrap().is_none()); + assert!(statetxn.get_deprecated_class_definition_at(state1, &dc1).unwrap().is_some()); + assert!(statetxn.get_deprecated_class_definition_at(state2, &dc1).unwrap().is_some()); + + // New Classes Test + drop(txn); + let txn = writer.begin_rw_txn().unwrap(); + let statetxn = txn.get_state_reader().unwrap(); + + // Class0. + assert!(statetxn.get_class_definition_at(state0, &nc0).unwrap().is_none()); + assert!(statetxn.get_class_definition_at(state1, &nc0).unwrap().is_some()); + assert!(statetxn.get_class_definition_at(state2, &nc0).unwrap().is_some()); + assert_eq!(statetxn.get_class_definition_block_number(&nc0).unwrap(), Some(BlockNumber(0))); + + // Class1. + assert!(statetxn.get_class_definition_at(state0, &nc1).unwrap().is_none()); + assert!(statetxn.get_class_definition_at(state1, &nc1).unwrap().is_none()); + assert!(statetxn.get_class_definition_at(state2, &nc1).unwrap().is_some()); + assert_eq!(statetxn.get_class_definition_block_number(&nc1).unwrap(), Some(BlockNumber(1))); +} + +#[test] +fn append_state_diff_replaced_classes() { + let contract_0 = ContractAddress(patricia_key!("0x00")); + let contract_1 = ContractAddress(patricia_key!("0x01")); + let compiled_class_hash = CompiledClassHash::default(); + let hash_0 = ClassHash(felt!("0x10")); + let hash_1 = ClassHash(felt!("0x11")); + let diff0 = ThinStateDiff { + deployed_contracts: IndexMap::from([(contract_0, hash_0), (contract_1, hash_1)]), + deprecated_declared_classes: vec![hash_0], + declared_classes: IndexMap::from([(hash_1, compiled_class_hash)]), + ..Default::default() + }; + // Replacements between different class types (cairo0 and cairo1). + let diff1 = ThinStateDiff { + replaced_classes: IndexMap::from([(contract_0, hash_1), (contract_1, hash_0)]), + ..Default::default() + }; + // Replace to class that was declared in the same block. + let hash_2 = ClassHash(felt!("0x12")); + let diff2 = ThinStateDiff { + declared_classes: IndexMap::from([(hash_2, compiled_class_hash)]), + replaced_classes: IndexMap::from([(contract_1, hash_2)]), + ..Default::default() + }; + + let ((_, mut writer), _temp_dir) = get_test_storage(); + let mut txn = writer.begin_rw_txn().unwrap(); + txn = txn.append_state_diff(BlockNumber(0), diff0).unwrap(); + txn = txn.append_state_diff(BlockNumber(1), diff1).unwrap(); + txn = txn.append_state_diff(BlockNumber(2), diff2).unwrap(); + txn.commit().unwrap(); + + // State numbers. + let state0 = StateNumber::right_before_block(BlockNumber(0)); + let state1 = StateNumber::right_before_block(BlockNumber(1)); + let state2 = StateNumber::right_before_block(BlockNumber(2)); + let state3 = StateNumber::right_before_block(BlockNumber(3)); + + let txn = writer.begin_rw_txn().unwrap(); + let statetxn = txn.get_state_reader().unwrap(); + + // Contract_0 + assert_eq!(statetxn.get_class_hash_at(state0, &contract_0).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &contract_0).unwrap(), Some(hash_0)); + assert_eq!(statetxn.get_class_hash_at(state2, &contract_0).unwrap(), Some(hash_1)); + assert_eq!(statetxn.get_class_hash_at(state3, &contract_0).unwrap(), Some(hash_1)); + + // Contract_1 + assert_eq!(statetxn.get_class_hash_at(state0, &contract_1).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &contract_1).unwrap(), Some(hash_1)); + assert_eq!(statetxn.get_class_hash_at(state2, &contract_1).unwrap(), Some(hash_0)); + assert_eq!(statetxn.get_class_hash_at(state3, &contract_1).unwrap(), Some(hash_2)); +} + +#[test] +fn append_state_diff() { + let c0 = ContractAddress(patricia_key!("0x11")); + let c1 = ContractAddress(patricia_key!("0x12")); + let c2 = ContractAddress(patricia_key!("0x13")); + let c3 = ContractAddress(patricia_key!("0x14")); + let cl0 = ClassHash(felt!("0x4")); + let cl1 = ClassHash(felt!("0x5")); + let c_cls = CompiledClassHash::default(); + let key0 = StorageKey(patricia_key!("0x1001")); + let key1 = StorageKey(patricia_key!("0x101")); + let diff0 = ThinStateDiff { + deployed_contracts: IndexMap::from([(c0, cl0), (c1, cl1)]), + storage_diffs: IndexMap::from([ + (c0, IndexMap::from([(key0, felt!("0x200")), (key1, felt!("0x201"))])), + (c1, IndexMap::new()), + ]), + deprecated_declared_classes: vec![cl0], + declared_classes: IndexMap::from([(cl1, c_cls)]), + nonces: IndexMap::from([(c0, Nonce(StarkHash::from(1_u8)))]), + replaced_classes: indexmap! {}, + }; + let diff1 = ThinStateDiff { + deployed_contracts: IndexMap::from([(c2, cl0)]), + storage_diffs: IndexMap::from([ + (c0, IndexMap::from([(key0, felt!("0x300")), (key1, felt!("0x0"))])), + (c1, IndexMap::from([(key0, felt!("0x0"))])), + ]), + deprecated_declared_classes: vec![cl0], + declared_classes: indexmap! {}, + nonces: IndexMap::from([ + (c0, Nonce(StarkHash::from(2_u8))), + (c1, Nonce(StarkHash::from(1_u8))), + (c2, Nonce(StarkHash::from(1_u8))), + ]), + replaced_classes: IndexMap::from([(c0, cl1)]), + }; + + let ((_, mut writer), _temp_dir) = get_test_storage(); + let mut txn = writer.begin_rw_txn().unwrap(); + assert_eq!(txn.get_state_diff(BlockNumber(0)).unwrap(), None); + assert_eq!(txn.get_state_diff(BlockNumber(1)).unwrap(), None); + txn = txn.append_state_diff(BlockNumber(0), diff0.clone()).unwrap(); + assert_eq!(txn.get_state_diff(BlockNumber(0)).unwrap().unwrap(), diff0); + assert_eq!(txn.get_state_diff(BlockNumber(1)).unwrap(), None); + txn = txn.append_state_diff(BlockNumber(1), diff1.clone()).unwrap(); + + txn.commit().unwrap(); + + let txn = writer.begin_rw_txn().unwrap(); + assert_eq!(txn.get_state_diff(BlockNumber(0)).unwrap().unwrap(), diff0); + assert_eq!(txn.get_state_diff(BlockNumber(1)).unwrap().unwrap(), diff1); + + let statetxn = txn.get_state_reader().unwrap(); + + // State numbers. + let state0 = StateNumber::right_before_block(BlockNumber(0)); + let state1 = StateNumber::right_before_block(BlockNumber(1)); + let state2 = StateNumber::right_before_block(BlockNumber(2)); + + // Contract0. + assert_eq!(statetxn.get_class_hash_at(state0, &c0).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &c0).unwrap(), Some(cl0)); + assert_eq!(statetxn.get_class_hash_at(state2, &c0).unwrap(), Some(cl1)); + assert_eq!(statetxn.get_nonce_at(state0, &c0).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state1, &c0).unwrap(), Some(Nonce(StarkHash::from(1_u8)))); + assert_eq!(statetxn.get_nonce_at(state2, &c0).unwrap(), Some(Nonce(StarkHash::from(2_u8)))); + + // Contract1. + assert_eq!(statetxn.get_class_hash_at(state0, &c1).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &c1).unwrap(), Some(cl1)); + assert_eq!(statetxn.get_class_hash_at(state2, &c1).unwrap(), Some(cl1)); + assert_eq!(statetxn.get_nonce_at(state0, &c1).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state1, &c1).unwrap(), Some(Nonce::default())); + assert_eq!(statetxn.get_nonce_at(state2, &c1).unwrap(), Some(Nonce(StarkHash::from(1_u8)))); + + // Contract2. + assert_eq!(statetxn.get_class_hash_at(state0, &c2).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &c2).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state2, &c2).unwrap(), Some(cl0)); + assert_eq!(statetxn.get_nonce_at(state0, &c2).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state1, &c2).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state2, &c2).unwrap(), Some(Nonce(StarkHash::from(1_u8)))); + + // Contract3. + assert_eq!(statetxn.get_class_hash_at(state0, &c3).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state1, &c3).unwrap(), None); + assert_eq!(statetxn.get_class_hash_at(state2, &c3).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state0, &c3).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state1, &c3).unwrap(), None); + assert_eq!(statetxn.get_nonce_at(state2, &c3).unwrap(), None); + + // Storage at key0. + assert_eq!(statetxn.get_storage_at(state0, &c0, &key0).unwrap(), felt!("0x0")); + assert_eq!(statetxn.get_storage_at(state1, &c0, &key0).unwrap(), felt!("0x200")); + assert_eq!(statetxn.get_storage_at(state2, &c0, &key0).unwrap(), felt!("0x300")); + + // Storage at key1. + assert_eq!(statetxn.get_storage_at(state0, &c0, &key1).unwrap(), felt!("0x0")); + assert_eq!(statetxn.get_storage_at(state1, &c0, &key1).unwrap(), felt!("0x201")); + assert_eq!(statetxn.get_storage_at(state2, &c0, &key1).unwrap(), felt!("0x0")); + + // Storage at key2. + assert_eq!(statetxn.get_storage_at(state0, &c1, &key0).unwrap(), felt!("0x0")); + assert_eq!(statetxn.get_storage_at(state1, &c1, &key0).unwrap(), felt!("0x0")); + assert_eq!(statetxn.get_storage_at(state2, &c1, &key0).unwrap(), felt!("0x0")); +} + +#[test] +fn test_update_compiled_class_marker() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + let mut txn = writer.begin_rw_txn().unwrap(); + // Append an empty state diff. + txn = txn.append_state_diff(BlockNumber(0), ThinStateDiff::default()).unwrap(); + assert_eq!(txn.get_compiled_class_marker().unwrap(), BlockNumber(1)); +} + +#[test] +fn test_get_class_after_append_thin_state_diff() { + const CLASS_HASH: ClassHash = ClassHash(StarkHash::ZERO); + const DEPRECATED_CLASS_HASH: ClassHash = ClassHash(StarkHash::ONE); + + let ((_, mut writer), _temp_dir) = get_test_storage(); + let mut txn = writer.begin_rw_txn().unwrap(); + // Append an empty state diff. + txn = txn + .append_state_diff( + BlockNumber(0), + ThinStateDiff { + declared_classes: indexmap! { CLASS_HASH => CompiledClassHash::default() }, + deprecated_declared_classes: vec![DEPRECATED_CLASS_HASH], + ..Default::default() + }, + ) + .unwrap(); + assert_eq!(txn.get_class_marker().unwrap(), BlockNumber(0)); + + let state_reader = txn.get_state_reader().unwrap(); + let state_number = StateNumber::unchecked_right_after_block(BlockNumber(0)); + + assert_eq!( + state_reader.get_class_definition_block_number(&CLASS_HASH).unwrap(), + Some(BlockNumber(0)) + ); + assert!(state_reader.get_class_definition_at(state_number, &CLASS_HASH).unwrap().is_none()); + assert!( + state_reader + .get_deprecated_class_definition_at(state_number, &DEPRECATED_CLASS_HASH) + .unwrap() + .is_none() + ); +} + +#[test] +fn revert_non_existing_state_diff() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + + let block_number = BlockNumber(5); + let (_, deleted_data) = writer.begin_rw_txn().unwrap().revert_state_diff(block_number).unwrap(); + assert!(deleted_data.is_none()); +} + +#[tokio::test] +async fn revert_last_state_diff_success() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + let state_diff = get_test_state_diff().into(); + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), state_diff) + .unwrap() + .commit() + .unwrap(); + + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(0)).unwrap(); + txn.commit().unwrap(); +} + +#[tokio::test] +async fn revert_old_state_diff_fails() { + let ((_, mut writer), _temp_dir) = get_test_storage(); + append_2_state_diffs(&mut writer); + let (_, deleted_data) = + writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(0)).unwrap(); + assert!(deleted_data.is_none()); +} + +#[tokio::test] +async fn revert_state_diff_updates_marker() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_state_diffs(&mut writer); + + // Verify that the state marker before revert is 2. + assert_eq!(reader.begin_ro_txn().unwrap().get_state_marker().unwrap(), BlockNumber(2)); + + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(1)).unwrap(); + txn.commit().unwrap(); + assert_eq!(reader.begin_ro_txn().unwrap().get_state_marker().unwrap(), BlockNumber(1)); +} + +#[tokio::test] +async fn get_reverted_state_diff_returns_none() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + append_2_state_diffs(&mut writer); + + // Verify that we can get block 1's state before the revert. + assert!(reader.begin_ro_txn().unwrap().get_state_diff(BlockNumber(1)).unwrap().is_some()); + + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(1)).unwrap(); + txn.commit().unwrap(); + assert!(reader.begin_ro_txn().unwrap().get_state_diff(BlockNumber(1)).unwrap().is_none()); +} + +fn append_2_state_diffs(writer: &mut StorageWriter) { + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), ThinStateDiff::default()) + .unwrap() + .append_state_diff(BlockNumber(1), ThinStateDiff::default()) + .unwrap() + .commit() + .unwrap(); +} + +#[test] +fn revert_doesnt_delete_previously_declared_classes() { + // Append 2 state diffs that use the same declared class. + let c0 = ContractAddress(patricia_key!("0x11")); + let cl0 = ClassHash(felt!("0x4")); + let c_cls0 = DeprecatedContractClass::default(); + let diff0 = ThinStateDiff { + deployed_contracts: IndexMap::from([(c0, cl0)]), + storage_diffs: IndexMap::new(), + deprecated_declared_classes: vec![cl0], + declared_classes: indexmap! {}, + nonces: IndexMap::from([(c0, Nonce(StarkHash::from(1_u8)))]), + replaced_classes: indexmap! {}, + }; + + let c1 = ContractAddress(patricia_key!("0x12")); + let diff1 = ThinStateDiff { + deployed_contracts: IndexMap::from([(c1, cl0)]), + storage_diffs: IndexMap::new(), + deprecated_declared_classes: vec![cl0], + declared_classes: indexmap! {}, + nonces: IndexMap::from([(c1, Nonce(StarkHash::from(2_u8)))]), + replaced_classes: indexmap! {}, + }; + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), diff0) + .unwrap() + .append_classes(BlockNumber(0), &[], &[(cl0, &c_cls0)]) + .unwrap() + .append_state_diff(BlockNumber(1), diff1) + .unwrap() + .append_classes(BlockNumber(1), &[], &[(cl0, &c_cls0)]) + .unwrap() + .commit() + .unwrap(); + + // Assert that reverting diff 1 doesn't delete declared class from diff 0. + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(1)).unwrap(); + txn.commit().unwrap(); + let declared_class = reader + .begin_ro_txn() + .unwrap() + .get_state_reader() + .unwrap() + .get_deprecated_class_definition_at( + StateNumber::unchecked_right_after_block(BlockNumber(0)), + &cl0, + ) + .unwrap(); + assert!(declared_class.is_some()); + + // Assert that reverting diff 0 deletes the declared class. + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(0)).unwrap(); + txn.commit().unwrap(); + let declared_class = reader + .begin_ro_txn() + .unwrap() + .get_state_reader() + .unwrap() + .get_deprecated_class_definition_at( + StateNumber::unchecked_right_after_block(BlockNumber(0)), + &cl0, + ) + .unwrap(); + assert!(declared_class.is_none()); +} + +#[test] +fn revert_state() { + let (state_diff0, classes0, deprecated_classes0) = + ThinStateDiff::from_state_diff(get_test_state_diff()); + let (contract0, class0) = state_diff0.deployed_contracts.first().unwrap(); + let (_contract0, nonce0) = state_diff0.nonces.first().unwrap(); + + // Create another state diff, deploying new contracts and changing the state and the class hash + // of the contract deployed in state0. + let contract1 = ContractAddress(patricia_key!("0x1")); + let contract2 = ContractAddress(patricia_key!("0x2")); + let class1 = ClassHash(felt!("0x11")); + let class2 = ClassHash(felt!("0x22")); + let compiled_class2 = CasmContractClass::default(); + let updated_storage_key = StorageKey(patricia_key!("0x1")); + let new_data = Felt::from(1_u8); + let updated_storage = IndexMap::from([(updated_storage_key, new_data)]); + let nonce1 = Nonce(Felt::from(111_u8)); + let state_diff1 = ThinStateDiff { + deployed_contracts: IndexMap::from([(contract1, class1), (contract2, class2)]), + storage_diffs: IndexMap::from([(*contract0, updated_storage)]), + deprecated_declared_classes: vec![class1], + declared_classes: IndexMap::from([(class2, CompiledClassHash::default())]), + nonces: IndexMap::from([(contract1, nonce1)]), + replaced_classes: IndexMap::from([(*contract0, class1)]), + }; + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), state_diff0.clone()) + .unwrap() + .append_state_diff(BlockNumber(1), state_diff1.clone()) + .unwrap() + .append_classes( + BlockNumber(0), + &classes0.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes0 + .iter() + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + ) + .unwrap() + .append_classes( + BlockNumber(1), + &[(class2, &ContractClass::default())], + &[(class1, &DeprecatedContractClass::default())], + ) + .unwrap() + .append_casm(&class2, &compiled_class2) + .unwrap() + .commit() + .unwrap(); + + let txn = reader.begin_ro_txn().unwrap(); + assert_eq!(txn.get_state_marker().unwrap(), BlockNumber(2)); + assert!(txn.get_state_diff(BlockNumber(1)).unwrap().is_some()); + + let state_reader = txn.get_state_reader().unwrap(); + let state_number = StateNumber::unchecked_right_after_block(BlockNumber(1)); + assert_eq!(state_reader.get_class_hash_at(state_number, contract0).unwrap().unwrap(), class1); + assert_eq!(state_reader.get_class_hash_at(state_number, &contract1).unwrap().unwrap(), class1); + assert_eq!(state_reader.get_class_hash_at(state_number, &contract2).unwrap().unwrap(), class2); + assert_eq!(state_reader.get_nonce_at(state_number, contract0).unwrap().unwrap(), *nonce0); + assert_eq!(state_reader.get_nonce_at(state_number, &contract1).unwrap().unwrap(), nonce1); + assert_eq!( + state_reader.get_storage_at(state_number, contract0, &updated_storage_key).unwrap(), + new_data + ); + + let block_number = BlockNumber(1); + let (txn, deleted_data) = + writer.begin_rw_txn().unwrap().revert_state_diff(block_number).unwrap(); + txn.commit().unwrap(); + + let expected_deleted_deprecated_classes = + IndexMap::from([(class1, DeprecatedContractClass::default())]); + let expected_deleted_classes = IndexMap::from([(class2, ContractClass::default())]); + let expected_deleted_compiled_classes = + IndexMap::from([(class2, CasmContractClass::default())]); + assert_matches!( + deleted_data, + Some((thin_state_diff, class_definitions, deprecated_class_definitions, compiled_classes)) + if thin_state_diff == state_diff1 + && class_definitions == expected_deleted_classes + && deprecated_class_definitions == expected_deleted_deprecated_classes + && compiled_classes == expected_deleted_compiled_classes + ); + + let txn = reader.begin_ro_txn().unwrap(); + assert_eq!(txn.get_state_marker().unwrap(), BlockNumber(1)); + assert!(txn.get_state_diff(BlockNumber(1)).unwrap().is_none()); + + let state_reader = txn.get_state_reader().unwrap(); + let state_number = StateNumber::unchecked_right_after_block(BlockNumber(0)); + assert_eq!(state_reader.get_class_hash_at(state_number, contract0).unwrap().unwrap(), *class0); + assert!(state_reader.get_class_hash_at(state_number, &contract1).unwrap().is_none()); + assert!(state_reader.get_class_hash_at(state_number, &contract2).unwrap().is_none()); + assert_eq!(state_reader.get_nonce_at(state_number, contract0).unwrap().unwrap(), *nonce0); + assert!(state_reader.get_nonce_at(state_number, &contract1).unwrap().is_none()); + assert_eq!( + state_reader.get_storage_at(state_number, contract0, &updated_storage_key).unwrap(), + Felt::from(0_u8) + ); + assert!(txn.get_casm(&class2).unwrap().is_none()); +} + +#[test] +fn get_nonce_key_serialization() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let contract_address = ContractAddress(patricia_key!("0x11")); + + for block_number in 0..(1 << 8) + 1 { + let state_diff = ThinStateDiff { + deployed_contracts: IndexMap::new(), + storage_diffs: IndexMap::new(), + declared_classes: IndexMap::new(), + deprecated_declared_classes: Vec::new(), + nonces: IndexMap::from([( + contract_address, + Nonce(StarkHash::from(block_number as u128 + 1)), + )]), + replaced_classes: IndexMap::new(), + }; + + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(block_number), state_diff) + .unwrap() + .commit() + .unwrap(); + } + + let txn = reader.begin_ro_txn().unwrap(); + let state_reader = txn.get_state_reader().unwrap(); + // No nonce in genesis. + assert_eq!( + state_reader + .get_nonce_at(StateNumber::right_before_block(BlockNumber(0)), &contract_address) + .unwrap(), + None + ); + + for block_number in 1..(1 << 8) + 1 { + println!("{block_number:?}"); + let nonce = state_reader + .get_nonce_at( + StateNumber::right_before_block(BlockNumber(block_number)), + &contract_address, + ) + .unwrap(); + println!("{nonce:?}"); + let nonce = nonce.unwrap(); + + assert_eq!(nonce, Nonce(StarkHash::from(block_number as u128))); + } +} + +#[test] +fn replace_class() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + let contract_address = ContractAddress(patricia_key!("0x0")); + + let class_hash0 = ClassHash(felt!("0x0")); + let state_diff1 = ThinStateDiff { + deployed_contracts: indexmap! { + contract_address => class_hash0 + }, + storage_diffs: IndexMap::new(), + declared_classes: IndexMap::new(), + deprecated_declared_classes: vec![class_hash0], + nonces: IndexMap::new(), + replaced_classes: IndexMap::new(), + }; + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), state_diff1) + .unwrap() + .commit() + .unwrap(); + + let state1 = StateNumber(BlockNumber(1)); + let current_class_hash = reader + .begin_ro_txn() + .unwrap() + .get_state_reader() + .unwrap() + .get_class_hash_at(state1, &contract_address) + .unwrap() + .unwrap(); + + assert_eq!(current_class_hash, class_hash0); + + let class_hash1 = ClassHash(felt!("0x1")); + let state_diff2 = ThinStateDiff { + deployed_contracts: IndexMap::new(), + storage_diffs: IndexMap::new(), + declared_classes: indexmap! { + class_hash1 => CompiledClassHash::default(), + }, + deprecated_declared_classes: Vec::new(), + nonces: IndexMap::new(), + replaced_classes: indexmap! { + contract_address => class_hash1, + }, + }; + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(1), state_diff2) + .unwrap() + .commit() + .unwrap(); + + // Verify that fetching the class hash returns the new class. + let state2 = StateNumber(BlockNumber(2)); + let current_class_hash = reader + .begin_ro_txn() + .unwrap() + .get_state_reader() + .unwrap() + .get_class_hash_at(state2, &contract_address) + .unwrap() + .unwrap(); + + assert_eq!(current_class_hash, class_hash1); + + // Verify that fetching the class hash from an old state returns the old class. + let current_class_hash = reader + .begin_ro_txn() + .unwrap() + .get_state_reader() + .unwrap() + .get_class_hash_at(state1, &contract_address) + .unwrap() + .unwrap(); + + assert_eq!(current_class_hash, class_hash0); +} + +// TODO(shahak): Add test where the state was reverted before the class definitions were written. +#[test] +fn declare_revert_declare_scenario() { + // Declare a class and a deprecated class. + let contract_address: ContractAddress = ContractAddress(patricia_key!("0x11")); + let deprecated_class_hash = ClassHash(felt!("0xc1a55")); + let class_hash = ClassHash(felt!("0xdec1a55")); + let deprecated_class = DeprecatedContractClass::default(); + let class = ContractClass::default(); + let compiled_class_hash = CompiledClassHash::default(); + let diff0 = ThinStateDiff { + deployed_contracts: IndexMap::from([(contract_address, deprecated_class_hash)]), + storage_diffs: IndexMap::new(), + deprecated_declared_classes: vec![deprecated_class_hash], + declared_classes: IndexMap::from([(class_hash, compiled_class_hash)]), + nonces: IndexMap::from([(contract_address, Nonce(StarkHash::from(1_u8)))]), + replaced_classes: indexmap! {}, + }; + + let ((reader, mut writer), _temp_dir) = get_test_storage(); + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), diff0.clone()) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash, &class)], + &[(deprecated_class_hash, &deprecated_class)], + ) + .unwrap() + .commit() + .unwrap(); + + // Assert that both classes are declared. + let state_number = StateNumber::unchecked_right_after_block(BlockNumber(0)); + let txn = reader.begin_ro_txn().unwrap(); + let state_reader = txn.get_state_reader().unwrap(); + assert!(state_reader.get_class_definition_at(state_number, &class_hash).unwrap().is_some()); + assert!( + state_reader + .get_deprecated_class_definition_at(state_number, &deprecated_class_hash) + .unwrap() + .is_some() + ); + + // Revert the block and assert that the classes are no longer declared. + let (txn, _) = writer.begin_rw_txn().unwrap().revert_state_diff(BlockNumber(0)).unwrap(); + txn.commit().unwrap(); + let txn = reader.begin_ro_txn().unwrap(); + let state_reader = txn.get_state_reader().unwrap(); + assert!(state_reader.get_class_definition_at(state_number, &class_hash).unwrap().is_none()); + assert!( + state_reader + .get_deprecated_class_definition_at(state_number, &deprecated_class_hash) + .unwrap() + .is_none() + ); + + // Re-declaring reverted classes should be possible. + writer + .begin_rw_txn() + .unwrap() + .append_state_diff(BlockNumber(0), diff0.clone()) + .unwrap() + .append_classes( + BlockNumber(0), + &[(class_hash, &class)], + &[(deprecated_class_hash, &deprecated_class)], + ) + .unwrap() + .commit() + .unwrap(); + + // Assert that both classes are declared. + let state_number = StateNumber::unchecked_right_after_block(BlockNumber(0)); + let txn = reader.begin_ro_txn().unwrap(); + let state_reader = txn.get_state_reader().unwrap(); + assert!(state_reader.get_class_definition_at(state_number, &class_hash).unwrap().is_some()); + assert!( + state_reader + .get_deprecated_class_definition_at(state_number, &deprecated_class_hash) + .unwrap() + .is_some() + ); +} diff --git a/crates/papyrus_storage/src/test_instances.rs b/crates/papyrus_storage/src/test_instances.rs new file mode 100644 index 00000000000..4f64166a6f4 --- /dev/null +++ b/crates/papyrus_storage/src/test_instances.rs @@ -0,0 +1,80 @@ +use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp, GasPricePerToken}; +use starknet_api::core::{ + EventCommitment, + GlobalRoot, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +use starknet_api::transaction::{ + EventIndexInTransactionOutput, + TransactionHash, + TransactionOffsetInBlock, +}; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, GetTestInstance}; + +use crate::body::TransactionIndex; +use crate::compression_utils::IsCompressed; +use crate::header::StorageBlockHeader; +use crate::mmap_file::LocationInFile; +use crate::state::data::IndexedDeprecatedContractClass; +use crate::version::Version; +use crate::{EventIndex, MarkerKind, OffsetKind, TransactionMetadata}; + +auto_impl_get_test_instance! { + pub struct StorageBlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, + pub n_transactions: usize, + pub n_events: usize, + } + + struct EventIndex(pub TransactionIndex, pub EventIndexInTransactionOutput); + pub struct IndexedDeprecatedContractClass { + pub block_number: BlockNumber, + pub location_in_file: LocationInFile, + } + pub enum IsCompressed { + No = 0, + Yes = 1, + } + enum MarkerKind { + Header = 0, + Body = 1, + Event = 2, + State = 3, + Class = 4, + CompiledClass = 5, + BaseLayerBlock = 6, + } + pub enum OffsetKind { + ThinStateDiff = 0, + ContractClass = 1, + Casm = 2, + DeprecatedContractClass = 3, + } + pub struct TransactionMetadata{ + pub tx_hash: TransactionHash, + pub tx_location: LocationInFile, + pub tx_output_location: LocationInFile, + } + struct TransactionIndex(pub BlockNumber, pub TransactionOffsetInBlock); + pub struct Version{ + pub major: u32, + pub minor: u32, + } +} diff --git a/crates/papyrus_storage/src/test_utils.rs b/crates/papyrus_storage/src/test_utils.rs new file mode 100644 index 00000000000..937b5f1ec13 --- /dev/null +++ b/crates/papyrus_storage/src/test_utils.rs @@ -0,0 +1,75 @@ +#![allow(clippy::unwrap_used)] +//! Test utilities for the storage crate users. + +use starknet_api::core::ChainId; +use tempfile::{tempdir, TempDir}; + +use crate::db::DbConfig; +use crate::mmap_file::MmapFileConfig; +use crate::{open_storage, StorageConfig, StorageReader, StorageScope, StorageWriter}; + +/// Returns a db config and the temporary directory that holds this db. +/// The TempDir object is returned as a handler for the lifetime of this object (the temp +/// directory), thus make sure the directory won't be destroyed. The caller should propagate the +/// TempDir object until it is no longer needed. When the TempDir object is dropped, the directory +/// is deleted. +pub fn get_test_config(storage_scope: Option) -> (StorageConfig, TempDir) { + let storage_scope = storage_scope.unwrap_or_default(); + let dir = tempdir().unwrap(); + println!("{dir:?}"); + ( + StorageConfig { + db_config: DbConfig { + path_prefix: dir.path().to_path_buf(), + chain_id: ChainId::Other("".to_owned()), + enforce_file_exists: false, + min_size: 1 << 20, // 1MB + max_size: 1 << 35, // 32GB + growth_step: 1 << 26, // 64MB + }, + scope: storage_scope, + mmap_file_config: get_mmap_file_test_config(), + }, + dir, + ) +} + +/// Returns [`StorageReader`], [`StorageWriter`] and the temporary directory that holds a db for +/// testing purposes. +pub fn get_test_storage() -> ((StorageReader, StorageWriter), TempDir) { + let (config, temp_dir) = get_test_config(None); + ((open_storage(config).unwrap()), temp_dir) +} + +/// Returns a [`MmapFileConfig`] for testing purposes. +pub fn get_mmap_file_test_config() -> MmapFileConfig { + MmapFileConfig { + max_size: 1 << 24, // 16MB + growth_step: 1 << 20, // 1MB + max_object_size: 1 << 16, // 64KB + } +} + +/// Returns [`StorageReader`], [`StorageWriter`] that configured by the given [`StorageScope`] and +/// the temporary directory that holds a db for testing purposes. +pub fn get_test_storage_by_scope( + storage_scope: StorageScope, +) -> ((StorageReader, StorageWriter), TempDir) { + let ((reader, writer), _config, temp_dir) = + get_test_storage_with_config_by_scope(storage_scope); + ((reader, writer), temp_dir) +} + +/// Returns [`StorageReader`], [`StorageWriter`] that configured by the given [`StorageScope`] and +/// the temporary directory that holds a db for testing purposes. The Returned [`StorageConfig`] can +/// be use to open the exact same storage again (same DB file). +pub fn get_test_storage_with_config_by_scope( + scope: StorageScope, +) -> ((StorageReader, StorageWriter), StorageConfig, TempDir) { + let (mut config, temp_dir) = get_test_config(Some(scope)); + let (reader, writer) = open_storage(config.clone()).unwrap(); + config.db_config.path_prefix = temp_dir.path().to_path_buf(); + config.scope = scope; + + ((reader, writer), config, temp_dir) +} diff --git a/crates/papyrus_storage/src/utils.rs b/crates/papyrus_storage/src/utils.rs new file mode 100644 index 00000000000..bcb33c99e97 --- /dev/null +++ b/crates/papyrus_storage/src/utils.rs @@ -0,0 +1,102 @@ +//! module for external utils, such as dumping a storage table to a file +#[cfg(test)] +#[path = "utils_test.rs"] +mod utils_test; + +use std::collections::HashMap; +use std::fs::File; +use std::io::{BufWriter, Write}; + +use metrics::{absolute_counter, gauge}; +use serde::Serialize; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ChainId, ClassHash, CompiledClassHash}; +use starknet_api::state::{EntryPoint, EntryPointType}; +use starknet_types_core::felt::Felt; +use tracing::debug; + +use crate::compiled_class::CasmStorageReader; +use crate::db::table_types::Table; +use crate::db::RO; +use crate::state::StateStorageReader; +use crate::{open_storage, StorageConfig, StorageError, StorageReader, StorageResult, StorageTxn}; + +#[derive(Serialize)] +struct DumpDeclaredClass { + class_hash: ClassHash, + compiled_class_hash: CompiledClassHash, + sierra_program: Vec, + entry_points_by_type: HashMap>, +} + +/// Dumps the declared_classes at a given block range from the storage to a file. +pub fn dump_declared_classes_table_by_block_range( + start_block: u64, + end_block: u64, + file_path: &str, + chain_id: &ChainId, +) -> StorageResult<()> { + let mut storage_config = StorageConfig::default(); + storage_config.db_config.chain_id = chain_id.clone(); + let (storage_reader, _) = open_storage(storage_config)?; + let txn = storage_reader.begin_ro_txn()?; + let compiled_class_marker = txn.get_compiled_class_marker()?; + if end_block > compiled_class_marker.0 { + return Err(StorageError::InvalidBlockNumber { + block: BlockNumber(end_block), + compiled_class_marker, + }); + } + dump_declared_classes_table_by_block_range_internal(&txn, file_path, start_block, end_block) +} + +fn dump_declared_classes_table_by_block_range_internal( + txn: &StorageTxn<'_, RO>, + file_path: &str, + start_block: u64, + end_block: u64, +) -> StorageResult<()> { + let table_handle = txn.txn.open_table(&txn.tables.declared_classes)?; + let file = File::create(file_path)?; + let mut writer = BufWriter::new(file); + writer.write_all(b"[")?; + let mut first = true; + for block_number in start_block..end_block { + if let Some(thin_state_diff) = txn.get_state_diff(BlockNumber(block_number))? { + for (class_hash, compiled_class_hash) in thin_state_diff.declared_classes.iter() { + if let Some(contract_class_location) = table_handle.get(&txn.txn, class_hash)? { + let contract_class = + txn.file_handlers.get_contract_class_unchecked(contract_class_location)?; + if !first { + writer.write_all(b",")?; + } + serde_json::to_writer( + &mut writer, + &DumpDeclaredClass { + class_hash: *class_hash, + compiled_class_hash: *compiled_class_hash, + sierra_program: contract_class.sierra_program.clone(), + entry_points_by_type: contract_class.entry_points_by_type.clone(), + }, + )?; + first = false; + } + } + }; + } + writer.write_all(b"]")?; + Ok(()) +} + +// TODO(dvir): consider adding storage size metrics. +// TODO(dvir): relocate all the storage metrics in one module and export them (also in other +// crates). +/// Updates storage metrics about the state of the storage. +pub fn update_storage_metrics(reader: &StorageReader) -> StorageResult<()> { + debug!("updating storage metrics"); + gauge!("storage_free_pages_number", reader.db_reader.get_free_pages()? as f64); + let info = reader.db_reader.get_db_info()?; + absolute_counter!("storage_last_page_number", info.last_pgno() as u64); + absolute_counter!("storage_last_transaction_index", info.last_txnid() as u64); + Ok(()) +} diff --git a/crates/papyrus_storage/src/utils_test.rs b/crates/papyrus_storage/src/utils_test.rs new file mode 100644 index 00000000000..ce281e697e4 --- /dev/null +++ b/crates/papyrus_storage/src/utils_test.rs @@ -0,0 +1,117 @@ +use std::collections::HashMap; +use std::fs; + +use indexmap::indexmap; +use metrics_exporter_prometheus::PrometheusBuilder; +use pretty_assertions::assert_eq; +use prometheus_parse::Value::{Counter, Gauge}; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, CompiledClassHash}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass, ThinStateDiff}; +use starknet_types_core::felt::Felt; +use test_utils::prometheus_is_contained; + +use super::update_storage_metrics; +use crate::class::ClassStorageWriter; +use crate::state::StateStorageWriter; +use crate::test_utils::get_test_storage; +use crate::utils::{dump_declared_classes_table_by_block_range_internal, DumpDeclaredClass}; + +// TODO(yael): fix dump_table_to_file. +#[test] +fn test_dump_declared_classes() { + let file_path = "tmp_test_dump_declared_classes_table.json"; + let compiled_class_hash = CompiledClassHash(StarkHash::default()); + let mut declared_classes = vec![]; + let mut state_diffs = vec![]; + let ((reader, mut writer), _temp_dir) = get_test_storage(); + for i in 0..5 { + let i_felt = Felt::from(i as u128); + declared_classes.push(( + ClassHash(i_felt), + ContractClass { + sierra_program: vec![i_felt, i_felt], + entry_points_by_type: HashMap::new(), + abi: "".to_string(), + }, + )); + state_diffs.push(ThinStateDiff { + deployed_contracts: indexmap!(), + storage_diffs: indexmap!(), + declared_classes: indexmap!( + declared_classes[i].0 => compiled_class_hash + ), + deprecated_declared_classes: vec![], + nonces: indexmap!(), + replaced_classes: indexmap!(), + }); + let block_number = BlockNumber(i as u64); + let txn = writer.begin_rw_txn().unwrap(); + txn.append_state_diff(block_number, state_diffs[i].clone()) + .unwrap() + .append_classes(block_number, &[(declared_classes[i].0, &declared_classes[i].1)], &[]) + .unwrap() + .commit() + .unwrap(); + } + let txn = reader.begin_ro_txn().unwrap(); + + // Test dump_declared_classes_table_by_block_range + dump_declared_classes_table_by_block_range_internal(&txn, file_path, 2, 4).unwrap(); + let file_content = fs::read_to_string(file_path).unwrap(); + let _ = fs::remove_file(file_path); + let expected_declared_classes = vec![ + DumpDeclaredClass { + class_hash: declared_classes[2].0, + compiled_class_hash, + sierra_program: declared_classes[2].1.sierra_program.clone(), + entry_points_by_type: declared_classes[2].1.entry_points_by_type.clone(), + }, + DumpDeclaredClass { + class_hash: declared_classes[3].0, + compiled_class_hash, + sierra_program: declared_classes[3].1.sierra_program.clone(), + entry_points_by_type: declared_classes[3].1.entry_points_by_type.clone(), + }, + ]; + assert_eq!(file_content, serde_json::to_string(&expected_declared_classes).unwrap()); +} + +#[test] +fn update_storage_metrics_test() { + let ((reader, _writer), _temp_dir) = get_test_storage(); + let handle = PrometheusBuilder::new().install_recorder().unwrap(); + + assert!(prometheus_is_contained(handle.render(), "storage_free_pages_number", &[]).is_none()); + assert!(prometheus_is_contained(handle.render(), "storage_last_page_number", &[]).is_none()); + assert!( + prometheus_is_contained(handle.render(), "storage_last_transaction_index", &[]).is_none() + ); + + update_storage_metrics(&reader).unwrap(); + + let Gauge(free_pages) = + prometheus_is_contained(handle.render(), "storage_free_pages_number", &[]).unwrap() + else { + panic!("storage_free_pages_number is not a Gauge") + }; + // TODO(dvir): add an upper limit when the bug in the binding freelist function will be fixed. + assert!(0f64 < free_pages); + + let Counter(last_page) = + prometheus_is_contained(handle.render(), "storage_last_page_number", &[]).unwrap() + else { + panic!("storage_last_page_number is not a Counter") + }; + assert!(0f64 < last_page); + assert!(last_page < 1000f64); + + let Counter(last_transaction) = + prometheus_is_contained(handle.render(), "storage_last_transaction_index", &[]).unwrap() + else { + panic!("storage_last_transaction_index is not a Counter") + }; + assert!(0f64 < last_transaction); + assert!(last_transaction < 100f64); +} diff --git a/crates/papyrus_storage/src/version.rs b/crates/papyrus_storage/src/version.rs new file mode 100644 index 00000000000..4d1e700ffea --- /dev/null +++ b/crates/papyrus_storage/src/version.rs @@ -0,0 +1,135 @@ +#[cfg(test)] +#[path = "version_test.rs"] +mod version_test; + +use std::fmt::Display; + +use crate::db::table_types::Table; +use crate::db::{TransactionKind, RW}; +use crate::{StorageError, StorageResult, StorageTxn}; + +const VERSION_STATE_KEY: &str = "storage_version_state"; +const VERSION_BLOCKS_KEY: &str = "storage_version_blocks"; + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Version { + pub major: u32, + pub minor: u32, +} + +#[derive(thiserror::Error, Debug)] +pub enum StorageVersionError { + #[error( + "Storage crate version {crate_version} is inconsistent with DB version {storage_version}. \ + If the major version is different, re-sync is needed." + )] + InconsistentStorageVersion { crate_version: Version, storage_version: Version }, + #[error( + "The existing storage is operating in state-only mode and cannot support the requested \ + full-archive mode." + )] + InconsistentStorageScope, + + #[error( + "Trying to set a DB minor version {crate_version:} which is not higher that the existing \ + one {storage_version}." + )] + SetLowerVersion { crate_version: Version, storage_version: Version }, + + #[error( + "Trying to set a DB major version {crate_version:} which is with different major than the \ + existing one {storage_version}." + )] + SetMajorVersion { crate_version: Version, storage_version: Version }, +} + +pub trait VersionStorageReader { + fn get_state_version(&self) -> StorageResult>; + fn get_blocks_version(&self) -> StorageResult>; +} + +pub trait VersionStorageWriter +where + Self: Sized, +{ + // To enforce that no commit happen after a failure, we consume and return Self on success. + fn set_state_version(self, version: &Version) -> StorageResult; + fn set_blocks_version(self, version: &Version) -> StorageResult; + fn delete_blocks_version(self) -> StorageResult; +} + +impl<'env, Mode: TransactionKind> VersionStorageReader for StorageTxn<'env, Mode> { + fn get_state_version(&self) -> StorageResult> { + let version_table = self.open_table(&self.tables.storage_version)?; + Ok(version_table.get(&self.txn, &VERSION_STATE_KEY.to_string())?) + } + + fn get_blocks_version(&self) -> StorageResult> { + let version_table = self.open_table(&self.tables.storage_version)?; + Ok(version_table.get(&self.txn, &VERSION_BLOCKS_KEY.to_string())?) + } +} + +impl<'env> VersionStorageWriter for StorageTxn<'env, RW> { + fn set_state_version(self, version: &Version) -> StorageResult { + let version_table = self.open_table(&self.tables.storage_version)?; + if let Some(current_storage_version) = self.get_state_version()? { + if current_storage_version.major != version.major { + return Err(StorageError::StorageVersionInconsistency( + StorageVersionError::SetMajorVersion { + crate_version: version.clone(), + storage_version: current_storage_version, + }, + )); + } + if current_storage_version.minor >= version.minor { + return Err(StorageError::StorageVersionInconsistency( + StorageVersionError::SetLowerVersion { + crate_version: version.clone(), + storage_version: current_storage_version, + }, + )); + }; + } + version_table.upsert(&self.txn, &VERSION_STATE_KEY.to_string(), version)?; + Ok(self) + } + + fn set_blocks_version(self, version: &Version) -> StorageResult { + let version_table = self.open_table(&self.tables.storage_version)?; + if let Some(current_storage_version) = self.get_blocks_version()? { + if current_storage_version.major != version.major { + return Err(StorageError::StorageVersionInconsistency( + StorageVersionError::SetMajorVersion { + crate_version: version.clone(), + storage_version: current_storage_version, + }, + )); + } + + if current_storage_version.minor >= version.minor { + return Err(StorageError::StorageVersionInconsistency( + StorageVersionError::SetLowerVersion { + crate_version: version.clone(), + storage_version: current_storage_version, + }, + )); + }; + } + version_table.upsert(&self.txn, &VERSION_BLOCKS_KEY.to_string(), version)?; + Ok(self) + } + fn delete_blocks_version(self) -> StorageResult { + let version_table = self.open_table(&self.tables.storage_version)?; + version_table.delete(&self.txn, &VERSION_BLOCKS_KEY.to_string())?; + Ok(self) + } +} + +impl Display for Version { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let major = self.major.to_string(); + let minor = self.minor.to_string(); + write!(f, "{major}.{minor}") + } +} diff --git a/crates/papyrus_storage/src/version_test.rs b/crates/papyrus_storage/src/version_test.rs new file mode 100644 index 00000000000..8a0b64d1ae5 --- /dev/null +++ b/crates/papyrus_storage/src/version_test.rs @@ -0,0 +1,289 @@ +use assert_matches::assert_matches; +use pretty_assertions::assert_eq; +use rand::Rng; + +use crate::db::table_types::Table; +use crate::test_utils::{ + get_test_storage, + get_test_storage_by_scope, + get_test_storage_with_config_by_scope, +}; +use crate::version::{ + StorageVersionError, + Version, + VersionStorageReader, + VersionStorageWriter, + VERSION_BLOCKS_KEY, + VERSION_STATE_KEY, +}; +use crate::{ + open_storage, + set_version_if_needed, + verify_storage_version, + StorageError, + StorageScope, + StorageWriter, + STORAGE_VERSION_BLOCKS, + STORAGE_VERSION_STATE, +}; + +// TODO: Add this test for set_blocks_version or combine the logic. +#[test] +fn set_state_version_test() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + + // No version initially - use crate version. + let version_state = reader.begin_ro_txn().unwrap().get_state_version().unwrap(); + let version_blocks = reader.begin_ro_txn().unwrap().get_blocks_version().unwrap(); + assert!(version_state.is_some()); + assert!(version_blocks.is_some()); + assert_eq!(version_state.unwrap(), STORAGE_VERSION_STATE); + assert_eq!(version_blocks.unwrap(), STORAGE_VERSION_BLOCKS); + + // Write and read version. + let higher_minor_version = + Version { major: STORAGE_VERSION_STATE.major, minor: STORAGE_VERSION_STATE.minor + 1 }; + writer + .begin_rw_txn() + .unwrap() + .set_state_version(&higher_minor_version) + .unwrap() + .commit() + .unwrap(); + let version_state = reader.begin_ro_txn().unwrap().get_state_version().unwrap(); + assert_eq!(version_state.unwrap(), higher_minor_version); + + // Fail to set a version which its minor not higher than the existing one. + let crate_storage_version = + Version { major: STORAGE_VERSION_STATE.major, minor: STORAGE_VERSION_STATE.minor }; + let Err(err) = writer.begin_rw_txn().unwrap().set_state_version(&crate_storage_version) else { + panic!("Unexpected Ok."); + }; + + assert_matches!( + err, + StorageError::StorageVersionInconsistency(StorageVersionError::SetLowerVersion { + crate_version, + storage_version + }) + if crate_version == crate_storage_version && storage_version == higher_minor_version + ); + + // Fail to set a version which its major is different. + let different_major_version = + Version { major: higher_minor_version.major + 1, minor: higher_minor_version.minor }; + let Err(err) = writer.begin_rw_txn().unwrap().set_state_version(&different_major_version) + else { + panic!("Unexpected Ok."); + }; + + assert_matches!( + err, + StorageError::StorageVersionInconsistency(StorageVersionError::SetMajorVersion { + crate_version, + storage_version + }) + if crate_version == different_major_version && storage_version == higher_minor_version + ); +} + +#[test] +fn version_migration() { + let ((reader, mut writer), config, _temp_dir) = + get_test_storage_with_config_by_scope(StorageScope::FullArchive); + + // Set the storage version on a lower minor version. + change_storage_version( + &mut writer, + VERSION_STATE_KEY, + &Version { major: STORAGE_VERSION_STATE.major, minor: 0 }, + ); + change_storage_version( + &mut writer, + VERSION_BLOCKS_KEY, + &Version { major: STORAGE_VERSION_BLOCKS.major, minor: 0 }, + ); + drop(reader); + drop(writer); + + // Reopen the storage and verify the version. + let (reader, _) = open_storage(config).unwrap(); + + let version_state = reader.begin_ro_txn().unwrap().get_state_version().unwrap(); + assert_eq!(version_state.unwrap(), STORAGE_VERSION_STATE); + let version_blocks = reader.begin_ro_txn().unwrap().get_blocks_version().unwrap(); + assert_eq!(version_blocks.unwrap(), STORAGE_VERSION_BLOCKS); +} + +#[test] +fn open_storage_full_archive_different_state_major_versions() { + let ((reader, mut writer), config, _temp_dir) = + get_test_storage_with_config_by_scope(StorageScope::FullArchive); + + let different_state_major_version = get_different_major_version(STORAGE_VERSION_STATE); + change_storage_version(&mut writer, VERSION_STATE_KEY, &different_state_major_version); + drop(reader); + drop(writer); + + // Reopen the storage and verify the version. + let Err(err) = open_storage(config) else { + panic!("Unexpected Ok."); + }; + assert_matches!( + err, + StorageError::StorageVersionInconsistency(StorageVersionError::InconsistentStorageVersion { + crate_version, + storage_version + }) + if crate_version == STORAGE_VERSION_STATE && storage_version == different_state_major_version + ); +} + +#[test] +fn open_storage_full_archive_different_blocks_major_versions() { + let ((reader, mut writer), config, _temp_dir) = + get_test_storage_with_config_by_scope(StorageScope::FullArchive); + + let different_blocks_major_version = get_different_major_version(STORAGE_VERSION_BLOCKS); + change_storage_version(&mut writer, VERSION_BLOCKS_KEY, &different_blocks_major_version); + drop(reader); + drop(writer); + + // Reopen the storage and verify the version. + let Err(err) = open_storage(config) else { + panic!("Unexpected Ok."); + }; + assert_matches!( + err, + StorageError::StorageVersionInconsistency(StorageVersionError::InconsistentStorageVersion { + crate_version, + storage_version + }) + if crate_version == STORAGE_VERSION_BLOCKS && storage_version == different_blocks_major_version + ); +} + +#[test] +fn open_storage_state_only_different_state_major_versions() { + let ((reader, mut writer), config, _temp_dir) = + get_test_storage_with_config_by_scope(StorageScope::StateOnly); + + let different_state_major_version = get_different_major_version(STORAGE_VERSION_STATE); + change_storage_version(&mut writer, VERSION_STATE_KEY, &different_state_major_version); + drop(reader); + drop(writer); + + // Reopen the storage and verify the version. + let Err(err) = open_storage(config) else { + panic!("Unexpected Ok."); + }; + assert_matches!( + err, + StorageError::StorageVersionInconsistency(StorageVersionError::InconsistentStorageVersion { + crate_version, + storage_version + }) + if crate_version == STORAGE_VERSION_STATE && storage_version == different_state_major_version + ); +} + +#[test] +fn open_storage_state_only_different_blocks_major_versions() { + let ((reader, mut writer), config, _temp_dir) = + get_test_storage_with_config_by_scope(StorageScope::StateOnly); + + let different_blocks_major_version = get_different_major_version(STORAGE_VERSION_BLOCKS); + change_storage_version(&mut writer, VERSION_BLOCKS_KEY, &different_blocks_major_version); + drop(reader); + drop(writer); + + // Reopen the storage and verify the version. + assert!(open_storage(config.clone()).is_ok()); +} + +// Changes the storage version with version_key to the given version. +fn change_storage_version(writer: &mut StorageWriter, version_key: &str, version: &Version) { + let wtxn = writer.begin_rw_txn().unwrap(); + let version_table = wtxn.open_table(&wtxn.tables.storage_version).unwrap(); + version_table.upsert(&wtxn.txn, &version_key.to_string(), version).unwrap(); + wtxn.commit().unwrap(); +} + +// Returns a random version with a different major version than the given one. +fn get_different_major_version(version: Version) -> Version { + let mut rng = rand::thread_rng(); + // The multiplication by two is to make the randomized version to be + // with a high enough probability to be less and more than the current version. + let minor = rng.gen_range(0..=2 * version.minor); + let mut major = rng.gen_range(0..=2 * version.major); + if major == version.major { + major += 1; + } + Version { major, minor } +} + +#[test] +fn test_verify_storage_version_good_flow() { + let ((reader_full_archive, _), _temp_dir) = + get_test_storage_by_scope(StorageScope::FullArchive); + let ((reader_state_only, _), _temp_dir) = get_test_storage_by_scope(StorageScope::StateOnly); + verify_storage_version(reader_full_archive).unwrap(); + verify_storage_version(reader_state_only).unwrap(); +} + +#[test] +fn test_verify_storage_version_different_minor_blocks_version() { + let ((reader, mut writer), _temp_dir) = get_test_storage_by_scope(StorageScope::FullArchive); + let blocks_higher_version = + Version { major: STORAGE_VERSION_BLOCKS.major, minor: STORAGE_VERSION_BLOCKS.minor + 1 }; + writer + .begin_rw_txn() + .unwrap() + .set_blocks_version(&blocks_higher_version) + .unwrap() + .commit() + .unwrap(); + assert_matches!( + verify_storage_version(reader), + Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageVersion { + crate_version: STORAGE_VERSION_BLOCKS, + storage_version: _, + }, + )) + ); +} + +#[test] +fn test_verify_storage_version_different_minor_state_version() { + let ((reader, mut writer), _temp_dir) = get_test_storage_by_scope(StorageScope::FullArchive); + let state_higher_version = + Version { major: STORAGE_VERSION_STATE.major, minor: STORAGE_VERSION_STATE.minor + 1 }; + writer + .begin_rw_txn() + .unwrap() + .set_state_version(&state_higher_version) + .unwrap() + .commit() + .unwrap(); + assert_matches!( + verify_storage_version(reader), + Err(StorageError::StorageVersionInconsistency( + StorageVersionError::InconsistentStorageVersion { + crate_version: STORAGE_VERSION_STATE, + storage_version: _, + }, + )) + ); +} + +#[test] +fn test_set_version_if_needed() { + let ((mut reader, mut writer), _temp_dir) = get_test_storage_by_scope(StorageScope::StateOnly); + reader.scope = StorageScope::FullArchive; + writer.scope = StorageScope::FullArchive; + assert!( + set_version_if_needed(reader, writer).is_err(), + "Should fail, because storage scope cannot shift from state-only to full-archive." + ); +} diff --git a/crates/papyrus_sync/Cargo.toml b/crates/papyrus_sync/Cargo.toml new file mode 100644 index 00000000000..3f7a66b3249 --- /dev/null +++ b/crates/papyrus_sync/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "papyrus_sync" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[dependencies] +async-stream.workspace = true +async-trait.workspace = true +cairo-lang-starknet-classes.workspace = true +chrono.workspace = true +futures-util.workspace = true +futures.workspace = true +indexmap = { workspace = true, features = ["serde"] } +itertools.workspace = true +lru.workspace = true +metrics.workspace = true +papyrus_storage = { path = "../papyrus_storage", version = "0.4.0-rc.0" } +papyrus_base_layer = { path = "../papyrus_base_layer", version = "0.4.0-rc.0" } +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +papyrus_proc_macros = { path = "../papyrus_proc_macros", version = "0.4.0-rc.0" } +reqwest = { workspace = true, features = ["json", "blocking"] } +serde = { workspace = true, features = ["derive"] } +starknet_api.workspace = true +starknet_client = { path = "../starknet_client" } +starknet-types-core.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tracing.workspace = true + +[dev-dependencies] +simple_logger.workspace = true +assert_matches.workspace = true +mockall.workspace = true +papyrus_storage = { path = "../papyrus_storage", features = ["testing"] } +pretty_assertions.workspace = true +starknet_client = { path = "../starknet_client", features = ["testing"] } +starknet_api = { workspace = true, features = ["testing"] } +test_utils = { path = "../test_utils" } +tokio-stream.workspace = true diff --git a/crates/papyrus_sync/src/lib.rs b/crates/papyrus_sync/src/lib.rs new file mode 100644 index 00000000000..d94ae024bd3 --- /dev/null +++ b/crates/papyrus_sync/src/lib.rs @@ -0,0 +1,906 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +#[cfg(test)] +mod sync_test; + +mod pending_sync; +pub mod sources; + +use std::cmp::min; +use std::collections::BTreeMap; +use std::sync::Arc; +use std::time::Duration; + +use async_stream::try_stream; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use chrono::{TimeZone, Utc}; +use futures_util::{pin_mut, select, Stream, StreamExt}; +use indexmap::IndexMap; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_common::{metrics as papyrus_metrics, BlockHashAndNumber}; +use papyrus_config::converters::deserialize_seconds_to_duration; +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_proc_macros::latency_histogram; +use papyrus_storage::base_layer::{BaseLayerStorageReader, BaseLayerStorageWriter}; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::{CasmStorageReader, CasmStorageWriter}; +use papyrus_storage::db::DbError; +use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; +use papyrus_storage::state::{StateStorageReader, StateStorageWriter}; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use serde::{Deserialize, Serialize}; +use sources::base_layer::BaseLayerSourceError; +use starknet_api::block::{Block, BlockHash, BlockNumber, BlockSignature}; +use starknet_api::core::{ClassHash, CompiledClassHash, SequencerPublicKey}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::{StateDiff, ThinStateDiff}; +use starknet_client::reader::PendingData; +use tokio::sync::RwLock; +use tracing::{debug, error, info, instrument, trace, warn}; + +use crate::pending_sync::sync_pending_data; +use crate::sources::base_layer::{BaseLayerSourceTrait, EthereumBaseLayerSource}; +use crate::sources::central::{CentralError, CentralSource, CentralSourceTrait}; +use crate::sources::pending::{PendingError, PendingSource, PendingSourceTrait}; + +// TODO(shahak): Consider adding genesis hash to the config to support chains that have +// different genesis hash. +// TODO: Consider moving to a more general place. +const GENESIS_HASH: &str = "0x0"; + +// TODO(dvir): add to config. +// Sleep duration between polling for pending data. +const PENDING_SLEEP_DURATION: Duration = Duration::from_millis(500); + +// Sleep duration, in seconds, between sync progress checks. +const SLEEP_TIME_SYNC_PROGRESS: Duration = Duration::from_secs(300); + +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +pub struct SyncConfig { + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub block_propagation_sleep_duration: Duration, + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub base_layer_propagation_sleep_duration: Duration, + #[serde(deserialize_with = "deserialize_seconds_to_duration")] + pub recoverable_error_sleep_duration: Duration, + pub blocks_max_stream_size: u32, + pub state_updates_max_stream_size: u32, + pub verify_blocks: bool, +} + +impl SerializeConfig for SyncConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "block_propagation_sleep_duration", + &self.block_propagation_sleep_duration.as_secs(), + "Time in seconds before checking for a new block after the node is synchronized.", + ParamPrivacyInput::Public, + ), + ser_param( + "base_layer_propagation_sleep_duration", + &self.base_layer_propagation_sleep_duration.as_secs(), + "Time in seconds to poll the base layer to get the latest proved block.", + ParamPrivacyInput::Public, + ), + ser_param( + "recoverable_error_sleep_duration", + &self.recoverable_error_sleep_duration.as_secs(), + "Waiting time in seconds before restarting synchronization after a recoverable \ + error.", + ParamPrivacyInput::Public, + ), + ser_param( + "blocks_max_stream_size", + &self.blocks_max_stream_size, + "Max amount of blocks to download in a stream.", + ParamPrivacyInput::Public, + ), + ser_param( + "state_updates_max_stream_size", + &self.state_updates_max_stream_size, + "Max amount of state updates to download in a stream.", + ParamPrivacyInput::Public, + ), + ser_param( + "verify_blocks", + &self.verify_blocks, + "Whether to verify incoming blocks.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl Default for SyncConfig { + fn default() -> Self { + SyncConfig { + block_propagation_sleep_duration: Duration::from_secs(2), + base_layer_propagation_sleep_duration: Duration::from_secs(10), + recoverable_error_sleep_duration: Duration::from_secs(3), + blocks_max_stream_size: 1000, + state_updates_max_stream_size: 1000, + verify_blocks: true, + } + } +} + +// Orchestrates specific network interfaces (e.g. central, p2p, l1) and writes to Storage and shared +// memory. +pub struct GenericStateSync< + TCentralSource: CentralSourceTrait + Sync + Send, + TPendingSource: PendingSourceTrait + Sync + Send, + TBaseLayerSource: BaseLayerSourceTrait + Sync + Send, +> { + config: SyncConfig, + shared_highest_block: Arc>>, + pending_data: Arc>, + central_source: Arc, + pending_source: Arc, + pending_classes: Arc>, + base_layer_source: Arc, + reader: StorageReader, + writer: StorageWriter, + sequencer_pub_key: Option, +} + +pub type StateSyncResult = Result<(), StateSyncError>; + +// TODO: Sort alphabetically. +#[derive(thiserror::Error, Debug)] +pub enum StateSyncError { + #[error("Sync stopped progress.")] + NoProgress, + #[error(transparent)] + StorageError(#[from] StorageError), + #[error(transparent)] + CentralSourceError(#[from] CentralError), + #[error(transparent)] + PendingSourceError(#[from] PendingError), + #[error( + "Parent block hash of block {block_number} is not consistent with the stored block. \ + Expected {expected_parent_block_hash}, found {stored_parent_block_hash}." + )] + ParentBlockHashMismatch { + block_number: BlockNumber, + expected_parent_block_hash: BlockHash, + stored_parent_block_hash: BlockHash, + }, + #[error("Header for block {block_number} wasn't found when trying to store base layer block.")] + BaseLayerBlockWithoutMatchingHeader { block_number: BlockNumber }, + #[error(transparent)] + BaseLayerSourceError(#[from] BaseLayerSourceError), + #[error( + "For {block_number} base layer and l2 doesn't match. Base layer hash: {base_layer_hash}, \ + L2 hash: {l2_hash}." + )] + BaseLayerHashMismatch { + block_number: BlockNumber, + base_layer_hash: BlockHash, + l2_hash: BlockHash, + }, + #[error("Sequencer public key changed from {old:?} to {new:?}.")] + SequencerPubKeyChanged { old: SequencerPublicKey, new: SequencerPublicKey }, +} + +#[allow(clippy::large_enum_variant)] +#[derive(Debug)] +pub enum SyncEvent { + NoProgress, + BlockAvailable { + block_number: BlockNumber, + block: Block, + signature: BlockSignature, + }, + StateDiffAvailable { + block_number: BlockNumber, + block_hash: BlockHash, + state_diff: StateDiff, + // TODO(anatg): Remove once there are no more deployed contracts with undeclared classes. + // Class definitions of deployed contracts with classes that were not declared in this + // state diff. + // Note: Since 0.11 new classes can not be implicitly declared. + deployed_contract_class_definitions: IndexMap, + }, + CompiledClassAvailable { + class_hash: ClassHash, + compiled_class_hash: CompiledClassHash, + compiled_class: CasmContractClass, + }, + NewBaseLayerBlock { + block_number: BlockNumber, + block_hash: BlockHash, + }, +} + +impl< + TCentralSource: CentralSourceTrait + Sync + Send + 'static, + TPendingSource: PendingSourceTrait + Sync + Send + 'static, + TBaseLayerSource: BaseLayerSourceTrait + Sync + Send, +> GenericStateSync +{ + pub async fn run(&mut self) -> StateSyncResult { + info!("State sync started."); + loop { + match self.sync_while_ok().await { + // A recoverable error occurred. Sleep and try syncing again. + Err(err) if is_recoverable(&err) => { + warn!("Recoverable error encountered while syncing, error: {}", err); + tokio::time::sleep(self.config.recoverable_error_sleep_duration).await; + continue; + } + // Unrecoverable errors. + Err(err) => { + error!("Fatal error while syncing: {}", err); + return Err(err); + } + Ok(_) => { + unreachable!("Sync should either return with an error or continue forever.") + } + } + } + + // Whitelisting of errors from which we might be able to recover. + fn is_recoverable(err: &StateSyncError) -> bool { + // We don't use here catch-all pattern to enforce conscious decision for each error + // kind. + match err { + StateSyncError::StorageError(error) => { + matches!(error, StorageError::InnerError(_)) + } + StateSyncError::NoProgress + | StateSyncError::CentralSourceError(_) + | StateSyncError::PendingSourceError(_) + | StateSyncError::BaseLayerSourceError(_) + | StateSyncError::ParentBlockHashMismatch { .. } + | StateSyncError::BaseLayerHashMismatch { .. } + | StateSyncError::BaseLayerBlockWithoutMatchingHeader { .. } => true, + StateSyncError::SequencerPubKeyChanged { .. } => false, + } + } + } + + async fn track_sequencer_public_key_changes(&mut self) -> StateSyncResult { + let sequencer_pub_key = self.central_source.get_sequencer_pub_key().await?; + match self.sequencer_pub_key { + // First time setting the sequencer public key. + None => { + info!("Sequencer public key set to {sequencer_pub_key:?}."); + self.sequencer_pub_key = Some(sequencer_pub_key); + } + Some(cur_key) => { + if cur_key != sequencer_pub_key { + warn!( + "Sequencer public key changed from {cur_key:?} to {sequencer_pub_key:?}." + ); + // TODO: Add alert. + self.sequencer_pub_key = Some(sequencer_pub_key); + return Err(StateSyncError::SequencerPubKeyChanged { + old: cur_key, + new: sequencer_pub_key, + }); + } + } + }; + Ok(()) + } + + // Sync until encountering an error: + // 1. If needed, revert blocks from the end of the chain. + // 2. Create infinite block and state diff streams to fetch data from the central source. + // 3. Fetch data from the streams with unblocking wait while there is no new data. + async fn sync_while_ok(&mut self) -> StateSyncResult { + if self.config.verify_blocks { + self.track_sequencer_public_key_changes().await?; + } + self.handle_block_reverts().await?; + let block_stream = stream_new_blocks( + self.reader.clone(), + self.central_source.clone(), + self.pending_source.clone(), + self.shared_highest_block.clone(), + self.pending_data.clone(), + self.pending_classes.clone(), + self.config.block_propagation_sleep_duration, + PENDING_SLEEP_DURATION, + self.config.blocks_max_stream_size, + ) + .fuse(); + let state_diff_stream = stream_new_state_diffs( + self.reader.clone(), + self.central_source.clone(), + self.config.block_propagation_sleep_duration, + self.config.state_updates_max_stream_size, + ) + .fuse(); + let compiled_class_stream = stream_new_compiled_classes( + self.reader.clone(), + self.central_source.clone(), + self.config.block_propagation_sleep_duration, + // TODO(yair): separate config param. + self.config.state_updates_max_stream_size, + ) + .fuse(); + let base_layer_block_stream = stream_new_base_layer_block( + self.reader.clone(), + self.base_layer_source.clone(), + self.config.base_layer_propagation_sleep_duration, + ) + .fuse(); + // TODO(dvir): try use interval instead of stream. + // TODO: fix the bug and remove this check. + let check_sync_progress = check_sync_progress(self.reader.clone()).fuse(); + pin_mut!( + block_stream, + state_diff_stream, + compiled_class_stream, + base_layer_block_stream, + check_sync_progress + ); + + loop { + debug!("Selecting between block sync and state diff sync."); + let sync_event = select! { + res = block_stream.next() => res, + res = state_diff_stream.next() => res, + res = compiled_class_stream.next() => res, + res = base_layer_block_stream.next() => res, + res = check_sync_progress.next() => res, + complete => break, + } + .expect("Received None as a sync event.")?; + self.process_sync_event(sync_event).await?; + debug!("Finished processing sync event."); + } + unreachable!("Fetching data loop should never return."); + } + + // Tries to store the incoming data. + async fn process_sync_event(&mut self, sync_event: SyncEvent) -> StateSyncResult { + match sync_event { + SyncEvent::BlockAvailable { block_number, block, signature } => { + self.store_block(block_number, block, &signature) + } + SyncEvent::StateDiffAvailable { + block_number, + block_hash, + state_diff, + deployed_contract_class_definitions, + } => self.store_state_diff( + block_number, + block_hash, + state_diff, + deployed_contract_class_definitions, + ), + SyncEvent::CompiledClassAvailable { + class_hash, + compiled_class_hash, + compiled_class, + } => self.store_compiled_class(class_hash, compiled_class_hash, compiled_class), + SyncEvent::NewBaseLayerBlock { block_number, block_hash } => { + self.store_base_layer_block(block_number, block_hash) + } + SyncEvent::NoProgress => Err(StateSyncError::NoProgress), + } + } + + #[latency_histogram("sync_store_block_latency_seconds", false)] + #[instrument( + skip(self, block), + level = "debug", + fields(block_hash = format_args!("{:#064x}", block.header.block_hash.0)), + err + )] + fn store_block( + &mut self, + block_number: BlockNumber, + block: Block, + signature: &BlockSignature, + ) -> StateSyncResult { + // Assuming the central source is trusted, detect reverts by comparing the incoming block's + // parent hash to the current hash. + self.verify_parent_block_hash(block_number, &block)?; + + debug!("Storing block."); + trace!("Block data: {block:#?}, signature: {signature:?}"); + self.writer + .begin_rw_txn()? + .append_header(block_number, &block.header)? + .append_block_signature(block_number, signature)? + .append_body(block_number, block.body)? + .commit()?; + metrics::gauge!( + papyrus_metrics::PAPYRUS_HEADER_MARKER, + block_number.unchecked_next().0 as f64 + ); + metrics::gauge!( + papyrus_metrics::PAPYRUS_BODY_MARKER, + block_number.unchecked_next().0 as f64 + ); + let dt = Utc::now() + - Utc + .timestamp_opt(block.header.timestamp.0 as i64, 0) + .single() + .expect("block timestamp should be valid"); + let header_latency = dt.num_seconds(); + debug!("Header latency: {}.", header_latency); + if header_latency >= 0 { + metrics::gauge!(papyrus_metrics::PAPYRUS_HEADER_LATENCY_SEC, header_latency as f64); + } + Ok(()) + } + + #[latency_histogram("sync_store_state_diff_latency_seconds", false)] + #[instrument(skip(self, state_diff, deployed_contract_class_definitions), level = "debug", err)] + fn store_state_diff( + &mut self, + block_number: BlockNumber, + block_hash: BlockHash, + state_diff: StateDiff, + deployed_contract_class_definitions: IndexMap, + ) -> StateSyncResult { + // TODO(dan): verifications - verify state diff against stored header. + debug!("Storing state diff."); + trace!("StateDiff data: {state_diff:#?}"); + + // TODO(shahak): split the state diff stream to 2 separate streams for blocks and for + // classes. + let (thin_state_diff, classes, deprecated_classes) = + ThinStateDiff::from_state_diff(state_diff); + self.writer + .begin_rw_txn()? + .append_state_diff(block_number, thin_state_diff)? + .append_classes( + block_number, + &classes.iter().map(|(class_hash, class)| (*class_hash, class)).collect::>(), + &deprecated_classes + .iter() + .chain(deployed_contract_class_definitions.iter()) + .map(|(class_hash, deprecated_class)| (*class_hash, deprecated_class)) + .collect::>(), + )? + .commit()?; + + metrics::gauge!( + papyrus_metrics::PAPYRUS_STATE_MARKER, + block_number.unchecked_next().0 as f64 + ); + let compiled_class_marker = self.reader.begin_ro_txn()?.get_compiled_class_marker()?; + metrics::gauge!( + papyrus_metrics::PAPYRUS_COMPILED_CLASS_MARKER, + compiled_class_marker.0 as f64 + ); + + // Info the user on syncing the block once all the data is stored. + info!("Added block {} with hash {:#064x}.", block_number, block_hash.0); + + Ok(()) + } + + #[latency_histogram("sync_store_compiled_class_latency_seconds", false)] + #[instrument(skip(self, compiled_class), level = "debug", err)] + fn store_compiled_class( + &mut self, + class_hash: ClassHash, + compiled_class_hash: CompiledClassHash, + compiled_class: CasmContractClass, + ) -> StateSyncResult { + let txn = self.writer.begin_rw_txn()?; + // TODO: verifications - verify casm corresponds to a class on storage. + match txn.append_casm(&class_hash, &compiled_class) { + Ok(txn) => { + txn.commit()?; + let compiled_class_marker = + self.reader.begin_ro_txn()?.get_compiled_class_marker()?; + metrics::gauge!( + papyrus_metrics::PAPYRUS_COMPILED_CLASS_MARKER, + compiled_class_marker.0 as f64 + ); + debug!("Added compiled class."); + Ok(()) + } + // TODO(yair): Modify the stream so it skips already stored classes. + // Compiled classes rewrite is valid because the stream downloads from the beginning of + // the block instead of the last downloaded class. + Err(StorageError::InnerError(DbError::KeyAlreadyExists(..))) => { + debug!("Compiled class of {class_hash} already stored."); + Ok(()) + } + Err(err) => Err(StateSyncError::StorageError(err)), + } + } + + #[instrument(skip(self), level = "debug", err)] + // In case of a mismatch between the base layer and l2, an error will be returned, then the + // sync will revert blocks if needed based on the l2 central source. This approach works as long + // as l2 is trusted so all the reverts can be detect by using it. + fn store_base_layer_block( + &mut self, + block_number: BlockNumber, + block_hash: BlockHash, + ) -> StateSyncResult { + let txn = self.writer.begin_rw_txn()?; + // Missing header can be because of a base layer reorg, the matching header may be reverted. + let expected_hash = txn + .get_block_header(block_number)? + .ok_or(StateSyncError::BaseLayerBlockWithoutMatchingHeader { block_number })? + .block_hash; + // Can be caused because base layer reorg or l2 reverts. + if expected_hash != block_hash { + return Err(StateSyncError::BaseLayerHashMismatch { + block_number, + base_layer_hash: block_hash, + l2_hash: expected_hash, + }); + } + if txn.get_base_layer_block_marker()? != block_number.unchecked_next() { + info!("Verified block {block_number} hash against base layer."); + txn.update_base_layer_block_marker(&block_number.unchecked_next())?.commit()?; + metrics::gauge!( + papyrus_metrics::PAPYRUS_BASE_LAYER_MARKER, + block_number.unchecked_next().0 as f64 + ); + } + Ok(()) + } + + // Compares the block's parent hash to the stored block. + fn verify_parent_block_hash( + &self, + block_number: BlockNumber, + block: &Block, + ) -> StateSyncResult { + let prev_block_number = match block_number.prev() { + None => return Ok(()), + Some(bn) => bn, + }; + let prev_hash = self + .reader + .begin_ro_txn()? + .get_block_header(prev_block_number)? + .ok_or(StorageError::DBInconsistency { + msg: format!( + "Missing block {prev_block_number} in the storage (for verifying block \ + {block_number}).", + ), + })? + .block_hash; + + if prev_hash != block.header.parent_hash { + // A revert detected, log and restart sync loop. + info!( + "Detected revert while processing block {}. Parent hash of the incoming block is \ + {}, current block hash is {}.", + block_number, block.header.parent_hash, prev_hash + ); + return Err(StateSyncError::ParentBlockHashMismatch { + block_number, + expected_parent_block_hash: block.header.parent_hash, + stored_parent_block_hash: prev_hash, + }); + } + + Ok(()) + } + + // Reverts data if needed. + async fn handle_block_reverts(&mut self) -> Result<(), StateSyncError> { + debug!("Handling block reverts."); + let header_marker = self.reader.begin_ro_txn()?.get_header_marker()?; + + // Revert last blocks if needed. + let mut last_block_in_storage = header_marker.prev(); + while let Some(block_number) = last_block_in_storage { + if self.should_revert_block(block_number).await? { + self.revert_block(block_number)?; + last_block_in_storage = block_number.prev(); + } else { + break; + } + } + Ok(()) + } + + // TODO(dan): update necessary metrics. + // Deletes the block data from the storage. + #[allow(clippy::expect_fun_call)] + #[instrument(skip(self), level = "debug", err)] + fn revert_block(&mut self, block_number: BlockNumber) -> StateSyncResult { + debug!("Reverting block."); + + let mut txn = self.writer.begin_rw_txn()?; + txn = txn.try_revert_base_layer_marker(block_number)?; + let res = txn.revert_header(block_number)?; + txn = res.0; + let mut reverted_block_hash: Option = None; + if let Some(header) = res.1 { + reverted_block_hash = Some(header.block_hash); + + let res = txn.revert_body(block_number)?; + txn = res.0; + + let res = txn.revert_state_diff(block_number)?; + txn = res.0; + } + + txn.commit()?; + if let Some(hash) = reverted_block_hash { + info!(%hash, "Reverted block."); + } + Ok(()) + } + + /// Checks if centrals block hash at the block number is different from ours (or doesn't exist). + /// If so, a revert is required. + async fn should_revert_block(&self, block_number: BlockNumber) -> Result { + if let Some(central_block_hash) = self.central_source.get_block_hash(block_number).await? { + let storage_block_header = + self.reader.begin_ro_txn()?.get_block_header(block_number)?; + + match storage_block_header { + Some(block_header) => Ok(block_header.block_hash != central_block_hash), + None => Ok(false), + } + } else { + // Block number doesn't exist in central, revert. + Ok(true) + } + } +} +// TODO(dvir): consider gathering in a single pending argument instead. +#[allow(clippy::too_many_arguments)] +fn stream_new_blocks< + TCentralSource: CentralSourceTrait + Sync + Send + 'static, + TPendingSource: PendingSourceTrait + Sync + Send + 'static, +>( + reader: StorageReader, + central_source: Arc, + pending_source: Arc, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + block_propagation_sleep_duration: Duration, + pending_sleep_duration: Duration, + max_stream_size: u32, +) -> impl Stream> { + try_stream! { + loop { + let header_marker = reader.begin_ro_txn()?.get_header_marker()?; + let latest_central_block = central_source.get_latest_block().await?; + *shared_highest_block.write().await = latest_central_block; + let central_block_marker = latest_central_block.map_or( + BlockNumber::default(), |block| block.block_number.unchecked_next() + ); + metrics::gauge!( + papyrus_metrics::PAPYRUS_CENTRAL_BLOCK_MARKER, central_block_marker.0 as f64 + ); + if header_marker == central_block_marker { + // Only if the node have the last block and state (without casms), sync pending data. + if reader.begin_ro_txn()?.get_state_marker()? == header_marker{ + // Here is the only place we update the pending data. + debug!("Start polling for pending data."); + sync_pending_data( + reader.clone(), + central_source.clone(), + pending_source.clone(), + pending_data.clone(), + pending_classes.clone(), + pending_sleep_duration, + ).await?; + } + else{ + debug!("Blocks syncing reached the last known block, waiting for blockchain to advance."); + tokio::time::sleep(block_propagation_sleep_duration).await; + }; + continue; + } + let up_to = min(central_block_marker, BlockNumber(header_marker.0 + max_stream_size as u64)); + debug!("Downloading blocks [{} - {}).", header_marker, up_to); + let block_stream = + central_source.stream_new_blocks(header_marker, up_to).fuse(); + pin_mut!(block_stream); + while let Some(maybe_block) = block_stream.next().await { + let (block_number, block, signature) = maybe_block?; + yield SyncEvent::BlockAvailable { block_number, block , signature }; + } + } + } +} + +fn stream_new_state_diffs( + reader: StorageReader, + central_source: Arc, + block_propagation_sleep_duration: Duration, + max_stream_size: u32, +) -> impl Stream> { + try_stream! { + loop { + let txn = reader.begin_ro_txn()?; + let state_marker = txn.get_state_marker()?; + let last_block_number = txn.get_header_marker()?; + drop(txn); + if state_marker == last_block_number { + debug!("State updates syncing reached the last downloaded block, waiting for more blocks."); + tokio::time::sleep(block_propagation_sleep_duration).await; + continue; + } + let up_to = min(last_block_number, BlockNumber(state_marker.0 + max_stream_size as u64)); + debug!("Downloading state diffs [{} - {}).", state_marker, up_to); + let state_diff_stream = + central_source.stream_state_updates(state_marker, up_to).fuse(); + pin_mut!(state_diff_stream); + + while let Some(maybe_state_diff) = state_diff_stream.next().await { + let ( + block_number, + block_hash, + mut state_diff, + deployed_contract_class_definitions, + ) = maybe_state_diff?; + sort_state_diff(&mut state_diff); + yield SyncEvent::StateDiffAvailable { + block_number, + block_hash, + state_diff, + deployed_contract_class_definitions, + }; + } + } + } +} + +pub fn sort_state_diff(diff: &mut StateDiff) { + diff.declared_classes.sort_unstable_keys(); + diff.deprecated_declared_classes.sort_unstable_keys(); + diff.deployed_contracts.sort_unstable_keys(); + diff.nonces.sort_unstable_keys(); + diff.replaced_classes.sort_unstable_keys(); + diff.storage_diffs.sort_unstable_keys(); + for storage_entries in diff.storage_diffs.values_mut() { + storage_entries.sort_unstable_keys(); + } +} + +pub type StateSync = GenericStateSync; + +impl StateSync { + #[allow(clippy::too_many_arguments)] + pub fn new( + config: SyncConfig, + shared_highest_block: Arc>>, + pending_data: Arc>, + pending_classes: Arc>, + central_source: CentralSource, + pending_source: PendingSource, + base_layer_source: EthereumBaseLayerSource, + reader: StorageReader, + writer: StorageWriter, + ) -> Self { + Self { + config, + shared_highest_block, + pending_data, + pending_classes, + central_source: Arc::new(central_source), + pending_source: Arc::new(pending_source), + base_layer_source: Arc::new(base_layer_source), + reader, + writer, + sequencer_pub_key: None, + } + } +} + +fn stream_new_compiled_classes( + reader: StorageReader, + central_source: Arc, + block_propagation_sleep_duration: Duration, + max_stream_size: u32, +) -> impl Stream> { + try_stream! { + loop { + let txn = reader.begin_ro_txn()?; + let mut from = txn.get_compiled_class_marker()?; + let state_marker = txn.get_state_marker()?; + // Avoid starting streams from blocks without declared classes. + while from < state_marker { + let state_diff = txn.get_state_diff(from)?.expect("Expecting to have state diff up to the marker."); + if state_diff.declared_classes.is_empty() { + from = from.unchecked_next(); + } + else { + break; + } + } + + if from == state_marker { + debug!( + "Compiled classes syncing reached the last downloaded state update, waiting \ + for more state updates." + ); + tokio::time::sleep(block_propagation_sleep_duration).await; + continue; + } + let up_to = min(state_marker, BlockNumber(from.0 + max_stream_size as u64)); + debug!("Downloading compiled classes of blocks [{} - {}).", from, up_to); + let compiled_classes_stream = + central_source.stream_compiled_classes(from, up_to).fuse(); + pin_mut!(compiled_classes_stream); + + while let Some(maybe_compiled_class) = compiled_classes_stream.next().await { + let (class_hash, compiled_class_hash, compiled_class) = maybe_compiled_class?; + yield SyncEvent::CompiledClassAvailable { + class_hash, + compiled_class_hash, + compiled_class, + }; + } + } + } +} + +// TODO(dvir): consider combine this function and store_base_layer_block. +fn stream_new_base_layer_block( + reader: StorageReader, + base_layer_source: Arc, + base_layer_propagation_sleep_duration: Duration, +) -> impl Stream> { + try_stream! { + loop { + tokio::time::sleep(base_layer_propagation_sleep_duration).await; + let txn = reader.begin_ro_txn()?; + let header_marker = txn.get_header_marker()?; + match base_layer_source.latest_proved_block().await? { + Some((block_number, _block_hash)) if header_marker <= block_number => { + debug!( + "Sync headers ({header_marker}) is behind the base layer tip \ + ({block_number}), waiting for sync to advance." + ); + } + Some((block_number, block_hash)) => { + debug!("Returns a block from the base layer. Block number: {block_number}."); + yield SyncEvent::NewBaseLayerBlock { block_number, block_hash } + } + None => { + debug!( + "No blocks were proved on the base layer, waiting for blockchain to \ + advance." + ); + } + } + } + } +} + +// This function is used to check if the sync is stuck. +// TODO: fix the bug and remove this function. +// TODO(dvir): add a test for this scenario. +fn check_sync_progress( + reader: StorageReader, +) -> impl Stream> { + try_stream! { + let mut txn=reader.begin_ro_txn()?; + let mut header_marker=txn.get_header_marker()?; + let mut state_marker=txn.get_state_marker()?; + let mut casm_marker=txn.get_compiled_class_marker()?; + loop{ + tokio::time::sleep(SLEEP_TIME_SYNC_PROGRESS).await; + debug!("Checking if sync stopped progress."); + txn=reader.begin_ro_txn()?; + let new_header_marker=txn.get_header_marker()?; + let new_state_marker=txn.get_state_marker()?; + let new_casm_marker=txn.get_compiled_class_marker()?; + if header_marker==new_header_marker || state_marker==new_state_marker || casm_marker==new_casm_marker{ + debug!("No progress in the sync. Return NoProgress event."); + yield SyncEvent::NoProgress; + } + header_marker=new_header_marker; + state_marker=new_state_marker; + casm_marker=new_casm_marker; + } + } +} diff --git a/crates/papyrus_sync/src/pending_sync.rs b/crates/papyrus_sync/src/pending_sync.rs new file mode 100644 index 00000000000..0a6afbce3d1 --- /dev/null +++ b/crates/papyrus_sync/src/pending_sync.rs @@ -0,0 +1,205 @@ +use std::collections::HashSet; +use std::sync::Arc; +use std::time::Duration; + +use futures::stream::FuturesUnordered; +use futures_util::{FutureExt, StreamExt}; +use papyrus_common::pending_classes::{PendingClasses, PendingClassesTrait}; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::StorageReader; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::ClassHash; +use starknet_client::reader::{DeclaredClassHashEntry, PendingData}; +use starknet_types_core::felt::Felt; +use tokio::sync::RwLock; +use tracing::{debug, trace}; + +use crate::sources::central::CentralSourceTrait; +use crate::sources::pending::PendingSourceTrait; +use crate::StateSyncError; + +// Update the pending data and return when a new block is discovered. +pub(crate) async fn sync_pending_data< + TPendingSource: PendingSourceTrait + Sync + Send + 'static, + TCentralSource: CentralSourceTrait + Sync + Send + 'static, +>( + reader: StorageReader, + central_source: Arc, + pending_source: Arc, + pending_data: Arc>, + pending_classes: Arc>, + sleep_duration: Duration, +) -> Result<(), StateSyncError> { + let txn = reader.begin_ro_txn()?; + let header_marker = txn.get_header_marker()?; + // TODO: Consider extracting this functionality to different а function. + let latest_block_hash = match header_marker { + BlockNumber(0) => BlockHash(Felt::from_hex_unchecked(crate::GENESIS_HASH)), + _ => { + txn.get_block_header( + header_marker + .prev() + .expect("All blocks other than the first block should have a predecessor."), + )? + .expect("Block before the header marker must have header in the database.") + .block_hash + } + }; + let mut tasks = FuturesUnordered::new(); + tasks.push( + get_pending_data( + latest_block_hash, + pending_source.clone(), + pending_data.clone(), + pending_classes.clone(), + Duration::ZERO, + ) + .boxed(), + ); + let mut processed_classes = HashSet::new(); + let mut processed_compiled_classes = HashSet::new(); + loop { + match tasks.next().await.expect("There should always be a task in the pending sync")? { + PendingSyncTaskResult::PendingSyncFinished => return Ok(()), + PendingSyncTaskResult::DownloadedNewPendingData => { + let (declared_classes, old_declared_contracts) = { + // TODO (shahak): Consider getting the pending data from the task result instead + // of reading from the lock. + let pending_state_diff = &pending_data.read().await.state_update.state_diff; + ( + pending_state_diff.declared_classes.clone(), + pending_state_diff.old_declared_contracts.clone(), + ) + }; + for DeclaredClassHashEntry { class_hash, compiled_class_hash } in declared_classes { + if processed_classes.insert(class_hash) { + tasks.push( + get_pending_class( + class_hash, + central_source.clone(), + pending_classes.clone(), + ) + .boxed(), + ); + } + if processed_compiled_classes.insert(compiled_class_hash) { + tasks.push( + get_pending_compiled_class( + class_hash, + central_source.clone(), + pending_classes.clone(), + ) + .boxed(), + ); + } + } + for class_hash in old_declared_contracts { + if processed_classes.insert(class_hash) { + tasks.push( + get_pending_class( + class_hash, + central_source.clone(), + pending_classes.clone(), + ) + .boxed(), + ); + } + } + tasks.push( + get_pending_data( + latest_block_hash, + pending_source.clone(), + pending_data.clone(), + pending_classes.clone(), + sleep_duration, + ) + .boxed(), + ) + } + PendingSyncTaskResult::DownloadedOldPendingData => tasks.push( + get_pending_data( + latest_block_hash, + pending_source.clone(), + pending_data.clone(), + pending_classes.clone(), + sleep_duration, + ) + .boxed(), + ), + PendingSyncTaskResult::DownloadedClassOrCompiledClass => {} + } + } +} + +enum PendingSyncTaskResult { + DownloadedNewPendingData, + DownloadedOldPendingData, + PendingSyncFinished, + DownloadedClassOrCompiledClass, +} + +async fn get_pending_data( + latest_block_hash: BlockHash, + pending_source: Arc, + pending_data: Arc>, + pending_classes: Arc>, + sleep_duration: Duration, +) -> Result { + tokio::time::sleep(sleep_duration).await; + + let new_pending_data = pending_source.get_pending_data().await?; + + // In Starknet, if there's no pending block then the latest block is returned. We prefer to + // treat this case as if the pending block is an empty block on top of the latest block. + // We distinguish this case by looking if the block_hash field is present. + let new_pending_parent_hash = + new_pending_data.block.block_hash().unwrap_or(new_pending_data.block.parent_block_hash()); + if new_pending_parent_hash != latest_block_hash { + // TODO(shahak): If block_hash is present, consider writing the pending data here so that + // the pending data will be available until the node syncs on the new block. + debug!("A new block was found. Stopping pending sync."); + return Ok(PendingSyncTaskResult::PendingSyncFinished); + }; + + let (current_pending_num_transactions, current_pending_parent_hash) = { + let pending_block = &pending_data.read().await.block; + ( + pending_block.transactions().len(), + pending_block.block_hash().unwrap_or(pending_block.parent_block_hash()), + ) + }; + let is_new_pending_data_more_advanced = current_pending_parent_hash != new_pending_parent_hash + || new_pending_data.block.transactions().len() > current_pending_num_transactions; + if is_new_pending_data_more_advanced { + debug!("Received new pending data."); + trace!("Pending data: {new_pending_data:#?}."); + if current_pending_parent_hash != new_pending_parent_hash { + pending_classes.write().await.clear(); + } + *pending_data.write().await = new_pending_data; + Ok(PendingSyncTaskResult::DownloadedNewPendingData) + } else { + debug!("Pending block wasn't updated. Waiting for pending block to be updated."); + Ok(PendingSyncTaskResult::DownloadedOldPendingData) + } +} + +async fn get_pending_class( + class_hash: ClassHash, + central_source: Arc, + pending_classes: Arc>, +) -> Result { + let class = central_source.get_class(class_hash).await?; + pending_classes.write().await.add_class(class_hash, class); + Ok(PendingSyncTaskResult::DownloadedClassOrCompiledClass) +} + +async fn get_pending_compiled_class( + class_hash: ClassHash, + central_source: Arc, + pending_classes: Arc>, +) -> Result { + let compiled_class = central_source.get_compiled_class(class_hash).await?; + pending_classes.write().await.add_compiled_class(class_hash, compiled_class); + Ok(PendingSyncTaskResult::DownloadedClassOrCompiledClass) +} diff --git a/crates/papyrus_sync/src/sources/base_layer.rs b/crates/papyrus_sync/src/sources/base_layer.rs new file mode 100644 index 00000000000..5c4eddb7a1c --- /dev/null +++ b/crates/papyrus_sync/src/sources/base_layer.rs @@ -0,0 +1,43 @@ +use async_trait::async_trait; +#[cfg(test)] +use mockall::automock; +use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerContract; +use papyrus_base_layer::BaseLayerContract; +use starknet_api::block::{BlockHash, BlockNumber}; + +pub type EthereumBaseLayerSource = EthereumBaseLayerContract; + +#[derive(thiserror::Error, Debug)] +pub enum BaseLayerSourceError { + #[error("Base layer error: {0}")] + BaseLayerContractError(Box), + #[error("Base layer source creation error: {0}.")] + BaseLayerSourceCreationError(String), +} + +pub trait BaseLayerSourceErrorTrait: std::error::Error + Sync + Send {} + +impl BaseLayerSourceErrorTrait for Error {} + +#[cfg_attr(test, automock)] +#[async_trait] +pub trait BaseLayerSourceTrait { + async fn latest_proved_block( + &self, + ) -> Result, BaseLayerSourceError>; +} + +#[async_trait] +impl< + Error: std::error::Error + 'static + Sync + Send, + BaseLayerSource: BaseLayerContract + Sync + Send, +> BaseLayerSourceTrait for BaseLayerSource +{ + async fn latest_proved_block( + &self, + ) -> Result, BaseLayerSourceError> { + self.latest_proved_block(None) + .await + .map_err(|e| BaseLayerSourceError::BaseLayerContractError(Box::new(e))) + } +} diff --git a/crates/papyrus_sync/src/sources/central.rs b/crates/papyrus_sync/src/sources/central.rs new file mode 100644 index 00000000000..f113bb26f33 --- /dev/null +++ b/crates/papyrus_sync/src/sources/central.rs @@ -0,0 +1,477 @@ +#[cfg(test)] +#[path = "central_test.rs"] +mod central_test; +mod state_update_stream; + +use std::collections::{BTreeMap, HashMap}; +use std::num::NonZeroUsize; +use std::sync::{Arc, Mutex}; + +use async_stream::stream; +use async_trait::async_trait; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use futures::stream::BoxStream; +use futures_util::StreamExt; +use indexmap::IndexMap; +use itertools::chain; +use lru::LruCache; +#[cfg(test)] +use mockall::automock; +use papyrus_common::pending_classes::ApiContractClass; +use papyrus_common::BlockHashAndNumber; +use papyrus_config::converters::{deserialize_optional_map, serialize_optional_map}; +use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::{StorageError, StorageReader}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{Block, BlockHash, BlockNumber, BlockSignature}; +use starknet_api::core::{ClassHash, CompiledClassHash, SequencerPublicKey}; +use starknet_api::crypto::utils::Signature; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::StateDiff; +use starknet_api::StarknetApiError; +use starknet_client::reader::{ + BlockSignatureData, + ReaderClientError, + StarknetFeederGatewayClient, + StarknetReader, +}; +use starknet_client::{ClientCreationError, RetryConfig}; +use tracing::{debug, trace}; + +use self::state_update_stream::{StateUpdateStream, StateUpdateStreamConfig}; + +type CentralResult = Result; +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct CentralSourceConfig { + pub concurrent_requests: usize, + pub url: String, + #[serde(deserialize_with = "deserialize_optional_map")] + pub http_headers: Option>, + pub max_state_updates_to_download: usize, + pub max_state_updates_to_store_in_memory: usize, + pub max_classes_to_download: usize, + // TODO(dan): validate that class_cache_size is a positive integer. + pub class_cache_size: usize, + pub retry_config: RetryConfig, +} + +impl Default for CentralSourceConfig { + fn default() -> Self { + CentralSourceConfig { + concurrent_requests: 10, + url: String::from("https://alpha-mainnet.starknet.io/"), + http_headers: None, + max_state_updates_to_download: 20, + max_state_updates_to_store_in_memory: 20, + max_classes_to_download: 20, + class_cache_size: 100, + retry_config: RetryConfig { + retry_base_millis: 30, + retry_max_delay_millis: 30000, + max_retries: 10, + }, + } + } +} + +impl SerializeConfig for CentralSourceConfig { + fn dump(&self) -> BTreeMap { + let self_params_dump = BTreeMap::from_iter([ + ser_param( + "concurrent_requests", + &self.concurrent_requests, + "Maximum number of concurrent requests to Starknet feeder-gateway for getting a \ + type of data (for example, blocks).", + ParamPrivacyInput::Public, + ), + ser_param( + "url", + &self.url, + "Starknet feeder-gateway URL. It should match chain_id.", + ParamPrivacyInput::Public, + ), + ser_param( + "http_headers", + &serialize_optional_map(&self.http_headers), + "'k1:v1 k2:v2 ...' headers for SN-client.", + ParamPrivacyInput::Private, + ), + ser_param( + "max_state_updates_to_download", + &self.max_state_updates_to_download, + "Maximum number of state updates to download at a given time.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_state_updates_to_store_in_memory", + &self.max_state_updates_to_store_in_memory, + "Maximum number of state updates to store in memory at a given time.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_classes_to_download", + &self.max_classes_to_download, + "Maximum number of classes to download at a given time.", + ParamPrivacyInput::Public, + ), + ser_param( + "class_cache_size", + &self.class_cache_size, + "Size of class cache, must be a positive integer.", + ParamPrivacyInput::Public, + ), + ]); + chain!(self_params_dump, append_sub_config_name(self.retry_config.dump(), "retry_config")) + .collect() + } +} + +pub struct GenericCentralSource { + pub concurrent_requests: usize, + pub starknet_client: Arc, + pub storage_reader: StorageReader, + pub state_update_stream_config: StateUpdateStreamConfig, + pub(crate) class_cache: Arc>>, + compiled_class_cache: Arc>>, +} + +#[derive(thiserror::Error, Debug)] +pub enum CentralError { + #[error(transparent)] + ClientCreation(#[from] ClientCreationError), + #[error(transparent)] + ClientError(#[from] Arc), + #[error("Could not find a state update.")] + StateUpdateNotFound, + #[error("Could not find a class definitions.")] + ClassNotFound, + #[error("Could not find a compiled class of {}.", class_hash)] + CompiledClassNotFound { class_hash: ClassHash }, + #[error("Could not find a block with block number {}.", block_number)] + BlockNotFound { block_number: BlockNumber }, + #[error(transparent)] + StarknetApiError(#[from] Arc), + #[error(transparent)] + StorageError(#[from] StorageError), + #[error("Wrong type of contract class")] + BadContractClassType, + #[error( + "Block downloaded from central is in 0.13.1 format, while signature is in 0.13.2 format." + )] + BlockAndSignatureVersionMismatch, +} + +#[cfg_attr(test, automock)] +#[async_trait] +pub trait CentralSourceTrait { + async fn get_latest_block(&self) -> Result, CentralError>; + fn stream_new_blocks( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> BlocksStream<'_>; + fn stream_state_updates( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> StateUpdatesStream<'_>; + + async fn get_block_hash( + &self, + block_number: BlockNumber, + ) -> Result, CentralError>; + + fn stream_compiled_classes( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> CompiledClassesStream<'_>; + + // TODO(shahak): Remove once pending block is removed. + async fn get_class(&self, class_hash: ClassHash) -> Result; + + // TODO(shahak): Remove once pending block is removed. + async fn get_compiled_class( + &self, + class_hash: ClassHash, + ) -> Result; + + async fn get_sequencer_pub_key(&self) -> Result; +} + +pub(crate) type BlocksStream<'a> = + BoxStream<'a, Result<(BlockNumber, Block, BlockSignature), CentralError>>; +type CentralStateUpdate = + (BlockNumber, BlockHash, StateDiff, IndexMap); +pub(crate) type StateUpdatesStream<'a> = BoxStream<'a, CentralResult>; +type CentralCompiledClass = (ClassHash, CompiledClassHash, CasmContractClass); +pub(crate) type CompiledClassesStream<'a> = BoxStream<'a, CentralResult>; + +#[async_trait] +impl CentralSourceTrait + for GenericCentralSource +{ + // Returns the block hash and the block number of the latest block from the central source. + async fn get_latest_block(&self) -> Result, CentralError> { + self.starknet_client.latest_block().await.map_err(Arc::new)?.map_or(Ok(None), |block| { + Ok(Some(BlockHashAndNumber { + block_hash: block.block_hash(), + block_number: block.block_number(), + })) + }) + } + + // Returns the current block hash of the given block number from the central source. + async fn get_block_hash( + &self, + block_number: BlockNumber, + ) -> Result, CentralError> { + self.starknet_client + .block(block_number) + .await + .map_err(Arc::new)? + .map_or(Ok(None), |block| Ok(Some(block.block_hash()))) + } + + // Returns a stream of state updates downloaded from the central source. + fn stream_state_updates( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> StateUpdatesStream<'_> { + StateUpdateStream::new( + initial_block_number, + up_to_block_number, + self.starknet_client.clone(), + self.storage_reader.clone(), + self.state_update_stream_config.clone(), + self.class_cache.clone(), + ) + .boxed() + } + + // TODO(shahak): rename. + // Returns a stream of blocks downloaded from the central source. + fn stream_new_blocks( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> BlocksStream<'_> { + stream! { + // TODO(dan): add explanation. + let mut res = + futures_util::stream::iter(initial_block_number.iter_up_to(up_to_block_number)) + .map(|bn| async move { + let block_and_signature = futures_util::try_join!( + self.starknet_client.block(bn), + self.starknet_client.block_signature(bn) + ); + (bn, block_and_signature) + }) + .buffered(self.concurrent_requests); + while let Some((current_block_number, maybe_client_block)) = res.next().await + { + let maybe_central_block = + client_to_central_block(current_block_number, maybe_client_block); + match maybe_central_block { + Ok((block, signature)) => { + yield Ok((current_block_number, block, signature)); + } + Err(err) => { + yield (Err(err)); + return; + } + } + } + } + .boxed() + } + + // Returns a stream of compiled classes downloaded from the central source. + fn stream_compiled_classes( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> CompiledClassesStream<'_> { + stream! { + let txn = self.storage_reader.begin_ro_txn().map_err(CentralError::StorageError)?; + let class_hashes_iter = initial_block_number + .iter_up_to(up_to_block_number) + .map(|bn| { + match txn.get_state_diff(bn) { + Err(err) => Err(CentralError::StorageError(err)), + // TODO(yair): Consider expecting, since the state diffs should not contain + // holes and we suppose to never exceed the state marker. + Ok(None) => Err(CentralError::StateUpdateNotFound), + Ok(Some(state_diff)) => Ok(state_diff), + } + }) + .flat_map(|maybe_state_diff| match maybe_state_diff { + Ok(state_diff) => { + state_diff + .declared_classes + .into_iter() + .map(Ok) + .collect() + } + Err(err) => vec![Err(err)], + }); + + let mut compiled_classes = futures_util::stream::iter(class_hashes_iter) + .map(|maybe_class_hashes| async move { + match maybe_class_hashes { + Ok((class_hash, compiled_class_hash)) => { + trace!("Downloading compiled class {:?}.", class_hash); + let compiled_class = self.get_compiled_class(class_hash).await?; + Ok((class_hash, compiled_class_hash, compiled_class)) + }, + Err(err) => Err(err), + } + }) + .buffered(self.concurrent_requests); + + while let Some(maybe_compiled_class) = compiled_classes.next().await { + match maybe_compiled_class { + Ok((class_hash, compiled_class_hash, compiled_class)) => { + yield Ok((class_hash, compiled_class_hash, compiled_class)); + } + Err(err) => { + yield Err(err); + return; + } + } + } + } + .boxed() + } + + async fn get_class(&self, class_hash: ClassHash) -> Result { + // TODO(shahak): Fix code duplication with StateUpdatesStream. + { + let mut class_cache = self.class_cache.lock().expect("Failed to lock class cache."); + if let Some(class) = class_cache.get(&class_hash) { + return Ok(class.clone()); + } + } + let client_class = + self.starknet_client.class_by_hash(class_hash).await.map_err(Arc::new)?; + match client_class { + None => Err(CentralError::ClassNotFound), + Some(class) => { + { + let mut class_cache = + self.class_cache.lock().expect("Failed to lock class cache."); + class_cache.put(class_hash, class.clone().into()); + } + Ok(class.into()) + } + } + } + + async fn get_compiled_class( + &self, + class_hash: ClassHash, + ) -> Result { + { + let mut compiled_class_cache = + self.compiled_class_cache.lock().expect("Failed to lock class cache."); + if let Some(class) = compiled_class_cache.get(&class_hash) { + return Ok(class.clone()); + } + } + match self.starknet_client.compiled_class_by_hash(class_hash).await { + Ok(Some(compiled_class)) => { + let mut compiled_class_cache = + self.compiled_class_cache.lock().expect("Failed to lock class cache."); + compiled_class_cache.put(class_hash, compiled_class.clone()); + Ok(compiled_class) + } + Ok(None) => Err(CentralError::CompiledClassNotFound { class_hash }), + Err(err) => Err(CentralError::ClientError(Arc::new(err))), + } + } + + async fn get_sequencer_pub_key(&self) -> Result { + Ok(self.starknet_client.sequencer_pub_key().await.map_err(Arc::new)?) + } +} + +fn client_to_central_block( + current_block_number: BlockNumber, + maybe_client_block: Result< + ( + Option, + Option, + ), + ReaderClientError, + >, +) -> CentralResult<(Block, BlockSignature)> { + match maybe_client_block { + Ok((Some(block), Some(signature_data))) => { + debug!( + "Received new block {current_block_number} with hash {:#064x}.", + block.block_hash().0 + ); + trace!("Block: {block:#?}, signature data: {signature_data:#?}."); + let block = block + .to_starknet_api_block_and_version() + .map_err(|err| CentralError::ClientError(Arc::new(err)))?; + let signature = match signature_data { + BlockSignatureData::Deprecated { signature, .. } => signature, + BlockSignatureData::V0_13_2 { signature, .. } => signature, + }; + Ok((block, BlockSignature(Signature { r: signature[0], s: signature[1] }))) + } + Ok((None, Some(_))) => { + debug!("Block {current_block_number} not found, but signature was found."); + Err(CentralError::BlockNotFound { block_number: current_block_number }) + } + Ok((Some(_), None)) => { + debug!("Block {current_block_number} found, but signature was not found."); + Err(CentralError::BlockNotFound { block_number: current_block_number }) + } + Ok((None, None)) => { + debug!("Block {current_block_number} not found."); + Err(CentralError::BlockNotFound { block_number: current_block_number }) + } + Err(err) => Err(CentralError::ClientError(Arc::new(err))), + } +} + +pub type CentralSource = GenericCentralSource; + +impl CentralSource { + pub fn new( + config: CentralSourceConfig, + node_version: &'static str, + storage_reader: StorageReader, + ) -> Result { + let starknet_client = StarknetFeederGatewayClient::new( + &config.url, + config.http_headers, + node_version, + config.retry_config, + )?; + + Ok(CentralSource { + concurrent_requests: config.concurrent_requests, + starknet_client: Arc::new(starknet_client), + storage_reader, + state_update_stream_config: StateUpdateStreamConfig { + max_state_updates_to_download: config.max_state_updates_to_download, + max_state_updates_to_store_in_memory: config.max_state_updates_to_store_in_memory, + max_classes_to_download: config.max_classes_to_download, + }, + class_cache: Arc::from(Mutex::new(LruCache::new( + NonZeroUsize::new(config.class_cache_size) + .expect("class_cache_size should be a positive integer."), + ))), + compiled_class_cache: Arc::from(Mutex::new(LruCache::new( + NonZeroUsize::new(config.class_cache_size) + .expect("class_cache_size should be a positive integer."), + ))), + }) + } +} diff --git a/crates/papyrus_sync/src/sources/central/state_update_stream.rs b/crates/papyrus_sync/src/sources/central/state_update_stream.rs new file mode 100644 index 00000000000..db811567c69 --- /dev/null +++ b/crates/papyrus_sync/src/sources/central/state_update_stream.rs @@ -0,0 +1,391 @@ +use std::collections::VecDeque; +use std::pin::Pin; +use std::sync::{Arc, Mutex}; +use std::task::Poll; + +use futures_util::stream::FuturesOrdered; +use futures_util::{Future, Stream, StreamExt}; +use indexmap::IndexMap; +use lru::LruCache; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::StorageReader; +use starknet_api::block::BlockNumber; +use starknet_api::core::ClassHash; +use starknet_api::state::{StateDiff, StateNumber}; +use starknet_client::reader::{ReaderClientResult, StarknetReader, StateUpdate}; +use tracing::log::trace; +use tracing::{debug, instrument}; + +use super::{ApiContractClass, CentralResult, CentralStateUpdate}; +use crate::CentralError; + +type TasksQueue = FuturesOrdered + Send>>>; +type NumberOfClasses = usize; + +#[derive(Clone)] +pub struct StateUpdateStreamConfig { + pub max_state_updates_to_download: usize, + pub max_state_updates_to_store_in_memory: usize, + pub max_classes_to_download: usize, +} + +pub(crate) struct StateUpdateStream { + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + starknet_client: Arc, + storage_reader: StorageReader, + download_state_update_tasks: TasksQueue<(BlockNumber, ReaderClientResult>)>, + // Contains NumberOfClasses so we don't need to calculate it from the StateUpdate. + downloaded_state_updates: VecDeque<(BlockNumber, NumberOfClasses, StateUpdate)>, + classes_to_download: VecDeque, + download_class_tasks: TasksQueue>>, + downloaded_classes: VecDeque, + class_cache: Arc>>, + config: StateUpdateStreamConfig, +} + +impl Stream + for StateUpdateStream +{ + type Item = CentralResult; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + loop { + // In case an existing task is done or a new task is initiated, mark that we should poll + // again. + let mut should_poll_again = false; + + // Advances scheduling logic. + if let Err(err) = self.do_scheduling(&mut should_poll_again, cx) { + return Poll::Ready(Some(Err(err))); + } + + // If available, returns the next block state update and corresponding classes. + if let Some(maybe_central_state_update) = self.next_output() { + return Poll::Ready(Some(maybe_central_state_update)); + } + + // In case no task is done and there are no newly initiated tasks, the stream is either + // exhausted or no new item is available. + if !should_poll_again { + break; + } + } + + // The stream is exhausted. + if self.download_class_tasks.is_empty() && self.download_state_update_tasks.is_empty() { + return Poll::Ready(None); + } + + Poll::Pending + } +} + +impl StateUpdateStream { + pub fn new( + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + starknet_client: Arc, + storage_reader: StorageReader, + config: StateUpdateStreamConfig, + class_cache: Arc>>, + ) -> Self { + StateUpdateStream { + initial_block_number, + up_to_block_number, + starknet_client, + storage_reader, + download_state_update_tasks: futures::stream::FuturesOrdered::new(), + downloaded_state_updates: VecDeque::with_capacity( + config.max_state_updates_to_store_in_memory, + ), + classes_to_download: VecDeque::with_capacity( + config.max_state_updates_to_store_in_memory * 5, + ), + download_class_tasks: futures::stream::FuturesOrdered::new(), + downloaded_classes: VecDeque::with_capacity( + config.max_state_updates_to_store_in_memory * 5, + ), + config, + class_cache, + } + } + + // Returns data needed for the next block CentralStateUpdate, or None if it is not yet ready. + fn next_output(&mut self) -> Option> { + let (_, n_classes, _) = self.downloaded_state_updates.front()?; + if self.downloaded_classes.len() < *n_classes { + return None; + } + let (block_number, n_classes, state_update) = + self.downloaded_state_updates.pop_front().expect("Should have a value"); + let class_hashes = state_update.state_diff.class_hashes(); + let classes = self.downloaded_classes.drain(..n_classes); + let classes: IndexMap = + class_hashes.into_iter().zip(classes).collect(); + Some(client_to_central_state_update(block_number, Ok((state_update, classes)))) + } + + // Advances scheduling logic. Propagates errors to be returned from the stream. + // - Schedules state update downloading tasks. + // - For each downloaded state update: stores the result and the corresponding classes needed to + // be downloaded. + // - Schedules class downloading tasks. + // - For each downloaded class: stores the result. + fn do_scheduling( + self: &mut std::pin::Pin<&mut Self>, + should_poll_again: &mut bool, + cx: &mut std::task::Context<'_>, + ) -> CentralResult<()> { + self.schedule_class_downloads(should_poll_again); + self.handle_downloaded_classes(cx, should_poll_again)?; + self.schedule_state_update_downloads(should_poll_again); + self.handle_downloaded_state_updates(cx, should_poll_again)?; + Ok(()) + } + + // Adds more class downloading tasks. + fn schedule_class_downloads(self: &mut std::pin::Pin<&mut Self>, should_poll_again: &mut bool) { + while self.download_class_tasks.len() < self.config.max_classes_to_download { + let Some(class_hash) = self.classes_to_download.pop_front() else { + break; + }; + let starknet_client = self.starknet_client.clone(); + let storage_reader = self.storage_reader.clone(); + let cache = self.class_cache.clone(); + self.download_class_tasks.push_back(Box::pin(download_class_if_necessary( + cache, + class_hash, + starknet_client, + storage_reader, + ))); + *should_poll_again = true; + } + } + + // Checks for finished class downloading tasks and adds the result to `downloaded_classes`. + fn handle_downloaded_classes( + self: &mut std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + should_poll_again: &mut bool, + ) -> CentralResult<()> { + let Poll::Ready(Some(maybe_class)) = self.download_class_tasks.poll_next_unpin(cx) else { + return Ok(()); + }; + + *should_poll_again = true; + match maybe_class { + // Add to downloaded classes. + Ok(Some(class)) => { + self.downloaded_classes.push_back(class); + Ok(()) + } + // Class was not found. + Ok(None) => Err(CentralError::ClassNotFound), + // An error occurred while downloading the class. + Err(err) => Err(err), + } + } + + // Adds more state update downloading tasks. + fn schedule_state_update_downloads( + self: &mut std::pin::Pin<&mut Self>, + should_poll_again: &mut bool, + ) { + while self.initial_block_number < self.up_to_block_number + && self.download_state_update_tasks.len() < self.config.max_state_updates_to_download + { + let current_block_number = self.initial_block_number; + let starknet_client = self.starknet_client.clone(); + *should_poll_again = true; + self.download_state_update_tasks.push_back(Box::pin(async move { + (current_block_number, starknet_client.state_update(current_block_number).await) + })); + self.initial_block_number = self.initial_block_number.unchecked_next(); + } + } + + // Checks for finished state update downloading tasks. + // Checks for finished class downloading tasks and adds the result to `downloaded_classes`. + fn handle_downloaded_state_updates( + self: &mut std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + should_poll_again: &mut bool, + ) -> CentralResult<()> { + if self.downloaded_state_updates.len() >= self.config.max_state_updates_to_store_in_memory { + return Ok(()); + } + + let Poll::Ready(Some((block_number, maybe_state_update))) = + self.download_state_update_tasks.poll_next_unpin(cx) + else { + return Ok(()); + }; + + *should_poll_again = true; + match maybe_state_update { + // Add to downloaded state updates. Adds the results to `downloaded_state_updates` and + // the corresponding classes needed to be downloaded to `classes_to_download`. + Ok(Some(state_update)) => { + let hashes = state_update.state_diff.class_hashes(); + let n_classes = hashes.len(); + self.classes_to_download.append(&mut VecDeque::from(hashes)); + self.downloaded_state_updates.push_back((block_number, n_classes, state_update)); + Ok(()) + } + // Class was not found. + Ok(None) => Err(CentralError::ClassNotFound), + // An error occurred while downloading the class. + Err(err) => Err(CentralError::ClientError(err.into())), + } + } +} + +fn client_to_central_state_update( + current_block_number: BlockNumber, + maybe_client_state_update: CentralResult<(StateUpdate, IndexMap)>, +) -> CentralResult { + match maybe_client_state_update { + Ok((state_update, mut declared_classes)) => { + // Destruct the state diff to avoid partial move. + let starknet_client::reader::StateDiff { + storage_diffs, + deployed_contracts, + declared_classes: declared_class_hashes, + old_declared_contracts: old_declared_contract_hashes, + nonces, + replaced_classes, + } = state_update.state_diff; + + // Separate the declared classes to new classes, old classes and classes of deployed + // contracts (both new and old). + let n_declared_classes = declared_class_hashes.len(); + let mut deprecated_classes = declared_classes.split_off(n_declared_classes); + let n_deprecated_declared_classes = old_declared_contract_hashes.len(); + let deployed_contract_class_definitions = + deprecated_classes.split_off(n_deprecated_declared_classes); + + let state_diff = StateDiff { + deployed_contracts: IndexMap::from_iter( + deployed_contracts.iter().map(|dc| (dc.address, dc.class_hash)), + ), + storage_diffs: IndexMap::from_iter(storage_diffs.into_iter().map( + |(address, entries)| { + (address, entries.into_iter().map(|se| (se.key, se.value)).collect()) + }, + )), + declared_classes: declared_classes + .into_iter() + .map(|(class_hash, class)| { + (class_hash, class.into_cairo1().expect("Expected Cairo1 class.")) + }) + .zip( + declared_class_hashes + .into_iter() + .map(|hash_entry| hash_entry.compiled_class_hash), + ) + .map(|((class_hash, class), compiled_class_hash)| { + (class_hash, (compiled_class_hash, class)) + }) + .collect(), + deprecated_declared_classes: deprecated_classes + .into_iter() + .map(|(class_hash, generic_class)| { + (class_hash, generic_class.into_cairo0().expect("Expected Cairo0 class.")) + }) + .collect(), + nonces, + replaced_classes: replaced_classes + .into_iter() + .map(|replaced_class| (replaced_class.address, replaced_class.class_hash)) + .collect(), + }; + // Filter out deployed contracts of new classes because since 0.11 new classes can not + // be implicitly declared by deployment. + let deployed_contract_class_definitions = deployed_contract_class_definitions + .into_iter() + .filter_map(|(class_hash, contract_class)| match contract_class { + ApiContractClass::DeprecatedContractClass(deprecated_contract_class) => { + Some((class_hash, deprecated_contract_class)) + } + ApiContractClass::ContractClass(_) => None, + }) + .collect(); + let block_hash = state_update.block_hash; + debug!( + "Received new state update of block {current_block_number} with hash {block_hash}." + ); + trace!( + "State diff: {state_diff:?}, deployed_contract_class_definitions: \ + {deployed_contract_class_definitions:?}." + ); + Ok((current_block_number, block_hash, state_diff, deployed_contract_class_definitions)) + } + Err(err) => { + debug!("Received error for state diff {}: {:?}.", current_block_number, err); + Err(err) + } + } +} + +// Given a class hash, returns the corresponding class definition. +// First tries to retrieve the class from the storage. +// If not found in the storage, the class is downloaded. +#[instrument(skip(starknet_client, storage_reader), level = "debug", err)] +async fn download_class_if_necessary( + cache: Arc>>, + class_hash: ClassHash, + starknet_client: Arc, + storage_reader: StorageReader, +) -> CentralResult> { + { + let mut cache = cache.lock().expect("Failed to lock class cache."); + if let Some(class) = cache.get(&class_hash) { + return Ok(Some(class.clone())); + } + } + + let txn = storage_reader.begin_ro_txn()?; + let state_reader = txn.get_state_reader()?; + let block_number = txn.get_state_marker()?; + let state_number = StateNumber::unchecked_right_after_block(block_number); + + // Check declared classes. + if let Ok(Some(class)) = state_reader.get_class_definition_at(state_number, &class_hash) { + trace!("Class {:?} retrieved from storage.", class_hash); + { + let mut cache = cache.lock().expect("Failed to lock class cache."); + cache.put(class_hash, ApiContractClass::ContractClass(class.clone())); + } + return Ok(Some(ApiContractClass::ContractClass(class))); + }; + + // Check deprecated classes. + if let Ok(Some(class)) = + state_reader.get_deprecated_class_definition_at(state_number, &class_hash) + { + trace!("Deprecated class {:?} retrieved from storage.", class_hash); + { + let mut cache = cache.lock().expect("Failed to lock class cache."); + cache.put(class_hash, ApiContractClass::DeprecatedContractClass(class.clone())); + } + return Ok(Some(ApiContractClass::DeprecatedContractClass(class))); + } + + // Class not found in storage - download. + trace!("Downloading class {:?}.", class_hash); + let client_class = starknet_client.class_by_hash(class_hash).await.map_err(Arc::new)?; + match client_class { + None => Ok(None), + Some(class) => { + { + let mut cache = cache.lock().expect("Failed to lock class cache."); + cache.put(class_hash, class.clone().into()); + } + Ok(Some(class.into())) + } + } +} diff --git a/crates/papyrus_sync/src/sources/central_sync_test.rs b/crates/papyrus_sync/src/sources/central_sync_test.rs new file mode 100644 index 00000000000..6826c557255 --- /dev/null +++ b/crates/papyrus_sync/src/sources/central_sync_test.rs @@ -0,0 +1,695 @@ +use std::sync::Arc; +use std::time::Duration; + +use assert_matches::assert_matches; +use async_stream::stream; +use async_trait::async_trait; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use futures::StreamExt; +use indexmap::IndexMap; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses}; +use papyrus_common::BlockHashAndNumber; +use papyrus_storage::base_layer::BaseLayerStorageReader; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::{StorageError, StorageReader, StorageWriter}; +use starknet_api::block::{Block, BlockBody, BlockHash, BlockHeader, BlockNumber, BlockSignature}; +use starknet_api::core::{ClassHash, SequencerPublicKey}; +use starknet_api::crypto::utils::PublicKey; +use starknet_api::felt; +use starknet_api::state::StateDiff; +use starknet_client::reader::PendingData; +use tokio::sync::{Mutex, RwLock}; +use tracing::{debug, error}; + +use super::pending::MockPendingSourceTrait; +use crate::sources::base_layer::{BaseLayerSourceTrait, MockBaseLayerSourceTrait}; +use crate::sources::central::{ + BlocksStream, + CompiledClassesStream, + MockCentralSourceTrait, + StateUpdatesStream, +}; +use crate::{ + CentralError, + CentralSourceTrait, + GenericStateSync, + StateSyncError, + StateSyncResult, + SyncConfig, +}; + +const SYNC_SLEEP_DURATION: Duration = Duration::from_millis(100); // 100ms +const BASE_LAYER_SLEEP_DURATION: Duration = Duration::from_millis(10); // 10ms +const DURATION_BEFORE_CHECKING_STORAGE: Duration = SYNC_SLEEP_DURATION.saturating_mul(2); // 200ms twice the sleep duration of the sync loop. +const MAX_CHECK_STORAGE_ITERATIONS: u8 = 3; +const STREAM_SIZE: u32 = 1000; + +// TODO(dvir): separate this file to flow tests and unit tests. +// TODO(dvir): consider adding a test for mismatch between the base layer and l2. + +enum CheckStoragePredicateResult { + InProgress, + Passed, + Error, +} + +// Checks periodically if the storage reached a certain state defined by f. +async fn check_storage( + reader: StorageReader, + timeout: Duration, + predicate: impl Fn(&StorageReader) -> CheckStoragePredicateResult, +) -> bool { + // Let the other thread opportunity to run before starting the check. + tokio::time::sleep(DURATION_BEFORE_CHECKING_STORAGE).await; + let interval_time = timeout.div_f32(MAX_CHECK_STORAGE_ITERATIONS.into()); + let mut interval = tokio::time::interval(interval_time); + for i in 0..MAX_CHECK_STORAGE_ITERATIONS { + debug!("== Checking predicate on storage ({}/{}). ==", i + 1, MAX_CHECK_STORAGE_ITERATIONS); + match predicate(&reader) { + CheckStoragePredicateResult::InProgress => { + debug!("== Check finished, test still in progress. =="); + interval.tick().await; + } + CheckStoragePredicateResult::Passed => { + debug!("== Check passed. =="); + return true; + } + CheckStoragePredicateResult::Error => { + debug!("== Check failed. =="); + return false; + } + } + } + error!("Check storage timed out."); + false +} + +fn get_test_sync_config(verify_blocks: bool) -> SyncConfig { + SyncConfig { + block_propagation_sleep_duration: SYNC_SLEEP_DURATION, + base_layer_propagation_sleep_duration: BASE_LAYER_SLEEP_DURATION, + recoverable_error_sleep_duration: SYNC_SLEEP_DURATION, + blocks_max_stream_size: STREAM_SIZE, + state_updates_max_stream_size: STREAM_SIZE, + verify_blocks, + } +} + +// Runs sync loop with a mocked central - infinite loop unless panicking. +async fn run_sync( + reader: StorageReader, + writer: StorageWriter, + central: impl CentralSourceTrait + Send + Sync + 'static, + base_layer: impl BaseLayerSourceTrait + Send + Sync, + config: SyncConfig, +) -> StateSyncResult { + // Mock to the pending source that always returns the default pending data. + let mut pending_source = MockPendingSourceTrait::new(); + pending_source.expect_get_pending_data().returning(|| Ok(PendingData::default())); + + let mut state_sync = GenericStateSync { + config, + shared_highest_block: Arc::new(RwLock::new(None)), + pending_data: Arc::new(RwLock::new(PendingData::default())), + central_source: Arc::new(central), + pending_source: Arc::new(pending_source), + pending_classes: Arc::new(RwLock::new(PendingClasses::default())), + base_layer_source: Arc::new(base_layer), + reader, + writer, + sequencer_pub_key: None, + }; + + state_sync.run().await?; + Ok(()) +} + +#[tokio::test] +async fn sync_empty_chain() { + let _ = simple_logger::init_with_env(); + + // Mock central without any block. + let mut central_mock = MockCentralSourceTrait::new(); + central_mock.expect_get_latest_block().returning(|| Ok(None)); + + // Mock base_layer without any block. + let mut base_layer_mock = MockBaseLayerSourceTrait::new(); + base_layer_mock.expect_latest_proved_block().returning(|| Ok(None)); + + let ((reader, writer), _temp_dir) = get_test_storage(); + let sync_future = run_sync( + reader.clone(), + writer, + central_mock, + base_layer_mock, + get_test_sync_config(false), + ); + + // Check that the header marker is 0. + let check_storage_future = check_storage(reader.clone(), Duration::from_millis(50), |reader| { + let marker = reader.begin_ro_txn().unwrap().get_header_marker().unwrap(); + if marker == BlockNumber(0) { + return CheckStoragePredicateResult::Passed; + } + CheckStoragePredicateResult::Error + }); + + tokio::select! { + sync_result = sync_future => sync_result.unwrap(), + storage_check_result = check_storage_future => assert!(storage_check_result), + } +} + +#[tokio::test] +async fn sync_happy_flow() { + const N_BLOCKS: u64 = 5; + const LATEST_BLOCK_NUMBER: BlockNumber = BlockNumber(N_BLOCKS - 1); + // FIXME: (Omri) analyze and set a lower value. + const MAX_TIME_TO_SYNC_MS: u64 = 800; + let _ = simple_logger::init_with_env(); + + // Mock having N_BLOCKS chain in central. + let mut central_mock = MockCentralSourceTrait::new(); + central_mock.expect_get_latest_block().returning(|| { + Ok(Some(BlockHashAndNumber { + block_number: LATEST_BLOCK_NUMBER, + block_hash: create_block_hash(LATEST_BLOCK_NUMBER, false), + })) + }); + central_mock.expect_stream_new_blocks().returning(move |initial, up_to| { + let blocks_stream: BlocksStream<'_> = stream! { + for block_number in initial.iter_up_to(up_to) { + if block_number.0 >= N_BLOCKS { + yield Err(CentralError::BlockNotFound { block_number }); + } + let header = BlockHeader { + block_number, + block_hash: create_block_hash(block_number, false), + parent_hash: create_block_hash(block_number.prev().unwrap_or_default(), false), + ..BlockHeader::default() + }; + yield Ok(( + block_number, + Block { header, body: BlockBody::default() }, + BlockSignature::default(), + )); + } + } + .boxed(); + blocks_stream + }); + central_mock.expect_stream_state_updates().returning(move |initial, up_to| { + let state_stream: StateUpdatesStream<'_> = stream! { + for block_number in initial.iter_up_to(up_to) { + if block_number.0 >= N_BLOCKS { + yield Err(CentralError::BlockNotFound { block_number }) + } + yield Ok(( + block_number, + create_block_hash(block_number, false), + StateDiff::default(), + IndexMap::new(), + )); + } + } + .boxed(); + state_stream + }); + central_mock.expect_get_block_hash().returning(|bn| Ok(Some(create_block_hash(bn, false)))); + + // TODO(dvir): find a better way to do this. + let mut base_layer_mock = MockBaseLayerSourceTrait::new(); + let mut base_layer_call_counter = 0; + base_layer_mock.expect_latest_proved_block().returning(move || { + base_layer_call_counter += 1; + Ok(match base_layer_call_counter { + 1 => None, + 2 => Some(( + BlockNumber(N_BLOCKS - 2), + create_block_hash(BlockNumber(N_BLOCKS - 2), false), + )), + _ => Some(( + BlockNumber(N_BLOCKS - 1), + create_block_hash(BlockNumber(N_BLOCKS - 1), false), + )), + }) + }); + + let ((reader, writer), _temp_dir) = get_test_storage(); + let sync_future = run_sync( + reader.clone(), + writer, + central_mock, + base_layer_mock, + get_test_sync_config(false), + ); + + // Check that the storage reached N_BLOCKS within MAX_TIME_TO_SYNC_MS. + let check_storage_future = + check_storage(reader, Duration::from_millis(MAX_TIME_TO_SYNC_MS), |reader| { + let header_marker = reader.begin_ro_txn().unwrap().get_header_marker().unwrap(); + debug!("Header marker currently at {}", header_marker); + if header_marker < BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::InProgress; + } + if header_marker > BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::Error; + } + + let state_marker = reader.begin_ro_txn().unwrap().get_state_marker().unwrap(); + debug!("State marker currently at {}", state_marker); + if state_marker < BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::InProgress; + } + if state_marker > BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::Error; + } + + let base_layer_marker = + reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + debug!("Base layer marker currently at {base_layer_marker}"); + if base_layer_marker < BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::InProgress; + } + if base_layer_marker > BlockNumber(N_BLOCKS) { + return CheckStoragePredicateResult::Error; + } + + CheckStoragePredicateResult::Passed + }); + + tokio::select! { + sync_result = sync_future => sync_result.unwrap(), + storage_check_result = check_storage_future => assert!(storage_check_result), + } +} + +#[tokio::test] +async fn sync_with_revert() { + let _ = simple_logger::init_with_env(); + let ((reader, writer), _temp_dir) = get_test_storage(); + + // Once the sync reaches N_BLOCKS_BEFORE_REVERT, the check_storage thread will set this flag to + // true to mark the central to simulate a revert, and for the check_storage to start checking + // for the new blocks after the revert. + let reverted_mutex = Arc::new(Mutex::new(false)); + + // Prepare sync thread with mocked central source that will perform a revert once the + // reverted_mutex is true. + let mock = MockedCentralWithRevert { reverted: reverted_mutex.clone() }; + let mut base_layer_mock = MockBaseLayerSourceTrait::new(); + base_layer_mock.expect_latest_proved_block().returning(|| Ok(None)); + let sync_future = + run_sync(reader.clone(), writer, mock, base_layer_mock, get_test_sync_config(false)); + + // Prepare functions that check that the sync worked up to N_BLOCKS_BEFORE_REVERT and then + // reacted correctly to the revert. + const N_BLOCKS_BEFORE_REVERT: u64 = 8; + const MAX_TIME_TO_SYNC_BEFORE_REVERT_MS: u64 = 100; + const CHAIN_FORK_BLOCK_NUMBER: u64 = 5; + const N_BLOCKS_AFTER_REVERT: u64 = 10; + // FIXME: (Omri) analyze and set a lower value. + const MAX_TIME_TO_SYNC_AFTER_REVERT_MS: u64 = 900; + + // Part 1 - check that the storage reached the point at which we will make the revert. + let check_storage_before_revert_future = check_storage( + reader.clone(), + Duration::from_millis(MAX_TIME_TO_SYNC_BEFORE_REVERT_MS), + |reader| { + let marker = reader.begin_ro_txn().unwrap().get_header_marker().unwrap(); + debug!("Before revert, block marker currently at {}", marker); + match marker { + BlockNumber(bn) if bn < N_BLOCKS_BEFORE_REVERT => { + CheckStoragePredicateResult::InProgress + } + BlockNumber(bn) if bn == N_BLOCKS_BEFORE_REVERT => { + CheckStoragePredicateResult::Passed + } + _ => CheckStoragePredicateResult::Error, + } + }, + ); + + // Part 2 - signal the mocked central to simulate a revert. + let signal_revert = async { + debug!("Reverting."); + let mut reverted = reverted_mutex.lock().await; + *reverted = true; + }; + + // Part 3 - check that the storage reverted correctly. + let check_storage_after_revert_future = check_storage( + reader.clone(), + Duration::from_millis(MAX_TIME_TO_SYNC_AFTER_REVERT_MS), + |reader| { + let block_marker = reader.begin_ro_txn().unwrap().get_header_marker().unwrap(); + let state_marker = reader.begin_ro_txn().unwrap().get_state_marker().unwrap(); + debug!( + "Block marker currently at {}, state marker currently at {}.", + block_marker, state_marker + ); + + // We can't check the storage data until the marker reaches N_BLOCKS_AFTER_REVERT + // because we can't know if the revert was already detected in the sync or not. + // Check both markers. + match (block_marker, state_marker) { + (BlockNumber(bm), BlockNumber(sm)) + if bm > N_BLOCKS_AFTER_REVERT || sm > N_BLOCKS_AFTER_REVERT => + { + CheckStoragePredicateResult::Error + } + + (BlockNumber(bm), BlockNumber(sm)) + if bm < N_BLOCKS_AFTER_REVERT || sm < N_BLOCKS_AFTER_REVERT => + { + CheckStoragePredicateResult::InProgress + } + (BlockNumber(bm), BlockNumber(sm)) + if bm == N_BLOCKS_AFTER_REVERT && sm == N_BLOCKS_AFTER_REVERT => + { + // Both blocks and state updates are fully synced, check the data validity. + for bn in BlockNumber(CHAIN_FORK_BLOCK_NUMBER) + .iter_up_to(BlockNumber(N_BLOCKS_AFTER_REVERT)) + { + debug!("checking hash for block {}", bn); + let block_header = + reader.begin_ro_txn().unwrap().get_block_header(bn).unwrap(); + + if block_header.is_none() { + error!("Block {} doesn't exist", bn); + return CheckStoragePredicateResult::Error; + } + let block_hash = block_header.unwrap().block_hash; + let expected_block_hash = create_block_hash(bn, true); + if block_hash != expected_block_hash { + error!( + "Wrong hash for block {}. Got {}, Expected {}.", + bn, block_hash, expected_block_hash + ); + return CheckStoragePredicateResult::Error; + } + + // TODO: add checks to the state diff. + } + + CheckStoragePredicateResult::Passed + } + _ => unreachable!("Should never happen."), + } + }, + ); + + // Assemble the pieces for the revert flow test. + let check_flow = async { + assert!(check_storage_before_revert_future.await); + signal_revert.await; + assert!(check_storage_after_revert_future.await); + }; + + tokio::select! { + sync_result = sync_future => sync_result.unwrap(), + _ = check_flow => {}, + } + + // Mock central source that performs a revert once the reverted mutex is set to true. + struct MockedCentralWithRevert { + reverted: Arc>, + } + impl MockedCentralWithRevert { + fn revert_happend(&self) -> bool { + match self.reverted.try_lock() { + Ok(reverted) => *reverted, + _ => false, + } + } + } + + #[async_trait] + impl CentralSourceTrait for MockedCentralWithRevert { + async fn get_latest_block(&self) -> Result, CentralError> { + let already_reverted = self.revert_happend(); + let block_number = match already_reverted { + false => BlockNumber(N_BLOCKS_BEFORE_REVERT), + true => BlockNumber(N_BLOCKS_AFTER_REVERT), + } + .prev() + .unwrap(); + Ok(Some(BlockHashAndNumber { + block_hash: create_block_hash(block_number, already_reverted), + block_number, + })) + } + + async fn get_block_hash( + &self, + block_number: BlockNumber, + ) -> Result, CentralError> { + match (self.revert_happend(), block_number) { + (false, BlockNumber(bn)) if bn >= N_BLOCKS_BEFORE_REVERT => Ok(None), + (false, BlockNumber(bn)) if bn < N_BLOCKS_BEFORE_REVERT => { + Ok(Some(create_block_hash(block_number, false))) + } + (true, BlockNumber(bn)) if bn >= N_BLOCKS_AFTER_REVERT => Ok(None), + (true, BlockNumber(bn)) if bn >= CHAIN_FORK_BLOCK_NUMBER => { + Ok(Some(create_block_hash(block_number, true))) + } + (true, BlockNumber(bn)) if bn < CHAIN_FORK_BLOCK_NUMBER => { + Ok(Some(create_block_hash(block_number, false))) + } + _ => unreachable!( + "get_block_hash when Revert happend: {}, bn: {}", + self.revert_happend(), + block_number + ), + } + } + + fn stream_new_blocks( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> BlocksStream<'_> { + match self.revert_happend() { + false => stream! { + for i in initial_block_number.iter_up_to(up_to_block_number) { + if i.0 >= N_BLOCKS_BEFORE_REVERT { + yield Err(CentralError::BlockNotFound { block_number: i }); + } + let header = BlockHeader{ + block_number: i, + block_hash: create_block_hash(i, false), + parent_hash: create_block_hash(i.prev().unwrap_or_default(), false), + ..BlockHeader::default() + }; + yield Ok(( + i, + Block{ header, body: BlockBody::default() }, + BlockSignature::default(), + )); + } + } + .boxed(), + true => stream! { + for i in initial_block_number.iter_up_to(up_to_block_number) { + if i.0 >= N_BLOCKS_AFTER_REVERT { + yield Err(CentralError::BlockNotFound { block_number: i }); + } + let header = BlockHeader { + block_number: i, + block_hash: create_block_hash(i, i.0 >= CHAIN_FORK_BLOCK_NUMBER), + parent_hash: create_block_hash(i.prev().unwrap_or_default(), i.0 > CHAIN_FORK_BLOCK_NUMBER), + ..BlockHeader::default() + }; + yield Ok(( + i, + Block{header, body: BlockBody::default()}, + BlockSignature::default(), + )); + } + } + .boxed() + } + } + + fn stream_state_updates( + &self, + initial_block_number: BlockNumber, + up_to_block_number: BlockNumber, + ) -> StateUpdatesStream<'_> { + match self.revert_happend() { + false => stream! { + for i in initial_block_number.iter_up_to(up_to_block_number) { + if i.0 >= N_BLOCKS_BEFORE_REVERT { + yield Err(CentralError::BlockNotFound { block_number: i }); + } + yield Ok((i, create_block_hash(i, false), StateDiff::default(), IndexMap::new())); + } + } + .boxed(), + true => stream! { + for i in initial_block_number.iter_up_to(up_to_block_number) { + if i.0 >= N_BLOCKS_AFTER_REVERT { + yield Err(CentralError::BlockNotFound { block_number: i }); + } + let is_reverted_state_diff = i.0 >= CHAIN_FORK_BLOCK_NUMBER; + yield Ok(( + i, + create_block_hash(i, is_reverted_state_diff), + StateDiff::default(), + IndexMap::new(), + )); + } + } + .boxed(), + } + } + + fn stream_compiled_classes( + &self, + _initial_block_number: BlockNumber, + _up_to_block_number: BlockNumber, + ) -> CompiledClassesStream<'_> { + // An empty stream. + let res: CompiledClassesStream<'_> = stream! { + for i in [] { + yield i; + } + } + .boxed(); + res + } + + async fn get_class( + &self, + _class_hash: ClassHash, + ) -> Result { + unimplemented!(); + } + + async fn get_compiled_class( + &self, + _class_hash: ClassHash, + ) -> Result { + unimplemented!(); + } + + async fn get_sequencer_pub_key(&self) -> Result { + unimplemented!() + } + } +} + +#[tokio::test] +async fn test_unrecoverable_sync_error_flow() { + let _ = simple_logger::init_with_env(); + + const LATEST_BLOCK_NUMBER: BlockNumber = BlockNumber(0); + const BLOCK_NUMBER: BlockNumber = BlockNumber(1); + const WRONG_BLOCK_NUMBER: BlockNumber = BlockNumber(2); + + // Mock central with one block but return wrong header. + let mut mock = MockCentralSourceTrait::new(); + mock.expect_get_latest_block().returning(|| { + Ok(Some(BlockHashAndNumber { + block_number: LATEST_BLOCK_NUMBER, + block_hash: create_block_hash(LATEST_BLOCK_NUMBER, false), + })) + }); + mock.expect_stream_new_blocks().returning(move |_, _| { + let blocks_stream: BlocksStream<'_> = stream! { + let header = BlockHeader { + block_number: BLOCK_NUMBER, + block_hash: create_block_hash(BLOCK_NUMBER, false), + parent_hash: create_block_hash(BLOCK_NUMBER.prev().unwrap_or_default(), false), + ..BlockHeader::default() + }; + yield Ok(( + BLOCK_NUMBER, + Block { header, body: BlockBody::default()}, + BlockSignature::default(), + )); + } + .boxed(); + blocks_stream + }); + mock.expect_stream_state_updates().returning(move |_, _| { + let state_stream: StateUpdatesStream<'_> = stream! { + yield Ok(( + BLOCK_NUMBER, + create_block_hash(BLOCK_NUMBER, false), + StateDiff::default(), + IndexMap::new(), + )); + } + .boxed(); + state_stream + }); + // make get_block_hash return a hash for the wrong block number + mock.expect_get_block_hash() + .returning(|_| Ok(Some(create_block_hash(WRONG_BLOCK_NUMBER, false)))); + + let ((reader, writer), _temp_dir) = get_test_storage(); + let sync_future = run_sync( + reader.clone(), + writer, + mock, + MockBaseLayerSourceTrait::new(), + get_test_sync_config(false), + ); + let sync_res = tokio::join! {sync_future}; + assert!(sync_res.0.is_err()); + // expect sync to raise the unrecoverable error it gets. In this case a DB Inconsistency error. + assert_matches!( + sync_res.0.unwrap_err(), + StateSyncError::StorageError(StorageError::DBInconsistency { msg: _ }) + ); +} + +#[tokio::test] +async fn sequencer_pub_key_management() { + let _ = simple_logger::init_with_env(); + + let first_sequencer_pub_key = SequencerPublicKey(PublicKey(felt!("0x111"))); + let second_sequencer_pub_key = SequencerPublicKey(PublicKey(felt!("0x222"))); + let first_copy = first_sequencer_pub_key; + + let mut central_mock = MockCentralSourceTrait::new(); + // Mock error in sync loop so the public key will be requested again over and over. + central_mock + .expect_get_latest_block() + .returning(|| Err(CentralError::BlockNotFound { block_number: BlockNumber(0) })); + + // Mock sequencer pub key change after the second request. + central_mock.expect_get_sequencer_pub_key().times(2).returning(move || Ok(first_copy)); + central_mock.expect_get_sequencer_pub_key().returning(move || Ok(second_sequencer_pub_key)); + + // Mock base_layer without any block. + let mut base_layer_mock = MockBaseLayerSourceTrait::new(); + base_layer_mock.expect_latest_proved_block().returning(|| Ok(None)); + + let ((reader, writer), _temp_dir) = get_test_storage(); + let config = get_test_sync_config(true); + let sync_future = run_sync(reader.clone(), writer, central_mock, base_layer_mock, config); + + let sync_result = + tokio::time::timeout(config.block_propagation_sleep_duration * 4, sync_future) + .await + .unwrap() + .expect_err("Expecting sync to fail due to sequencer pub key change."); + + assert_matches!( + sync_result, + StateSyncError::SequencerPubKeyChanged { old, new } + if old == first_copy && new == second_sequencer_pub_key + ); +} + +fn create_block_hash(bn: BlockNumber, is_reverted_block: bool) -> BlockHash { + if is_reverted_block { + BlockHash(felt!(format!("0x{}10", bn.0).as_str())) + } else { + BlockHash(felt!(format!("0x{}", bn.0).as_str())) + } +} diff --git a/crates/papyrus_sync/src/sources/central_test.rs b/crates/papyrus_sync/src/sources/central_test.rs new file mode 100644 index 00000000000..41b687ca758 --- /dev/null +++ b/crates/papyrus_sync/src/sources/central_test.rs @@ -0,0 +1,658 @@ +use std::num::NonZeroUsize; +use std::sync::{Arc, Mutex}; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use futures_util::pin_mut; +use indexmap::{indexmap, IndexMap}; +use lru::LruCache; +use mockall::predicate; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use pretty_assertions::assert_eq; +use reqwest::StatusCode; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + GlobalRoot, + Nonce, + PatriciaKey, + SequencerPublicKey, +}; +use starknet_api::crypto::utils::PublicKey; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass as sn_api_ContractClass, StorageKey, ThinStateDiff}; +use starknet_api::{felt, patricia_key}; +use starknet_client::reader::objects::block::BlockPostV0_13_1; +use starknet_client::reader::{ + Block, + BlockSignatureData, + ContractClass, + DeclaredClassHashEntry, + DeployedContract, + GenericContractClass, + MockStarknetReader, + ReaderClientError, + ReplacedClass, + StateUpdate, + StorageEntry, +}; +use starknet_client::ClientError; +use tokio_stream::StreamExt; + +use super::state_update_stream::StateUpdateStreamConfig; +use super::ApiContractClass; +use crate::sources::central::{CentralError, CentralSourceTrait, GenericCentralSource}; + +const TEST_CONCURRENT_REQUESTS: usize = 300; + +#[tokio::test] +async fn last_block_number() { + let mut mock = MockStarknetReader::new(); + + // We need to perform all the mocks before moving the mock into central_source. + const EXPECTED_LAST_BLOCK_NUMBER: BlockNumber = BlockNumber(0); + mock.expect_latest_block().times(1).returning(|| { + Ok(Some(Block::PostV0_13_1(BlockPostV0_13_1 { + block_number: EXPECTED_LAST_BLOCK_NUMBER, + ..Default::default() + }))) + }); + + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + starknet_client: Arc::new(mock), + concurrent_requests: TEST_CONCURRENT_REQUESTS, + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + let last_block_number = central_source.get_latest_block().await.unwrap().unwrap().block_number; + assert_eq!(last_block_number, EXPECTED_LAST_BLOCK_NUMBER); +} + +#[tokio::test] +async fn stream_block_headers() { + const START_BLOCK_NUMBER: u64 = 5; + const END_BLOCK_NUMBER: u64 = 9; + let mut mock = MockStarknetReader::new(); + + // We need to perform all the mocks before moving the mock into central_source. + for i in START_BLOCK_NUMBER..END_BLOCK_NUMBER { + mock.expect_block().with(predicate::eq(BlockNumber(i))).times(1).returning( + |_block_number| { + Ok(Some(Block::PostV0_13_1(BlockPostV0_13_1 { + state_diff_commitment: Some(Default::default()), + ..Default::default() + }))) + }, + ); + mock.expect_block_signature().with(predicate::eq(BlockNumber(i))).times(1).returning( + |_block_number| { + Ok(Some(BlockSignatureData::V0_13_2 { + block_hash: Default::default(), + signature: Default::default(), + })) + }, + ); + } + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + let mut expected_block_num = BlockNumber(START_BLOCK_NUMBER); + let stream = + central_source.stream_new_blocks(expected_block_num, BlockNumber(END_BLOCK_NUMBER)); + pin_mut!(stream); + while let Some(Ok((block_number, _block, _signature_data))) = stream.next().await { + assert_eq!(expected_block_num, block_number); + expected_block_num = expected_block_num.unchecked_next(); + } + assert_eq!(expected_block_num, BlockNumber(END_BLOCK_NUMBER)); +} + +#[tokio::test] +async fn stream_block_headers_some_are_missing() { + // TODO(yair): Find a way to use test_case with async. + let test_cases = [ + (true, true, "both missing"), + (true, false, "block missing"), + (false, true, "signature missing"), + ]; + for (block_missing, signature_missing, test_case_description) in test_cases { + println!("Test case: {}", test_case_description); + const START_BLOCK_NUMBER: u64 = 5; + const END_BLOCK_NUMBER: u64 = 13; + const MISSING_BLOCK_NUMBER: u64 = 9; + let mut mock = MockStarknetReader::new(); + + // We need to perform all the mocks before moving the mock into central_source. + for i in START_BLOCK_NUMBER..MISSING_BLOCK_NUMBER { + mock.expect_block() + .with(predicate::eq(BlockNumber(i))) + .times(1) + .returning(|_| Ok(Some(Block::default()))); + mock.expect_block_signature().with(predicate::eq(BlockNumber(i))).times(1).returning( + |block_number| { + Ok(Some(BlockSignatureData::Deprecated { + block_number, + signature: Default::default(), + signature_input: Default::default(), + })) + }, + ); + } + if block_missing { + mock.expect_block() + .with(predicate::eq(BlockNumber(MISSING_BLOCK_NUMBER))) + .times(1) + .returning(|_| Ok(None)); + } else { + mock.expect_block() + .with(predicate::eq(BlockNumber(MISSING_BLOCK_NUMBER))) + .times(1) + .returning(|_| Ok(Some(Block::default()))); + } + if signature_missing { + mock.expect_block_signature() + .with(predicate::eq(BlockNumber(MISSING_BLOCK_NUMBER))) + .times(1) + .returning(|_| Ok(None)); + } else { + mock.expect_block_signature() + .with(predicate::eq(BlockNumber(MISSING_BLOCK_NUMBER))) + .times(1) + .returning(|_| { + Ok(Some(BlockSignatureData::Deprecated { + block_number: BlockNumber(MISSING_BLOCK_NUMBER), + signature: Default::default(), + signature_input: Default::default(), + })) + }); + } + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + let mut expected_block_num = BlockNumber(START_BLOCK_NUMBER); + let stream = + central_source.stream_new_blocks(expected_block_num, BlockNumber(END_BLOCK_NUMBER)); + pin_mut!(stream); + while let Some(block_tuple) = stream.next().await { + if expected_block_num == BlockNumber(MISSING_BLOCK_NUMBER) { + assert_matches!( + block_tuple, + Err(CentralError::BlockNotFound { block_number }) + if block_number == expected_block_num + ); + } else { + let block_number = block_tuple.unwrap().0; + assert_eq!(expected_block_num, block_number); + } + expected_block_num = expected_block_num.unchecked_next(); + } + assert_eq!(expected_block_num, BlockNumber(MISSING_BLOCK_NUMBER + 1)); + } +} + +#[tokio::test] +async fn stream_block_headers_error() { + const START_BLOCK_NUMBER: u64 = 5; + const END_BLOCK_NUMBER: u64 = 13; + const ERROR_BLOCK_NUMBER: u64 = 9; + let mut mock = MockStarknetReader::new(); + const CODE: StatusCode = StatusCode::NOT_FOUND; + const MESSAGE: &str = "msg"; + + // We need to perform all the mocks before moving the mock into central_source. + for i in START_BLOCK_NUMBER..ERROR_BLOCK_NUMBER { + mock.expect_block() + .with(predicate::eq(BlockNumber(i))) + .times(1) + .returning(|_x| Ok(Some(Block::default()))); + mock.expect_block_signature().with(predicate::eq(BlockNumber(i))).times(1).returning( + |block_number| { + Ok(Some(BlockSignatureData::Deprecated { + block_number, + signature: Default::default(), + signature_input: Default::default(), + })) + }, + ); + } + mock.expect_block().with(predicate::eq(BlockNumber(ERROR_BLOCK_NUMBER))).times(1).returning( + |_block_number| { + Err(ReaderClientError::ClientError(ClientError::BadResponseStatus { + code: CODE, + message: String::from(MESSAGE), + })) + }, + ); + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + let mut expected_block_num = BlockNumber(START_BLOCK_NUMBER); + let stream = + central_source.stream_new_blocks(expected_block_num, BlockNumber(END_BLOCK_NUMBER)); + pin_mut!(stream); + while let Some(block_tuple) = stream.next().await { + if expected_block_num == BlockNumber(ERROR_BLOCK_NUMBER) { + assert_matches!( + block_tuple, + Err(CentralError::ClientError(err_ptr)) + if match &*err_ptr { + ReaderClientError::ClientError(ClientError::BadResponseStatus { code, message }) => + code == &CODE && message == MESSAGE, + _ => false, + } + ); + } else { + let block_number = block_tuple.unwrap().0; + assert_eq!(expected_block_num, block_number); + } + expected_block_num = expected_block_num.unchecked_next(); + } + assert_eq!(expected_block_num, BlockNumber(ERROR_BLOCK_NUMBER + 1)); +} + +#[tokio::test] +async fn stream_state_updates() { + const START_BLOCK_NUMBER: u64 = 5; + const END_BLOCK_NUMBER: u64 = 7; + + let class_hash1 = ClassHash(felt!("0x123")); + let class_hash2 = ClassHash(felt!("0x456")); + let class_hash3 = ClassHash(felt!("0x789")); + let class_hash4 = ClassHash(felt!("0x101112")); + let contract_address1 = ContractAddress(patricia_key!("0xabc")); + let contract_address2 = ContractAddress(patricia_key!("0xdef")); + let contract_address3 = ContractAddress(patricia_key!("0x0abc")); + let nonce1 = Nonce(felt!("0x123456789abcdef")); + let root1 = GlobalRoot(felt!("0x111")); + let root2 = GlobalRoot(felt!("0x222")); + let block_hash1 = BlockHash(felt!("0x333")); + let block_hash2 = BlockHash(felt!("0x444")); + let key = StorageKey(patricia_key!("0x555")); + let value = felt!("0x666"); + + // TODO(shahak): Fill these contract classes with non-empty data. + let deprecated_contract_class1 = DeprecatedContractClass::default(); + let deprecated_contract_class2 = DeprecatedContractClass::default(); + let deprecated_contract_class3 = DeprecatedContractClass::default(); + + let contract_class1 = ContractClass::default(); + let contract_class2 = ContractClass::default(); + let new_class_hash1 = ClassHash(felt!("0x111")); + let new_class_hash2 = ClassHash(felt!("0x222")); + let compiled_class_hash1 = CompiledClassHash(felt!("0x00111")); + let compiled_class_hash2 = CompiledClassHash(felt!("0x00222")); + let class_hash_entry1 = DeclaredClassHashEntry { + class_hash: new_class_hash1, + compiled_class_hash: compiled_class_hash1, + }; + let class_hash_entry2 = DeclaredClassHashEntry { + class_hash: new_class_hash2, + compiled_class_hash: compiled_class_hash2, + }; + + let client_state_diff1 = starknet_client::reader::StateDiff { + storage_diffs: IndexMap::from([(contract_address1, vec![StorageEntry { key, value }])]), + deployed_contracts: vec![ + DeployedContract { address: contract_address1, class_hash: class_hash2 }, + DeployedContract { address: contract_address2, class_hash: class_hash3 }, + ], + old_declared_contracts: vec![class_hash1, class_hash3], + declared_classes: vec![class_hash_entry1, class_hash_entry2], + nonces: IndexMap::from([(contract_address1, nonce1)]), + replaced_classes: vec![ReplacedClass { + address: contract_address3, + class_hash: class_hash4, + }], + }; + let client_state_diff2 = starknet_client::reader::StateDiff::default(); + + let block_state_update1 = StateUpdate { + block_hash: block_hash1, + new_root: root2, + old_root: root1, + state_diff: client_state_diff1, + }; + let block_state_update2 = StateUpdate { + block_hash: block_hash2, + new_root: root2, + old_root: root2, + state_diff: client_state_diff2, + }; + + let mut mock = MockStarknetReader::new(); + let block_state_update1_clone = block_state_update1.clone(); + mock.expect_state_update() + .with(predicate::eq(BlockNumber(START_BLOCK_NUMBER))) + .times(1) + .returning(move |_x| Ok(Some(block_state_update1_clone.clone()))); + let block_state_update2_clone = block_state_update2.clone(); + mock.expect_state_update() + .with(predicate::eq(BlockNumber(START_BLOCK_NUMBER + 1))) + .times(1) + .returning(move |_x| Ok(Some(block_state_update2_clone.clone()))); + let new_contract_class1_clone = contract_class1.clone(); + mock.expect_class_by_hash().with(predicate::eq(new_class_hash1)).times(1).returning( + move |_x| { + Ok(Some(GenericContractClass::Cairo1ContractClass(new_contract_class1_clone.clone()))) + }, + ); + let new_contract_class2_clone = contract_class2.clone(); + mock.expect_class_by_hash().with(predicate::eq(new_class_hash2)).times(1).returning( + move |_x| { + Ok(Some(GenericContractClass::Cairo1ContractClass(new_contract_class2_clone.clone()))) + }, + ); + let contract_class1_clone = deprecated_contract_class1.clone(); + mock.expect_class_by_hash().with(predicate::eq(class_hash1)).times(1).returning(move |_x| { + Ok(Some(GenericContractClass::Cairo0ContractClass(contract_class1_clone.clone()))) + }); + let contract_class2_clone = deprecated_contract_class2.clone(); + mock.expect_class_by_hash().with(predicate::eq(class_hash2)).times(1).returning(move |_x| { + Ok(Some(GenericContractClass::Cairo0ContractClass(contract_class2_clone.clone()))) + }); + let contract_class3_clone = deprecated_contract_class3.clone(); + mock.expect_class_by_hash().with(predicate::eq(class_hash3)).times(1).returning(move |_x| { + Ok(Some(GenericContractClass::Cairo0ContractClass(contract_class3_clone.clone()))) + }); + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + // TODO(shahak): Check that downloaded classes appear in the cache. + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + let initial_block_num = BlockNumber(START_BLOCK_NUMBER); + + let stream = + central_source.stream_state_updates(initial_block_num, BlockNumber(END_BLOCK_NUMBER)); + pin_mut!(stream); + + let Some(Ok(state_diff_tuple)) = stream.next().await else { + panic!("Match of streamed state_update failed!"); + }; + let (current_block_num, current_block_hash, state_diff, deployed_contract_class_definitions) = + state_diff_tuple; + + assert_eq!(initial_block_num, current_block_num); + assert_eq!(block_hash1, current_block_hash); + assert_eq!( + IndexMap::from([(class_hash2, deprecated_contract_class2)]), + deployed_contract_class_definitions, + ); + + assert_eq!( + IndexMap::from([(contract_address1, class_hash2), (contract_address2, class_hash3)]), + state_diff.deployed_contracts + ); + assert_eq!( + IndexMap::from([(contract_address1, IndexMap::from([(key, value)]))]), + state_diff.storage_diffs + ); + assert_eq!( + IndexMap::from([ + (class_hash1, deprecated_contract_class1), + (class_hash3, deprecated_contract_class3), + ]), + state_diff.deprecated_declared_classes, + ); + assert_eq!( + IndexMap::from([ + ( + new_class_hash1, + (compiled_class_hash1, starknet_api::state::ContractClass::from(contract_class1)) + ), + ( + new_class_hash2, + (compiled_class_hash2, starknet_api::state::ContractClass::from(contract_class2)) + ), + ]), + state_diff.declared_classes, + ); + assert_eq!(IndexMap::from([(contract_address1, nonce1)]), state_diff.nonces); + assert_eq!(IndexMap::from([(contract_address3, class_hash4)]), state_diff.replaced_classes); + + let Some(Ok(state_diff_tuple)) = stream.next().await else { + panic!("Match of streamed state_update failed!"); + }; + let (current_block_num, current_block_hash, state_diff, _deployed_classes) = state_diff_tuple; + + assert_eq!(initial_block_num.unchecked_next(), current_block_num); + assert_eq!(block_hash2, current_block_hash); + assert_eq!(state_diff, starknet_api::state::StateDiff::default()); + + assert!(stream.next().await.is_none()); +} + +#[tokio::test] +async fn stream_compiled_classes() { + let ((reader, mut writer), _temp_dir) = get_test_storage(); + writer + .begin_rw_txn() + .unwrap() + .append_state_diff( + BlockNumber(0), + ThinStateDiff { + deployed_contracts: indexmap! {}, + storage_diffs: indexmap! {}, + declared_classes: indexmap! { + ClassHash(felt!("0x0")) => CompiledClassHash(felt!("0x0")), + ClassHash(felt!("0x1")) => CompiledClassHash(felt!("0x1")), + }, + deprecated_declared_classes: vec![], + nonces: indexmap! {}, + replaced_classes: indexmap! {}, + }, + ) + .unwrap() + .append_state_diff( + BlockNumber(1), + ThinStateDiff { + deployed_contracts: indexmap! {}, + storage_diffs: indexmap! {}, + declared_classes: indexmap! { + ClassHash(felt!("0x2")) => CompiledClassHash(felt!("0x2")), + ClassHash(felt!("0x3")) => CompiledClassHash(felt!("0x3")), + }, + deprecated_declared_classes: vec![], + nonces: indexmap! {}, + replaced_classes: indexmap! {}, + }, + ) + .unwrap() + .append_classes( + BlockNumber(0), + &[ + (ClassHash(felt!("0x0")), &sn_api_ContractClass::default()), + (ClassHash(felt!("0x1")), &sn_api_ContractClass::default()), + ], + &[], + ) + .unwrap() + .append_classes( + BlockNumber(1), + &[ + (ClassHash(felt!("0x2")), &sn_api_ContractClass::default()), + (ClassHash(felt!("0x3")), &sn_api_ContractClass::default()), + ], + &[], + ) + .unwrap() + .commit() + .unwrap(); + + let felts: Vec<_> = (0..4).map(|i| felt!(format!("0x{i}").as_str())).collect(); + let mut mock = MockStarknetReader::new(); + for felt in felts.clone() { + mock.expect_compiled_class_by_hash() + .with(predicate::eq(ClassHash(felt))) + .times(1) + .returning(move |_x| Ok(Some(CasmContractClass::default()))); + } + + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + let stream = central_source.stream_compiled_classes(BlockNumber(0), BlockNumber(2)); + pin_mut!(stream); + + let expected_compiled_class = CasmContractClass::default(); + for felt in felts { + let (class_hash, compiled_class_hash, compiled_class) = + stream.next().await.unwrap().unwrap(); + let expected_class_hash = ClassHash(felt); + let expected_compiled_class_hash = CompiledClassHash(felt); + assert_eq!(class_hash, expected_class_hash); + assert_eq!(compiled_class_hash, expected_compiled_class_hash); + assert_eq!(compiled_class, expected_compiled_class); + } +} + +#[tokio::test] +async fn get_class() { + let mut mock = MockStarknetReader::new(); + + let deprecated_class_hash = ClassHash(StarkHash::ONE); + let deprecated_contract_class = + GenericContractClass::Cairo0ContractClass(DeprecatedContractClass::default()); + let deprecated_contract_class_clone = deprecated_contract_class.clone(); + mock.expect_class_by_hash() + .with(predicate::eq(deprecated_class_hash)) + .times(1) + .return_once(move |_x| Ok(Some(deprecated_contract_class_clone))); + + let class_hash = ClassHash(StarkHash::TWO); + let contract_class = GenericContractClass::Cairo1ContractClass(ContractClass::default()); + let contract_class_clone = contract_class.clone(); + mock.expect_class_by_hash() + .with(predicate::eq(class_hash)) + .times(1) + .return_once(move |_x| Ok(Some(contract_class_clone))); + + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + assert_eq!( + central_source.get_class(deprecated_class_hash).await.unwrap(), + deprecated_contract_class.clone().into() + ); + assert_eq!(central_source.get_class(class_hash).await.unwrap(), contract_class.clone().into()); + + // Repeating the calls to see that source doesn't call the client and gets the result from + // cache. + assert_eq!( + central_source.get_class(deprecated_class_hash).await.unwrap(), + deprecated_contract_class.into() + ); + assert_eq!(central_source.get_class(class_hash).await.unwrap(), contract_class.into()); +} + +#[tokio::test] +async fn get_compiled_class() { + let mut mock = MockStarknetReader::new(); + + let class_hash = ClassHash(StarkHash::ONE); + let compiled_class = CasmContractClass::default(); + let compiled_class_clone = compiled_class.clone(); + mock.expect_compiled_class_by_hash() + .with(predicate::eq(class_hash)) + .times(1) + .return_once(move |_x| Ok(Some(compiled_class_clone))); + + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + assert_eq!(central_source.get_compiled_class(class_hash).await.unwrap(), compiled_class); + + // Repeating the call to see that source doesn't call the client and gets the result from + // cache. + assert_eq!(central_source.get_compiled_class(class_hash).await.unwrap(), compiled_class); +} + +#[tokio::test] +async fn get_sequencer_pub_key() { + let mut mock = MockStarknetReader::new(); + + let sequencer_pub_key = SequencerPublicKey(PublicKey(felt!("0x123"))); + mock.expect_sequencer_pub_key().times(1).return_once(move || Ok(sequencer_pub_key)); + + let ((reader, _), _temp_dir) = get_test_storage(); + let central_source = GenericCentralSource { + concurrent_requests: TEST_CONCURRENT_REQUESTS, + starknet_client: Arc::new(mock), + storage_reader: reader, + state_update_stream_config: state_update_stream_config_for_test(), + class_cache: get_test_class_cache(), + compiled_class_cache: get_test_compiled_class_cache(), + }; + + assert_eq!(central_source.get_sequencer_pub_key().await.unwrap(), sequencer_pub_key); +} + +fn state_update_stream_config_for_test() -> StateUpdateStreamConfig { + StateUpdateStreamConfig { + max_state_updates_to_download: 10, + max_state_updates_to_store_in_memory: 10, + max_classes_to_download: 10, + } +} + +fn get_test_class_cache() -> Arc>> { + Arc::from(Mutex::new(LruCache::new(NonZeroUsize::new(2).unwrap()))) +} + +fn get_test_compiled_class_cache() -> Arc>> { + Arc::from(Mutex::new(LruCache::new(NonZeroUsize::new(2).unwrap()))) +} diff --git a/crates/papyrus_sync/src/sources/mod.rs b/crates/papyrus_sync/src/sources/mod.rs new file mode 100644 index 00000000000..fe37526dcf0 --- /dev/null +++ b/crates/papyrus_sync/src/sources/mod.rs @@ -0,0 +1,5 @@ +pub mod base_layer; +pub mod central; +#[cfg(test)] +mod central_sync_test; +pub mod pending; diff --git a/crates/papyrus_sync/src/sources/pending.rs b/crates/papyrus_sync/src/sources/pending.rs new file mode 100644 index 00000000000..6ab434fbcf9 --- /dev/null +++ b/crates/papyrus_sync/src/sources/pending.rs @@ -0,0 +1,69 @@ +#[cfg(test)] +#[path = "pending_test.rs"] +mod pending_test; + +use std::sync::Arc; + +use async_trait::async_trait; +#[cfg(test)] +use mockall::automock; +use starknet_client::reader::{ + PendingData, + ReaderClientError, + StarknetFeederGatewayClient, + StarknetReader, +}; +use starknet_client::ClientCreationError; + +// TODO(dvir): add pending config. +use super::central::CentralSourceConfig; + +pub struct GenericPendingSource { + pub starknet_client: Arc, +} + +#[derive(thiserror::Error, Debug)] +pub enum PendingError { + #[error(transparent)] + ClientCreation(#[from] ClientCreationError), + #[error(transparent)] + ClientError(#[from] Arc), + #[error("Pending block not found")] + PendingBlockNotFound, +} +#[cfg_attr(test, automock)] +#[async_trait] +pub trait PendingSourceTrait { + async fn get_pending_data(&self) -> Result; +} + +#[async_trait] +impl PendingSourceTrait + for GenericPendingSource +{ + async fn get_pending_data(&self) -> Result { + match self.starknet_client.pending_data().await { + Ok(Some(pending_data)) => Ok(pending_data), + Ok(None) => Err(PendingError::PendingBlockNotFound), + Err(err) => Err(PendingError::ClientError(Arc::new(err))), + } + } +} + +pub type PendingSource = GenericPendingSource; + +impl PendingSource { + pub fn new( + config: CentralSourceConfig, + node_version: &'static str, + ) -> Result { + let starknet_client = StarknetFeederGatewayClient::new( + &config.url, + config.http_headers, + node_version, + config.retry_config, + )?; + + Ok(PendingSource { starknet_client: Arc::new(starknet_client) }) + } +} diff --git a/crates/papyrus_sync/src/sources/pending_test.rs b/crates/papyrus_sync/src/sources/pending_test.rs new file mode 100644 index 00000000000..68e0140397a --- /dev/null +++ b/crates/papyrus_sync/src/sources/pending_test.rs @@ -0,0 +1,20 @@ +use std::sync::Arc; + +use pretty_assertions::assert_eq; +use starknet_client::reader::{MockStarknetReader, PendingData}; + +use crate::sources::pending::{GenericPendingSource, PendingSourceTrait}; + +#[tokio::test] +async fn get_pending_data() { + let mut client_mock = MockStarknetReader::new(); + + // We need to perform all the mocks before moving the mock into pending_source. + // TODO(dvir): use pending_data which isn't the default. + client_mock.expect_pending_data().times(1).returning(|| Ok(Some(PendingData::default()))); + + let pending_source = GenericPendingSource { starknet_client: Arc::new(client_mock) }; + + let pending_data = pending_source.get_pending_data().await.unwrap(); + assert_eq!(pending_data, PendingData::default()); +} diff --git a/crates/papyrus_sync/src/sync_test.rs b/crates/papyrus_sync/src/sync_test.rs new file mode 100644 index 00000000000..6b3191f75ab --- /dev/null +++ b/crates/papyrus_sync/src/sync_test.rs @@ -0,0 +1,772 @@ +use std::sync::Arc; +use std::time::Duration; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use futures_util::StreamExt; +use indexmap::IndexMap; +use papyrus_common::pending_classes::{ApiContractClass, PendingClasses, PendingClassesTrait}; +use papyrus_storage::base_layer::BaseLayerStorageReader; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use papyrus_storage::{StorageReader, StorageWriter}; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockHash, BlockHeader, BlockNumber}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::hash::StarkHash; +use starknet_api::state::{ContractClass, StateDiff, StorageKey}; +use starknet_api::{felt, patricia_key}; +use starknet_client::reader::objects::pending_data::{ + AcceptedOnL2ExtraData, + DeprecatedPendingBlock, + PendingBlockOrDeprecated, + PendingStateUpdate, +}; +use starknet_client::reader::objects::state::StateDiff as ClientStateDiff; +use starknet_client::reader::objects::transaction::Transaction as ClientTransaction; +use starknet_client::reader::{DeclaredClassHashEntry, PendingData}; +use test_utils::{get_rng, GetTestInstance}; +use tokio::sync::RwLock; + +use crate::sources::base_layer::MockBaseLayerSourceTrait; +use crate::sources::central::MockCentralSourceTrait; +use crate::sources::pending::MockPendingSourceTrait; +use crate::{ + sort_state_diff, + stream_new_base_layer_block, + sync_pending_data, + GenericStateSync, + StateSyncError, + SyncConfig, + SyncEvent, + GENESIS_HASH, +}; + +// TODO(anatg): Add a test to check that the sync calls the sort_state_diff function +// before writing to the storage. +#[test] +fn state_sorted() { + let hash0 = felt!("0x0"); + let patricia_key0 = patricia_key!("0x0"); + let hash1 = felt!("0x1"); + let patricia_key1 = patricia_key!("0x1"); + + let dep_contract_0 = (ContractAddress(patricia_key0), ClassHash(hash0)); + let dep_contract_1 = (ContractAddress(patricia_key1), ClassHash(hash1)); + let storage_key_0 = StorageKey(patricia_key!("0x0")); + let storage_key_1 = StorageKey(patricia_key!("0x1")); + let declare_class_0 = + (ClassHash(hash0), (CompiledClassHash::default(), ContractClass::default())); + let declare_class_1 = + (ClassHash(hash1), (CompiledClassHash::default(), ContractClass::default())); + let deprecated_declared_0 = (ClassHash(hash0), DeprecatedContractClass::default()); + let deprecated_declared_1 = (ClassHash(hash1), DeprecatedContractClass::default()); + let nonce_0 = (ContractAddress(patricia_key0), Nonce(hash0)); + let nonce_1 = (ContractAddress(patricia_key1), Nonce(hash1)); + let replaced_class_0 = (ContractAddress(patricia_key0), ClassHash(hash0)); + let replaced_class_1 = (ContractAddress(patricia_key1), ClassHash(hash1)); + + let unsorted_deployed_contracts = IndexMap::from([dep_contract_1, dep_contract_0]); + let unsorted_declared_classes = + IndexMap::from([declare_class_1.clone(), declare_class_0.clone()]); + let unsorted_deprecated_declared = + IndexMap::from([deprecated_declared_1.clone(), deprecated_declared_0.clone()]); + let unsorted_nonces = IndexMap::from([nonce_1, nonce_0]); + let unsorted_storage_entries = IndexMap::from([(storage_key_1, hash1), (storage_key_0, hash0)]); + let unsorted_storage_diffs = IndexMap::from([ + (ContractAddress(patricia_key1), unsorted_storage_entries.clone()), + (ContractAddress(patricia_key0), unsorted_storage_entries), + ]); + let unsorted_replaced_classes = IndexMap::from([replaced_class_1, replaced_class_0]); + + let mut state_diff = StateDiff { + deployed_contracts: unsorted_deployed_contracts, + storage_diffs: unsorted_storage_diffs, + deprecated_declared_classes: unsorted_deprecated_declared, + declared_classes: unsorted_declared_classes, + nonces: unsorted_nonces, + replaced_classes: unsorted_replaced_classes, + }; + + let sorted_deployed_contracts = IndexMap::from([dep_contract_0, dep_contract_1]); + let sorted_declared_classes = IndexMap::from([declare_class_0, declare_class_1]); + let sorted_deprecated_declared = IndexMap::from([deprecated_declared_0, deprecated_declared_1]); + let sorted_nonces = IndexMap::from([nonce_0, nonce_1]); + let sorted_storage_entries = IndexMap::from([(storage_key_0, hash0), (storage_key_1, hash1)]); + let sorted_storage_diffs = IndexMap::from([ + (ContractAddress(patricia_key0), sorted_storage_entries.clone()), + (ContractAddress(patricia_key1), sorted_storage_entries.clone()), + ]); + let sorted_replaced_classes = IndexMap::from([replaced_class_0, replaced_class_1]); + + sort_state_diff(&mut state_diff); + assert_eq!( + state_diff.deployed_contracts.get_index(0).unwrap(), + sorted_deployed_contracts.get_index(0).unwrap(), + ); + assert_eq!( + state_diff.declared_classes.get_index(0).unwrap(), + sorted_declared_classes.get_index(0).unwrap(), + ); + assert_eq!( + state_diff.deprecated_declared_classes.get_index(0).unwrap(), + sorted_deprecated_declared.get_index(0).unwrap(), + ); + assert_eq!( + state_diff.storage_diffs.get_index(0).unwrap(), + sorted_storage_diffs.get_index(0).unwrap(), + ); + assert_eq!( + state_diff.storage_diffs.get_index(0).unwrap().1.get_index(0).unwrap(), + sorted_storage_entries.get_index(0).unwrap(), + ); + assert_eq!(state_diff.nonces.get_index(0).unwrap(), sorted_nonces.get_index(0).unwrap()); + assert_eq!( + state_diff.replaced_classes.get_index(0).unwrap(), + sorted_replaced_classes.get_index(0).unwrap(), + ); +} + +#[tokio::test] +async fn stream_new_base_layer_block_test_header_marker() { + let (reader, mut writer) = get_test_storage().0; + + // Header marker points to to block number 5. + add_headers(5, &mut writer); + + // TODO(dvir): find a better way to do it. + // Base layer after the header marker, skip 5 and 10 and return only 1 and 4. + let block_numbers = vec![5, 1, 10, 4]; + let mut iter = block_numbers.into_iter().map(|bn| (BlockNumber(bn), BlockHash::default())); + let mut mock = MockBaseLayerSourceTrait::new(); + mock.expect_latest_proved_block().times(4).returning(move || Ok(iter.next())); + let mut stream = + stream_new_base_layer_block(reader, Arc::new(mock), Duration::from_millis(0)).boxed(); + + let event = stream.next().await.unwrap().unwrap(); + assert_matches!(event, SyncEvent::NewBaseLayerBlock { block_number: BlockNumber(1), .. }); + + let event = stream.next().await.unwrap().unwrap(); + assert_matches!(event, SyncEvent::NewBaseLayerBlock { block_number: BlockNumber(4), .. }); +} + +#[tokio::test] +async fn stream_new_base_layer_block_no_blocks_on_base_layer() { + let (reader, mut writer) = get_test_storage().0; + + // Header marker points to to block number 5. + add_headers(5, &mut writer); + + // In the first polling of the base layer no blocks were found, in the second polling a block + // was found. + let mut values = vec![None, Some((BlockNumber(1), BlockHash::default()))].into_iter(); + let mut mock = MockBaseLayerSourceTrait::new(); + mock.expect_latest_proved_block().times(2).returning(move || Ok(values.next().unwrap())); + + let mut stream = + stream_new_base_layer_block(reader, Arc::new(mock), Duration::from_millis(0)).boxed(); + + let event = stream.next().await.unwrap().unwrap(); + assert_matches!(event, SyncEvent::NewBaseLayerBlock { block_number: BlockNumber(1), .. }); +} + +#[test] +fn store_base_layer_block_test() { + let (reader, mut writer) = get_test_storage().0; + + let header_hash = BlockHash(felt!("0x0")); + let header = BlockHeader { + block_number: BlockNumber(0), + block_hash: header_hash, + ..BlockHeader::default() + }; + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(0), &header) + .unwrap() + .commit() + .unwrap(); + + let mut gen_state_sync = GenericStateSync { + config: SyncConfig::default(), + shared_highest_block: Arc::new(RwLock::new(None)), + pending_data: Arc::new(RwLock::new(PendingData::default())), + central_source: Arc::new(MockCentralSourceTrait::new()), + pending_source: Arc::new(MockPendingSourceTrait::new()), + pending_classes: Arc::new(RwLock::new(PendingClasses::default())), + base_layer_source: Arc::new(MockBaseLayerSourceTrait::new()), + reader, + writer, + sequencer_pub_key: None, + }; + + // Trying to store a block without a header in the storage. + let res = gen_state_sync.store_base_layer_block(BlockNumber(1), BlockHash::default()); + assert_matches!(res, Err(StateSyncError::BaseLayerBlockWithoutMatchingHeader { .. })); + + // Trying to store a block with mismatching header. + let res = gen_state_sync.store_base_layer_block(BlockNumber(0), BlockHash(felt!("0x666"))); + assert_matches!(res, Err(StateSyncError::BaseLayerHashMismatch { .. })); + + // Happy flow. + let res = gen_state_sync.store_base_layer_block(BlockNumber(0), header_hash); + assert!(res.is_ok()); + let base_layer_marker = + gen_state_sync.reader.begin_ro_txn().unwrap().get_base_layer_block_marker().unwrap(); + assert_eq!(base_layer_marker, BlockNumber(1)); +} + +// Adds to the storage 'headers_num' headers. +fn add_headers(headers_num: u64, writer: &mut StorageWriter) { + for i in 0..headers_num { + let header = BlockHeader { + block_number: BlockNumber(i), + block_hash: BlockHash(i.into()), + ..BlockHeader::default() + }; + writer + .begin_rw_txn() + .unwrap() + .append_header(BlockNumber(i), &header) + .unwrap() + .commit() + .unwrap(); + } +} + +#[allow(clippy::too_many_arguments)] +async fn test_pending_sync( + reader: StorageReader, + old_pending_data: PendingData, + new_pending_datas: Vec, + expected_pending_data: PendingData, + old_pending_classes_data: Option, + // Verifies that the classes will be requested in the given order. + new_pending_classes: Vec<(ClassHash, ApiContractClass)>, + new_pending_compiled_classes: Vec<(ClassHash, CasmContractClass)>, + expected_pending_classes: Option, +) { + let mut mock_pending_source = MockPendingSourceTrait::new(); + let mut mock_central_source = MockCentralSourceTrait::new(); + let pending_data_lock = Arc::new(RwLock::new(old_pending_data)); + let pending_classes_lock = Arc::new(RwLock::new(old_pending_classes_data.unwrap_or_default())); + + for new_pending_data in new_pending_datas { + mock_pending_source + .expect_get_pending_data() + .times(1) + .return_once(move || Ok(new_pending_data)); + } + + for (expected_class_hash, new_pending_class) in new_pending_classes { + mock_central_source.expect_get_class().times(1).return_once(move |class_hash| { + assert_eq!(class_hash, expected_class_hash); + Ok(new_pending_class) + }); + } + for (expected_class_hash, new_pending_compiled_class) in new_pending_compiled_classes { + mock_central_source.expect_get_compiled_class().times(1).return_once(move |class_hash| { + assert_eq!(class_hash, expected_class_hash); + Ok(new_pending_compiled_class) + }); + } + + sync_pending_data( + reader, + Arc::new(mock_central_source), + Arc::new(mock_pending_source), + pending_data_lock.clone(), + pending_classes_lock.clone(), + Duration::ZERO, + ) + .await + .unwrap(); + + assert_eq!(pending_data_lock.read().await.clone(), expected_pending_data); + if let Some(expected_pending_classes) = expected_pending_classes { + assert_eq!(pending_classes_lock.read().await.clone(), expected_pending_classes); + } +} + +#[tokio::test] +async fn pending_sync_advances_only_when_new_data_has_more_transactions() { + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with no block headers. + let (reader, _) = get_test_storage().0; + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }; + let advanced_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ], + ..Default::default() + }), + ..Default::default() + }; + let less_advanced_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ], + ..Default::default() + }), + ..Default::default() + }; + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::ONE), + ..Default::default() + }), + ..Default::default() + }; + + let new_pending_datas = + vec![advanced_pending_data.clone(), less_advanced_pending_data, new_block_pending_data]; + let expected_pending_data = advanced_pending_data; + let old_pending_classes_data = None; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = None; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + old_pending_classes_data, + new_pending_classes, + new_pending_compiled_classes, + expected_pending_classes, + ) + .await +} + +#[tokio::test] +async fn pending_sync_new_data_has_more_advanced_hash_and_less_transactions() { + const FIRST_BLOCK_HASH: BlockHash = BlockHash(StarkHash::ONE); + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with one block header. + let (reader, mut writer) = get_test_storage().0; + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + block_hash: FIRST_BLOCK_HASH, + parent_hash: genesis_hash, + block_number: BlockNumber(0), + ..Default::default() + }, + ) + .unwrap() + .commit() + .unwrap(); + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ], + ..Default::default() + }), + ..Default::default() + }; + let new_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: FIRST_BLOCK_HASH, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }; + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::TWO), + ..Default::default() + }), + ..Default::default() + }; + + let new_pending_datas = vec![new_pending_data.clone(), new_block_pending_data]; + let expected_pending_data = new_pending_data; + let old_pending_classes_data = None; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = None; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + old_pending_classes_data, + new_pending_classes, + new_pending_compiled_classes, + expected_pending_classes, + ) + .await +} + +#[tokio::test] +async fn pending_sync_stops_when_data_has_block_hash_field_with_a_different_hash() { + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with no block headers. + let (reader, _) = get_test_storage().0; + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }; + let new_pending_datas = vec![PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + accepted_on_l2_extra_data: Some(AcceptedOnL2ExtraData { + block_hash: BlockHash(StarkHash::ONE), + ..Default::default() + }), + parent_block_hash: genesis_hash, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }]; + let expected_pending_data = old_pending_data.clone(); + let old_pending_classes_data = None; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = None; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + old_pending_classes_data, + new_pending_classes, + new_pending_compiled_classes, + expected_pending_classes, + ) + .await +} + +#[tokio::test] +async fn pending_sync_doesnt_stop_when_data_has_block_hash_field_with_the_same_hash() { + const FIRST_BLOCK_HASH: BlockHash = BlockHash(StarkHash::ONE); + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with one block header. + let (reader, mut writer) = get_test_storage().0; + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + block_hash: FIRST_BLOCK_HASH, + parent_hash: genesis_hash, + block_number: BlockNumber(0), + ..Default::default() + }, + ) + .unwrap() + .commit() + .unwrap(); + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: FIRST_BLOCK_HASH, + transactions: vec![ + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ], + ..Default::default() + }), + ..Default::default() + }; + let new_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + accepted_on_l2_extra_data: Some(AcceptedOnL2ExtraData { + block_hash: FIRST_BLOCK_HASH, + ..Default::default() + }), + parent_block_hash: genesis_hash, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }; + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::TWO), + ..Default::default() + }), + ..Default::default() + }; + + let new_pending_datas = vec![new_pending_data, new_block_pending_data]; + let expected_pending_data = old_pending_data.clone(); + let old_pending_classes_data = None; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = None; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + old_pending_classes_data, + new_pending_classes, + new_pending_compiled_classes, + expected_pending_classes, + ) + .await +} + +#[tokio::test] +async fn pending_sync_updates_when_data_has_block_hash_field_with_the_same_hash_and_more_transactions() + { + const FIRST_BLOCK_HASH: BlockHash = BlockHash(StarkHash::ONE); + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with one block header. + let (reader, mut writer) = get_test_storage().0; + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + block_hash: FIRST_BLOCK_HASH, + parent_hash: genesis_hash, + block_number: BlockNumber(0), + ..Default::default() + }, + ) + .unwrap() + .commit() + .unwrap(); + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: FIRST_BLOCK_HASH, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + ..Default::default() + }; + let new_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + accepted_on_l2_extra_data: Some(AcceptedOnL2ExtraData { + block_hash: FIRST_BLOCK_HASH, + ..Default::default() + }), + parent_block_hash: genesis_hash, + transactions: vec![ + ClientTransaction::get_test_instance(&mut rng), + ClientTransaction::get_test_instance(&mut rng), + ], + ..Default::default() + }), + ..Default::default() + }; + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::TWO), + ..Default::default() + }), + ..Default::default() + }; + + let new_pending_datas = vec![new_pending_data.clone(), new_block_pending_data]; + let expected_pending_data = new_pending_data; + let old_pending_classes_data = None; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = None; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + old_pending_classes_data, + new_pending_classes, + new_pending_compiled_classes, + expected_pending_classes, + ) + .await +} + +#[tokio::test] +async fn pending_sync_classes_request_only_new_classes() { + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with no blocks. + let (reader, _writer) = get_test_storage().0; + let mut rng = get_rng(); + + let first_class_hash = ClassHash(StarkHash::ONE); + let second_class_hash = ClassHash(StarkHash::TWO); + + let first_new_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + transactions: vec![ClientTransaction::get_test_instance(&mut rng)], + ..Default::default() + }), + state_update: PendingStateUpdate { + state_diff: ClientStateDiff { + declared_classes: vec![DeclaredClassHashEntry { + class_hash: first_class_hash, + compiled_class_hash: CompiledClassHash(StarkHash::ONE), + }], + ..Default::default() + }, + ..Default::default() + }, + }; + let mut second_new_pending_data = first_new_pending_data.clone(); + second_new_pending_data + .block + .transactions_mutable() + .push(ClientTransaction::get_test_instance(&mut rng)); + second_new_pending_data.state_update.state_diff.old_declared_contracts.push(second_class_hash); + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::ONE), + ..Default::default() + }), + ..Default::default() + }; + + let first_class = ApiContractClass::DeprecatedContractClass( + DeprecatedContractClass::get_test_instance(&mut rng), + ); + let second_class = ApiContractClass::ContractClass(ContractClass::get_test_instance(&mut rng)); + let compiled_class = CasmContractClass::get_test_instance(&mut rng); + + let mut expected_pending_classes = PendingClasses::default(); + expected_pending_classes.add_class(first_class_hash, first_class.clone()); + expected_pending_classes.add_class(second_class_hash, second_class.clone()); + expected_pending_classes.add_compiled_class(first_class_hash, compiled_class.clone()); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + ..Default::default() + }), + ..Default::default() + }; + let new_pending_datas = + vec![first_new_pending_data, second_new_pending_data.clone(), new_block_pending_data]; + let expected_pending_data = second_new_pending_data; + let old_pending_classes_data = PendingClasses::default(); + let new_pending_classes = + vec![(first_class_hash, first_class.clone()), (second_class_hash, second_class.clone())]; + let new_pending_compiled_classes = vec![(first_class_hash, compiled_class.clone())]; + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + Some(old_pending_classes_data), + new_pending_classes, + new_pending_compiled_classes, + Some(expected_pending_classes), + ) + .await +} + +#[tokio::test] +async fn pending_sync_classes_are_cleaned_on_first_pending_data_from_latest_block() { + const FIRST_BLOCK_HASH: BlockHash = BlockHash(StarkHash::ONE); + let genesis_hash = BlockHash(felt!(GENESIS_HASH)); + // Storage with one block header. + let (reader, mut writer) = get_test_storage().0; + writer + .begin_rw_txn() + .unwrap() + .append_header( + BlockNumber(0), + &BlockHeader { + block_hash: FIRST_BLOCK_HASH, + parent_hash: genesis_hash, + block_number: BlockNumber(0), + ..Default::default() + }, + ) + .unwrap() + .commit() + .unwrap(); + let mut rng = get_rng(); + + let old_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: genesis_hash, + ..Default::default() + }), + ..Default::default() + }; + let new_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: FIRST_BLOCK_HASH, + ..Default::default() + }), + ..Default::default() + }; + let new_block_pending_data = PendingData { + block: PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock { + parent_block_hash: BlockHash(StarkHash::TWO), + ..Default::default() + }), + ..Default::default() + }; + + let mut old_pending_classes_data = PendingClasses::default(); + old_pending_classes_data.add_class( + ClassHash(StarkHash::ONE), + ApiContractClass::DeprecatedContractClass(DeprecatedContractClass::get_test_instance( + &mut rng, + )), + ); + old_pending_classes_data.add_compiled_class( + ClassHash(StarkHash::TWO), + CasmContractClass::get_test_instance(&mut rng), + ); + + let new_pending_datas = vec![new_pending_data.clone(), new_block_pending_data]; + let expected_pending_data = new_pending_data; + let new_pending_classes = vec![]; + let new_pending_compiled_classes = vec![]; + let expected_pending_classes = PendingClasses::default(); + test_pending_sync( + reader, + old_pending_data, + new_pending_datas, + expected_pending_data, + Some(old_pending_classes_data), + new_pending_classes, + new_pending_compiled_classes, + Some(expected_pending_classes), + ) + .await +} diff --git a/crates/sequencing/papyrus_block_builder/Cargo.toml b/crates/sequencing/papyrus_block_builder/Cargo.toml new file mode 100644 index 00000000000..a0c57f7dd6b --- /dev/null +++ b/crates/sequencing/papyrus_block_builder/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "papyrus_block_builder" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "A block-builder for Starknet blocks" + +[dependencies] +papyrus_storage = { path = "../../papyrus_storage", version = "0.4.0-rc.0", features = ["testing"] } +starknet_api.workspace = true +thiserror.workspace = true +tracing.workspace = true + +[dev-dependencies] +pretty_assertions.workspace = true +test_utils = { path = "../../test_utils" } diff --git a/crates/sequencing/papyrus_block_builder/src/lib.rs b/crates/sequencing/papyrus_block_builder/src/lib.rs new file mode 100644 index 00000000000..7725bc48e8d --- /dev/null +++ b/crates/sequencing/papyrus_block_builder/src/lib.rs @@ -0,0 +1,68 @@ +//! This crate contains a mock block-builder that echoes [`Starknet`] blocks. +//! +//! +//! [`Starknet`]: https://starknet.io/ + +use std::sync::mpsc::{self, Receiver}; + +use papyrus_storage::body::BodyStorageReader; +use papyrus_storage::StorageReader; +use starknet_api::block::BlockNumber; +use starknet_api::transaction::Transaction; +use tracing::instrument; + +#[cfg(test)] +mod test; + +/// A block builder. +struct BlockBuilder { + // A storage reader to read blocks from. Will be replaced with mempool. + #[allow(unused)] + storage_reader: StorageReader, +} + +pub trait BlockBuilderTrait { + fn build(&self, block_number: BlockNumber) -> BlockBuilderResult>; +} + +type BlockBuilderResult = Result; + +#[derive(thiserror::Error, Debug)] +pub enum BlockBuilderError { + #[error("Could not find a block with block number {}.", block_number)] + BlockNotFound { block_number: BlockNumber }, +} + +impl BlockBuilder { + /// Create a new block builder. + #[allow(unused)] + pub fn new(storage_reader: StorageReader) -> Self { + Self { storage_reader } + } +} + +impl BlockBuilderTrait for BlockBuilder { + // The block must already be in storage. + #[instrument(skip(self), level = "debug")] + fn build(&self, block_number: BlockNumber) -> BlockBuilderResult> { + let (sender, receiver) = mpsc::channel(); + + // TODO: spawn a task to send the transactions and return the receiver immediately. + let block = self + .storage_reader + .begin_ro_txn() + .expect("Failed to read storage") + .get_block_transactions(block_number) + .expect("Block should be in storage"); + + match block { + Some(block) => { + for txn in block { + sender.send(txn).expect("Failed to send transaction"); + } + Ok(receiver) + } + None => Err(BlockBuilderError::BlockNotFound { block_number }), + } + } +} diff --git a/crates/sequencing/papyrus_block_builder/src/test.rs b/crates/sequencing/papyrus_block_builder/src/test.rs new file mode 100644 index 00000000000..3033e8a685d --- /dev/null +++ b/crates/sequencing/papyrus_block_builder/src/test.rs @@ -0,0 +1,32 @@ +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::test_utils::get_test_storage_by_scope; +use papyrus_storage::StorageScope; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockNumber; +use test_utils::get_test_block; + +use crate::{BlockBuilder, BlockBuilderTrait}; + +#[test] +fn block_proposer() { + let storage_scope = StorageScope::FullArchive; + let ((storage_reader, mut storage_writer), _temp_dir) = + get_test_storage_by_scope(storage_scope); + let block_body = get_test_block(2, Some(1), None, None).body; + storage_writer + .begin_rw_txn() + .unwrap() + .append_body(BlockNumber(0), block_body.clone()) + .unwrap() + .commit() + .unwrap(); + + let proposer = BlockBuilder::new(storage_reader); + let block_number = BlockNumber(0); + let proposal_receiver = proposer.build(block_number).unwrap(); + let proposal = proposal_receiver.iter().collect::>(); + assert_eq!(proposal, block_body.transactions.as_slice()); +} + +// TODO: add test for non-existing block. +// TODO: add test for sending info and dropping the sender before receiving. diff --git a/crates/sequencing/papyrus_consensus/Cargo.toml b/crates/sequencing/papyrus_consensus/Cargo.toml new file mode 100644 index 00000000000..d91e455524e --- /dev/null +++ b/crates/sequencing/papyrus_consensus/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "papyrus_consensus" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Reach consensus for Starknet" + +[dependencies] +async-trait.workspace = true +futures.workspace = true +metrics.workspace = true +papyrus_common = { path = "../../papyrus_common", version = "0.4.0-dev.2" } +papyrus_network = { path = "../../papyrus_network", version = "0.4.0-dev.2" } +papyrus_config = { path = "../../papyrus_config", version = "0.4.0-dev.2" } +papyrus_protobuf = { path = "../../papyrus_protobuf", version = "0.4.0-dev.2" } +papyrus_storage = { path = "../../papyrus_storage", version = "0.4.0-dev.2" } +serde = { workspace = true, features = ["derive"] } +starknet_api.workspace = true +starknet-types-core.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["full"] } +tracing.workspace = true + +[dev-dependencies] +mockall.workspace = true +papyrus_network = { path = "../../papyrus_network", version = "0.4.0-dev.2", features = ["testing"] } +papyrus_storage = { path = "../../papyrus_storage", features = ["testing"] } +test_utils = { path = "../../test_utils" } +test-case.workspace = true \ No newline at end of file diff --git a/crates/sequencing/papyrus_consensus/README.md b/crates/sequencing/papyrus_consensus/README.md new file mode 100644 index 00000000000..4dcbfc0b104 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/README.md @@ -0,0 +1,30 @@ +# papyrus-consensus + +This crate provides an implementation of consensus for a Starknet node. + +### Disclaimer +This crate is still under development and is not keeping backwards compatibility with previous +versions. Breaking changes are expected to happen in the near future. + +## How to run +1. You must turn consensus on and provide a validator ID by passing: `--consensus.#is_none false --consensus.validator_id 0x` +2. Start by running any nodes which are validators for `consensus.start_height` which is by default 0 to avoid them missing the proposal. + 1. You can change the default number of validators by passing: `--consensus.num_validators ` + 2. You can change the default topic by passing: `--consensus.topic "TOPIC"` + +#### Bootstrap Node +This must be run first: +``` +cargo run --package papyrus_node --bin papyrus_node -- --base_layer.node_url --network.#is_none false --consensus.#is_none false --consensus.validator_id 0x1 --storage.db_config.path_prefix +``` +- This will log `local_peer_id` which is used by other nodes. (Alternatively pass `network.secret_key` to have a fixed peer id). + +#### Other Nodes +Run each of the other nodes separately, using different `consensus.validator_id` {`0x2`, `0x3`, `0x0`}: + +``` +cargo run --package papyrus_node --bin papyrus_node -- --base_layer.node_url --network.#is_none false --consensus.#is_none false --consensus.validator_id 0x --network.tcp_port --network.bootstrap_peer_multiaddr.#is_none false --rpc.server_address 127.0.0.1: --monitoring_gateway.server_address 127.0.0.1: --storage.db_config.path_prefix --network.bootstrap_peer_multiaddr /ip4/127.0.0.1/tcp/10000/p2p/ +``` +- Node 0 is the first proposer and should be run last. + +UNIQUE - a value unique among all nodes running locally. diff --git a/crates/sequencing/papyrus_consensus/run_consensus.py b/crates/sequencing/papyrus_consensus/run_consensus.py new file mode 100644 index 00000000000..4fdfe012b18 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/run_consensus.py @@ -0,0 +1,189 @@ +import subprocess +import time +import os +import signal +import argparse +import tempfile +import socket +from contextlib import closing + +# The SECRET_KEY is used for building the BOOT_NODE_PEER_ID, so they are coupled and must be used together. +SECRET_KEY = "0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" +BOOT_NODE_PEER_ID = "12D3KooWDFYi71juk6dYWo3UDvqs5gAzGDc124LSvcR5d187Tdvi" + +MONITORING_PERIOD = 10 + + +class Node: + def __init__(self, validator_id, monitoring_gateway_server_port, cmd): + self.validator_id = validator_id + self.monitoring_gateway_server_port = monitoring_gateway_server_port + self.cmd = cmd + self.process = None + self.height_and_timestamp = (None, None) # (height, timestamp) + + def start(self): + self.process = subprocess.Popen(self.cmd, shell=True, preexec_fn=os.setsid) + + def stop(self): + if self.process: + os.killpg(os.getpgid(self.process.pid), signal.SIGINT) + self.process.wait() + + def get_height(self): + port = self.monitoring_gateway_server_port + command = f"curl -s -X GET http://localhost:{port}/monitoring/metrics | grep -oP 'papyrus_consensus_height \\K\\d+'" + result = subprocess.run(command, shell=True, capture_output=True, text=True) + # returns the most recently decided height, or None if node is not ready or consensus has not yet reached any height. + return int(result.stdout) if result.stdout else None + + def check_height(self): + height = self.get_height() + if self.height_and_timestamp[0] != height: + if self.height_and_timestamp[0] is not None and height is not None: + assert height > self.height_and_timestamp[0], "Height should be increasing." + self.height_and_timestamp = (height, time.time()) + + return self.height_and_timestamp + + +def find_free_port(): + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: + s.bind(("", 0)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + return s.getsockname()[1] + + +BOOTNODE_TCP_PORT = find_free_port() + + +# Returns if the simulation should exit. +def monitor_simulation(nodes, start_time, duration, stagnation_timeout): + curr_time = time.time() + if duration is not None and duration < (curr_time - start_time): + return True + stagnated_nodes = [] + for node in nodes: + (height, last_update) = node.check_height() + print(f"Node: {node.validator_id}, height: {height}") + if height is not None and (curr_time - last_update) > stagnation_timeout: + stagnated_nodes.append(node.validator_id) + if stagnated_nodes: + print(f"Nodes {stagnated_nodes} have stagnated. Exiting simulation.") + return True + return False + + +def run_simulation(nodes, duration, stagnation_timeout): + for node in nodes: + node.start() + + start_time = time.time() + try: + while True: + time.sleep(MONITORING_PERIOD) + print(f"\nTime elapsed: {time.time() - start_time}s") + should_exit = monitor_simulation(nodes, start_time, duration, stagnation_timeout) + if should_exit: + break + except KeyboardInterrupt: + print("\nTerminating subprocesses...") + finally: + for node in nodes: + node.stop() + + +def build_node(base_layer_node_url, temp_dir, num_validators, i): + is_bootstrap = i == 1 + tcp_port = BOOTNODE_TCP_PORT if is_bootstrap else find_free_port() + monitoring_gateway_server_port = find_free_port() + + cmd = ( + f"RUST_LOG=papyrus_consensus=debug,papyrus=info " + f"target/release/papyrus_node --network.#is_none false " + f"--base_layer.node_url {base_layer_node_url} " + f"--storage.db_config.path_prefix {temp_dir}/data{i} " + f"--consensus.#is_none false --consensus.validator_id 0x{i} " + f"--consensus.num_validators {num_validators} " + f"--network.tcp_port {tcp_port} " + f"--rpc.server_address 127.0.0.1:{find_free_port()} " + f"--monitoring_gateway.server_address 127.0.0.1:{monitoring_gateway_server_port} " + f"--collect_metrics true " + ) + + if is_bootstrap: + cmd += ( + f"--network.secret_key {SECRET_KEY} " + + f"| sed -r 's/\\x1B\\[[0-9;]*[mK]//g' > {temp_dir}/validator{i}.txt" + ) + + else: + cmd += ( + f"--network.bootstrap_peer_multiaddr.#is_none false " + f"--network.bootstrap_peer_multiaddr /ip4/127.0.0.1/tcp/{BOOTNODE_TCP_PORT}/p2p/{BOOT_NODE_PEER_ID} " + + f"| sed -r 's/\\x1B\\[[0-9;]*[mK]//g' > {temp_dir}/validator{i}.txt" + ) + + return Node( + validator_id=i, + monitoring_gateway_server_port=monitoring_gateway_server_port, + cmd=cmd, + ) + + +def build_all_nodes(base_layer_node_url, temp_dir, num_validators): + # Validators are started in a specific order to ensure proper network formation: + # 1. The bootnode (validator 1) is started first for network peering. + # 2. Validators 2+ are started next to join the network through the bootnode. + # 3. Validator 0, which is the proposer, is started last so the validators don't miss the proposals. + nodes = [] + + nodes.append(build_node(base_layer_node_url, temp_dir, num_validators, 1)) # Bootstrap + + for i in range(2, num_validators): + nodes.append(build_node(base_layer_node_url, temp_dir, num_validators, i)) + + nodes.append(build_node(base_layer_node_url, temp_dir, num_validators, 0)) # Proposer + + return nodes + + +def main(base_layer_node_url, num_validators, stagnation_threshold, duration): + assert num_validators >= 2, "At least 2 validators are required for the simulation." + # Building the Papyrus Node package assuming its output will be located in the papyrus target directory. + print("Running cargo build...") + subprocess.run("cargo build --release --package papyrus_node", shell=True, check=True) + + temp_dir = tempfile.mkdtemp() + print(f"Output files will be stored in: {temp_dir}") + + # Create data directories + for i in range(num_validators): + data_dir = os.path.join(temp_dir, f"data{i}") + os.makedirs(data_dir) + + nodes = build_all_nodes(base_layer_node_url, temp_dir, num_validators) + + # Run validator commands in parallel and manage duration time + print("Running validators...") + run_simulation(nodes, duration, stagnation_threshold) + print(f"Output files were stored in: {temp_dir}") + print("Simulation complete.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Run Papyrus Node simulation.") + parser.add_argument("--base_layer_node_url", required=True) + parser.add_argument("--num_validators", type=int, required=True) + parser.add_argument( + "--stagnation_threshold", + type=int, + required=False, + default=60, + help="Time in seconds to check for height stagnation.", + ) + parser.add_argument("--duration", type=int, required=False, default=None) + + args = parser.parse_args() + main(args.base_layer_node_url, args.num_validators, args.stagnation_threshold, args.duration) diff --git a/crates/sequencing/papyrus_consensus/src/config.rs b/crates/sequencing/papyrus_consensus/src/config.rs new file mode 100644 index 00000000000..1508dd91d78 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/config.rs @@ -0,0 +1,68 @@ +//! This module contains the configuration for consensus, including the `ConsensusConfig` struct +//! and its implementation of the `SerializeConfig` trait. The configuration includes parameters +//! such as the validator ID, the network topic of the consensus, and the starting block height. + +use std::collections::BTreeMap; + +use papyrus_config::dumping::{ser_param, ser_required_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializationType, SerializedParam}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockNumber; + +use super::types::ValidatorId; + +/// Configuration for consensus. +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +pub struct ConsensusConfig { + /// The validator ID of the node. + pub validator_id: ValidatorId, + /// The network topic of the consensus. + pub topic: String, + /// The height to start the consensus from. + pub start_height: BlockNumber, + /// The number of validators in the consensus. + // Used for testing in an early milestones. + pub num_validators: u64, +} + +impl SerializeConfig for ConsensusConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_required_param( + "validator_id", + SerializationType::String, + "The validator id of the node.", + ParamPrivacyInput::Public, + ), + ser_param( + "topic", + &self.topic, + "The topic of the consensus.", + ParamPrivacyInput::Public, + ), + ser_param( + "start_height", + &self.start_height, + "The height to start the consensus from.", + ParamPrivacyInput::Public, + ), + ser_param( + "num_validators", + &self.num_validators, + "The number of validators in the consensus.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +impl Default for ConsensusConfig { + fn default() -> Self { + Self { + validator_id: ValidatorId::default(), + topic: "consensus".to_string(), + start_height: BlockNumber::default(), + num_validators: 4, + } + } +} diff --git a/crates/sequencing/papyrus_consensus/src/lib.rs b/crates/sequencing/papyrus_consensus/src/lib.rs new file mode 100644 index 00000000000..274c53d046b --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/lib.rs @@ -0,0 +1,140 @@ +#![warn(missing_docs)] +// TODO(Matan): Add a description of the crate. +// TODO(Matan): fix #[allow(missing_docs)]. +//! A consensus implementation for a [`Starknet`](https://www.starknet.io/) node. + +use futures::channel::{mpsc, oneshot}; +use papyrus_common::metrics as papyrus_metrics; +use papyrus_network::network_manager::BroadcastSubscriberReceiver; +use papyrus_protobuf::consensus::{ConsensusMessage, Proposal}; +use single_height_consensus::SingleHeightConsensus; +use starknet_api::block::{BlockHash, BlockNumber}; +use tracing::{debug, info, instrument}; +use types::{ + ConsensusBlock, + ConsensusContext, + ConsensusError, + Decision, + ProposalInit, + ValidatorId, +}; + +pub mod config; +#[allow(missing_docs)] +pub mod papyrus_consensus_context; +#[allow(missing_docs)] +pub mod single_height_consensus; +#[allow(missing_docs)] +pub mod state_machine; +#[cfg(test)] +pub(crate) mod test_utils; +#[allow(missing_docs)] +pub mod types; + +use futures::StreamExt; + +#[instrument(skip(context, validator_id, network_receiver, cached_messages), level = "info")] +#[allow(missing_docs)] +async fn run_height>( + context: &mut ContextT, + height: BlockNumber, + validator_id: ValidatorId, + network_receiver: &mut BroadcastSubscriberReceiver, + cached_messages: &mut Vec, +) -> Result, ConsensusError> +where + ProposalWrapper: + Into<(ProposalInit, mpsc::Receiver, oneshot::Receiver)>, +{ + let validators = context.validators(height).await; + let mut shc = SingleHeightConsensus::new(height, validator_id, validators); + + if let Some(decision) = shc.start(context).await? { + return Ok(decision); + } + + let mut current_height_messages = Vec::new(); + for msg in std::mem::take(cached_messages) { + match height.0.cmp(&msg.height()) { + std::cmp::Ordering::Less => cached_messages.push(msg), + std::cmp::Ordering::Equal => current_height_messages.push(msg), + std::cmp::Ordering::Greater => {} + } + } + + loop { + let message = if let Some(msg) = current_height_messages.pop() { + msg + } else { + // TODO(matan): Handle parsing failures and utilize ReportCallback. + network_receiver + .next() + .await + .expect("Network receiver closed unexpectedly") + .0 + .expect("Failed to parse consensus message") + }; + + if message.height() != height.0 { + debug!("Received a message for a different height. {:?}", message); + if message.height() > height.0 { + cached_messages.push(message); + } + continue; + } + + let maybe_decision = match message { + ConsensusMessage::Proposal(proposal) => { + // Special case due to fake streaming. + let (proposal_init, content_receiver, fin_receiver) = + ProposalWrapper(proposal).into(); + shc.handle_proposal(context, proposal_init, content_receiver, fin_receiver).await? + } + _ => shc.handle_message(context, message).await?, + }; + + if let Some(decision) = maybe_decision { + return Ok(decision); + } + } +} + +// TODO(dvir): add test for this. +#[instrument(skip(context, start_height, network_receiver), level = "info")] +#[allow(missing_docs)] +pub async fn run_consensus>( + mut context: ContextT, + start_height: BlockNumber, + validator_id: ValidatorId, + mut network_receiver: BroadcastSubscriberReceiver, +) -> Result<(), ConsensusError> +where + ProposalWrapper: + Into<(ProposalInit, mpsc::Receiver, oneshot::Receiver)>, +{ + let mut current_height = start_height; + let mut future_messages = Vec::new(); + loop { + let decision = run_height( + &mut context, + current_height, + validator_id, + &mut network_receiver, + &mut future_messages, + ) + .await?; + + info!( + "Finished consensus for height: {current_height}. Agreed on block with id: {:x}", + decision.block.id().0 + ); + debug!("Decision: {:?}", decision); + metrics::gauge!(papyrus_metrics::PAPYRUS_CONSENSUS_HEIGHT, current_height.0 as f64); + current_height = current_height.unchecked_next(); + } +} + +// `Proposal` is defined in the protobuf crate so we can't implement `Into` for it because of the +// orphan rule. This wrapper enables us to implement `Into` for the inner `Proposal`. +#[allow(missing_docs)] +pub struct ProposalWrapper(Proposal); diff --git a/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context.rs b/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context.rs new file mode 100644 index 00000000000..d4e4d228071 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context.rs @@ -0,0 +1,249 @@ +#[cfg(test)] +#[path = "papyrus_consensus_context_test.rs"] +mod papyrus_consensus_context_test; + +use core::panic; +use std::time::Duration; + +use async_trait::async_trait; +use futures::channel::{mpsc, oneshot}; +use futures::sink::SinkExt; +use futures::StreamExt; +use papyrus_network::network_manager::BroadcastSubscriberSender; +use papyrus_protobuf::consensus::{ConsensusMessage, Proposal}; +use papyrus_storage::body::BodyStorageReader; +use papyrus_storage::header::HeaderStorageReader; +use papyrus_storage::{StorageError, StorageReader}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::ContractAddress; +use starknet_api::transaction::Transaction; +use tracing::debug; + +use crate::types::{ConsensusBlock, ConsensusContext, ConsensusError, ProposalInit, ValidatorId}; +use crate::ProposalWrapper; + +// TODO: add debug messages and span to the tasks. + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct PapyrusConsensusBlock { + content: Vec, + id: BlockHash, +} + +impl ConsensusBlock for PapyrusConsensusBlock { + type ProposalChunk = Transaction; + type ProposalIter = std::vec::IntoIter; + + fn id(&self) -> BlockHash { + self.id + } + + fn proposal_iter(&self) -> Self::ProposalIter { + self.content.clone().into_iter() + } +} + +pub struct PapyrusConsensusContext { + storage_reader: StorageReader, + broadcast_sender: BroadcastSubscriberSender, + validators: Vec, +} + +impl PapyrusConsensusContext { + // TODO(dvir): remove the dead code attribute after we will use this function. + #[allow(dead_code)] + pub fn new( + storage_reader: StorageReader, + broadcast_sender: BroadcastSubscriberSender, + num_validators: u64, + ) -> Self { + Self { + storage_reader, + broadcast_sender, + validators: (0..num_validators).map(ContractAddress::from).collect(), + } + } +} + +const CHANNEL_SIZE: usize = 5000; + +#[async_trait] +impl ConsensusContext for PapyrusConsensusContext { + type Block = PapyrusConsensusBlock; + + async fn build_proposal( + &self, + height: BlockNumber, + ) -> (mpsc::Receiver, oneshot::Receiver) { + let (mut sender, receiver) = mpsc::channel(CHANNEL_SIZE); + let (fin_sender, fin_receiver) = oneshot::channel(); + + let storage_reader = self.storage_reader.clone(); + tokio::spawn(async move { + // TODO(dvir): consider fix this for the case of reverts. If between the check that the + // block in storage and to getting the transaction was a revert this flow will fail. + wait_for_block(&storage_reader, height).await.expect("Failed to wait to block"); + + let txn = storage_reader.begin_ro_txn().expect("Failed to begin ro txn"); + let transactions = txn + .get_block_transactions(height) + .expect("Get transactions from storage failed") + .unwrap_or_else(|| { + panic!("Block in {height} was not found in storage despite waiting for it") + }); + + for tx in transactions.clone() { + sender.try_send(tx).expect("Send should succeed"); + } + sender.close_channel(); + + let block_hash = txn + .get_block_header(height) + .expect("Get header from storage failed") + .unwrap_or_else(|| { + panic!("Block in {height} was not found in storage despite waiting for it") + }) + .block_hash; + fin_sender + .send(PapyrusConsensusBlock { content: transactions, id: block_hash }) + .expect("Send should succeed"); + }); + + (receiver, fin_receiver) + } + + async fn validate_proposal( + &self, + height: BlockNumber, + mut content: mpsc::Receiver, + ) -> oneshot::Receiver { + let (fin_sender, fin_receiver) = oneshot::channel(); + + let storage_reader = self.storage_reader.clone(); + tokio::spawn(async move { + // TODO(dvir): consider fix this for the case of reverts. If between the check that the + // block in storage and to getting the transaction was a revert this flow will fail. + wait_for_block(&storage_reader, height).await.expect("Failed to wait to block"); + + let txn = storage_reader.begin_ro_txn().expect("Failed to begin ro txn"); + let transactions = txn + .get_block_transactions(height) + .expect("Get transactions from storage failed") + .unwrap_or_else(|| { + panic!("Block in {height} was not found in storage despite waiting for it") + }); + + for tx in transactions.iter() { + let received_tx = content + .next() + .await + .unwrap_or_else(|| panic!("Not received transaction equals to {tx:?}")); + if tx != &received_tx { + panic!("Transactions are not equal. In storage: {tx:?}, : {received_tx:?}"); + } + } + + if content.next().await.is_some() { + panic!("Received more transactions than expected"); + } + + let block_hash = txn + .get_block_header(height) + .expect("Get header from storage failed") + .unwrap_or_else(|| { + panic!("Block in {height} was not found in storage despite waiting for it") + }) + .block_hash; + fin_sender + .send(PapyrusConsensusBlock { content: transactions, id: block_hash }) + .expect("Send should succeed"); + }); + + fin_receiver + } + + async fn validators(&self, _height: BlockNumber) -> Vec { + self.validators.clone() + } + + fn proposer(&self, _validators: &[ValidatorId], _height: BlockNumber) -> ValidatorId { + *self.validators.first().expect("validators should have at least 2 validators") + } + + async fn broadcast(&mut self, message: ConsensusMessage) -> Result<(), ConsensusError> { + debug!("Broadcasting message: {message:?}"); + self.broadcast_sender.send(message).await?; + Ok(()) + } + + async fn propose( + &self, + init: ProposalInit, + mut content_receiver: mpsc::Receiver, + fin_receiver: oneshot::Receiver, + ) -> Result<(), ConsensusError> { + let mut broadcast_sender = self.broadcast_sender.clone(); + + tokio::spawn(async move { + let mut transactions = Vec::new(); + while let Some(tx) = content_receiver.next().await { + transactions.push(tx); + } + + let block_hash = + fin_receiver.await.expect("Failed to get block hash from fin receiver"); + let proposal = Proposal { + height: init.height.0, + proposer: init.proposer, + transactions, + block_hash, + }; + debug!( + "Sending proposal: height={:?} id={:?} num_txs={} block_hash={:?}", + proposal.height, + proposal.proposer, + proposal.transactions.len(), + proposal.block_hash + ); + + broadcast_sender + .send(ConsensusMessage::Proposal(proposal)) + .await + .expect("Failed to send proposal"); + }); + Ok(()) + } +} + +const SLEEP_BETWEEN_CHECK_FOR_BLOCK: Duration = Duration::from_secs(10); + +async fn wait_for_block( + storage_reader: &StorageReader, + height: BlockNumber, +) -> Result<(), StorageError> { + while storage_reader.begin_ro_txn()?.get_body_marker()? <= height { + debug!("Waiting for block {height:?} to continue consensus"); + tokio::time::sleep(SLEEP_BETWEEN_CHECK_FOR_BLOCK).await; + } + Ok(()) +} + +impl From + for (ProposalInit, mpsc::Receiver, oneshot::Receiver) +{ + fn from(val: ProposalWrapper) -> Self { + let transactions: Vec = val.0.transactions.into_iter().collect(); + let proposal_init = + ProposalInit { height: BlockNumber(val.0.height), proposer: val.0.proposer }; + let (mut content_sender, content_receiver) = mpsc::channel(transactions.len()); + for tx in transactions { + content_sender.try_send(tx).expect("Send should succeed"); + } + content_sender.close_channel(); + + let (fin_sender, fin_receiver) = oneshot::channel(); + fin_sender.send(val.0.block_hash).expect("Send should succeed"); + + (proposal_init, content_receiver, fin_receiver) + } +} diff --git a/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context_test.rs b/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context_test.rs new file mode 100644 index 00000000000..9f1f25d8570 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/papyrus_consensus_context_test.rs @@ -0,0 +1,121 @@ +use futures::channel::{mpsc, oneshot}; +use futures::StreamExt; +use papyrus_network::network_manager::{mock_register_broadcast_subscriber, BroadcastNetworkMock}; +use papyrus_protobuf::consensus::{ConsensusMessage, Proposal}; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::test_utils::get_test_storage; +use starknet_api::block::Block; +use starknet_api::core::ContractAddress; +use starknet_api::transaction::Transaction; +use test_utils::get_test_block; + +use crate::papyrus_consensus_context::PapyrusConsensusContext; +use crate::types::{ConsensusBlock, ConsensusContext, ProposalInit}; + +// TODO(dvir): consider adding tests for times, i.e, the calls are returned immediately and nothing +// happen until it should (for example, not creating a block before we have it in storage). + +const TEST_CHANNEL_SIZE: usize = 10; + +#[tokio::test] +async fn build_proposal() { + let (block, papyrus_context, _mock_network) = test_setup(); + let block_number = block.header.block_number; + + let (mut proposal_receiver, fin_receiver) = papyrus_context.build_proposal(block_number).await; + + let mut transactions = Vec::new(); + while let Some(tx) = proposal_receiver.next().await { + transactions.push(tx); + } + assert_eq!(transactions, block.body.transactions); + + let fin = fin_receiver.await.unwrap(); + assert_eq!(fin.id(), block.header.block_hash); + assert_eq!(fin.proposal_iter().collect::>(), block.body.transactions); +} + +#[tokio::test] +async fn validate_proposal_success() { + let (block, papyrus_context, _mock_network) = test_setup(); + let block_number = block.header.block_number; + + let (mut validate_sender, validate_receiver) = mpsc::channel(TEST_CHANNEL_SIZE); + for tx in block.body.transactions.clone() { + validate_sender.try_send(tx).unwrap(); + } + validate_sender.close_channel(); + + let fin = + papyrus_context.validate_proposal(block_number, validate_receiver).await.await.unwrap(); + + assert_eq!(fin.id(), block.header.block_hash); + assert_eq!(fin.proposal_iter().collect::>(), block.body.transactions); +} + +#[tokio::test] +async fn validate_proposal_fail() { + let (block, papyrus_context, _mock_network) = test_setup(); + let block_number = block.header.block_number; + + let different_block = get_test_block(4, None, None, None); + let (mut validate_sender, validate_receiver) = mpsc::channel(5000); + for tx in different_block.body.transactions.clone() { + validate_sender.try_send(tx).unwrap(); + } + validate_sender.close_channel(); + + let fin = papyrus_context.validate_proposal(block_number, validate_receiver).await.await; + assert_eq!(fin, Err(oneshot::Canceled)); +} + +#[tokio::test] +async fn propose() { + let (block, papyrus_context, mut mock_network) = test_setup(); + let block_number = block.header.block_number; + + let (mut content_sender, content_receiver) = mpsc::channel(TEST_CHANNEL_SIZE); + for tx in block.body.transactions.clone() { + content_sender.try_send(tx).unwrap(); + } + content_sender.close_channel(); + + let (fin_sender, fin_receiver) = oneshot::channel(); + fin_sender.send(block.header.block_hash).unwrap(); + + let proposal_init = ProposalInit { height: block_number, proposer: ContractAddress::default() }; + papyrus_context.propose(proposal_init.clone(), content_receiver, fin_receiver).await.unwrap(); + + let expected_message = ConsensusMessage::Proposal(Proposal { + height: proposal_init.height.0, + proposer: proposal_init.proposer, + transactions: block.body.transactions, + block_hash: block.header.block_hash, + }); + + assert_eq!(mock_network.messages_to_broadcast_receiver.next().await.unwrap(), expected_message); +} + +fn test_setup() -> (Block, PapyrusConsensusContext, BroadcastNetworkMock) { + let ((storage_reader, mut storage_writer), _temp_dir) = get_test_storage(); + let block = get_test_block(5, None, None, None); + let block_number = block.header.block_number; + storage_writer + .begin_rw_txn() + .unwrap() + .append_header(block_number, &block.header) + .unwrap() + .append_body(block_number, block.body.clone()) + .unwrap() + .commit() + .unwrap(); + + let test_channels = mock_register_broadcast_subscriber().unwrap(); + let papyrus_context = PapyrusConsensusContext::new( + storage_reader.clone(), + test_channels.subscriber_channels.messages_to_broadcast_sender, + 4, + ); + (block, papyrus_context, test_channels.mock_network) +} diff --git a/crates/sequencing/papyrus_consensus/src/single_height_consensus.rs b/crates/sequencing/papyrus_consensus/src/single_height_consensus.rs new file mode 100644 index 00000000000..4b33524ce26 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/single_height_consensus.rs @@ -0,0 +1,294 @@ +#[cfg(test)] +#[path = "single_height_consensus_test.rs"] +mod single_height_consensus_test; + +use std::collections::{HashMap, VecDeque}; + +use futures::channel::{mpsc, oneshot}; +use papyrus_protobuf::consensus::{ConsensusMessage, Vote, VoteType}; +use starknet_api::block::{BlockHash, BlockNumber}; +use tracing::{debug, info, instrument, trace}; + +use crate::state_machine::{StateMachine, StateMachineEvent}; +use crate::types::{ + ConsensusBlock, + ConsensusContext, + ConsensusError, + Decision, + ProposalInit, + Round, + ValidatorId, +}; + +const ROUND_ZERO: Round = 0; + +/// Struct which represents a single height of consensus. Each height is expected to be begun with a +/// call to `start`, which is relevant if we are the proposer for this height's first round. +/// SingleHeightConsensus receives messages directly as parameters to function calls. It can send +/// out messages "directly" to the network, and returning a decision to the caller. +pub(crate) struct SingleHeightConsensus { + height: BlockNumber, + validators: Vec, + id: ValidatorId, + state_machine: StateMachine, + proposals: HashMap, + prevotes: HashMap<(Round, ValidatorId), Vote>, + precommits: HashMap<(Round, ValidatorId), Vote>, +} + +impl SingleHeightConsensus { + pub(crate) fn new(height: BlockNumber, id: ValidatorId, validators: Vec) -> Self { + // TODO(matan): Use actual weights, not just `len`. + let state_machine = StateMachine::new(validators.len() as u32); + Self { + height, + validators, + id, + state_machine, + proposals: HashMap::new(), + prevotes: HashMap::new(), + precommits: HashMap::new(), + } + } + + #[instrument(skip_all, fields(height=self.height.0), level = "debug")] + pub(crate) async fn start>( + &mut self, + context: &mut ContextT, + ) -> Result>, ConsensusError> { + info!("Starting consensus with validators {:?}", self.validators); + let events = self.state_machine.start(); + self.handle_state_machine_events(context, events).await + } + + /// Receive a proposal from a peer node. Returns only once the proposal has been fully received + /// and processed. + #[instrument( + skip_all, + fields(height = %self.height), + level = "debug", + )] + pub(crate) async fn handle_proposal>( + &mut self, + context: &mut ContextT, + init: ProposalInit, + p2p_messages_receiver: mpsc::Receiver<::ProposalChunk>, + fin_receiver: oneshot::Receiver, + ) -> Result>, ConsensusError> { + debug!( + "Received proposal: proposal_height={}, proposer={:?}", + init.height.0, init.proposer + ); + let proposer_id = context.proposer(&self.validators, self.height); + if init.height != self.height { + let msg = format!("invalid height: expected {:?}, got {:?}", self.height, init.height); + return Err(ConsensusError::InvalidProposal(proposer_id, self.height, msg)); + } + if init.proposer != proposer_id { + let msg = + format!("invalid proposer: expected {:?}, got {:?}", proposer_id, init.proposer); + return Err(ConsensusError::InvalidProposal(proposer_id, self.height, msg)); + } + + let block_receiver = context.validate_proposal(self.height, p2p_messages_receiver).await; + // TODO(matan): Actual Tendermint should handle invalid proposals. + let block = block_receiver.await.map_err(|_| { + ConsensusError::InvalidProposal( + proposer_id, + self.height, + "block validation failed".into(), + ) + })?; + // TODO(matan): Actual Tendermint should handle invalid proposals. + let fin = fin_receiver.await.map_err(|_| { + ConsensusError::InvalidProposal( + proposer_id, + self.height, + "proposal fin never received".into(), + ) + })?; + // TODO(matan): Switch to signature validation and handle invalid proposals. + if block.id() != fin { + return Err(ConsensusError::InvalidProposal( + proposer_id, + self.height, + "block signature doesn't match expected block hash".into(), + )); + } + let sm_proposal = StateMachineEvent::Proposal(block.id(), ROUND_ZERO); + // TODO(matan): Handle multiple rounds. + self.proposals.insert(ROUND_ZERO, block); + let sm_events = self.state_machine.handle_event(sm_proposal); + self.handle_state_machine_events(context, sm_events).await + } + + /// Handle messages from peer nodes. + #[instrument(skip_all)] + pub(crate) async fn handle_message>( + &mut self, + context: &mut ContextT, + message: ConsensusMessage, + ) -> Result>, ConsensusError> { + debug!("Received message: {:?}", message); + match message { + ConsensusMessage::Proposal(_) => { + unimplemented!("Proposals should use `handle_proposal` due to fake streaming") + } + ConsensusMessage::Vote(vote) => self.handle_vote(context, vote).await, + } + } + + #[instrument(skip_all)] + async fn handle_vote>( + &mut self, + context: &mut ContextT, + vote: Vote, + ) -> Result>, ConsensusError> { + let (votes, sm_vote) = match vote.vote_type { + VoteType::Prevote => { + (&mut self.prevotes, StateMachineEvent::Prevote(vote.block_hash, ROUND_ZERO)) + } + VoteType::Precommit => { + (&mut self.precommits, StateMachineEvent::Precommit(vote.block_hash, ROUND_ZERO)) + } + }; + if let Some(old) = votes.get(&(ROUND_ZERO, vote.voter)) { + if old.block_hash != vote.block_hash { + return Err(ConsensusError::Equivocation( + self.height, + ConsensusMessage::Vote(old.clone()), + ConsensusMessage::Vote(vote), + )); + } else { + // Replay, ignore. + return Ok(None); + } + } + + votes.insert((ROUND_ZERO, vote.voter), vote); + let sm_events = self.state_machine.handle_event(sm_vote); + self.handle_state_machine_events(context, sm_events).await + } + + // Handle events output by the state machine. + #[instrument(skip_all)] + async fn handle_state_machine_events>( + &mut self, + context: &mut ContextT, + mut events: VecDeque, + ) -> Result>, ConsensusError> { + while let Some(event) = events.pop_front() { + trace!("Handling event: {:?}", event); + match event { + StateMachineEvent::StartRound(block_hash, round) => { + events.append( + &mut self + .handle_state_machine_start_round(context, block_hash, round) + .await, + ); + } + StateMachineEvent::Proposal(_, _) => { + // Ignore proposals sent by the StateMachine as SingleHeightConsensus already + // sent this out when responding to a StartRound. + } + StateMachineEvent::Decision(block_hash, round) => { + return self.handle_state_machine_decision(block_hash, round).await; + } + StateMachineEvent::Prevote(block_hash, round) => { + self.handle_state_machine_vote(context, block_hash, round, VoteType::Prevote) + .await?; + } + StateMachineEvent::Precommit(block_hash, round) => { + self.handle_state_machine_vote(context, block_hash, round, VoteType::Precommit) + .await?; + } + } + } + Ok(None) + } + + #[instrument(skip(self, context), level = "debug")] + async fn handle_state_machine_start_round>( + &mut self, + context: &mut ContextT, + block_hash: Option, + round: Round, + ) -> VecDeque { + // TODO(matan): Support re-proposing validValue. + assert!(block_hash.is_none(), "Reproposing is not yet supported"); + let proposer_id = context.proposer(&self.validators, self.height); + if proposer_id != self.id { + debug!("Validator"); + return self.state_machine.handle_event(StateMachineEvent::StartRound(None, round)); + } + debug!("Proposer"); + + let (p2p_messages_receiver, block_receiver) = context.build_proposal(self.height).await; + let (fin_sender, fin_receiver) = oneshot::channel(); + let init = ProposalInit { height: self.height, proposer: self.id }; + // Peering is a permanent component, so if sending to it fails we cannot continue. + context + .propose(init, p2p_messages_receiver, fin_receiver) + .await + .expect("Failed sending Proposal to Peering"); + let block = block_receiver.await.expect("Block building failed."); + let id = block.id(); + // If we choose to ignore this error, we should carefully consider how this affects + // Tendermint. The partially synchronous model assumes all messages arrive at some point, + // and this failure means this proposal will never arrive. + // + // TODO(matan): Switch this to the Proposal signature. + fin_sender.send(id).expect("Failed to send ProposalFin to Peering."); + let old = self.proposals.insert(round, block); + assert!(old.is_none(), "There should be no entry for this round."); + + // TODO(matan): Send to the state machine and handle voting. + self.state_machine.handle_event(StateMachineEvent::StartRound(Some(id), round)) + } + + #[instrument(skip_all)] + async fn handle_state_machine_vote>( + &mut self, + context: &mut ContextT, + block_hash: BlockHash, + round: Round, + vote_type: VoteType, + ) -> Result>, ConsensusError> { + let votes = match vote_type { + VoteType::Prevote => &mut self.prevotes, + VoteType::Precommit => &mut self.precommits, + }; + let vote = Vote { vote_type, height: self.height.0, block_hash, voter: self.id }; + if let Some(old) = votes.insert((round, self.id), vote.clone()) { + // TODO(matan): Consider refactoring not to panic, rather log and return the error. + panic!("State machine should not send repeat votes: old={:?}, new={:?}", old, vote); + } + context.broadcast(ConsensusMessage::Vote(vote)).await?; + Ok(None) + } + + #[instrument(skip_all)] + async fn handle_state_machine_decision( + &mut self, + block_hash: BlockHash, + round: Round, + ) -> Result>, ConsensusError> { + let block = + self.proposals.remove(&round).expect("StateMachine arrived at an unknown decision"); + assert_eq!(block.id(), block_hash, "StateMachine block hash should match the stored block"); + let supporting_precommits: Vec = self + .validators + .iter() + .filter_map(|v| { + let vote = self.precommits.get(&(round, *v))?; + if vote.block_hash != block_hash { + return None; + } + Some(vote.clone()) + }) + .collect(); + // TODO(matan): Check actual weights. + assert!(supporting_precommits.len() >= self.state_machine.quorum_size() as usize); + Ok(Some(Decision { precommits: supporting_precommits, block })) + } +} diff --git a/crates/sequencing/papyrus_consensus/src/single_height_consensus_test.rs b/crates/sequencing/papyrus_consensus/src/single_height_consensus_test.rs new file mode 100644 index 00000000000..38fedb418d2 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/single_height_consensus_test.rs @@ -0,0 +1,164 @@ +use std::sync::{Arc, OnceLock}; + +use futures::channel::{mpsc, oneshot}; +use papyrus_protobuf::consensus::{ConsensusMessage, Vote, VoteType}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_types_core::felt::Felt; +use tokio; + +use super::SingleHeightConsensus; +use crate::test_utils::{MockTestContext, TestBlock}; +use crate::types::{ConsensusBlock, ProposalInit, ValidatorId}; + +fn prevote(block_hash: BlockHash, height: u64, voter: ValidatorId) -> ConsensusMessage { + ConsensusMessage::Vote(Vote { vote_type: VoteType::Prevote, height, block_hash, voter }) +} + +fn precommit(block_hash: BlockHash, height: u64, voter: ValidatorId) -> ConsensusMessage { + ConsensusMessage::Vote(Vote { vote_type: VoteType::Precommit, height, block_hash, voter }) +} + +#[tokio::test] +async fn proposer() { + let mut context = MockTestContext::new(); + + let node_id: ValidatorId = 1_u32.into(); + let block = TestBlock { content: vec![1, 2, 3], id: BlockHash(Felt::ONE) }; + let block_id = block.id(); + + let mut shc = SingleHeightConsensus::new( + BlockNumber(0), + node_id, + vec![node_id, 2_u32.into(), 3_u32.into(), 4_u32.into()], + ); + + context.expect_proposer().returning(move |_, _| node_id); + let block_clone = block.clone(); + context.expect_build_proposal().returning(move |_| { + let (_, content_receiver) = mpsc::channel(1); + let (block_sender, block_receiver) = oneshot::channel(); + block_sender.send(block_clone.clone()).unwrap(); + (content_receiver, block_receiver) + }); + let fin_receiver = Arc::new(OnceLock::new()); + let fin_receiver_clone = Arc::clone(&fin_receiver); + context.expect_propose().return_once(move |init, _, fin_receiver| { + // Ignore content receiver, since this is the context's responsibility. + assert_eq!(init.height, BlockNumber(0)); + assert_eq!(init.proposer, node_id); + fin_receiver_clone.set(fin_receiver).unwrap(); + Ok(()) + }); + context + .expect_broadcast() + .withf(move |msg: &ConsensusMessage| msg == &prevote(block_id, 0, node_id)) + .returning(move |_| Ok(())); + // Sends proposal and prevote. + assert!(matches!(shc.start(&mut context).await, Ok(None))); + + assert_eq!( + shc.handle_message(&mut context, prevote(block.id(), 0, 2_u32.into())).await, + Ok(None) + ); + // 3 of 4 Prevotes is enough to send a Precommit. + context + .expect_broadcast() + .withf(move |msg: &ConsensusMessage| msg == &precommit(block_id, 0, node_id)) + .returning(move |_| Ok(())); + assert_eq!( + shc.handle_message(&mut context, prevote(block.id(), 0, 3_u32.into())).await, + Ok(None) + ); + + let precommits = vec![ + precommit(block.id(), 0, 1_u32.into()), + precommit(BlockHash(Felt::TWO), 0, 4_u32.into()), // Ignores since disagrees. + precommit(block.id(), 0, 2_u32.into()), + precommit(block.id(), 0, 3_u32.into()), + ]; + assert_eq!(shc.handle_message(&mut context, precommits[1].clone()).await, Ok(None)); + assert_eq!(shc.handle_message(&mut context, precommits[2].clone()).await, Ok(None)); + let decision = shc.handle_message(&mut context, precommits[3].clone()).await.unwrap().unwrap(); + assert_eq!(decision.block, block); + assert!( + decision + .precommits + .into_iter() + .all(|item| precommits.contains(&ConsensusMessage::Vote(item))) + ); + + // Check the fin sent to the network. + let fin = Arc::into_inner(fin_receiver).unwrap().take().unwrap().await.unwrap(); + assert_eq!(fin, block.id()); +} + +#[tokio::test] +async fn validator() { + let mut context = MockTestContext::new(); + + let node_id: ValidatorId = 1_u32.into(); + let proposer: ValidatorId = 2_u32.into(); + let block = TestBlock { content: vec![1, 2, 3], id: BlockHash(Felt::ONE) }; + let block_id = block.id(); + + // Creation calls to `context.validators`. + let mut shc = SingleHeightConsensus::new( + BlockNumber(0), + node_id, + vec![node_id, proposer, 3_u32.into(), 4_u32.into()], + ); + + // Send the proposal from the peer. + let (fin_sender, fin_receiver) = oneshot::channel(); + fin_sender.send(block.id()).unwrap(); + + context.expect_proposer().returning(move |_, _| proposer); + let block_clone = block.clone(); + context.expect_validate_proposal().returning(move |_, _| { + let (block_sender, block_receiver) = oneshot::channel(); + block_sender.send(block_clone.clone()).unwrap(); + block_receiver + }); + context + .expect_broadcast() + .withf(move |msg: &ConsensusMessage| msg == &prevote(block_id, 0, node_id)) + .returning(move |_| Ok(())); + let res = shc + .handle_proposal( + &mut context, + ProposalInit { height: BlockNumber(0), proposer }, + mpsc::channel(1).1, // content - ignored by SHC. + fin_receiver, + ) + .await; + assert_eq!(res, Ok(None)); + + assert_eq!( + shc.handle_message(&mut context, prevote(block.id(), 0, 2_u32.into())).await, + Ok(None) + ); + // 3 of 4 Prevotes is enough to send a Precommit. + context + .expect_broadcast() + .withf(move |msg: &ConsensusMessage| msg == &precommit(block_id, 0, node_id)) + .returning(move |_| Ok(())); + assert_eq!( + shc.handle_message(&mut context, prevote(block.id(), 0, 3_u32.into())).await, + Ok(None) + ); + + let precommits = vec![ + precommit(block.id(), 0, 2_u32.into()), + precommit(block.id(), 0, 3_u32.into()), + precommit(block.id(), 0, node_id), + ]; + assert_eq!(shc.handle_message(&mut context, precommits[0].clone()).await, Ok(None)); + let decision = shc.handle_message(&mut context, precommits[1].clone()).await.unwrap().unwrap(); + assert_eq!(decision.block, block); + assert!( + decision + .precommits + .into_iter() + .all(|item| precommits.contains(&ConsensusMessage::Vote(item))) + ); +} diff --git a/crates/sequencing/papyrus_consensus/src/state_machine.rs b/crates/sequencing/papyrus_consensus/src/state_machine.rs new file mode 100644 index 00000000000..f0a706d54f8 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/state_machine.rs @@ -0,0 +1,297 @@ +//! State machine for Starknet consensus. +//! +//! LOC refers to the line of code from Algorithm 1 (page 6) of the tendermint +//! [paper](https://arxiv.org/pdf/1807.04938). + +#[cfg(test)] +#[path = "state_machine_test.rs"] +mod state_machine_test; + +use std::collections::{HashMap, VecDeque}; + +use starknet_api::block::BlockHash; +use tracing::trace; + +use crate::types::Round; + +/// Events which the state machine sends/receives. +#[derive(Debug, Clone, PartialEq)] +pub enum StateMachineEvent { + /// StartRound is effective 2 questions: + /// 1. Is the local node the proposer for this round? + /// 2. If so, what value should be proposed? + /// While waiting for the response to this event, the state machine will buffer all other + /// events. + /// + /// How should the caller handle this event? + /// 1. If the local node is not the proposer, the caller responds with with `None` as the block + /// hash. + /// 2. If the local node is the proposer and a block hash was supplied by the state machine, + /// the caller responds with the supplied block hash. + /// 3. If the local node is the proposer and no block hash was supplied by the state machine, + /// the caller must find/build a block to respond with. + StartRound(Option, Round), + /// Consensus message, can be both sent from and to the state machine. + Proposal(BlockHash, Round), + /// Consensus message, can be both sent from and to the state machine. + Prevote(BlockHash, Round), + /// Consensus message, can be both sent from and to the state machine. + Precommit(BlockHash, Round), + /// The state machine returns this event to the caller when a decision is reached. Not + /// expected as an inbound message. We presume that the caller is able to recover the set of + /// precommits which led to this decision from the information returned here. + Decision(BlockHash, Round), +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Step { + Propose, + Prevote, + Precommit, +} + +/// State Machine. Major assumptions: +/// 1. SHC handles replays and conflicts. +/// 2. SM must handle "out of order" messages (E.g. vote arrives before proposal). +/// 3. Only valid proposals (e.g. no NIL) +/// 4. No network failures - together with 3 this means we only support round 0. +pub struct StateMachine { + round: Round, + step: Step, + quorum: u32, + proposals: HashMap, + // {round: {block_hash: vote_count} + prevotes: HashMap>, + precommits: HashMap>, + // When true, the state machine will wait for a GetProposal event, buffering all other input + // events in `events_queue`. + starting_round: bool, + events_queue: VecDeque, +} + +impl StateMachine { + /// total_weight - the total voting weight of all validators for this height. + pub fn new(total_weight: u32) -> Self { + Self { + round: 0, + step: Step::Propose, + quorum: (2 * total_weight / 3) + 1, + proposals: HashMap::new(), + prevotes: HashMap::new(), + precommits: HashMap::new(), + starting_round: false, + events_queue: VecDeque::new(), + } + } + + pub fn quorum_size(&self) -> u32 { + self.quorum + } + + /// Starts the state machine, effectively calling `StartRound(0)` from the paper. This is needed + /// to trigger the first leader to propose. See [`StartRound`](StateMachineEvent::StartRound) + pub fn start(&mut self) -> VecDeque { + self.starting_round = true; + VecDeque::from([StateMachineEvent::StartRound(None, self.round)]) + } + + /// Process the incoming event. + /// + /// If we are waiting for a response to `StartRound` all other incoming events are buffered + /// until that response arrives. + /// + /// Returns a set of events for the caller to handle. The caller should not mirror the output + /// events back to the state machine, as it makes sure to handle them before returning. + // This means that the StateMachine handles events the same regardless of whether it was sent by + // self or a peer. This is in line with the Algorithm 1 in the paper and keeps the code simpler. + pub fn handle_event(&mut self, event: StateMachineEvent) -> VecDeque { + trace!("Handling event: {:?}", event); + // Mimic LOC 18 in the paper; the state machine doesn't + // handle any events until `getValue` completes. + if self.starting_round { + match event { + StateMachineEvent::StartRound(_, round) if round == self.round => { + self.events_queue.push_front(event); + } + _ => { + self.events_queue.push_back(event); + return VecDeque::new(); + } + } + } else { + self.events_queue.push_back(event); + } + + // The events queue only maintains state while we are waiting for a proposal. + let events_queue = std::mem::take(&mut self.events_queue); + self.handle_enqueued_events(events_queue) + } + + fn handle_enqueued_events( + &mut self, + mut events_queue: VecDeque, + ) -> VecDeque { + let mut output_events = VecDeque::new(); + while let Some(event) = events_queue.pop_front() { + // Handle a specific event and then decide which of the output events should also be + // sent to self. + for e in self.handle_event_internal(event) { + match e { + StateMachineEvent::Proposal(_, _) + | StateMachineEvent::Prevote(_, _) + | StateMachineEvent::Precommit(_, _) => { + events_queue.push_back(e.clone()); + } + StateMachineEvent::Decision(_, _) => { + output_events.push_back(e); + return output_events; + } + _ => {} + } + output_events.push_back(e); + } + } + output_events + } + + fn handle_event_internal(&mut self, event: StateMachineEvent) -> VecDeque { + match event { + StateMachineEvent::StartRound(block_hash, round) => { + self.handle_start_round(block_hash, round) + } + StateMachineEvent::Proposal(block_hash, round) => { + self.handle_proposal(block_hash, round) + } + StateMachineEvent::Prevote(block_hash, round) => self.handle_prevote(block_hash, round), + StateMachineEvent::Precommit(block_hash, round) => { + self.handle_precommit(block_hash, round) + } + StateMachineEvent::Decision(_, _) => { + unimplemented!( + "If the caller knows of a decision, it can just drop the state machine." + ) + } + } + } + + fn handle_start_round( + &mut self, + block_hash: Option, + round: u32, + ) -> VecDeque { + // TODO(matan): Will we allow other events (timeoutPropose) to exit this state? + assert!(self.starting_round); + assert_eq!(round, self.round); + self.starting_round = false; + + let Some(hash) = block_hash else { + // Validator. + return VecDeque::new(); + }; + + // Proposer. + VecDeque::from([StateMachineEvent::Proposal(hash, round)]) + } + + // A proposal from a peer (or self) node. + fn handle_proposal( + &mut self, + block_hash: BlockHash, + round: u32, + ) -> VecDeque { + let old = self.proposals.insert(round, block_hash); + assert!(old.is_none(), "SHC should handle conflicts & replays"); + if self.step != Step::Propose { + return VecDeque::new(); + } + + let mut output = VecDeque::from([StateMachineEvent::Prevote(block_hash, round)]); + output.append(&mut self.advance_to_step(Step::Prevote)); + output + } + + // A prevote from a peer (or self) node. + fn handle_prevote(&mut self, block_hash: BlockHash, round: u32) -> VecDeque { + assert_eq!(round, 0, "Only round 0 is supported in this milestone."); + let prevote_count = self.prevotes.entry(round).or_default().entry(block_hash).or_insert(0); + // TODO(matan): Use variable weight. + *prevote_count += 1; + if *prevote_count < self.quorum { + return VecDeque::new(); + } + if self.step != Step::Prevote { + return VecDeque::new(); + } + + self.send_precommit(block_hash, round) + } + + // A precommit from a peer (or self) node. + fn handle_precommit( + &mut self, + block_hash: BlockHash, + round: u32, + ) -> VecDeque { + assert_eq!(round, 0, "Only round 0 is supported in this milestone."); + let precommit_count = + self.precommits.entry(round).or_default().entry(block_hash).or_insert(0); + // TODO(matan): Use variable weight. + *precommit_count += 1; + if *precommit_count < self.quorum { + return VecDeque::new(); + } + let Some(proposed_value) = self.proposals.get(&round) else { + return VecDeque::new(); + }; + // TODO(matan): Handle this due to malicious proposer. + assert_eq!(*proposed_value, block_hash, "Proposal should match quorum."); + + VecDeque::from([StateMachineEvent::Decision(block_hash, round)]) + } + + fn advance_to_step(&mut self, step: Step) -> VecDeque { + self.step = step; + // Check for an existing quorum in case messages arrived out of order. + match self.step { + Step::Propose => { + unimplemented!("Handled by `advance_round`") + } + Step::Prevote => self.check_prevote_quorum(self.round), + Step::Precommit => self.check_precommit_quorum(self.round), + } + } + + fn check_prevote_quorum(&mut self, round: u32) -> VecDeque { + let Some((block_hash, count)) = leading_vote(&self.prevotes, round) else { + return VecDeque::new(); + }; + if *count < self.quorum { + return VecDeque::new(); + } + self.send_precommit(*block_hash, round) + } + + fn check_precommit_quorum(&mut self, round: u32) -> VecDeque { + let Some((block_hash, count)) = leading_vote(&self.precommits, round) else { + return VecDeque::new(); + }; + if *count < self.quorum { + return VecDeque::new(); + } + VecDeque::from([StateMachineEvent::Decision(*block_hash, round)]) + } + + fn send_precommit(&mut self, block_hash: BlockHash, round: u32) -> VecDeque { + let mut output = VecDeque::from([StateMachineEvent::Precommit(block_hash, round)]); + output.append(&mut self.advance_to_step(Step::Precommit)); + output + } +} + +fn leading_vote( + votes: &HashMap>, + round: u32, +) -> Option<(&BlockHash, &u32)> { + // We don't care which value is chosen in the case of a tie, since consensus requires 2/3+1. + votes.get(&round)?.iter().max_by(|a, b| a.1.cmp(b.1)) +} diff --git a/crates/sequencing/papyrus_consensus/src/state_machine_test.rs b/crates/sequencing/papyrus_consensus/src/state_machine_test.rs new file mode 100644 index 00000000000..1f0aef0fda2 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/state_machine_test.rs @@ -0,0 +1,91 @@ +use starknet_api::block::BlockHash; +use starknet_types_core::felt::Felt; +use test_case::test_case; + +use super::Round; +use crate::state_machine::{StateMachine, StateMachineEvent}; + +const BLOCK_HASH: BlockHash = BlockHash(Felt::ONE); +const ROUND: Round = 0; + +#[test_case(true; "proposer")] +#[test_case(false; "validator")] +fn events_arrive_in_ideal_order(is_proposer: bool) { + let mut state_machine = StateMachine::new(4); + + let mut events = state_machine.start(); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::StartRound(None, ROUND)); + if is_proposer { + events = state_machine.handle_event(StateMachineEvent::StartRound(Some(BLOCK_HASH), ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Proposal(BLOCK_HASH, ROUND)); + } else { + state_machine.handle_event(StateMachineEvent::StartRound(None, ROUND)); + assert!(events.is_empty()); + events = state_machine.handle_event(StateMachineEvent::Proposal(BLOCK_HASH, ROUND)); + } + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Prevote(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); + + events = state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); + + events = state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Precommit(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); + + events = state_machine.handle_event(StateMachineEvent::Precommit(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); + + events = state_machine.handle_event(StateMachineEvent::Precommit(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Decision(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); +} + +#[test] +fn validator_receives_votes_first() { + let mut state_machine = StateMachine::new(4); + + let mut events = state_machine.start(); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::StartRound(None, ROUND)); + assert!(events.is_empty(), "{:?}", events); + events = state_machine.handle_event(StateMachineEvent::StartRound(None, ROUND)); + assert!(events.is_empty(), "{:?}", events); + + // Receives votes from all the other nodes first (more than minimum for a quorum). + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Precommit(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Precommit(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Precommit(BLOCK_HASH, ROUND))); + assert!(events.is_empty(), "{:?}", events); + + // Finally the proposal arrives. + events = state_machine.handle_event(StateMachineEvent::Proposal(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Prevote(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Precommit(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Decision(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); +} + +#[test] +fn buffer_events_during_start_round() { + let mut state_machine = StateMachine::new(4); + let mut events = state_machine.start(); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::StartRound(None, 0)); + assert!(events.is_empty(), "{:?}", events); + + // TODO(matan): When we support NIL votes, we should send them. Real votes without the proposal + // doesn't make sense. + events.append(&mut state_machine.handle_event(StateMachineEvent::Proposal(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + events.append(&mut state_machine.handle_event(StateMachineEvent::Prevote(BLOCK_HASH, ROUND))); + assert!(events.is_empty(), "{:?}", events); + + // Node finishes building the proposal. + events = state_machine.handle_event(StateMachineEvent::StartRound(None, 0)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Prevote(BLOCK_HASH, ROUND)); + assert_eq!(events.pop_front().unwrap(), StateMachineEvent::Precommit(BLOCK_HASH, ROUND)); + assert!(events.is_empty(), "{:?}", events); +} diff --git a/crates/sequencing/papyrus_consensus/src/test_utils.rs b/crates/sequencing/papyrus_consensus/src/test_utils.rs new file mode 100644 index 00000000000..098dc262987 --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/test_utils.rs @@ -0,0 +1,61 @@ +use async_trait::async_trait; +use futures::channel::{mpsc, oneshot}; +use mockall::mock; +use papyrus_protobuf::consensus::ConsensusMessage; +use starknet_api::block::{BlockHash, BlockNumber}; + +use crate::types::{ConsensusBlock, ConsensusContext, ConsensusError, ProposalInit, ValidatorId}; + +/// Define a consensus block which can be used to enable auto mocking Context. +#[derive(Debug, PartialEq, Clone)] +pub struct TestBlock { + pub content: Vec, + pub id: BlockHash, +} + +impl ConsensusBlock for TestBlock { + type ProposalChunk = u32; + type ProposalIter = std::vec::IntoIter; + + fn id(&self) -> BlockHash { + self.id + } + + fn proposal_iter(&self) -> Self::ProposalIter { + self.content.clone().into_iter() + } +} + +// TODO(matan): When QSelf is supported, switch to automocking `ConsensusContext`. +mock! { + pub TestContext {} + + #[async_trait] + impl ConsensusContext for TestContext { + type Block = TestBlock; + + async fn build_proposal(&self, height: BlockNumber) -> ( + mpsc::Receiver, + oneshot::Receiver + ); + + async fn validate_proposal( + &self, + height: BlockNumber, + content: mpsc::Receiver + ) -> oneshot::Receiver; + + async fn validators(&self, height: BlockNumber) -> Vec; + + fn proposer(&self, validators: &[ValidatorId], height: BlockNumber) -> ValidatorId; + + async fn broadcast(&mut self, message: ConsensusMessage) -> Result<(), ConsensusError>; + + async fn propose( + &self, + init: ProposalInit, + content_receiver: mpsc::Receiver, + fin_receiver: oneshot::Receiver, + ) -> Result<(), ConsensusError>; + } +} diff --git a/crates/sequencing/papyrus_consensus/src/types.rs b/crates/sequencing/papyrus_consensus/src/types.rs new file mode 100644 index 00000000000..4ac435d6a5a --- /dev/null +++ b/crates/sequencing/papyrus_consensus/src/types.rs @@ -0,0 +1,170 @@ +use std::fmt::Debug; + +use async_trait::async_trait; +use futures::channel::{mpsc, oneshot}; +use papyrus_protobuf::consensus::{ConsensusMessage, Vote}; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::ContractAddress; + +/// Used to identify the node by consensus. +/// 1. This ID is derived from the id registered with Starknet's L2 staking contract. +/// 2. We must be able to derive the public key associated with this ID for the sake of validating +/// signatures. +// TODO(matan): Determine the actual type of NodeId. +pub type ValidatorId = ContractAddress; +pub type Round = u32; + +/// Interface that any concrete block type must implement to be used by consensus. +/// +/// In principle Consensus does not care about the content of a block. In practice though it will +/// need to perform certain activities with blocks: +/// 1. All proposals for a given height are held by consensus for book keeping, with only the +/// decided block returned to ConsensusContext. +/// 2. Tendermint may require re-broadcasting an old proposal [Line 16 of Algorithm 1](https://arxiv.org/pdf/1807.04938) +// This trait was designed with the following in mind: +// 1. It must allow `ConsensusContext` to be object safe. This precludes generics. +// 2. Starknet blocks are expected to be quite large, and we expect consensus to hold something akin +// to a reference with a small stack size and cheap shallow cloning. +pub trait ConsensusBlock: Send { + /// The chunks of content returned when iterating the proposal. + // In practice I expect this to match the type sent to the network + // (papyrus_protobuf::ConsensusMessage), and not to be specific to just the block's content. + type ProposalChunk; + /// Iterator for accessing the proposal's content. + // An associated type is used instead of returning `impl Iterator` due to object safety. + type ProposalIter: Iterator; + + /// Identifies the block for the sake of Consensus voting. + // The proposal's round must not be included in the ID, as, beyond being a detail of + // consensus, Tendermint must be able to progress a value across multiple rounds of a given + // height. + // + // Including a proposal's height in ID is optional from the perspective of consensus. + // Since the proposal as well as votes sign not only on the block ID but also the height at + // which they vote, not including height poses no security risk. Including it has no impact on + // Tendermint. + fn id(&self) -> BlockHash; + + /// Returns an iterator for streaming out this block as a proposal to other nodes. + // Note on the ownership and lifetime model. This call is done by reference, yet the returned + // iterator is implicitly an owning iterator. + // 1. Why did we not want reference iteration? This would require a lifetime to be part of the + // type definition for `ProposalIter` and therefore `ConsensusBlock`. This results in a lot + // of lifetime pollution making it much harder to work with this type; attempted both options + // from here: + // https://stackoverflow.com/questions/33734640/how-do-i-specify-lifetime-parameters-in-an-associated-type + // 2. Why is owning iteration reasonable? The expected use case for this is to stream out the + // proposal to other nodes, which implies ownership of data, not just a reference for + // internal use. We also expect the actual object implementing this trait to be itself a + // reference to the underlying data, and so returning an "owning" iterator to be relatively + // cheap. + // TODO(matan): Consider changing ConsensusBlock to `IntoIterator + Clone` and removing + // `proposal_iter`. + fn proposal_iter(&self) -> Self::ProposalIter; +} + +/// Interface for consensus to call out to the node. +#[async_trait] +pub trait ConsensusContext { + /// The [block](`ConsensusBlock`) type built by `ConsensusContext` from a proposal. + // We use an associated type since consensus is indifferent to the actual content of a proposal, + // but we cannot use generics due to object safety. + type Block: ConsensusBlock; + + // TODO(matan): The oneshot for receiving the build block could be generalized to just be some + // future which returns a block. + + /// This function is called by consensus to request a block from the node. It expects that this + /// call will return immediately and that consensus can then stream in the block's content in + /// parallel to the block being built. + /// + /// Params: + /// - `height`: The height of the block to be built. Specifically this indicates the initial + /// state of the block. + /// + /// Returns: + /// - A receiver for the stream of the block's content. + /// - A receiver for the fully built block once ConsensusContext has finished streaming out the + /// content and building it. If the block fails to be built, the Sender will be dropped by + /// ConsensusContext. + async fn build_proposal( + &self, + height: BlockNumber, + ) -> ( + mpsc::Receiver<::ProposalChunk>, + oneshot::Receiver, + ); + + /// This function is called by consensus to validate a block. It expects that this call will + /// return immediately and that context can then stream in the block's content in parallel to + /// consensus continuing to handle other tasks. + /// + /// Params: + /// - `height`: The height of the block to be built. Specifically this indicates the initial + /// state of the block. + /// - A receiver for the stream of the block's content. + /// + /// Returns: + /// - A receiver for the fully built block. If a valid block cannot be built the Sender will be + /// dropped by ConsensusContext. + async fn validate_proposal( + &self, + height: BlockNumber, + content: mpsc::Receiver<::ProposalChunk>, + ) -> oneshot::Receiver; + + /// Get the set of validators for a given height. These are the nodes that can propose and vote + /// on blocks. + // TODO(matan): We expect this to change in the future to BTreeMap. Why? + // 1. Map - The nodes will have associated information (e.g. voting weight). + // 2. BTreeMap - We want a stable ordering of the nodes for deterministic leader selection. + async fn validators(&self, height: BlockNumber) -> Vec; + + /// Calculates the ID of the Proposer based on the inputs. + fn proposer(&self, validators: &[ValidatorId], height: BlockNumber) -> ValidatorId; + + async fn broadcast(&mut self, message: ConsensusMessage) -> Result<(), ConsensusError>; + + /// This should be non-blocking. Meaning it returns immediately and waits to receive from the + /// input channels in parallel (ie on a separate task). + // TODO(matan): change to just be a generic broadcast function. + async fn propose( + &self, + init: ProposalInit, + content_receiver: mpsc::Receiver<::ProposalChunk>, + fin_receiver: oneshot::Receiver, + ) -> Result<(), ConsensusError>; +} + +#[derive(PartialEq)] +pub struct Decision { + pub precommits: Vec, + pub block: BlockT, +} + +impl Debug for Decision { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Decision") + .field("block_id", &self.block.id()) + .field("precommits", &self.precommits) + .finish() + } +} + +#[derive(PartialEq, Debug, Clone)] +pub struct ProposalInit { + pub height: BlockNumber, + pub proposer: ValidatorId, +} + +#[derive(thiserror::Error, PartialEq, Debug)] +pub enum ConsensusError { + #[error(transparent)] + Canceled(#[from] oneshot::Canceled), + #[error("Invalid proposal sent by peer {0:?} at height {1}: {2}")] + InvalidProposal(ValidatorId, BlockNumber, String), + #[error(transparent)] + SendError(#[from] mpsc::SendError), + #[error("Conflicting messages for block {0}. Old: {1:?}, New: {2:?}")] + Equivocation(BlockNumber, ConsensusMessage, ConsensusMessage), +} diff --git a/crates/starknet_api/Cargo.toml b/crates/starknet_api/Cargo.toml new file mode 100644 index 00000000000..d7047ff5f39 --- /dev/null +++ b/crates/starknet_api/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "starknet_api" +version = "0.13.0-rc.0" +edition = "2021" +repository = "https://github.com/starkware-libs/starknet-api" +license = "Apache-2.0" +license-file = "LICENSE" +description = "Starknet Rust types related to computation and execution." + +[features] +testing = [] + +[dependencies] +bitvec = "1.0.1" +cairo-lang-starknet-classes = "2.7.0-dev.0" +derive_more = "0.99.17" +hex = "0.4.3" +indexmap = { version = "2.1.0", features = ["serde"] } +itertools = "0.12.1" +once_cell = "1.17.1" +primitive-types = { version = "0.12.1", features = ["serde"] } +serde = { version = "1.0.130", features = ["derive", "rc"] } +serde_json = "1.0.81" +sha3 = "0.10.8" +starknet-crypto = "0.5.1" +starknet-types-core = { version = "0.1.4", features = ["hash"] } +strum = "0.24.1" +strum_macros = "0.24.3" +thiserror = "1.0.31" + +[dev-dependencies] +assert_matches = "1.5.0" +rstest = "0.17.0" diff --git a/crates/starknet_api/scripts/rust_fmt.sh b/crates/starknet_api/scripts/rust_fmt.sh new file mode 100755 index 00000000000..a220c5944f1 --- /dev/null +++ b/crates/starknet_api/scripts/rust_fmt.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cargo +nightly-2023-07-05 fmt --all -- "$@" diff --git a/crates/starknet_api/src/block.rs b/crates/starknet_api/src/block.rs new file mode 100644 index 00000000000..e38aa490b56 --- /dev/null +++ b/crates/starknet_api/src/block.rs @@ -0,0 +1,244 @@ +#[cfg(test)] +#[path = "block_test.rs"] +mod block_test; + +use std::fmt::Display; + +use derive_more::Display; +use serde::{Deserialize, Serialize}; +use starknet_types_core::hash::{Poseidon, StarkHash as CoreStarkHash}; + +use crate::core::{ + EventCommitment, GlobalRoot, ReceiptCommitment, SequencerContractAddress, SequencerPublicKey, + StateDiffCommitment, TransactionCommitment, +}; +use crate::crypto::utils::{verify_message_hash_signature, CryptoError, Signature}; +use crate::data_availability::L1DataAvailabilityMode; +use crate::hash::StarkHash; +use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex}; +use crate::transaction::{Transaction, TransactionHash, TransactionOutput}; + +/// A block. +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct Block { + // TODO: Consider renaming to BlockWithCommitments, for the header use BlockHeaderWithoutHash + // instead of BlockHeader, and add BlockHeaderCommitments and BlockHash fields. + pub header: BlockHeader, + pub body: BlockBody, +} + +/// A version of the Starknet protocol used when creating a block. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StarknetVersion(pub String); + +impl Default for StarknetVersion { + fn default() -> Self { + Self("0.0.0".to_string()) + } +} + +impl Display for StarknetVersion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +/// The header of a [Block](`crate::block::Block`). +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct BlockHeader { + // TODO: Consider removing the block hash from the header (note it can be computed from + // the rest of the fields. + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + // The optional fields below are not included in older versions of the block. + // Currently they are not included in any RPC spec, so we skip their serialization. + // TODO: Once all environments support these fields, remove the Option (make sure to + // update/resync any storage is missing the data). + #[serde(skip_serializing)] + pub state_diff_commitment: Option, + #[serde(skip_serializing)] + pub state_diff_length: Option, + #[serde(skip_serializing)] + pub transaction_commitment: Option, + #[serde(skip_serializing)] + pub event_commitment: Option, + #[serde(skip_serializing)] + pub n_transactions: usize, + #[serde(skip_serializing)] + pub n_events: usize, + #[serde(skip_serializing)] + pub receipt_commitment: Option, + pub starknet_version: StarknetVersion, +} + +/// The header of a [Block](`crate::block::Block`) without hashing. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct BlockHeaderWithoutHash { + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub starknet_version: StarknetVersion, +} + +/// The [transactions](`crate::transaction::Transaction`) and their +/// [outputs](`crate::transaction::TransactionOutput`) in a [block](`crate::block::Block`). +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct BlockBody { + pub transactions: Vec, + pub transaction_outputs: Vec, + pub transaction_hashes: Vec, +} + +/// The status of a [Block](`crate::block::Block`). +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub enum BlockStatus { + /// A pending block; i.e., a block that is yet to be closed. + #[serde(rename = "PENDING")] + Pending, + /// A block that was created on L2. + #[serde(rename = "ACCEPTED_ON_L2")] + AcceptedOnL2, + /// A block that was accepted on L1. + #[serde(rename = "ACCEPTED_ON_L1")] + AcceptedOnL1, + /// A block rejected on L1. + #[serde(rename = "REJECTED")] + Rejected, +} + +/// The hash of a [Block](`crate::block::Block`). +#[derive( + Debug, + Default, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct BlockHash(pub StarkHash); + +/// The number of a [Block](`crate::block::Block`). +#[derive( + Debug, + Default, + Copy, + Display, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, +)] +pub struct BlockNumber(pub u64); + +impl BlockNumber { + /// Returns the next block number, without checking if it's in range. + pub fn unchecked_next(&self) -> BlockNumber { + BlockNumber(self.0 + 1) + } + + /// Returns the next block number, or None if the next block number is out of range. + pub fn next(&self) -> Option { + Some(Self(self.0.checked_add(1)?)) + } + + /// Returns the previous block number, or None if the previous block number is out of range. + pub fn prev(&self) -> Option { + match self.0 { + 0 => None, + i => Some(BlockNumber(i - 1)), + } + } + + /// Returns an iterator over the block numbers from self to up_to (exclusive). + pub fn iter_up_to(&self, up_to: Self) -> impl Iterator { + let range = self.0..up_to.0; + range.map(Self) + } +} + +// TODO(yair): Consider moving GasPricePerToken and GasPrice to core. +/// The gas price per token. +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct GasPricePerToken { + pub price_in_fri: GasPrice, + pub price_in_wei: GasPrice, +} + +/// The gas price at a [Block](`crate::block::Block`). +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +#[serde(from = "PrefixedBytesAsHex<16_usize>", into = "PrefixedBytesAsHex<16_usize>")] +pub struct GasPrice(pub u128); + +impl From> for GasPrice { + fn from(val: PrefixedBytesAsHex<16_usize>) -> Self { + GasPrice(u128::from_be_bytes(val.0)) + } +} + +impl From for PrefixedBytesAsHex<16_usize> { + fn from(val: GasPrice) -> Self { + BytesAsHex(val.0.to_be_bytes()) + } +} + +/// The timestamp of a [Block](`crate::block::Block`). +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct BlockTimestamp(pub u64); + +/// The signature of a [Block](`crate::block::Block`), signed by the sequencer. The signed message +/// is defined as poseidon_hash(block_hash, state_diff_commitment). +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct BlockSignature(pub Signature); + +/// The error type returned from the block verification functions. +#[derive(thiserror::Error, Clone, Debug)] +pub enum BlockVerificationError { + #[error("Failed to verify the signature of block {block_hash}. Error: {error}")] + BlockSignatureVerificationFailed { block_hash: BlockHash, error: CryptoError }, +} + +/// Verifies that the the block header was signed by the expected sequencer. +pub fn verify_block_signature( + sequencer_pub_key: &SequencerPublicKey, + signature: &BlockSignature, + state_diff_commitment: &GlobalRoot, + block_hash: &BlockHash, +) -> Result { + let message_hash = Poseidon::hash_array(&[block_hash.0, state_diff_commitment.0]); + verify_message_hash_signature(&message_hash, &signature.0, &sequencer_pub_key.0).map_err( + |err| BlockVerificationError::BlockSignatureVerificationFailed { + block_hash: *block_hash, + error: err, + }, + ) +} diff --git a/crates/starknet_api/src/block_hash.rs b/crates/starknet_api/src/block_hash.rs new file mode 100644 index 00000000000..6a476942061 --- /dev/null +++ b/crates/starknet_api/src/block_hash.rs @@ -0,0 +1,8 @@ +pub mod block_hash_calculator; +pub mod event_commitment; +pub mod receipt_commitment; +pub mod state_diff_hash; +pub mod transaction_commitment; + +#[cfg(test)] +pub mod test_utils; diff --git a/crates/starknet_api/src/block_hash/block_hash_calculator.rs b/crates/starknet_api/src/block_hash/block_hash_calculator.rs new file mode 100644 index 00000000000..72a4bdb6334 --- /dev/null +++ b/crates/starknet_api/src/block_hash/block_hash_calculator.rs @@ -0,0 +1,158 @@ +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::Poseidon; + +use super::event_commitment::{calculate_event_commitment, EventLeafElement}; +use super::receipt_commitment::{calculate_receipt_commitment, ReceiptElement}; +use super::state_diff_hash::calculate_state_diff_hash; +use super::transaction_commitment::{calculate_transaction_commitment, TransactionLeafElement}; +use crate::block::{BlockHash, BlockHeaderWithoutHash}; +use crate::core::{EventCommitment, ReceiptCommitment, StateDiffCommitment, TransactionCommitment}; +use crate::crypto::utils::HashChain; +use crate::data_availability::L1DataAvailabilityMode; +use crate::state::ThinStateDiff; +use crate::transaction::{ + Event, Fee, GasVector, MessageToL1, TransactionExecutionStatus, TransactionHash, + TransactionSignature, +}; +use crate::transaction_hash::ascii_as_felt; + +#[cfg(test)] +#[path = "block_hash_calculator_test.rs"] +mod block_hash_calculator_test; + +static STARKNET_BLOCK_HASH0: Lazy = Lazy::new(|| { + ascii_as_felt("STARKNET_BLOCK_HASH0").expect("ascii_as_felt failed for 'STARKNET_BLOCK_HASH0'") +}); + +/// The common fields of transaction output types. +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +pub struct TransactionOutputForHash { + pub actual_fee: Fee, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub gas_consumed: GasVector, + pub messages_sent: Vec, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +pub struct TransactionHashingData { + pub transaction_signature: Option, + pub transaction_output: TransactionOutputForHash, + pub transaction_hash: TransactionHash, +} + +/// Commitments of a block. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub struct BlockHeaderCommitments { + pub transaction_commitment: TransactionCommitment, + pub event_commitment: EventCommitment, + pub receipt_commitment: ReceiptCommitment, + pub state_diff_commitment: StateDiffCommitment, + pub concatenated_counts: Felt, +} + +/// Poseidon ( +/// “STARKNET_BLOCK_HASH0”, block_number, global_state_root, sequencer_address, +/// block_timestamp, concat_counts, state_diff_hash, transaction_commitment, +/// event_commitment, receipt_commitment, gas_price_wei, gas_price_fri, +/// data_gas_price_wei, data_gas_price_fri, starknet_version, 0, parent_block_hash +/// ). +pub fn calculate_block_hash( + header: BlockHeaderWithoutHash, + block_commitments: BlockHeaderCommitments, +) -> BlockHash { + BlockHash( + HashChain::new() + .chain(&STARKNET_BLOCK_HASH0) + .chain(&header.block_number.0.into()) + .chain(&header.state_root.0) + .chain(&header.sequencer.0) + .chain(&header.timestamp.0.into()) + .chain(&block_commitments.concatenated_counts) + .chain(&block_commitments.state_diff_commitment.0.0) + .chain(&block_commitments.transaction_commitment.0) + .chain(&block_commitments.event_commitment.0) + .chain(&block_commitments.receipt_commitment.0) + .chain(&header.l1_gas_price.price_in_wei.0.into()) + .chain(&header.l1_gas_price.price_in_fri.0.into()) + .chain(&header.l1_data_gas_price.price_in_wei.0.into()) + .chain(&header.l1_data_gas_price.price_in_fri.0.into()) + .chain(&ascii_as_felt(&header.starknet_version.0).expect("Expect ASCII version")) + .chain(&Felt::ZERO) + .chain(&header.parent_hash.0) + .get_poseidon_hash(), + ) +} + +/// Calculates the commitments of the transactions data for the block hash. +pub fn calculate_block_commitments( + transactions_data: &[TransactionHashingData], + state_diff: &ThinStateDiff, + l1_da_mode: L1DataAvailabilityMode, +) -> BlockHeaderCommitments { + let transaction_leaf_elements: Vec = + transactions_data.iter().map(TransactionLeafElement::from).collect(); + let transaction_commitment = + calculate_transaction_commitment::(&transaction_leaf_elements); + + let event_leaf_elements: Vec = transactions_data + .iter() + .flat_map(|transaction_data| { + transaction_data.transaction_output.events.iter().map(|event| EventLeafElement { + event: event.clone(), + transaction_hash: transaction_data.transaction_hash, + }) + }) + .collect(); + let event_commitment = calculate_event_commitment::(&event_leaf_elements); + + let receipt_elements: Vec = + transactions_data.iter().map(ReceiptElement::from).collect(); + let receipt_commitment = calculate_receipt_commitment::(&receipt_elements); + let state_diff_commitment = calculate_state_diff_hash(state_diff); + let concatenated_counts = concat_counts( + transactions_data.len(), + event_leaf_elements.len(), + state_diff.len(), + l1_da_mode, + ); + BlockHeaderCommitments { + transaction_commitment, + event_commitment, + receipt_commitment, + state_diff_commitment, + concatenated_counts, + } +} + +// A single felt: [ +// transaction_count (64 bits) | event_count (64 bits) | state_diff_length (64 bits) +// | L1 data availability mode: 0 for calldata, 1 for blob (1 bit) | 0 ... +// ]. +fn concat_counts( + transaction_count: usize, + event_count: usize, + state_diff_length: usize, + l1_data_availability_mode: L1DataAvailabilityMode, +) -> Felt { + let l1_data_availability_byte: u8 = match l1_data_availability_mode { + L1DataAvailabilityMode::Calldata => 0, + L1DataAvailabilityMode::Blob => 0b10000000, + }; + let concat_bytes = [ + to_64_bits(transaction_count).as_slice(), + to_64_bits(event_count).as_slice(), + to_64_bits(state_diff_length).as_slice(), + &[l1_data_availability_byte], + &[0_u8; 7], // zero padding + ] + .concat(); + Felt::from_bytes_be_slice(concat_bytes.as_slice()) +} + +fn to_64_bits(num: usize) -> [u8; 8] { + let sized_transaction_count: u64 = num.try_into().expect("Expect usize is at most 8 bytes"); + sized_transaction_count.to_be_bytes() +} diff --git a/crates/starknet_api/src/block_hash/block_hash_calculator_test.rs b/crates/starknet_api/src/block_hash/block_hash_calculator_test.rs new file mode 100644 index 00000000000..60ddcff5fd6 --- /dev/null +++ b/crates/starknet_api/src/block_hash/block_hash_calculator_test.rs @@ -0,0 +1,137 @@ +use starknet_types_core::felt::Felt; + +use super::concat_counts; +use crate::block::{ + BlockHash, BlockHeaderWithoutHash, BlockNumber, BlockTimestamp, GasPrice, GasPricePerToken, + StarknetVersion, +}; +use crate::block_hash::block_hash_calculator::{ + calculate_block_commitments, calculate_block_hash, BlockHeaderCommitments, + TransactionHashingData, +}; +use crate::block_hash::test_utils::{get_state_diff, get_transaction_output}; +use crate::core::{ + ContractAddress, EventCommitment, GlobalRoot, PatriciaKey, ReceiptCommitment, + SequencerContractAddress, StateDiffCommitment, TransactionCommitment, +}; +use crate::data_availability::L1DataAvailabilityMode; +use crate::felt; +use crate::hash::PoseidonHash; +use crate::transaction::{TransactionHash, TransactionSignature}; + +/// Macro to test if changing any field in the header or commitments +/// results a change in the block hash. +/// The macro clones the original header and commitments, modifies each specified field, +/// and asserts that the block hash changes as a result. +macro_rules! test_hash_changes { + ($header:expr, $commitments:expr, header_fields => { $($header_field:ident),* }, commitments_fields => { $($commitments_field:ident),* }) => { + { + let original_hash = calculate_block_hash($header.clone(), $commitments.clone()); + + $( + // Test changing the field in the header. + let mut modified_header = $header.clone(); + modified_header.$header_field = Default::default(); + let new_hash = calculate_block_hash(modified_header, $commitments.clone()); + assert_ne!(original_hash, new_hash, concat!("Hash should change when ", stringify!($header_field), " is modified")); + )* + + $( + // Test changing the field in the commitments. + let mut modified_commitments = $commitments.clone(); + modified_commitments.$commitments_field = Default::default(); + let new_hash = calculate_block_hash($header.clone(), modified_commitments); + assert_ne!(original_hash, new_hash, concat!("Hash should change when ", stringify!($commitments_field), " is modified")); + )* + } + }; +} + +#[test] +fn test_block_hash_regression() { + let block_header = BlockHeaderWithoutHash { + block_number: BlockNumber(1_u64), + state_root: GlobalRoot(Felt::from(2_u8)), + sequencer: SequencerContractAddress(ContractAddress(PatriciaKey::from(3_u8))), + timestamp: BlockTimestamp(4), + l1_da_mode: L1DataAvailabilityMode::Blob, + l1_gas_price: GasPricePerToken { price_in_fri: GasPrice(6), price_in_wei: GasPrice(7) }, + l1_data_gas_price: GasPricePerToken { + price_in_fri: GasPrice(10), + price_in_wei: GasPrice(9), + }, + starknet_version: StarknetVersion("10".to_owned()), + parent_hash: BlockHash(Felt::from(11_u8)), + }; + let transactions_data = vec![TransactionHashingData { + transaction_signature: Some(TransactionSignature(vec![Felt::TWO, Felt::THREE])), + transaction_output: get_transaction_output(), + transaction_hash: TransactionHash(Felt::ONE), + }]; + + let state_diff = get_state_diff(); + let block_commitments = + calculate_block_commitments(&transactions_data, &state_diff, block_header.l1_da_mode); + + let expected_hash = felt!("0x061e4998d51a248f1d0288d7e17f6287757b0e5e6c5e1e58ddf740616e312134"); + + assert_eq!(BlockHash(expected_hash), calculate_block_hash(block_header, block_commitments),); +} + +#[test] +fn concat_counts_test() { + let concated = concat_counts(4, 3, 2, L1DataAvailabilityMode::Blob); + let expected_felt = felt!("0x0000000000000004000000000000000300000000000000028000000000000000"); + assert_eq!(concated, expected_felt) +} + +/// Test that if one of the input to block hash changes, the hash changes. +#[test] +fn change_field_of_hash_input() { + let header = BlockHeaderWithoutHash { + parent_hash: BlockHash(Felt::ONE), + block_number: BlockNumber(1), + l1_gas_price: GasPricePerToken { price_in_fri: GasPrice(1), price_in_wei: GasPrice(1) }, + l1_data_gas_price: GasPricePerToken { + price_in_fri: GasPrice(1), + price_in_wei: GasPrice(1), + }, + state_root: GlobalRoot(Felt::ONE), + sequencer: SequencerContractAddress(ContractAddress::from(1_u128)), + timestamp: BlockTimestamp(1), + l1_da_mode: L1DataAvailabilityMode::Blob, + starknet_version: StarknetVersion("0.1.0".to_string()), + }; + + let block_commitments = BlockHeaderCommitments { + transaction_commitment: TransactionCommitment(Felt::ONE), + event_commitment: EventCommitment(Felt::ONE), + receipt_commitment: ReceiptCommitment(Felt::ONE), + state_diff_commitment: StateDiffCommitment(PoseidonHash(Felt::ONE)), + concatenated_counts: Felt::ONE, + }; + + // Test that changing any of the fields in the header or the commitments changes the hash. + test_hash_changes!( + header, + block_commitments, + header_fields => { + parent_hash, + block_number, + l1_gas_price, + l1_data_gas_price, + state_root, + sequencer, + timestamp, + starknet_version + }, + commitments_fields => { + transaction_commitment, + event_commitment, + receipt_commitment, + state_diff_commitment, + concatenated_counts + } + ); + // TODO(Aviv, 10/06/2024): add tests that changes the first hash input, and the const zero. +} diff --git a/crates/starknet_api/src/block_hash/event_commitment.rs b/crates/starknet_api/src/block_hash/event_commitment.rs new file mode 100644 index 00000000000..aa0469b1c57 --- /dev/null +++ b/crates/starknet_api/src/block_hash/event_commitment.rs @@ -0,0 +1,42 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::StarkHash; + +use crate::core::EventCommitment; +use crate::crypto::patricia_hash::calculate_root; +use crate::crypto::utils::HashChain; +use crate::transaction::{Event, TransactionHash}; + +#[cfg(test)] +#[path = "event_commitment_test.rs"] +mod event_commitment_test; + +/// The elements used to calculate a leaf in the transactions Patricia tree. +#[derive(Clone)] +pub struct EventLeafElement { + pub(crate) event: Event, + pub(crate) transaction_hash: TransactionHash, +} + +/// Returns the root of a Patricia tree where each leaf is an event hash. +pub fn calculate_event_commitment( + event_leaf_elements: &[EventLeafElement], +) -> EventCommitment { + let event_leaves = event_leaf_elements.iter().map(calculate_event_hash).collect(); + EventCommitment(calculate_root::(event_leaves)) +} + +// Poseidon( +// from_address, transaction_hash, +// num_keys, key0, key1, ..., +// num_contents, content0, content1, ... +// ). +fn calculate_event_hash(event_leaf_element: &EventLeafElement) -> Felt { + let keys = &event_leaf_element.event.content.keys.iter().map(|k| k.0).collect::>(); + let data = &event_leaf_element.event.content.data.0; + HashChain::new() + .chain(event_leaf_element.event.from_address.0.key()) + .chain(&event_leaf_element.transaction_hash.0) + .chain_size_and_elements(keys) + .chain_size_and_elements(data) + .get_poseidon_hash() +} diff --git a/crates/starknet_api/src/block_hash/event_commitment_test.rs b/crates/starknet_api/src/block_hash/event_commitment_test.rs new file mode 100644 index 00000000000..132bc86d87c --- /dev/null +++ b/crates/starknet_api/src/block_hash/event_commitment_test.rs @@ -0,0 +1,44 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::Poseidon; + +use super::{calculate_event_commitment, calculate_event_hash, EventLeafElement}; +use crate::core::{ContractAddress, EventCommitment, PatriciaKey}; +use crate::transaction::{Event, EventContent, EventData, EventKey, TransactionHash}; +use crate::{contract_address, felt, patricia_key}; + +#[test] +fn test_event_commitment_regression() { + let event_leaf_elements = + [get_event_leaf_element(0), get_event_leaf_element(1), get_event_leaf_element(2)]; + + let expected_root = felt!("0x069bb140ddbbeb01d81c7201ecfb933031306e45dab9c77ff9f9ba3cd4c2b9c3"); + + assert_eq!( + EventCommitment(expected_root), + calculate_event_commitment::(&event_leaf_elements), + ); +} + +#[test] +fn test_event_hash_regression() { + let event_leaf_element = get_event_leaf_element(2); + + let expected_hash = felt!("0x367807f532742a4dcbe2d8a47b974b22dd7496faa75edc64a3a5fdb6709057"); + + assert_eq!(expected_hash, calculate_event_hash(&event_leaf_element)); +} + +fn get_event_leaf_element(seed: u8) -> EventLeafElement { + EventLeafElement { + event: Event { + from_address: contract_address!(format!("{:x}", seed + 8).as_str()), + content: EventContent { + keys: [seed, seed + 1].iter().map(|key| EventKey(Felt::from(*key))).collect(), + data: EventData( + [seed + 2, seed + 3, seed + 4].into_iter().map(Felt::from).collect(), + ), + }, + }, + transaction_hash: TransactionHash(felt!("0x1234")), + } +} diff --git a/crates/starknet_api/src/block_hash/receipt_commitment.rs b/crates/starknet_api/src/block_hash/receipt_commitment.rs new file mode 100644 index 00000000000..8dfd104c3ca --- /dev/null +++ b/crates/starknet_api/src/block_hash/receipt_commitment.rs @@ -0,0 +1,90 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::StarkHash; + +use super::block_hash_calculator::{TransactionHashingData, TransactionOutputForHash}; +use crate::core::ReceiptCommitment; +use crate::crypto::patricia_hash::calculate_root; +use crate::crypto::utils::HashChain; +use crate::hash::starknet_keccak_hash; +use crate::transaction::{GasVector, MessageToL1, TransactionExecutionStatus, TransactionHash}; + +#[cfg(test)] +#[path = "receipt_commitment_test.rs"] +mod receipt_commitment_test; + +// The elements used to calculate a leaf in the transactions Patricia tree. +#[derive(Clone)] +pub struct ReceiptElement { + pub transaction_hash: TransactionHash, + pub transaction_output: TransactionOutputForHash, +} + +impl From<&TransactionHashingData> for ReceiptElement { + fn from(transaction_data: &TransactionHashingData) -> Self { + Self { + transaction_hash: transaction_data.transaction_hash, + transaction_output: transaction_data.transaction_output.clone(), + } + } +} + +/// Returns the root of a Patricia tree where each leaf is a receipt hash. +pub fn calculate_receipt_commitment( + receipt_elements: &[ReceiptElement], +) -> ReceiptCommitment { + ReceiptCommitment(calculate_root::( + receipt_elements.iter().map(calculate_receipt_hash).collect(), + )) +} + +// Poseidon( +// transaction hash, amount of fee paid, hash of messages sent, revert reason, +// execution resources +// ). +fn calculate_receipt_hash(receipt_element: &ReceiptElement) -> Felt { + let hash_chain = HashChain::new() + .chain(&receipt_element.transaction_hash) + .chain(&receipt_element.transaction_output.actual_fee.0.into()) + .chain(&calculate_messages_sent_hash(&receipt_element.transaction_output.messages_sent)) + .chain(&get_revert_reason_hash(&receipt_element.transaction_output.execution_status)); + chain_gas_consumed(hash_chain, &receipt_element.transaction_output.gas_consumed) + .get_poseidon_hash() +} + +// Poseidon( +// num_messages_sent, +// from_address_0, to_address_0, payload_length_0, payload_0, +// from_address_1, to_address_1, payload_length_1, payload_1, ... +// ). +fn calculate_messages_sent_hash(messages_sent: &Vec) -> Felt { + let mut messages_hash_chain = HashChain::new().chain(&messages_sent.len().into()); + for message_sent in messages_sent { + messages_hash_chain = messages_hash_chain + .chain(&message_sent.from_address) + .chain(&message_sent.to_address.into()) + .chain_size_and_elements(&message_sent.payload.0); + } + messages_hash_chain.get_poseidon_hash() +} + +// Returns starknet-keccak of the revert reason ASCII string, or 0 if the transaction succeeded. +fn get_revert_reason_hash(execution_status: &TransactionExecutionStatus) -> Felt { + match execution_status { + TransactionExecutionStatus::Succeeded => Felt::ZERO, + TransactionExecutionStatus::Reverted(reason) => { + starknet_keccak_hash(reason.revert_reason.as_bytes()) + } + } +} + +// Chains: +// L2 gas consumed (In the current RPC: always 0), +// L1 gas consumed (In the current RPC: +// L1 gas consumed for calldata + L1 gas consumed for steps and builtins. +// L1 data gas consumed (In the current RPC: L1 data gas consumed for blob). +fn chain_gas_consumed(hash_chain: HashChain, gas_consumed: &GasVector) -> HashChain { + hash_chain + .chain(&Felt::ZERO) // L2 gas consumed + .chain(&gas_consumed.l1_gas.into()) + .chain(&gas_consumed.l1_data_gas.into()) +} diff --git a/crates/starknet_api/src/block_hash/receipt_commitment_test.rs b/crates/starknet_api/src/block_hash/receipt_commitment_test.rs new file mode 100644 index 00000000000..3e443c557d8 --- /dev/null +++ b/crates/starknet_api/src/block_hash/receipt_commitment_test.rs @@ -0,0 +1,49 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::Poseidon; + +use super::calculate_messages_sent_hash; +use crate::block_hash::receipt_commitment::{ + calculate_receipt_commitment, calculate_receipt_hash, get_revert_reason_hash, ReceiptElement, +}; +use crate::block_hash::test_utils::{generate_message_to_l1, get_transaction_output}; +use crate::core::ReceiptCommitment; +use crate::felt; +use crate::transaction::{ + RevertedTransactionExecutionStatus, TransactionExecutionStatus, TransactionHash, +}; + +#[test] +fn test_receipt_hash_regression() { + let transaction_receipt = ReceiptElement { + transaction_hash: TransactionHash(Felt::from(1234_u16)), + transaction_output: get_transaction_output(), + }; + + let expected_hash = felt!("0x6276abf21e7c68b2eecfdc8a845b11b44401901f5f040efe10c60d625049646"); + assert_eq!(calculate_receipt_hash(&transaction_receipt), expected_hash); + + let expected_root = ReceiptCommitment(felt!( + "0x31963cb891ebb825e83514deb748c89b6967b5368cbc48a9b56193a1464ca87" + )); + assert_eq!(calculate_receipt_commitment::(&[transaction_receipt]), expected_root); +} + +#[test] +fn test_messages_sent_regression() { + let messages_sent = vec![generate_message_to_l1(0), generate_message_to_l1(1)]; + let messages_hash = calculate_messages_sent_hash(&messages_sent); + let expected_hash = felt!("0x00c89474a9007dc060aed76caf8b30b927cfea1ebce2d134b943b8d7121004e4"); + assert_eq!(messages_hash, expected_hash); +} + +#[test] +fn test_revert_reason_hash_regression() { + let execution_succeeded = TransactionExecutionStatus::Succeeded; + assert_eq!(get_revert_reason_hash(&execution_succeeded), Felt::ZERO); + let execution_reverted = + TransactionExecutionStatus::Reverted(RevertedTransactionExecutionStatus { + revert_reason: "ABC".to_string(), + }); + let expected_hash = felt!("0x01629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8"); + assert_eq!(get_revert_reason_hash(&execution_reverted), expected_hash); +} diff --git a/crates/starknet_api/src/block_hash/state_diff_hash.rs b/crates/starknet_api/src/block_hash/state_diff_hash.rs new file mode 100644 index 00000000000..d588992bfda --- /dev/null +++ b/crates/starknet_api/src/block_hash/state_diff_hash.rs @@ -0,0 +1,123 @@ +use indexmap::IndexMap; +use once_cell::sync::Lazy; +use starknet_types_core::felt::Felt; + +use crate::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, StateDiffCommitment}; +use crate::crypto::utils::HashChain; +use crate::hash::PoseidonHash; +use crate::state::{StorageKey, ThinStateDiff}; +use crate::transaction_hash::ascii_as_felt; + +#[cfg(test)] +#[path = "state_diff_hash_test.rs"] +mod state_diff_hash_test; + +static STARKNET_STATE_DIFF0: Lazy = Lazy::new(|| { + ascii_as_felt("STARKNET_STATE_DIFF0").expect("ascii_as_felt failed for 'STARKNET_STATE_DIFF0'") +}); + +/// Poseidon( +/// "STARKNET_STATE_DIFF0", deployed_contracts, declared_classes, deprecated_declared_classes, +/// 1, 0, storage_diffs, nonces +/// ). +pub fn calculate_state_diff_hash(state_diff: &ThinStateDiff) -> StateDiffCommitment { + let mut hash_chain = HashChain::new(); + hash_chain = hash_chain.chain(&STARKNET_STATE_DIFF0); + hash_chain = chain_updated_contracts( + &state_diff.deployed_contracts, + &state_diff.replaced_classes, + hash_chain, + ); + hash_chain = chain_declared_classes(&state_diff.declared_classes, hash_chain); + hash_chain = + chain_deprecated_declared_classes(&state_diff.deprecated_declared_classes, hash_chain); + hash_chain = hash_chain.chain(&Felt::ONE) // placeholder. + .chain(&Felt::ZERO); // placeholder. + hash_chain = chain_storage_diffs(&state_diff.storage_diffs, hash_chain); + hash_chain = chain_nonces(&state_diff.nonces, hash_chain); + StateDiffCommitment(PoseidonHash(hash_chain.get_poseidon_hash())) +} + +// Chains: [number_of_updated_contracts, address_0, class_hash_0, address_1, class_hash_1, ...]. +// The updated contracts includes deployed contracts and replaced classes. +fn chain_updated_contracts( + deployed_contracts: &IndexMap, + replaced_classes: &IndexMap, + mut hash_chain: HashChain, +) -> HashChain { + let updated_contracts = deployed_contracts.iter().chain(replaced_classes.iter()); + hash_chain = hash_chain.chain(&(deployed_contracts.len() + replaced_classes.len()).into()); + for (address, class_hash) in sorted_index_map(&updated_contracts.collect()) { + hash_chain = hash_chain.chain(&address.0).chain(class_hash); + } + hash_chain +} + +// Chains: [number_of_declared_classes, +// class_hash_0, compiled_class_hash_0, class_hash_1, compiled_class_hash_1, ...]. +fn chain_declared_classes( + declared_classes: &IndexMap, + mut hash_chain: HashChain, +) -> HashChain { + hash_chain = hash_chain.chain(&declared_classes.len().into()); + for (class_hash, compiled_class_hash) in sorted_index_map(declared_classes) { + hash_chain = hash_chain.chain(&class_hash).chain(&compiled_class_hash.0) + } + hash_chain +} + +// Chains: [number_of_old_declared_classes, class_hash_0, class_hash_1, ...]. +fn chain_deprecated_declared_classes( + deprecated_declared_classes: &[ClassHash], + hash_chain: HashChain, +) -> HashChain { + let mut sorted_deprecated_declared_classes = deprecated_declared_classes.to_vec(); + sorted_deprecated_declared_classes.sort_unstable(); + hash_chain + .chain(&sorted_deprecated_declared_classes.len().into()) + .chain_iter(sorted_deprecated_declared_classes.iter().map(|class_hash| &class_hash.0)) +} + +// Chains: [number_of_updated_contracts, +// contract_address_0, number_of_updates_in_contract_0, key_0, value0, key1, value1, ..., +// contract_address_1, number_of_updates_in_contract_1, key_0, value0, key1, value1, ..., +// ] +fn chain_storage_diffs( + storage_diffs: &IndexMap>, + hash_chain: HashChain, +) -> HashChain { + let mut n_updated_contracts = 0_u64; + let mut storage_diffs_chain = HashChain::new(); + for (contract_address, key_value_map) in sorted_index_map(storage_diffs) { + if key_value_map.is_empty() { + // Filter out a contract with empty storage maps. + continue; + } + n_updated_contracts += 1; + storage_diffs_chain = storage_diffs_chain.chain(&contract_address); + storage_diffs_chain = storage_diffs_chain.chain(&key_value_map.len().into()); + for (key, value) in sorted_index_map(&key_value_map) { + storage_diffs_chain = storage_diffs_chain.chain(&key).chain(&value); + } + } + hash_chain.chain(&n_updated_contracts.into()).extend(storage_diffs_chain) +} + +// Chains: [number_of_updated_contracts nonces, +// contract_address_0, nonce_0, contract_address_1, nonce_1, ..., +// ] +fn chain_nonces(nonces: &IndexMap, mut hash_chain: HashChain) -> HashChain { + hash_chain = hash_chain.chain(&nonces.len().into()); + for (contract_address, nonce) in sorted_index_map(nonces) { + hash_chain = hash_chain.chain(&contract_address); + hash_chain = hash_chain.chain(&nonce); + } + hash_chain +} + +// Returns a clone of the map, sorted by keys. +fn sorted_index_map(map: &IndexMap) -> IndexMap { + let mut sorted_map = map.clone(); + sorted_map.sort_unstable_keys(); + sorted_map +} diff --git a/crates/starknet_api/src/block_hash/state_diff_hash_test.rs b/crates/starknet_api/src/block_hash/state_diff_hash_test.rs new file mode 100644 index 00000000000..ef11443742d --- /dev/null +++ b/crates/starknet_api/src/block_hash/state_diff_hash_test.rs @@ -0,0 +1,136 @@ +use indexmap::indexmap; + +use crate::block_hash::state_diff_hash::{ + calculate_state_diff_hash, chain_declared_classes, chain_deprecated_declared_classes, + chain_nonces, chain_storage_diffs, chain_updated_contracts, +}; +use crate::block_hash::test_utils::get_state_diff; +use crate::core::{ClassHash, CompiledClassHash, Nonce, StateDiffCommitment}; +use crate::crypto::utils::HashChain; +use crate::felt; +use crate::hash::PoseidonHash; + +#[test] +fn test_state_diff_hash_regression() { + let state_diff = get_state_diff(); + + let expected_hash = StateDiffCommitment(PoseidonHash(felt!( + "0x0281f5966e49ad7dad9323826d53d1d27c0c4e6ebe5525e2e2fbca549bfa0a67" + ))); + + assert_eq!(expected_hash, calculate_state_diff_hash(&state_diff)); +} + +#[test] +fn test_sorting_deployed_contracts() { + let deployed_contracts_0 = indexmap! { + 0u64.into() => ClassHash(3u64.into()), + 1u64.into() => ClassHash(2u64.into()), + }; + let replaced_classes_0 = indexmap! { + 2u64.into() => ClassHash(1u64.into()), + }; + let deployed_contracts_1 = indexmap! { + 2u64.into() => ClassHash(1u64.into()), + 0u64.into() => ClassHash(3u64.into()), + }; + let replaced_classes_1 = indexmap! { + 1u64.into() => ClassHash(2u64.into()), + }; + assert_eq!( + chain_updated_contracts(&deployed_contracts_0, &replaced_classes_0, HashChain::new()) + .get_poseidon_hash(), + chain_updated_contracts(&deployed_contracts_1, &replaced_classes_1, HashChain::new()) + .get_poseidon_hash(), + ); +} + +#[test] +fn test_sorting_declared_classes() { + let declared_classes_0 = indexmap! { + ClassHash(0u64.into()) => CompiledClassHash(3u64.into()), + ClassHash(1u64.into()) => CompiledClassHash(2u64.into()), + }; + let declared_classes_1 = indexmap! { + ClassHash(1u64.into()) => CompiledClassHash(2u64.into()), + ClassHash(0u64.into()) => CompiledClassHash(3u64.into()), + }; + assert_eq!( + chain_declared_classes(&declared_classes_0, HashChain::new()).get_poseidon_hash(), + chain_declared_classes(&declared_classes_1, HashChain::new()).get_poseidon_hash(), + ); +} + +#[test] +fn test_sorting_deprecated_declared_classes() { + let deprecated_declared_classes_0 = vec![ClassHash(0u64.into()), ClassHash(1u64.into())]; + let deprecated_declared_classes_1 = vec![ClassHash(1u64.into()), ClassHash(0u64.into())]; + assert_eq!( + chain_deprecated_declared_classes(&deprecated_declared_classes_0, HashChain::new()) + .get_poseidon_hash(), + chain_deprecated_declared_classes(&deprecated_declared_classes_1, HashChain::new()) + .get_poseidon_hash(), + ); +} + +#[test] +fn test_sorting_storage_diffs() { + let storage_diffs_0 = indexmap! { + 0u64.into() => indexmap! { + 1u64.into() => 2u64.into(), + 3u64.into() => 4u64.into(), + }, + 5u64.into() => indexmap! { + 6u64.into() => 7u64.into(), + }, + }; + let storage_diffs_1 = indexmap! { + 5u64.into() => indexmap! { + 6u64.into() => 7u64.into(), + }, + 0u64.into() => indexmap! { + 3u64.into() => 4u64.into(), + 1u64.into() => 2u64.into(), + }, + }; + assert_eq!( + chain_storage_diffs(&storage_diffs_0, HashChain::new()).get_poseidon_hash(), + chain_storage_diffs(&storage_diffs_1, HashChain::new()).get_poseidon_hash(), + ); +} + +#[test] +fn test_empty_storage_diffs() { + let storage_diffs_0 = indexmap! { + 0u64.into() => indexmap! { + 1u64.into() => 2u64.into(), + }, + 3u64.into() => indexmap! { + }, + }; + let storage_diffs_1 = indexmap! { + 0u64.into() => indexmap! { + 1u64.into() => 2u64.into(), + }, + }; + assert_eq!( + chain_storage_diffs(&storage_diffs_0, HashChain::new()).get_poseidon_hash(), + chain_storage_diffs(&storage_diffs_1, HashChain::new()).get_poseidon_hash(), + ); +} + +#[test] +fn test_sorting_nonces() { + let nonces_0 = indexmap! { + 0u64.into() => Nonce(3u64.into()), + 1u64.into() => Nonce(2u64.into()), + }; + let nonces_1 = indexmap! { + 1u64.into() => Nonce(2u64.into()), + 0u64.into() => Nonce(3u64.into()), + }; + assert_eq!( + chain_nonces(&nonces_0, HashChain::new()).get_poseidon_hash(), + chain_nonces(&nonces_1, HashChain::new()).get_poseidon_hash(), + ); +} diff --git a/crates/starknet_api/src/block_hash/test_utils.rs b/crates/starknet_api/src/block_hash/test_utils.rs new file mode 100644 index 00000000000..cc3b24b3bc2 --- /dev/null +++ b/crates/starknet_api/src/block_hash/test_utils.rs @@ -0,0 +1,62 @@ +use indexmap::indexmap; +use primitive_types::H160; +use starknet_types_core::felt::Felt; + +use super::block_hash_calculator::TransactionOutputForHash; +use crate::core::{ClassHash, CompiledClassHash, ContractAddress, EthAddress, Nonce}; +use crate::state::ThinStateDiff; +use crate::transaction::{ + Fee, GasVector, L2ToL1Payload, MessageToL1, RevertedTransactionExecutionStatus, + TransactionExecutionStatus, +}; + +pub(crate) fn get_transaction_output() -> TransactionOutputForHash { + let execution_status = + TransactionExecutionStatus::Reverted(RevertedTransactionExecutionStatus { + revert_reason: "aborted".to_string(), + }); + TransactionOutputForHash { + actual_fee: Fee(99804), + messages_sent: vec![generate_message_to_l1(34), generate_message_to_l1(56)], + events: vec![], + execution_status, + gas_consumed: GasVector { l1_gas: 16580, l1_data_gas: 32 }, + } +} + +pub(crate) fn generate_message_to_l1(seed: u64) -> MessageToL1 { + MessageToL1 { + from_address: ContractAddress::from(seed), + to_address: EthAddress(H160::from_low_u64_be(seed + 1)), + payload: L2ToL1Payload(vec![Felt::from(seed + 2), Felt::from(seed + 3)]), + } +} + +pub(crate) fn get_state_diff() -> ThinStateDiff { + ThinStateDiff { + deployed_contracts: indexmap! { + 0u64.into() => ClassHash(1u64.into()), + 2u64.into() => ClassHash(3u64.into()), + }, + storage_diffs: indexmap! { + 4u64.into() => indexmap! { + 5u64.into() => 6u64.into(), + 7u64.into() => 8u64.into(), + }, + 9u64.into() => indexmap! { + 10u64.into() => 11u64.into(), + }, + }, + declared_classes: indexmap! { + ClassHash(12u64.into()) => CompiledClassHash(13u64.into()), + ClassHash(14u64.into()) => CompiledClassHash(15u64.into()), + }, + deprecated_declared_classes: vec![ClassHash(16u64.into())], + nonces: indexmap! { + 17u64.into() => Nonce(18u64.into()), + }, + replaced_classes: indexmap! { + 19u64.into() => ClassHash(20u64.into()), + }, + } +} diff --git a/crates/starknet_api/src/block_hash/transaction_commitment.rs b/crates/starknet_api/src/block_hash/transaction_commitment.rs new file mode 100644 index 00000000000..b1a2b79077a --- /dev/null +++ b/crates/starknet_api/src/block_hash/transaction_commitment.rs @@ -0,0 +1,53 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::StarkHash as CoreStarkHash; + +use super::block_hash_calculator::TransactionHashingData; +use crate::core::TransactionCommitment; +use crate::crypto::patricia_hash::calculate_root; +use crate::crypto::utils::HashChain; +use crate::transaction::{TransactionHash, TransactionSignature}; + +#[cfg(test)] +#[path = "transaction_commitment_test.rs"] +mod transaction_commitment_test; + +/// The elements used to calculate a leaf in the transactions Patricia tree. +#[derive(Clone)] +pub struct TransactionLeafElement { + pub(crate) transaction_hash: TransactionHash, + pub(crate) transaction_signature: Option, +} + +impl From<&TransactionHashingData> for TransactionLeafElement { + fn from(transaction_data: &TransactionHashingData) -> Self { + Self { + transaction_hash: transaction_data.transaction_hash, + transaction_signature: transaction_data.transaction_signature.clone(), + } + } +} + +/// Returns the root of a Patricia tree where each leaf is +/// H(transaction_hash, transaction_signature). +/// The leaf of a transaction types without a signature field is: H(transaction_hash, 0). +pub fn calculate_transaction_commitment( + transaction_leaf_elements: &[TransactionLeafElement], +) -> TransactionCommitment { + let transaction_leaves = + transaction_leaf_elements.iter().map(calculate_transaction_leaf).collect(); + TransactionCommitment(calculate_root::(transaction_leaves)) +} + +fn calculate_transaction_leaf(transaction_leaf_elements: &TransactionLeafElement) -> Felt { + HashChain::new() + .chain(&transaction_leaf_elements.transaction_hash.0) + .chain_iter( + transaction_leaf_elements + .transaction_signature + .as_ref() + .unwrap_or(&TransactionSignature(vec![Felt::ZERO])) + .0 + .iter(), + ) + .get_poseidon_hash() +} diff --git a/crates/starknet_api/src/block_hash/transaction_commitment_test.rs b/crates/starknet_api/src/block_hash/transaction_commitment_test.rs new file mode 100644 index 00000000000..4e949ea9211 --- /dev/null +++ b/crates/starknet_api/src/block_hash/transaction_commitment_test.rs @@ -0,0 +1,49 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::Poseidon; + +use super::TransactionLeafElement; +use crate::block_hash::transaction_commitment::{ + calculate_transaction_commitment, calculate_transaction_leaf, +}; +use crate::core::TransactionCommitment; +use crate::felt; +use crate::transaction::{TransactionHash, TransactionSignature}; + +#[test] +fn test_transaction_leaf_regression() { + let transaction_leaf_elements = get_transaction_leaf_element(); + let expected_leaf = felt!("0x2f0d8840bcf3bc629598d8a6cc80cb7c0d9e52d93dab244bbf9cd0dca0ad082"); + + assert_eq!(expected_leaf, calculate_transaction_leaf(&transaction_leaf_elements)); +} + +#[test] +fn test_transaction_leaf_without_signature_regression() { + let transaction_leaf_elements = TransactionLeafElement { + transaction_hash: TransactionHash(Felt::ONE), + transaction_signature: None, + }; + let expected_leaf = felt!("0x00a93bf5e58b9378d093aa86ddc2f61a3295a1d1e665bd0ef3384dd07b30e033"); + + assert_eq!(expected_leaf, calculate_transaction_leaf(&transaction_leaf_elements)); +} + +#[test] +fn test_transaction_commitment_regression() { + let transaction_leaf_elements = get_transaction_leaf_element(); + let expected_root = felt!("0x0282b635972328bd1cfa86496fe920d20bd9440cd78ee8dc90ae2b383d664dcf"); + + assert_eq!( + TransactionCommitment(expected_root), + calculate_transaction_commitment::(&[ + transaction_leaf_elements.clone(), + transaction_leaf_elements + ]) + ); +} + +fn get_transaction_leaf_element() -> TransactionLeafElement { + let transaction_hash = TransactionHash(Felt::ONE); + let transaction_signature = TransactionSignature(vec![Felt::TWO, Felt::THREE]); + TransactionLeafElement { transaction_hash, transaction_signature: Some(transaction_signature) } +} diff --git a/crates/starknet_api/src/block_test.rs b/crates/starknet_api/src/block_test.rs new file mode 100644 index 00000000000..632ed6d871d --- /dev/null +++ b/crates/starknet_api/src/block_test.rs @@ -0,0 +1,47 @@ +use super::verify_block_signature; +use crate::block::{BlockHash, BlockNumber, BlockSignature}; +use crate::core::{GlobalRoot, SequencerPublicKey}; +use crate::crypto::utils::{PublicKey, Signature}; +use crate::felt; + +#[test] +fn test_block_number_iteration() { + let start: u64 = 3; + let up_until: u64 = 10; + + let mut expected = vec![]; + for i in start..up_until { + expected.push(BlockNumber(i)); + } + + let start_block_number = BlockNumber(start); + let up_until_block_number = BlockNumber(up_until); + + let mut from_iter: Vec<_> = vec![]; + for i in start_block_number.iter_up_to(up_until_block_number) { + from_iter.push(i); + } + + assert_eq!(expected, from_iter); +} + +#[test] +fn block_signature_verification() { + // Values taken from Mainnet. + let block_hash = + BlockHash(felt!("0x7d5db04c5ca2aea828180dc441afb1580e3cee7547a3567ced3aa5bb8b273c0")); + let state_commitment = + GlobalRoot(felt!("0x64689c12248e1110af4b3af0e2b43cd51ad13e8855f10e37669e2a4baf919c6")); + let signature = BlockSignature(Signature { + r: felt!("0x1b382bbfd693011c9b7692bc932b23ed9c288deb27c8e75772e172abbe5950c"), + s: felt!("0xbe4438085057e1a7c704a0da3b30f7b8340fe3d24c86772abfd24aa597e42"), + }); + let sequencer_pub_key = SequencerPublicKey(PublicKey(felt!( + "0x48253ff2c3bed7af18bde0b611b083b39445959102d4947c51c4db6aa4f4e58" + ))); + + assert!( + verify_block_signature(&sequencer_pub_key, &signature, &state_commitment, &block_hash) + .unwrap() + ); +} diff --git a/crates/starknet_api/src/core.rs b/crates/starknet_api/src/core.rs new file mode 100644 index 00000000000..ab9f3754b7a --- /dev/null +++ b/crates/starknet_api/src/core.rs @@ -0,0 +1,427 @@ +#[cfg(test)] +#[path = "core_test.rs"] +mod core_test; + +use core::fmt::Display; +use std::fmt::Debug; + +use derive_more::Display; +use once_cell::sync::Lazy; +use primitive_types::H160; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use starknet_types_core::felt::{Felt, NonZeroFelt}; +use starknet_types_core::hash::{Pedersen, StarkHash as CoreStarkHash}; + +use crate::crypto::utils::PublicKey; +use crate::hash::{PoseidonHash, StarkHash}; +use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex}; +use crate::transaction::{Calldata, ContractAddressSalt}; +use crate::{impl_from_through_intermediate, StarknetApiError}; + +/// A chain id. +#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub enum ChainId { + Mainnet, + Sepolia, + IntegrationSepolia, + Other(String), +} + +impl Serialize for ChainId { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for ChainId { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(ChainId::from(s)) + } +} +impl From for ChainId { + fn from(s: String) -> Self { + match s.as_ref() { + "SN_MAIN" => ChainId::Mainnet, + "SN_SEPOLIA" => ChainId::Sepolia, + "SN_INTEGRATION_SEPOLIA" => ChainId::IntegrationSepolia, + other => ChainId::Other(other.to_owned()), + } + } +} +impl Display for ChainId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ChainId::Mainnet => write!(f, "SN_MAIN"), + ChainId::Sepolia => write!(f, "SN_SEPOLIA"), + ChainId::IntegrationSepolia => write!(f, "SN_INTEGRATION_SEPOLIA"), + ChainId::Other(ref s) => write!(f, "{}", s), + } + } +} + +impl ChainId { + pub fn as_hex(&self) -> String { + format!("0x{}", hex::encode(self.to_string())) + } +} + +/// The address of a contract, used for example in [StateDiff](`crate::state::StateDiff`), +/// [DeclareTransaction](`crate::transaction::DeclareTransaction`), and +/// [BlockHeader](`crate::block::BlockHeader`). + +// The block hash table is stored in address 0x1, +// this is a special address that is not used for contracts. +pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKey(StarkHash::ONE)); +#[derive( + Debug, + Default, + Copy, + Clone, + Display, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +pub struct ContractAddress(pub PatriciaKey); + +impl From for Felt { + fn from(contract_address: ContractAddress) -> Felt { + **contract_address + } +} + +impl From for ContractAddress { + fn from(val: u128) -> Self { + ContractAddress(PatriciaKey::from(val)) + } +} + +impl_from_through_intermediate!(u128, ContractAddress, u8, u16, u32, u64); + +/// The maximal size of storage var. +pub const MAX_STORAGE_ITEM_SIZE: u16 = 256; +/// The prefix used in the calculation of a contract address. +pub const CONTRACT_ADDRESS_PREFIX: &str = "STARKNET_CONTRACT_ADDRESS"; +/// The size of the contract address domain. +pub const CONTRACT_ADDRESS_DOMAIN_SIZE: Felt = Felt::from_hex_unchecked(PATRICIA_KEY_UPPER_BOUND); +/// The address upper bound; it is defined to be congruent with the storage var address upper bound. +pub static L2_ADDRESS_UPPER_BOUND: Lazy = Lazy::new(|| { + NonZeroFelt::try_from(CONTRACT_ADDRESS_DOMAIN_SIZE - Felt::from(MAX_STORAGE_ITEM_SIZE)).unwrap() +}); + +impl TryFrom for ContractAddress { + type Error = StarknetApiError; + fn try_from(hash: StarkHash) -> Result { + Ok(Self(PatriciaKey::try_from(hash)?)) + } +} + +// TODO: Add a hash_function as a parameter +pub fn calculate_contract_address( + salt: ContractAddressSalt, + class_hash: ClassHash, + constructor_calldata: &Calldata, + deployer_address: ContractAddress, +) -> Result { + let constructor_calldata_hash = Pedersen::hash_array(&constructor_calldata.0); + let contract_address_prefix = format!("0x{}", hex::encode(CONTRACT_ADDRESS_PREFIX)); + let address = Pedersen::hash_array(&[ + Felt::from_hex(contract_address_prefix.as_str()).map_err(|_| { + StarknetApiError::OutOfRange { string: contract_address_prefix.clone() } + })?, + *deployer_address.0.key(), + salt.0, + class_hash.0, + constructor_calldata_hash, + ]); + let (_, address) = address.div_rem(&L2_ADDRESS_UPPER_BOUND); + + ContractAddress::try_from(address) +} + +/// The hash of a ContractClass. +#[derive( + Debug, + Default, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, + derive_more::Deref, +)] +pub struct ClassHash(pub StarkHash); + +/// The hash of a compiled ContractClass. +#[derive( + Debug, + Default, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct CompiledClassHash(pub StarkHash); + +/// A general type for nonces. +#[derive( + Debug, + Default, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +pub struct Nonce(pub Felt); + +impl Nonce { + pub fn try_increment(&self) -> Result { + // Check if an overflow occurred during increment. + let incremented = self.0 + Felt::ONE; + if incremented == Felt::ZERO { + return Err(StarknetApiError::OutOfRange { string: format!("{:?}", self) }); + } + Ok(Self(incremented)) + } +} + +/// The selector of an [EntryPoint](`crate::deprecated_contract_class::EntryPoint`). +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct EntryPointSelector(pub StarkHash); + +/// The root of the global state at a [Block](`crate::block::Block`) +/// and [StateUpdate](`crate::state::StateUpdate`). +#[derive( + Debug, + Copy, + Clone, + Default, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct GlobalRoot(pub StarkHash); + +/// The commitment on the transactions in a [Block](`crate::block::Block`). +#[derive( + Debug, + Copy, + Clone, + Default, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct TransactionCommitment(pub StarkHash); + +/// The commitment on the events in a [Block](`crate::block::Block`). +#[derive( + Debug, + Copy, + Clone, + Default, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct EventCommitment(pub StarkHash); + +/// The commitment on the receipts in a [Block](`crate::block::Block`). +#[derive( + Debug, + Copy, + Clone, + Default, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Display, +)] +pub struct ReceiptCommitment(pub StarkHash); + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct StateDiffCommitment(pub PoseidonHash); + +/// A key for nodes of a Patricia tree. +// Invariant: key is in range. +#[derive( + Copy, + Clone, + Display, + Eq, + PartialEq, + Default, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more:: Deref, +)] +#[display(fmt = "{}", "_0.to_fixed_hex_string()")] +pub struct PatriciaKey(StarkHash); + +// 2**251 +pub const PATRICIA_KEY_UPPER_BOUND: &str = + "0x800000000000000000000000000000000000000000000000000000000000000"; + +impl PatriciaKey { + pub fn key(&self) -> &StarkHash { + &self.0 + } +} + +impl From for PatriciaKey { + fn from(val: u128) -> Self { + PatriciaKey::try_from(Felt::from(val)).expect("Failed to convert u128 to PatriciaKey.") + } +} + +impl_from_through_intermediate!(u128, PatriciaKey, u8, u16, u32, u64); + +impl TryFrom for PatriciaKey { + type Error = StarknetApiError; + + fn try_from(value: StarkHash) -> Result { + if value < CONTRACT_ADDRESS_DOMAIN_SIZE { + return Ok(PatriciaKey(value)); + } + Err(StarknetApiError::OutOfRange { string: format!("[0x0, {PATRICIA_KEY_UPPER_BOUND})") }) + } +} + +impl Debug for PatriciaKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PatriciaKey").field(&self.0).finish() + } +} + +/// A utility macro to create a [`PatriciaKey`] from a hex string / unsigned integer representation. +#[cfg(any(feature = "testing", test))] +#[macro_export] +macro_rules! patricia_key { + ($s:expr) => { + PatriciaKey::try_from(felt!($s)).unwrap() + }; +} + +/// A utility macro to create a [`ClassHash`] from a hex string / unsigned integer representation. +#[cfg(any(feature = "testing", test))] +#[macro_export] +macro_rules! class_hash { + ($s:expr) => { + ClassHash(felt!($s)) + }; +} + +/// A utility macro to create a [`ContractAddress`] from a hex string / unsigned integer +/// representation. +#[cfg(any(feature = "testing", test))] +#[macro_export] +macro_rules! contract_address { + ($s:expr) => { + ContractAddress(patricia_key!($s)) + }; +} + +/// An Ethereum address. +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +#[serde(try_from = "PrefixedBytesAsHex<20_usize>", into = "PrefixedBytesAsHex<20_usize>")] +pub struct EthAddress(pub H160); + +impl TryFrom for EthAddress { + type Error = StarknetApiError; + fn try_from(felt: Felt) -> Result { + const COMPLIMENT_OF_H160: usize = std::mem::size_of::() - H160::len_bytes(); + + let bytes = felt.to_bytes_be(); + let (rest, h160_bytes) = bytes.split_at(COMPLIMENT_OF_H160); + if rest != [0u8; COMPLIMENT_OF_H160] { + return Err(StarknetApiError::OutOfRange { string: felt.to_string() }); + } + + Ok(EthAddress(H160::from_slice(h160_bytes))) + } +} + +impl From for Felt { + fn from(value: EthAddress) -> Self { + Felt::from_bytes_be_slice(value.0.as_bytes()) + } +} + +impl TryFrom> for EthAddress { + type Error = StarknetApiError; + fn try_from(val: PrefixedBytesAsHex<20_usize>) -> Result { + Ok(EthAddress(H160::from_slice(&val.0))) + } +} + +impl From for PrefixedBytesAsHex<20_usize> { + fn from(felt: EthAddress) -> Self { + BytesAsHex(felt.0.to_fixed_bytes()) + } +} + +/// A public key of a sequencer. +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct SequencerPublicKey(pub PublicKey); + +#[derive( + Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct SequencerContractAddress(pub ContractAddress); diff --git a/crates/starknet_api/src/core_test.rs b/crates/starknet_api/src/core_test.rs new file mode 100644 index 00000000000..543d137445c --- /dev/null +++ b/crates/starknet_api/src/core_test.rs @@ -0,0 +1,96 @@ +use assert_matches::assert_matches; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Pedersen, StarkHash as CoreStarkHash}; + +use crate::core::{ + calculate_contract_address, ClassHash, ContractAddress, EthAddress, Nonce, PatriciaKey, + StarknetApiError, CONTRACT_ADDRESS_PREFIX, L2_ADDRESS_UPPER_BOUND, +}; +use crate::hash::StarkHash; +use crate::transaction::{Calldata, ContractAddressSalt}; +use crate::{class_hash, felt, patricia_key}; + +#[test] +fn patricia_key_valid() { + let hash = felt!("0x123"); + let patricia_key = PatriciaKey::try_from(hash).unwrap(); + assert_eq!(patricia_key.0, hash); +} + +#[test] +fn patricia_key_out_of_range() { + // 2**251 + let hash = felt!("0x800000000000000000000000000000000000000000000000000000000000000"); + let err = PatriciaKey::try_from(hash); + assert_matches!(err, Err(StarknetApiError::OutOfRange { string: _err_str })); +} + +#[test] +fn patricia_key_macro() { + assert_eq!( + patricia_key!("0x123"), + PatriciaKey::try_from(StarkHash::from_bytes_be(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x1, 0x23 + ])) + .unwrap() + ); +} + +#[test] +fn test_calculate_contract_address() { + let salt = ContractAddressSalt(Felt::from(1337_u16)); + let class_hash = class_hash!("0x110"); + let deployer_address = ContractAddress::default(); + let constructor_calldata = + Calldata(vec![Felt::from(60_u16), Felt::from(70_u16), Felt::MAX].into()); + + let actual_address = + calculate_contract_address(salt, class_hash, &constructor_calldata, deployer_address) + .unwrap(); + + let constructor_calldata_hash = Pedersen::hash_array(&constructor_calldata.0); + let address = Pedersen::hash_array(&[ + Felt::from_hex_unchecked(format!("0x{}", hex::encode(CONTRACT_ADDRESS_PREFIX)).as_str()), + *deployer_address.0.key(), + salt.0, + class_hash.0, + constructor_calldata_hash, + ]); + let (_, mod_address) = address.div_rem(&L2_ADDRESS_UPPER_BOUND); + let expected_address = ContractAddress::try_from(mod_address).unwrap(); + + assert_eq!(actual_address, expected_address); +} + +#[test] +fn eth_address_serde() { + let eth_address = EthAddress::try_from(felt!("0x001")).unwrap(); + let serialized = serde_json::to_string(ð_address).unwrap(); + assert_eq!(serialized, r#""0x1""#); + + let restored = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(restored, eth_address); +} + +#[test] +fn nonce_overflow() { + // Increment on this value should overflow back to 0. + let max_nonce = Nonce(Felt::MAX); + + let overflowed_nonce = max_nonce.try_increment(); + assert_matches!(overflowed_nonce, Err(StarknetApiError::OutOfRange { string: _err_str })); +} + +#[test] +fn test_patricia_key_display() { + assert_eq!(format!("{}", patricia_key!(7_u8)), String::from("0x") + &"0".repeat(63) + "7"); +} + +#[test] +fn test_contract_address_display() { + assert_eq!( + format!("{}", ContractAddress(patricia_key!(16_u8))), + String::from("0x") + &"0".repeat(62) + "10" + ); +} diff --git a/crates/starknet_api/src/crypto.rs b/crates/starknet_api/src/crypto.rs new file mode 100644 index 00000000000..3e4100ee5c9 --- /dev/null +++ b/crates/starknet_api/src/crypto.rs @@ -0,0 +1,2 @@ +pub mod patricia_hash; +pub mod utils; diff --git a/crates/starknet_api/src/crypto/crypto_test.rs b/crates/starknet_api/src/crypto/crypto_test.rs new file mode 100644 index 00000000000..7d78fc35bac --- /dev/null +++ b/crates/starknet_api/src/crypto/crypto_test.rs @@ -0,0 +1,26 @@ +// Unittest for verify_message_signature + +use starknet_types_core::hash::{Poseidon, StarkHash}; + +use crate::crypto::utils::{verify_message_hash_signature, PublicKey, Signature}; +use crate::felt; + +#[test] +fn signature_verification() { + // The signed message of block 4256. + let message_hash = Poseidon::hash_array(&[ + felt!("0x7d5db04c5ca2aea828180dc441afb1580e3cee7547a3567ced3aa5bb8b273c0"), + felt!("0x64689c12248e1110af4b3af0e2b43cd51ad13e8855f10e37669e2a4baf919c6"), + ]); + // The signature of the message. + let signature = Signature { + r: felt!("0x1b382bbfd693011c9b7692bc932b23ed9c288deb27c8e75772e172abbe5950c"), + s: felt!("0xbe4438085057e1a7c704a0da3b30f7b8340fe3d24c86772abfd24aa597e42"), + }; + // The public key of the sequencer. + let public_key = + PublicKey(felt!("0x48253ff2c3bed7af18bde0b611b083b39445959102d4947c51c4db6aa4f4e58")); + + let result = verify_message_hash_signature(&message_hash, &signature, &public_key).unwrap(); + assert!(result); +} diff --git a/crates/starknet_api/src/crypto/patricia_hash.rs b/crates/starknet_api/src/crypto/patricia_hash.rs new file mode 100644 index 00000000000..41acf4e22f3 --- /dev/null +++ b/crates/starknet_api/src/crypto/patricia_hash.rs @@ -0,0 +1,132 @@ +//! Patricia hash tree implementation. +//! +//! Supports root hash calculation for Stark felt values, keyed by consecutive 64 bits numbers, +//! starting from 0. +//! +//! Each edge is marked with one or more bits. +//! The key of a node is the concatenation of the edges' marks in the path from the root to this +//! node. +//! The input keys are in the leaves, and each leaf is an input key. +//! +//! The edges coming out of an internal node with a key `K` are: +//! - If there are input keys that start with 'K0...' and 'K1...', then two edges come out, marked +//! with '0' and '1' bits. +//! - Otherwise, a single edge mark with 'Z' is coming out. 'Z' is the longest string, such that all +//! the input keys that start with 'K...' start with 'KZ...' as well. Note, the order of the input +//! keys in this implementation forces 'Z' to be a zeros string. +//! +//! Hash of a node depends on the number of edges coming out of it: +//! - A leaf: The hash is the input value of its key. +//! - A single edge: hash(child_hash, edge_mark) + edge_length. +//! - '0' and '1' edges: hash(zero_child_hash, one_child_hash). + +#[cfg(test)] +#[path = "patricia_hash_test.rs"] +mod patricia_hash_test; + +use bitvec::prelude::{BitArray, Msb0}; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::StarkHash as CoreStarkHash; + +const TREE_HEIGHT: u8 = 64; +type BitPath = BitArray<[u8; 8], Msb0>; + +// An entry in a Patricia tree. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Entry { + key: BitPath, + value: Felt, +} + +// A sub-tree is defined by a sub-sequence of leaves with a common ancestor at the specified height, +// with no other leaves under it besides these. +#[derive(Debug)] +struct SubTree<'a> { + leaves: &'a [Entry], + // Levels from the root. + height: u8, +} + +enum SubTreeSplitting { + // Number of '0' bits that all the keys start with. + CommonZerosPrefix(u8), + // The index of the first key that starts with a '1' bit. + PartitionPoint(usize), +} + +/// Calculates Patricia hash root on the given values. +/// The values are keyed by consecutive numbers, starting from 0. +pub fn calculate_root(values: Vec) -> Felt { + if values.is_empty() { + return Felt::ZERO; + } + let leaves: Vec = values + .into_iter() + .zip(0u64..) + .map(|(felt, idx)| Entry { key: idx.to_be_bytes().into(), value: felt }) + .collect(); + get_hash::(SubTree { leaves: &leaves[..], height: 0_u8 }) +} + +// Recursive hash calculation. There are 3 cases: +// - Leaf: The sub tree height is maximal. It should contain exactly one entry. +// - Edge: All the keys start with a longest common ('0's) prefix. NOTE: We assume that the keys are +// a continuous range, and hence the case of '1's in the longest common prefix is impossible. +// - Binary: Some keys start with '0' bit and some start with '1' bit. +fn get_hash(sub_tree: SubTree<'_>) -> Felt { + if sub_tree.height == TREE_HEIGHT { + return sub_tree.leaves.first().expect("a leaf should not be empty").value; + } + match get_splitting(&sub_tree) { + SubTreeSplitting::CommonZerosPrefix(n_zeros) => get_edge_hash::(sub_tree, n_zeros), + SubTreeSplitting::PartitionPoint(partition_point) => { + get_binary_hash::(sub_tree, partition_point) + } + } +} + +// Hash on a '0's sequence with the bottom sub tree. +fn get_edge_hash(sub_tree: SubTree<'_>, n_zeros: u8) -> Felt { + let child_hash = + get_hash::(SubTree { leaves: sub_tree.leaves, height: sub_tree.height + n_zeros }); + let child_and_path_hash = H::hash(&child_hash, &Felt::ZERO); + child_and_path_hash + Felt::from(n_zeros) +} + +// Hash on both sides: starts with '0' bit and starts with '1' bit. +// Assumes: 0 < partition point < sub_tree.len(). +fn get_binary_hash(sub_tree: SubTree<'_>, partition_point: usize) -> Felt { + let zero_hash = get_hash::(SubTree { + leaves: &sub_tree.leaves[..partition_point], + height: sub_tree.height + 1, + }); + let one_hash = get_hash::(SubTree { + leaves: &sub_tree.leaves[partition_point..], + height: sub_tree.height + 1, + }); + H::hash(&zero_hash, &one_hash) +} + +// Returns the manner the keys of a subtree are splitting: some keys start with '1' or all keys +// start with '0'. +fn get_splitting(sub_tree: &SubTree<'_>) -> SubTreeSplitting { + let mut height = sub_tree.height; + + let first_one_bit_index = + sub_tree.leaves.partition_point(|entry| !entry.key[usize::from(height)]); + if first_one_bit_index < sub_tree.leaves.len() { + return SubTreeSplitting::PartitionPoint(first_one_bit_index); + } + + height += 1; + let mut n_zeros = 1; + + while height < TREE_HEIGHT { + if sub_tree.leaves.last().expect("sub tree should not be empty").key[usize::from(height)] { + break; + } + n_zeros += 1; + height += 1; + } + SubTreeSplitting::CommonZerosPrefix(n_zeros) +} diff --git a/crates/starknet_api/src/crypto/patricia_hash_test.rs b/crates/starknet_api/src/crypto/patricia_hash_test.rs new file mode 100644 index 00000000000..ef2f983a647 --- /dev/null +++ b/crates/starknet_api/src/crypto/patricia_hash_test.rs @@ -0,0 +1,27 @@ +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::Poseidon; + +use super::calculate_root; +use crate::felt; + +#[test] +fn test_patricia_regression() { + let root = + calculate_root::(vec![Felt::from(1_u8), Felt::from(2_u8), Felt::from(3_u8)]); + let expected_root = felt!("0x3b5cc7f1292eb3847c3f902d048a7e5dc7702d1c191ccd17c2d33f797e6fc32"); + assert_eq!(root, expected_root); +} + +#[test] +fn test_edge_patricia_regression() { + let root = calculate_root::(vec![Felt::from(1_u8)]); + let expected_root = felt!("0x7752582c54a42fe0fa35c40f07293bb7d8efe90e21d8d2c06a7db52d7d9b7e1"); + assert_eq!(root, expected_root); +} + +#[test] +fn test_binary_patricia_regression() { + let root = calculate_root::(vec![Felt::from(1_u8), Felt::from(2_u8)]); + let expected_root = felt!("0x1c1ba983ee0a0de87d87d67ea3cbee7023aa65f6b7bcf71259f122ea3af80bf"); + assert_eq!(root, expected_root); +} diff --git a/crates/starknet_api/src/crypto/utils.rs b/crates/starknet_api/src/crypto/utils.rs new file mode 100644 index 00000000000..170de7e4cee --- /dev/null +++ b/crates/starknet_api/src/crypto/utils.rs @@ -0,0 +1,129 @@ +//! Cryptographic utilities. +//! This module provides cryptographic utilities. +#[cfg(test)] +#[path = "crypto_test.rs"] +#[allow(clippy::explicit_auto_deref)] +mod crypto_test; + +use std::fmt; +use std::fmt::LowerHex; + +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; +use starknet_types_core::hash::{Pedersen, Poseidon, StarkHash as CoreStarkHash}; + +use crate::hash::StarkHash; + +/// An error that can occur during cryptographic operations. + +#[derive(thiserror::Error, Clone, Debug)] +pub enum CryptoError { + #[error("Invalid public key {0:#x}.")] + InvalidPublicKey(PublicKey), + #[error("Invalid message hash {0:#x}.")] + InvalidMessageHash(Felt), + #[error("Invalid r {0}.")] + InvalidR(Felt), + #[error("Invalid s {0}.")] + InvalidS(Felt), +} + +/// A public key. +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct PublicKey(pub Felt); + +impl LowerHex for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.0, f) + } +} + +/// A signature. +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct Signature { + pub r: Felt, + pub s: Felt, +} + +fn to_field_element(felt: &Felt) -> starknet_crypto::FieldElement { + starknet_crypto::FieldElement::from_mont(felt.to_raw_reversed()) +} + +/// Verifies the authenticity of a signed message hash given the public key of the signer. +pub fn verify_message_hash_signature( + message_hash: &Felt, + signature: &Signature, + public_key: &PublicKey, +) -> Result { + starknet_crypto::verify( + &to_field_element(&public_key.0), + &to_field_element(message_hash), + &to_field_element(&signature.r), + &to_field_element(&signature.s), + ) + .map_err(|err| match err { + starknet_crypto::VerifyError::InvalidPublicKey => { + CryptoError::InvalidPublicKey(*public_key) + } + starknet_crypto::VerifyError::InvalidMessageHash => { + CryptoError::InvalidMessageHash(*message_hash) + } + starknet_crypto::VerifyError::InvalidR => CryptoError::InvalidR(signature.r), + starknet_crypto::VerifyError::InvalidS => CryptoError::InvalidS(signature.s), + }) +} + +// Collect elements for applying hash chain. +pub(crate) struct HashChain { + elements: Vec, +} + +impl HashChain { + pub fn new() -> HashChain { + HashChain { elements: Vec::new() } + } + + // Chains a felt to the hash chain. + pub fn chain(mut self, felt: &Felt) -> Self { + self.elements.push(*felt); + self + } + + // Chains the result of a function to the hash chain. + pub fn chain_if_fn Option>(self, f: F) -> Self { + match f() { + Some(felt) => self.chain(&felt), + None => self, + } + } + + // Chains many felts to the hash chain. + pub fn chain_iter<'a>(self, felts: impl Iterator) -> Self { + felts.fold(self, |current, felt| current.chain(felt)) + } + + // Chains the number of felts followed by the felts themselves to the hash chain. + pub fn chain_size_and_elements(self, felts: &[Felt]) -> Self { + self.chain(&felts.len().into()).chain_iter(felts.iter()) + } + + // Chains a chain of felts to the hash chain. + pub fn extend(mut self, chain: HashChain) -> Self { + self.elements.extend(chain.elements); + self + } + + // Returns the pedersen hash of the chained felts, hashed with the length of the chain. + pub fn get_pedersen_hash(&self) -> StarkHash { + Pedersen::hash_array(self.elements.as_slice()) + } + + // Returns the poseidon hash of the chained felts. + pub fn get_poseidon_hash(&self) -> StarkHash { + Poseidon::hash_array(self.elements.as_slice()) + } +} diff --git a/crates/starknet_api/src/data_availability.rs b/crates/starknet_api/src/data_availability.rs new file mode 100644 index 00000000000..0fc3f948009 --- /dev/null +++ b/crates/starknet_api/src/data_availability.rs @@ -0,0 +1,75 @@ +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; + +use crate::StarknetApiError; + +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[serde(try_from = "Deserializer")] +pub enum DataAvailabilityMode { + L1 = 0, + L2 = 1, +} + +/// Deserialize a `DataAvailabilityMode` from a given `Deserializer`. +/// +/// This implementation supports deserializing the `DataAvailabilityMode` enum from both numerical +/// and textual representations. +#[derive(Deserialize)] +#[serde(untagged)] +enum Deserializer { + Num(u8), + Text(String), +} + +impl TryFrom for DataAvailabilityMode { + type Error = StarknetApiError; + + fn try_from(value: Deserializer) -> Result { + match value { + Deserializer::Num(0_u8) => Ok(DataAvailabilityMode::L1), + Deserializer::Num(1_u8) => Ok(DataAvailabilityMode::L2), + Deserializer::Text(text) if &text == "L1" => Ok(DataAvailabilityMode::L1), + Deserializer::Text(text) if &text == "L2" => Ok(DataAvailabilityMode::L2), + _ => Err(StarknetApiError::OutOfRange { + string: "Data availability must be either 'L1' or '0' for L1, or 'L2' or '1' for \ + L2." + .to_string(), + }), + } + } +} + +impl TryFrom for DataAvailabilityMode { + type Error = StarknetApiError; + + fn try_from(felt: Felt) -> Result { + if felt == Felt::ZERO { + return Ok(DataAvailabilityMode::L1); + } + if felt == Felt::ONE { + return Ok(DataAvailabilityMode::L2); + } + Err(StarknetApiError::OutOfRange { + string: format!("Invalid data availability mode: {felt}."), + }) + } +} + +impl From for Felt { + fn from(data_availability_mode: DataAvailabilityMode) -> Felt { + match data_availability_mode { + DataAvailabilityMode::L1 => Felt::ZERO, + DataAvailabilityMode::L2 => Felt::ONE, + } + } +} + +#[derive( + Clone, Default, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, +)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum L1DataAvailabilityMode { + #[default] + Calldata, + Blob, +} diff --git a/crates/starknet_api/src/deprecated_contract_class.rs b/crates/starknet_api/src/deprecated_contract_class.rs new file mode 100644 index 00000000000..eb5de5db907 --- /dev/null +++ b/crates/starknet_api/src/deprecated_contract_class.rs @@ -0,0 +1,245 @@ +use std::collections::HashMap; +use std::num::ParseIntError; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractEntryPoint; +use itertools::Itertools; +use serde::de::Error as DeserializationError; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::Value; + +use crate::core::EntryPointSelector; +use crate::hash::StarkHash; +use crate::serde_utils::deserialize_optional_contract_class_abi_entry_vector; +use crate::StarknetApiError; + +/// A deprecated contract class. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + // Starknet does not verify the abi. If we can't parse it, we set it to None. + #[serde(default, deserialize_with = "deserialize_optional_contract_class_abi_entry_vector")] + pub abi: Option>, + pub program: Program, + /// The selector of each entry point is a unique identifier in the program. + // TODO: Consider changing to IndexMap, since this is used for computing the + // class hash. + pub entry_points_by_type: HashMap>, +} + +/// A [ContractClass](`crate::deprecated_contract_class::ContractClass`) abi entry. +// Using untagged so the serialization will be sorted by the keys (the default behavior of Serde for +// untagged enums). We care about the order of the fields in the serialization because it affects +// the class hash calculation. +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields, untagged)] +pub enum ContractClassAbiEntry { + Constructor(FunctionAbiEntry), + Event(EventAbiEntry), + Function(FunctionAbiEntry), + L1Handler(FunctionAbiEntry), + Struct(StructAbiEntry), +} + +/// An event abi entry. +// The members of the struct are sorted lexicographically for correct hash computation. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct EventAbiEntry { + pub data: Vec, + pub keys: Vec, + pub name: String, + pub r#type: EventType, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum EventType { + #[default] + Event, +} + +/// A function abi entry. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct FunctionAbiEntry { + pub inputs: Vec, + pub name: String, + pub outputs: Vec, + #[serde(rename = "stateMutability", default, skip_serializing_if = "Option::is_none")] + pub state_mutability: Option, + pub r#type: TYPE, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum FunctionType { + #[default] + Function, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum ConstructorType { + #[default] + Constructor, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum L1HandlerType { + #[default] + L1Handler, +} + +/// A function state mutability. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub enum FunctionStateMutability { + #[serde(rename = "view")] + #[default] + View, +} + +/// A struct abi entry. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct StructAbiEntry { + pub members: Vec, + pub name: String, + pub size: usize, + pub r#type: StructType, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum StructType { + #[default] + Struct, +} + +/// A struct member for [StructAbiEntry](`crate::deprecated_contract_class::StructAbiEntry`). +// The members of the struct are sorted lexicographically for correct hash computation. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct StructMember { + pub name: String, + pub offset: usize, + pub r#type: String, +} + +/// A program corresponding to a [ContractClass](`crate::deprecated_contract_class::ContractClass`). +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct Program { + #[serde(default)] + pub attributes: serde_json::Value, + pub builtins: serde_json::Value, + #[serde(default)] + pub compiler_version: serde_json::Value, + pub data: serde_json::Value, + #[serde(default)] + pub debug_info: serde_json::Value, + #[serde(serialize_with = "serialize_hints_sorted")] + pub hints: serde_json::Value, + pub identifiers: serde_json::Value, + pub main_scope: serde_json::Value, + pub prime: serde_json::Value, + pub reference_manager: serde_json::Value, +} + +// Serialize hints as a sorted mapping for correct hash computation. +fn serialize_hints_sorted(hints: &serde_json::Value, serializer: S) -> Result +where + S: Serializer, +{ + if hints.is_null() { + return serializer.serialize_none(); + } + let hints_map = + hints.as_object().ok_or(serde::ser::Error::custom("Hints are not a mapping."))?; + serializer.collect_map( + hints_map + .iter() + // Parse the keys as integers and sort them. + .map(|(k, v)| Ok((k.parse::()?, v))) + .collect::, ParseIntError>>() + .map_err(serde::ser::Error::custom)? + .iter() + .sorted_by_key(|(k, _v)| *k) + // Convert the keys back to strings. + .map(|(k, v)| (k.to_string(), v)), + ) +} + +/// An entry point type of a [ContractClass](`crate::deprecated_contract_class::ContractClass`). +#[derive( + Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +#[serde(deny_unknown_fields)] +pub enum EntryPointType { + /// A constructor entry point. + #[serde(rename = "CONSTRUCTOR")] + Constructor, + /// An external4 entry point. + #[serde(rename = "EXTERNAL")] + #[default] + External, + /// An L1 handler entry point. + #[serde(rename = "L1_HANDLER")] + L1Handler, +} + +/// An entry point of a [ContractClass](`crate::deprecated_contract_class::ContractClass`). +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct EntryPoint { + pub selector: EntryPointSelector, + pub offset: EntryPointOffset, +} + +impl TryFrom for EntryPoint { + type Error = StarknetApiError; + + fn try_from(value: CasmContractEntryPoint) -> Result { + Ok(EntryPoint { + selector: EntryPointSelector(StarkHash::from(value.selector)), + offset: EntryPointOffset(value.offset), + }) + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct TypedParameter { + pub name: String, + pub r#type: String, +} + +/// The offset of an [EntryPoint](`crate::deprecated_contract_class::EntryPoint`). +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct EntryPointOffset( + #[serde(deserialize_with = "number_or_string", serialize_with = "usize_to_hex")] pub usize, +); +impl TryFrom for EntryPointOffset { + type Error = StarknetApiError; + + fn try_from(value: String) -> Result { + Ok(Self(hex_string_try_into_usize(&value)?)) + } +} + +pub fn number_or_string<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let usize_value = match Value::deserialize(deserializer)? { + Value::Number(number) => { + number.as_u64().ok_or(DeserializationError::custom("Cannot cast number to usize."))? + as usize + } + Value::String(s) => hex_string_try_into_usize(&s).map_err(DeserializationError::custom)?, + _ => return Err(DeserializationError::custom("Cannot cast value into usize.")), + }; + Ok(usize_value) +} + +fn hex_string_try_into_usize(hex_string: &str) -> Result { + usize::from_str_radix(hex_string.trim_start_matches("0x"), 16) +} + +fn usize_to_hex(value: &usize, s: S) -> Result +where + S: Serializer, +{ + s.serialize_str(format!("{:#x}", value).as_str()) +} diff --git a/crates/starknet_api/src/hash.rs b/crates/starknet_api/src/hash.rs new file mode 100644 index 00000000000..7dfa3b0447b --- /dev/null +++ b/crates/starknet_api/src/hash.rs @@ -0,0 +1,61 @@ +use std::fmt::Debug; + +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Keccak256}; +use starknet_types_core::felt::Felt; + +pub type StarkHash = Felt; + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct PoseidonHash(pub Felt); + +/// Computes the first 250 bits of the Keccak256 hash, in order to fit into a field element. +pub fn starknet_keccak_hash(input: &[u8]) -> Felt { + let mut keccak = Keccak256::default(); + keccak.update(input); + let mut hashed_bytes: [u8; 32] = keccak.finalize().into(); + hashed_bytes[0] &= 0b00000011_u8; // Discard the six MSBs. + Felt::from_bytes_be(&hashed_bytes) +} + +#[cfg(any(feature = "testing", test))] +pub struct FeltConverter; + +#[cfg(any(feature = "testing", test))] +pub trait TryIntoFelt { + fn to_felt_unchecked(v: V) -> Felt; +} + +macro_rules! impl_try_into_felt { + ($type:ty) => { + #[cfg(any(feature = "testing", test))] + impl TryIntoFelt<$type> for FeltConverter { + fn to_felt_unchecked(v: $type) -> Felt { + Felt::from(v) + } + } + }; +} + +impl_try_into_felt!(u128); +impl_try_into_felt!(u64); +impl_try_into_felt!(u32); +impl_try_into_felt!(u16); +impl_try_into_felt!(u8); + +#[cfg(any(feature = "testing", test))] +impl TryIntoFelt<&str> for FeltConverter { + fn to_felt_unchecked(v: &str) -> Felt { + Felt::from_hex_unchecked(v) + } +} + +/// A utility macro to create a [`starknet_types_core::felt::Felt`] from an intergert or a hex +/// string representation. +#[cfg(any(feature = "testing", test))] +#[macro_export] +macro_rules! felt { + ($s:expr) => { + <$crate::hash::FeltConverter as $crate::hash::TryIntoFelt<_>>::to_felt_unchecked($s) + }; +} diff --git a/crates/starknet_api/src/internal_transaction.rs b/crates/starknet_api/src/internal_transaction.rs new file mode 100644 index 00000000000..12572b356de --- /dev/null +++ b/crates/starknet_api/src/internal_transaction.rs @@ -0,0 +1,90 @@ +use crate::core::{ContractAddress, Nonce}; +use crate::state::ContractClass; +use crate::transaction::{ + DeclareTransaction, DeployAccountTransaction, InvokeTransaction, Tip, TransactionHash, +}; + +/// Represents a paid Starknet transaction. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum InternalTransaction { + Declare(InternalDeclareTransaction), + DeployAccount(InternalDeployAccountTransaction), + Invoke(InternalInvokeTransaction), +} + +impl InternalTransaction { + pub fn contract_address(&self) -> ContractAddress { + match self { + InternalTransaction::Declare(tx_data) => tx_data.tx.sender_address(), + InternalTransaction::DeployAccount(tx_data) => tx_data.contract_address, + InternalTransaction::Invoke(tx_data) => tx_data.tx.sender_address(), + } + } + + pub fn nonce(&self) -> Nonce { + match self { + InternalTransaction::Declare(tx_data) => tx_data.tx.nonce(), + InternalTransaction::DeployAccount(tx_data) => tx_data.tx.nonce(), + InternalTransaction::Invoke(tx_data) => tx_data.tx.nonce(), + } + } + + pub fn tx_hash(&self) -> TransactionHash { + match self { + InternalTransaction::Declare(tx_data) => tx_data.tx_hash, + InternalTransaction::DeployAccount(tx_data) => tx_data.tx_hash, + InternalTransaction::Invoke(tx_data) => tx_data.tx_hash, + } + } + + pub fn tip(&self) -> Option { + match self { + InternalTransaction::Declare(declare_tx) => match &declare_tx.tx { + DeclareTransaction::V3(tx_v3) => Some(tx_v3.tip), + _ => None, + }, + InternalTransaction::DeployAccount(deploy_account_tx) => match &deploy_account_tx.tx { + DeployAccountTransaction::V3(tx_v3) => Some(tx_v3.tip), + _ => None, + }, + InternalTransaction::Invoke(invoke_tx) => match &invoke_tx.tx { + InvokeTransaction::V3(tx_v3) => Some(tx_v3.tip), + _ => None, + }, + } + } +} + +// TODO(Mohammad): Add constructor for all the transaction's structs. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InternalDeclareTransaction { + pub tx: DeclareTransaction, + pub tx_hash: TransactionHash, + // Indicates the presence of the only_query bit in the version. + pub only_query: bool, + pub class_info: ClassInfo, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InternalDeployAccountTransaction { + pub tx: DeployAccountTransaction, + pub tx_hash: TransactionHash, + pub contract_address: ContractAddress, + // Indicates the presence of the only_query bit in the version. + pub only_query: bool, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InternalInvokeTransaction { + pub tx: InvokeTransaction, + pub tx_hash: TransactionHash, + // Indicates the presence of the only_query bit in the version. + pub only_query: bool, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ClassInfo { + pub contract_class: ContractClass, + pub sierra_program_length: usize, + pub abi_length: usize, +} diff --git a/crates/starknet_api/src/lib.rs b/crates/starknet_api/src/lib.rs new file mode 100644 index 00000000000..8700b8e861b --- /dev/null +++ b/crates/starknet_api/src/lib.rs @@ -0,0 +1,40 @@ +//! Representations of canonical [`Starknet`] components. +//! +//! [`Starknet`]: https://starknet.io/ + +pub mod block; +pub mod block_hash; +pub mod core; +pub mod crypto; +pub mod data_availability; +pub mod deprecated_contract_class; +pub mod hash; +pub mod internal_transaction; +pub mod rpc_transaction; +pub mod serde_utils; +pub mod state; +pub mod transaction; +pub mod transaction_hash; +pub mod type_utils; + +use std::num::ParseIntError; + +use serde_utils::InnerDeserializationError; + +/// The error type returned by StarknetApi. +// Note: if you need `Eq` see InnerDeserializationError's docstring. +#[derive(thiserror::Error, Clone, Debug, PartialEq)] +pub enum StarknetApiError { + /// Error in the inner deserialization of the node. + #[error(transparent)] + InnerDeserialization(#[from] InnerDeserializationError), + #[error("Out of range {string}.")] + /// An error for when a value is out of range. + OutOfRange { string: String }, + /// Error when serializing into number. + #[error(transparent)] + ParseIntError(#[from] ParseIntError), + /// Missing resource type / duplicated resource type. + #[error("Missing resource type / duplicated resource type; got {0}.")] + InvalidResourceMappingInitializer(String), +} diff --git a/crates/starknet_api/src/rpc_transaction.rs b/crates/starknet_api/src/rpc_transaction.rs new file mode 100644 index 00000000000..dd9892ec0b4 --- /dev/null +++ b/crates/starknet_api/src/rpc_transaction.rs @@ -0,0 +1,180 @@ +#[cfg(test)] +#[path = "rpc_transaction_test.rs"] +mod rpc_transaction_test; + +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; + +use crate::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; +use crate::data_availability::DataAvailabilityMode; +use crate::state::EntryPoint; +use crate::transaction::{ + AccountDeploymentData, Calldata, ContractAddressSalt, PaymasterData, Resource, ResourceBounds, + Tip, TransactionSignature, +}; + +/// Transactions that are ready to be broadcasted to the network through RPC and are not included in +/// a block. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(tag = "type")] +#[serde(deny_unknown_fields)] +pub enum RpcTransaction { + #[serde(rename = "DECLARE")] + Declare(RpcDeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(RpcDeployAccountTransaction), + #[serde(rename = "INVOKE")] + Invoke(RpcInvokeTransaction), +} + +macro_rules! implement_ref_getters { + ($(($member_name:ident, $member_type:ty)), *) => { + $(pub fn $member_name(&self) -> &$member_type { + match self { + RpcTransaction::Declare( + RpcDeclareTransaction::V3(tx) + ) => &tx.$member_name, + RpcTransaction::DeployAccount( + RpcDeployAccountTransaction::V3(tx) + ) => &tx.$member_name, + RpcTransaction::Invoke( + RpcInvokeTransaction::V3(tx) + ) => &tx.$member_name + } + })* + }; +} + +impl RpcTransaction { + implement_ref_getters!( + (nonce, Nonce), + (resource_bounds, ResourceBoundsMapping), + (signature, TransactionSignature), + (tip, Tip) + ); +} + +/// A RPC declare transaction. +/// +/// This transaction is equivalent to the component DECLARE_TXN in the +/// [`Starknet specs`] with a contract class (DECLARE_TXN allows having +/// either a contract class or a class hash). +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(tag = "version")] +pub enum RpcDeclareTransaction { + #[serde(rename = "0x3")] + V3(RpcDeclareTransactionV3), +} + +/// A RPC deploy account transaction. +/// +/// This transaction is equivalent to the component DEPLOY_ACCOUNT_TXN in the +/// [`Starknet specs`]. +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[serde(tag = "version")] +pub enum RpcDeployAccountTransaction { + #[serde(rename = "0x3")] + V3(RpcDeployAccountTransactionV3), +} + +/// A RPC invoke transaction. +/// +/// This transaction is equivalent to the component INVOKE_TXN in the +/// [`Starknet specs`]. +/// +/// [`Starknet specs`]: https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json +#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[serde(tag = "version")] +pub enum RpcInvokeTransaction { + #[serde(rename = "0x3")] + V3(RpcInvokeTransactionV3), +} + +/// A declare transaction of a Cairo-v1 contract class that can be added to Starknet through the +/// RPC. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub struct RpcDeclareTransactionV3 { + // TODO: Check with Shahak why we need to keep the DeclareType. + // pub r#type: DeclareType, + pub sender_address: ContractAddress, + pub compiled_class_hash: CompiledClassHash, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +/// A deploy account transaction that can be added to Starknet through the RPC. +#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct RpcDeployAccountTransactionV3 { + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +/// An invoke account transaction that can be added to Starknet through the RPC. +#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct RpcInvokeTransactionV3 { + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, +} + +// The contract class in SN_API state doesn't have `contract_class_version`, not following the spec. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct ContractClass { + pub sierra_program: Vec, + pub contract_class_version: String, + pub entry_points_by_type: EntryPointByType, + pub abi: String, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct EntryPointByType { + #[serde(rename = "CONSTRUCTOR")] + pub constructor: Vec, + #[serde(rename = "EXTERNAL")] + pub external: Vec, + #[serde(rename = "L1_HANDLER")] + pub l1handler: Vec, +} + +// The serialization of the struct in transaction is in capital letters, not following the spec. +#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct ResourceBoundsMapping { + pub l1_gas: ResourceBounds, + pub l2_gas: ResourceBounds, +} + +impl From for crate::transaction::ResourceBoundsMapping { + fn from(mapping: ResourceBoundsMapping) -> crate::transaction::ResourceBoundsMapping { + let map = + BTreeMap::from([(Resource::L1Gas, mapping.l1_gas), (Resource::L2Gas, mapping.l2_gas)]); + crate::transaction::ResourceBoundsMapping(map) + } +} diff --git a/crates/starknet_api/src/rpc_transaction_test.rs b/crates/starknet_api/src/rpc_transaction_test.rs new file mode 100644 index 00000000000..d288a5d063e --- /dev/null +++ b/crates/starknet_api/src/rpc_transaction_test.rs @@ -0,0 +1,80 @@ +use std::sync::Arc; + +use rstest::rstest; +use starknet_types_core::felt::Felt; + +use crate::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey}; +use crate::rpc_transaction::{ + ContractClass, DataAvailabilityMode, ResourceBoundsMapping, RpcDeclareTransaction, + RpcDeclareTransactionV3, RpcDeployAccountTransaction, RpcDeployAccountTransactionV3, + RpcInvokeTransaction, RpcInvokeTransactionV3, RpcTransaction, +}; +use crate::transaction::{ + AccountDeploymentData, Calldata, ContractAddressSalt, PaymasterData, ResourceBounds, Tip, + TransactionSignature, +}; +use crate::{contract_address, felt, patricia_key}; + +fn create_resource_bounds_for_testing() -> ResourceBoundsMapping { + ResourceBoundsMapping { + l1_gas: ResourceBounds { max_amount: 100, max_price_per_unit: 12 }, + l2_gas: ResourceBounds { max_amount: 58, max_price_per_unit: 31 }, + } +} + +fn create_declare_v3() -> RpcDeclareTransaction { + RpcDeclareTransaction::V3(RpcDeclareTransactionV3 { + contract_class: ContractClass::default(), + resource_bounds: create_resource_bounds_for_testing(), + tip: Tip(1), + signature: TransactionSignature(vec![Felt::ONE, Felt::TWO]), + nonce: Nonce(Felt::ONE), + compiled_class_hash: CompiledClassHash(Felt::TWO), + sender_address: contract_address!("0x3"), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L2, + paymaster_data: PaymasterData(vec![Felt::ZERO]), + account_deployment_data: AccountDeploymentData(vec![Felt::THREE]), + }) +} + +fn create_deploy_account_v3() -> RpcDeployAccountTransaction { + RpcDeployAccountTransaction::V3(RpcDeployAccountTransactionV3 { + resource_bounds: create_resource_bounds_for_testing(), + tip: Tip::default(), + contract_address_salt: ContractAddressSalt(felt!("0x23")), + class_hash: ClassHash(Felt::TWO), + constructor_calldata: Calldata(Arc::new(vec![Felt::ZERO])), + nonce: Nonce(felt!("0x60")), + signature: TransactionSignature(vec![Felt::TWO]), + nonce_data_availability_mode: DataAvailabilityMode::L2, + fee_data_availability_mode: DataAvailabilityMode::L1, + paymaster_data: PaymasterData(vec![Felt::TWO, Felt::ZERO]), + }) +} + +fn create_invoke_v3() -> RpcInvokeTransaction { + RpcInvokeTransaction::V3(RpcInvokeTransactionV3 { + resource_bounds: create_resource_bounds_for_testing(), + tip: Tip(50), + calldata: Calldata(Arc::new(vec![felt!("0x2000"), felt!("0x1000")])), + sender_address: contract_address!("0x53"), + nonce: Nonce(felt!("0x32")), + signature: TransactionSignature::default(), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + paymaster_data: PaymasterData(vec![Felt::TWO, Felt::ZERO]), + account_deployment_data: AccountDeploymentData(vec![felt!("0x87")]), + }) +} + +// We are testing the `RpcTransaction` serialization. Passing non-default values. +#[rstest] +#[case(RpcTransaction::Declare(create_declare_v3()))] +#[case(RpcTransaction::DeployAccount(create_deploy_account_v3()))] +#[case(RpcTransaction::Invoke(create_invoke_v3()))] +fn test_rpc_transactions(#[case] tx: RpcTransaction) { + let serialized = serde_json::to_string(&tx).unwrap(); + let deserialized: RpcTransaction = serde_json::from_str(&serialized).unwrap(); + assert_eq!(tx, deserialized); +} diff --git a/crates/starknet_api/src/serde_utils.rs b/crates/starknet_api/src/serde_utils.rs new file mode 100644 index 00000000000..c23b7f4ed73 --- /dev/null +++ b/crates/starknet_api/src/serde_utils.rs @@ -0,0 +1,151 @@ +//! Utilities for serialising/deserialising hexadecimal values. +#[cfg(test)] +#[path = "serde_utils_test.rs"] +mod serde_utils_test; + +use serde::de::{Deserialize, Visitor}; +use serde::ser::{Serialize, SerializeTuple}; +use serde::Deserializer; + +use crate::deprecated_contract_class::ContractClassAbiEntry; + +/// A [BytesAsHex](`crate::serde_utils::BytesAsHex`) prefixed with '0x'. +pub type PrefixedBytesAsHex = BytesAsHex; + +/// A byte array that serializes as a hex string. +/// +/// The `PREFIXED` generic type symbolize whether a string representation of the hex value should be +/// prefixed by `0x` or not. +#[derive(Debug, Eq, PartialEq)] +pub struct BytesAsHex(pub(crate) [u8; N]); + +impl<'de, const N: usize, const PREFIXED: bool> Deserialize<'de> for BytesAsHex { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct ByteArrayVisitor; + impl<'de, const N: usize, const PREFIXED: bool> Visitor<'de> for ByteArrayVisitor { + type Value = BytesAsHex; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut res = [0u8; N]; + let mut i = 0; + while let Some(value) = seq.next_element()? { + res[i] = value; + i += 1; + } + Ok(BytesAsHex(res)) + } + } + + if deserializer.is_human_readable() { + let s = String::deserialize(deserializer)?; + bytes_from_hex_str::(s.as_str()) + .map_err(serde::de::Error::custom) + .map(BytesAsHex) + } else { + deserializer.deserialize_tuple(N, ByteArrayVisitor) + } + } +} + +impl Serialize for BytesAsHex { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if serializer.is_human_readable() { + let hex_str = hex_str_from_bytes::(self.0); + serializer.serialize_str(&hex_str) + } else { + let mut seq = serializer.serialize_tuple(N)?; + for element in &self.0[..] { + seq.serialize_element(element)?; + } + seq.end() + } + } +} + +/// The error type returned by the inner deserialization. +// If you need `eq`, add `impl Eq fro InnerDeserializationError {}` and read warning below. +// +// For some reason `hex` (now unmaintained for > 3 years) didn't implement `Eq`, even though +// there's no reason not too, so we can't use `derive(Eq)` unfortunately. +// Note that adding the impl is risky, because if at some point `hex` decide to add non-Eq +// things to the error, then combined with the manual `impl Eq` this will create very nasty bugs. +// So, for prudence, we'll hold off on adding `Eq` until we have a good reason to. +// Existing (ignored) issue on this: https://github.com/KokaKiwi/rust-hex/issues/76. +#[derive(thiserror::Error, Clone, Debug, PartialEq)] +pub enum InnerDeserializationError { + /// Error parsing the hex string. + #[error(transparent)] + FromHex(#[from] hex::FromHexError), + /// Missing 0x prefix in the hex string. + #[error("Missing prefix 0x in {hex_str}")] + MissingPrefix { hex_str: String }, + /// Unexpected input byte count. + #[error("Bad input - expected #bytes: {expected_byte_count}, string found: {string_found}.")] + BadInput { expected_byte_count: usize, string_found: String }, +} + +/// Deserializes a Hex decoded as string to a byte array. +pub fn bytes_from_hex_str( + hex_str: &str, +) -> Result<[u8; N], InnerDeserializationError> { + let hex_str = if PREFIXED { + hex_str + .strip_prefix("0x") + .ok_or(InnerDeserializationError::MissingPrefix { hex_str: hex_str.into() })? + } else { + hex_str + }; + + // Make sure string is not too long. + if hex_str.len() > 2 * N { + let mut err_str = "0x".to_owned(); + err_str.push_str(hex_str); + return Err(InnerDeserializationError::BadInput { + expected_byte_count: N, + string_found: err_str, + }); + } + + // Pad if needed. + let to_add = 2 * N - hex_str.len(); + let padded_str = vec!["0"; to_add].join("") + hex_str; + + Ok(hex::decode(padded_str)?.try_into().expect("Unexpected length of deserialized hex bytes.")) +} + +/// Encodes a byte array to a string. +pub fn hex_str_from_bytes(bytes: [u8; N]) -> String { + let hex_str = hex::encode(bytes); + let mut hex_str = hex_str.trim_start_matches('0'); + hex_str = if hex_str.is_empty() { "0" } else { hex_str }; + if PREFIXED { format!("0x{hex_str}") } else { hex_str.to_string() } +} + +pub fn deserialize_optional_contract_class_abi_entry_vector<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + // Deserialize the field as an `Option>` + let result: Result>, _> = Option::deserialize(deserializer); + + // If the field contains junk or an invalid value, return `None`. + match result { + Ok(value) => Ok(value), + Err(_) => Ok(None), + } +} diff --git a/crates/starknet_api/src/serde_utils_test.rs b/crates/starknet_api/src/serde_utils_test.rs new file mode 100644 index 00000000000..711de14621e --- /dev/null +++ b/crates/starknet_api/src/serde_utils_test.rs @@ -0,0 +1,182 @@ +use assert_matches::assert_matches; +use serde::Deserialize; + +use crate::deprecated_contract_class::{ + ConstructorType, ContractClassAbiEntry, FunctionAbiEntry, TypedParameter, +}; +use crate::serde_utils::{ + bytes_from_hex_str, deserialize_optional_contract_class_abi_entry_vector, hex_str_from_bytes, + BytesAsHex, InnerDeserializationError, +}; + +#[test] +fn hex_str_from_bytes_scenarios() { + // even length. + assert_eq!(hex_str_from_bytes::<1, true>([106]), "0x6a"); + + // odd length. + assert_eq!(hex_str_from_bytes::<1, true>([6]), "0x6"); + + // Remove padding. + assert_eq!(hex_str_from_bytes::<2, true>([0, 6]), "0x6"); + + // Non-prefixed. + assert_eq!(hex_str_from_bytes::<2, false>([13, 162]), "da2"); +} + +#[test] +fn hex_str_from_bytes_zero() { + // Prefixed. + assert_eq!(hex_str_from_bytes::<3, true>([0, 0, 0]), "0x0"); + + // Non-prefixed. + assert_eq!(hex_str_from_bytes::<2, false>([0, 0]), "0"); +} + +#[test] +fn bytes_from_hex_str_scenarios() { + // even length. + let hex_str = "0x6a"; + let res = bytes_from_hex_str::<1, true>(hex_str).unwrap(); + assert_eq!(res, [106]); + + // odd length. + let hex_str = "0x6"; + let res = bytes_from_hex_str::<1, true>(hex_str).unwrap(); + assert_eq!(res, [6]); + + // No prefix. + let hex_str = "6"; + let res = bytes_from_hex_str::<1, false>(hex_str).unwrap(); + assert_eq!(res, [6]); +} + +#[test] +fn bytes_from_hex_str_padding() { + // even length. + let hex_str = "0xda2b"; + let res = bytes_from_hex_str::<4, true>(hex_str).unwrap(); + assert_eq!(res, [0, 0, 218, 43]); + + // odd length. + let hex_str = "0xda2"; + let res = bytes_from_hex_str::<4, true>(hex_str).unwrap(); + assert_eq!(res, [0, 0, 13, 162]); +} + +#[test] +fn bytes_from_hex_str_errors() { + // Short buffer. + let hex_str = "0xda2b"; + let err = bytes_from_hex_str::<1, true>(hex_str); + assert_matches!(err, Err(InnerDeserializationError::BadInput { expected_byte_count: 1, .. })); + + // Invalid hex char. + let err = bytes_from_hex_str::<1, false>("1z"); + assert_matches!( + err, + Err(InnerDeserializationError::FromHex(hex::FromHexError::InvalidHexCharacter { + c: 'z', + index: 1 + })) + ); + + // Missing prefix. + let err = bytes_from_hex_str::<2, true>("11"); + assert_matches!(err, Err(InnerDeserializationError::MissingPrefix { .. })); + + // Unneeded prefix. + let err = bytes_from_hex_str::<2, false>("0x11"); + assert_matches!( + err, + Err(InnerDeserializationError::FromHex(hex::FromHexError::InvalidHexCharacter { + c: 'x', + index: 1 + })) + ); +} + +#[test] +fn hex_as_bytes_serde_prefixed() { + let hex_as_bytes = BytesAsHex::<3, true>([1, 2, 3]); + assert_eq!( + hex_as_bytes, + serde_json::from_str(&serde_json::to_string(&hex_as_bytes).unwrap()).unwrap() + ); +} + +#[test] +fn hex_as_bytes_serde_not_prefixed() { + let hex_as_bytes = BytesAsHex::<3, false>([1, 2, 3]); + assert_eq!( + hex_as_bytes, + serde_json::from_str(&serde_json::to_string(&hex_as_bytes).unwrap()).unwrap() + ); +} + +#[derive(Deserialize, PartialEq, Eq, Debug)] +struct DummyContractClass { + #[serde(default, deserialize_with = "deserialize_optional_contract_class_abi_entry_vector")] + pub abi: Option>, +} + +#[test] +fn deserialize_valid_optional_contract_class_abi_entry_vector() { + let json = r#" + { + "abi": + [ + { + "inputs": [ + { + "name": "implementation", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + } + ] + } + "#; + let res: DummyContractClass = serde_json::from_str(json).unwrap(); + assert_eq!( + res, + DummyContractClass { + abi: Some(vec![ContractClassAbiEntry::Constructor(FunctionAbiEntry::< + ConstructorType, + > { + name: "constructor".to_string(), + inputs: vec![TypedParameter { + name: "implementation".to_string(), + r#type: "felt".to_string(), + }], + outputs: vec![], + state_mutability: None, + r#type: ConstructorType::Constructor, + })]) + } + ); +} + +#[test] +fn deserialize_optional_contract_class_abi_entry_vector_junk() { + let json = r#" + { + "abi": "Junk" + } + "#; + let res: DummyContractClass = serde_json::from_str(json).unwrap(); + assert_eq!(res, DummyContractClass { abi: None }); +} + +#[test] +fn deserialize_optional_contract_class_abi_entry_vector_none() { + let json = r#" + { + } + "#; + let res: DummyContractClass = serde_json::from_str(json).unwrap(); + assert_eq!(res, DummyContractClass { abi: None }); +} diff --git a/crates/starknet_api/src/state.rs b/crates/starknet_api/src/state.rs new file mode 100644 index 00000000000..599b6541367 --- /dev/null +++ b/crates/starknet_api/src/state.rs @@ -0,0 +1,235 @@ +#[cfg(test)] +#[path = "state_test.rs"] +mod state_test; + +use std::collections::HashMap; +use std::fmt::Debug; + +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; + +use crate::block::{BlockHash, BlockNumber}; +use crate::core::{ + ClassHash, CompiledClassHash, ContractAddress, EntryPointSelector, GlobalRoot, Nonce, + PatriciaKey, +}; +use crate::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use crate::hash::StarkHash; +use crate::{impl_from_through_intermediate, StarknetApiError}; + +pub type DeclaredClasses = IndexMap; +pub type DeprecatedDeclaredClasses = IndexMap; + +/// The differences between two states before and after a block with hash block_hash +/// and their respective roots. +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct StateUpdate { + pub block_hash: BlockHash, + pub new_root: GlobalRoot, + pub old_root: GlobalRoot, + pub state_diff: StateDiff, +} + +/// The differences between two states. +// Invariant: Addresses are strictly increasing. +// Invariant: Class hashes of declared_classes and deprecated_declared_classes are exclusive. +// TODO(yair): Enforce this invariant. +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct StateDiff { + pub deployed_contracts: IndexMap, + pub storage_diffs: IndexMap>, + pub declared_classes: IndexMap, + pub deprecated_declared_classes: IndexMap, + pub nonces: IndexMap, + pub replaced_classes: IndexMap, +} + +// Invariant: Addresses are strictly increasing. +// The invariant is enforced as [`ThinStateDiff`] is created only from [`starknet_api`][`StateDiff`] +// where the addresses are strictly increasing. +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct ThinStateDiff { + pub deployed_contracts: IndexMap, + pub storage_diffs: IndexMap>, + pub declared_classes: IndexMap, + pub deprecated_declared_classes: Vec, + pub nonces: IndexMap, + pub replaced_classes: IndexMap, +} + +impl ThinStateDiff { + // Returns also the declared classes without cloning them. + pub fn from_state_diff(diff: StateDiff) -> (Self, DeclaredClasses, DeprecatedDeclaredClasses) { + ( + Self { + deployed_contracts: diff.deployed_contracts, + storage_diffs: diff.storage_diffs, + declared_classes: diff + .declared_classes + .iter() + .map(|(class_hash, (compiled_hash, _class))| (*class_hash, *compiled_hash)) + .collect(), + deprecated_declared_classes: diff + .deprecated_declared_classes + .keys() + .copied() + .collect(), + nonces: diff.nonces, + replaced_classes: diff.replaced_classes, + }, + diff.declared_classes + .into_iter() + .map(|(class_hash, (_compiled_class_hash, class))| (class_hash, class)) + .collect(), + diff.deprecated_declared_classes, + ) + } + + /// This has the same value as `state_diff_length` in the corresponding `BlockHeader`. + pub fn len(&self) -> usize { + let mut result = 0usize; + result += self.deployed_contracts.len(); + result += self.declared_classes.len(); + result += self.deprecated_declared_classes.len(); + result += self.nonces.len(); + result += self.replaced_classes.len(); + + for (_contract_address, storage_diffs) in &self.storage_diffs { + result += storage_diffs.len(); + } + result + } + + pub fn is_empty(&self) -> bool { + self.deployed_contracts.is_empty() + && self.declared_classes.is_empty() + && self.deprecated_declared_classes.is_empty() + && self.nonces.is_empty() + && self.replaced_classes.is_empty() + && self + .storage_diffs + .iter() + .all(|(_contract_address, storage_diffs)| storage_diffs.is_empty()) + } +} + +impl From for ThinStateDiff { + fn from(diff: StateDiff) -> Self { + Self::from_state_diff(diff).0 + } +} + +/// The sequential numbering of the states between blocks. +// Example: +// States: S0 S1 S2 +// Blocks B0-> B1-> +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct StateNumber(pub BlockNumber); + +impl StateNumber { + /// The state at the beginning of the block. + pub fn right_before_block(block_number: BlockNumber) -> StateNumber { + StateNumber(block_number) + } + + /// The state at the end of the block, or None if it's is out of range. + pub fn right_after_block(block_number: BlockNumber) -> Option { + Some(StateNumber(block_number.next()?)) + } + + /// The state at the end of the block, without checking if it's in range. + pub fn unchecked_right_after_block(block_number: BlockNumber) -> StateNumber { + StateNumber(block_number.unchecked_next()) + } + + pub fn is_before(&self, block_number: BlockNumber) -> bool { + self.0 <= block_number + } + + pub fn is_after(&self, block_number: BlockNumber) -> bool { + !self.is_before(block_number) + } + + pub fn block_after(&self) -> BlockNumber { + self.0 + } +} + +/// A storage key in a contract. +#[derive( + Debug, + Default, + Clone, + Copy, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +pub struct StorageKey(pub PatriciaKey); + +impl From for Felt { + fn from(storage_key: StorageKey) -> Felt { + **storage_key + } +} + +impl TryFrom for StorageKey { + type Error = StarknetApiError; + + fn try_from(val: StarkHash) -> Result { + Ok(Self(PatriciaKey::try_from(val)?)) + } +} + +impl From for StorageKey { + fn from(val: u128) -> Self { + StorageKey(PatriciaKey::from(val)) + } +} + +impl_from_through_intermediate!(u128, StorageKey, u8, u16, u32, u64); + +/// A contract class. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub sierra_program: Vec, + pub entry_points_by_type: HashMap>, + pub abi: String, +} + +#[derive( + Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +#[serde(deny_unknown_fields)] +pub enum EntryPointType { + /// A constructor entry point. + #[serde(rename = "CONSTRUCTOR")] + Constructor, + /// An external entry point. + #[serde(rename = "EXTERNAL")] + #[default] + External, + /// An L1 handler entry point. + #[serde(rename = "L1_HANDLER")] + L1Handler, +} + +/// An entry point of a [ContractClass](`crate::state::ContractClass`). +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct EntryPoint { + pub function_idx: FunctionIndex, + pub selector: EntryPointSelector, +} + +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct FunctionIndex(pub usize); diff --git a/crates/starknet_api/src/state_test.rs b/crates/starknet_api/src/state_test.rs new file mode 100644 index 00000000000..47b9a56b15e --- /dev/null +++ b/crates/starknet_api/src/state_test.rs @@ -0,0 +1,118 @@ +use std::collections::HashMap; + +use indexmap::{indexmap, IndexMap}; +use serde_json::json; + +use super::ThinStateDiff; +use crate::core::{ClassHash, CompiledClassHash, Nonce}; +use crate::deprecated_contract_class::EntryPointOffset; + +#[test] +fn entry_point_offset_from_json_str() { + let data = r#" + { + "offset_1": 2 , + "offset_2": "0x7b" + }"#; + let offsets: HashMap = serde_json::from_str(data).unwrap(); + + assert_eq!(EntryPointOffset(2), offsets["offset_1"]); + assert_eq!(EntryPointOffset(123), offsets["offset_2"]); +} + +#[test] +fn entry_point_offset_into_json_str() { + let offset = EntryPointOffset(123); + assert_eq!(json!(offset), json!(format!("{:#x}", offset.0))); +} + +#[test] +fn thin_state_diff_len() { + let state_diff = ThinStateDiff { + deployed_contracts: indexmap! { + 0u64.into() => ClassHash(4u64.into()), + }, + storage_diffs: indexmap! { + 0u64.into() => indexmap! { + 0u64.into() => 0u64.into(), + 1u64.into() => 1u64.into(), + }, + 1u64.into() => indexmap! { + 0u64.into() => 0u64.into(), + }, + }, + declared_classes: indexmap! { + ClassHash(4u64.into()) => CompiledClassHash(9u64.into()), + ClassHash(5u64.into()) => CompiledClassHash(10u64.into()), + }, + deprecated_declared_classes: vec![ + ClassHash(6u64.into()), + ClassHash(7u64.into()), + ClassHash(8u64.into()), + ], + nonces: indexmap! { + 0u64.into() => Nonce(1u64.into()), + 1u64.into() => Nonce(1u64.into()), + }, + replaced_classes: indexmap! { + 2u64.into() => ClassHash(4u64.into()), + 3u64.into() => ClassHash(5u64.into()), + }, + }; + assert_eq!(state_diff.len(), 13); +} + +#[test] +fn thin_state_diff_is_empty() { + assert!(ThinStateDiff::default().is_empty()); + assert!( + ThinStateDiff { + storage_diffs: indexmap! { Default::default() => IndexMap::new() }, + ..Default::default() + } + .is_empty() + ); + + assert!( + !ThinStateDiff { + deployed_contracts: indexmap! { Default::default() => Default::default() }, + ..Default::default() + } + .is_empty() + ); + assert!( + !ThinStateDiff { + storage_diffs: indexmap! { Default::default() => indexmap! { Default::default() => Default::default() } }, + ..Default::default() + } + .is_empty() + ); + assert!( + !ThinStateDiff { + declared_classes: indexmap! { Default::default() => Default::default() }, + ..Default::default() + } + .is_empty() + ); + assert!( + !ThinStateDiff { + deprecated_declared_classes: vec![Default::default()], + ..Default::default() + } + .is_empty() + ); + assert!( + !ThinStateDiff { + nonces: indexmap! { Default::default() => Default::default() }, + ..Default::default() + } + .is_empty() + ); + assert!( + !ThinStateDiff { + replaced_classes: indexmap! { Default::default() => Default::default() }, + ..Default::default() + } + .is_empty() + ); +} diff --git a/crates/starknet_api/src/transaction.rs b/crates/starknet_api/src/transaction.rs new file mode 100644 index 00000000000..dde4b3dc753 --- /dev/null +++ b/crates/starknet_api/src/transaction.rs @@ -0,0 +1,1010 @@ +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::fmt::Display; +use std::sync::Arc; + +use derive_more::{Display, From}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use starknet_types_core::felt::Felt; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; + +use crate::block::{BlockHash, BlockNumber}; +use crate::core::{ + ChainId, ClassHash, CompiledClassHash, ContractAddress, EntryPointSelector, EthAddress, Nonce, +}; +use crate::data_availability::DataAvailabilityMode; +use crate::hash::StarkHash; +use crate::serde_utils::PrefixedBytesAsHex; +use crate::transaction_hash::{ + get_declare_transaction_v0_hash, get_declare_transaction_v1_hash, + get_declare_transaction_v2_hash, get_declare_transaction_v3_hash, + get_deploy_account_transaction_v1_hash, get_deploy_account_transaction_v3_hash, + get_deploy_transaction_hash, get_invoke_transaction_v0_hash, get_invoke_transaction_v1_hash, + get_invoke_transaction_v3_hash, get_l1_handler_transaction_hash, +}; +use crate::StarknetApiError; + +pub trait TransactionHasher { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result; +} + +/// A transaction. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub enum Transaction { + /// A declare transaction. + Declare(DeclareTransaction), + /// A deploy transaction. + Deploy(DeployTransaction), + /// A deploy account transaction. + DeployAccount(DeployAccountTransaction), + /// An invoke transaction. + Invoke(InvokeTransaction), + /// An L1 handler transaction. + L1Handler(L1HandlerTransaction), +} + +impl Transaction { + pub fn version(&self) -> TransactionVersion { + match self { + Transaction::Declare(tx) => tx.version(), + Transaction::Deploy(tx) => tx.version, + Transaction::DeployAccount(tx) => tx.version(), + Transaction::Invoke(tx) => tx.version(), + Transaction::L1Handler(tx) => tx.version, + } + } +} + +impl TransactionHasher for Transaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + match self { + Transaction::Declare(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + Transaction::Deploy(tx) => tx.calculate_transaction_hash(chain_id, transaction_version), + Transaction::DeployAccount(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + Transaction::Invoke(tx) => tx.calculate_transaction_hash(chain_id, transaction_version), + Transaction::L1Handler(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + } + } +} + +/// A transaction output. +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub enum TransactionOutput { + /// A declare transaction output. + Declare(DeclareTransactionOutput), + /// A deploy transaction output. + Deploy(DeployTransactionOutput), + /// A deploy account transaction output. + DeployAccount(DeployAccountTransactionOutput), + /// An invoke transaction output. + Invoke(InvokeTransactionOutput), + /// An L1 handler transaction output. + L1Handler(L1HandlerTransactionOutput), +} + +impl TransactionOutput { + pub fn actual_fee(&self) -> Fee { + match self { + TransactionOutput::Declare(output) => output.actual_fee, + TransactionOutput::Deploy(output) => output.actual_fee, + TransactionOutput::DeployAccount(output) => output.actual_fee, + TransactionOutput::Invoke(output) => output.actual_fee, + TransactionOutput::L1Handler(output) => output.actual_fee, + } + } + + pub fn events(&self) -> &[Event] { + match self { + TransactionOutput::Declare(output) => &output.events, + TransactionOutput::Deploy(output) => &output.events, + TransactionOutput::DeployAccount(output) => &output.events, + TransactionOutput::Invoke(output) => &output.events, + TransactionOutput::L1Handler(output) => &output.events, + } + } + + pub fn execution_status(&self) -> &TransactionExecutionStatus { + match self { + TransactionOutput::Declare(output) => &output.execution_status, + TransactionOutput::Deploy(output) => &output.execution_status, + TransactionOutput::DeployAccount(output) => &output.execution_status, + TransactionOutput::Invoke(output) => &output.execution_status, + TransactionOutput::L1Handler(output) => &output.execution_status, + } + } + + pub fn execution_resources(&self) -> &ExecutionResources { + match self { + TransactionOutput::Declare(output) => &output.execution_resources, + TransactionOutput::Deploy(output) => &output.execution_resources, + TransactionOutput::DeployAccount(output) => &output.execution_resources, + TransactionOutput::Invoke(output) => &output.execution_resources, + TransactionOutput::L1Handler(output) => &output.execution_resources, + } + } + + pub fn messages_sent(&self) -> &Vec { + match self { + TransactionOutput::Declare(output) => &output.messages_sent, + TransactionOutput::Deploy(output) => &output.messages_sent, + TransactionOutput::DeployAccount(output) => &output.messages_sent, + TransactionOutput::Invoke(output) => &output.messages_sent, + TransactionOutput::L1Handler(output) => &output.messages_sent, + } + } +} + +/// A declare V0 or V1 transaction (same schema but different version). +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV0V1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub sender_address: ContractAddress, +} + +impl TransactionHasher for DeclareTransactionV0V1 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + if *transaction_version == TransactionVersion::ZERO { + return get_declare_transaction_v0_hash(self, chain_id, transaction_version); + } + if *transaction_version == TransactionVersion::ONE { + return get_declare_transaction_v1_hash(self, chain_id, transaction_version); + } + panic!("Illegal transaction version."); + } +} + +/// A declare V2 transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeclareTransactionV2 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, +} + +impl TransactionHasher for DeclareTransactionV2 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_declare_transaction_v2_hash(self, chain_id, transaction_version) + } +} + +/// A declare V3 transaction. +#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct DeclareTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, +} + +impl TransactionHasher for DeclareTransactionV3 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_declare_transaction_v3_hash(self, chain_id, transaction_version) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub enum DeclareTransaction { + V0(DeclareTransactionV0V1), + V1(DeclareTransactionV0V1), + V2(DeclareTransactionV2), + V3(DeclareTransactionV3), +} + +macro_rules! implement_declare_tx_getters { + ($(($field:ident, $field_type:ty)),*) => { + $(pub fn $field(&self) -> $field_type { + match self { + Self::V0(tx) => tx.$field.clone(), + Self::V1(tx) => tx.$field.clone(), + Self::V2(tx) => tx.$field.clone(), + Self::V3(tx) => tx.$field.clone(), + } + })* + }; +} + +impl DeclareTransaction { + implement_declare_tx_getters!( + (class_hash, ClassHash), + (nonce, Nonce), + (sender_address, ContractAddress), + (signature, TransactionSignature) + ); + + pub fn version(&self) -> TransactionVersion { + match self { + DeclareTransaction::V0(_) => TransactionVersion::ZERO, + DeclareTransaction::V1(_) => TransactionVersion::ONE, + DeclareTransaction::V2(_) => TransactionVersion::TWO, + DeclareTransaction::V3(_) => TransactionVersion::THREE, + } + } +} + +impl TransactionHasher for DeclareTransaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + match self { + DeclareTransaction::V0(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + DeclareTransaction::V1(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + DeclareTransaction::V2(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + DeclareTransaction::V3(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + } + } +} + +/// A deploy account V1 transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, +} + +impl TransactionHasher for DeployAccountTransactionV1 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_deploy_account_transaction_v1_hash(self, chain_id, transaction_version) + } +} + +/// A deploy account V3 transaction. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployAccountTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, +} + +impl TransactionHasher for DeployAccountTransactionV3 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_deploy_account_transaction_v3_hash(self, chain_id, transaction_version) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, From)] +pub enum DeployAccountTransaction { + V1(DeployAccountTransactionV1), + V3(DeployAccountTransactionV3), +} + +macro_rules! implement_deploy_account_tx_getters { + ($(($field:ident, $field_type:ty)),*) => { + $( + pub fn $field(&self) -> $field_type { + match self { + Self::V1(tx) => tx.$field.clone(), + Self::V3(tx) => tx.$field.clone(), + } + } + )* + }; +} + +impl DeployAccountTransaction { + implement_deploy_account_tx_getters!( + (class_hash, ClassHash), + (constructor_calldata, Calldata), + (contract_address_salt, ContractAddressSalt), + (nonce, Nonce), + (signature, TransactionSignature) + ); + + pub fn version(&self) -> TransactionVersion { + match self { + DeployAccountTransaction::V1(_) => TransactionVersion::ONE, + DeployAccountTransaction::V3(_) => TransactionVersion::THREE, + } + } +} + +impl TransactionHasher for DeployAccountTransaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + match self { + DeployAccountTransaction::V1(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + DeployAccountTransaction::V3(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + } + } +} + +/// A deploy transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct DeployTransaction { + pub version: TransactionVersion, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, +} + +impl TransactionHasher for DeployTransaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_deploy_transaction_hash(self, chain_id, transaction_version) + } +} + +/// An invoke V0 transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +impl TransactionHasher for InvokeTransactionV0 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_invoke_transaction_v0_hash(self, chain_id, transaction_version) + } +} + +/// An invoke V1 transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, +} + +impl TransactionHasher for InvokeTransactionV1 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_invoke_transaction_v1_hash(self, chain_id, transaction_version) + } +} + +/// An invoke V3 transaction. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct InvokeTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, +} + +impl TransactionHasher for InvokeTransactionV3 { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_invoke_transaction_v3_hash(self, chain_id, transaction_version) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, From)] +pub enum InvokeTransaction { + V0(InvokeTransactionV0), + V1(InvokeTransactionV1), + V3(InvokeTransactionV3), +} + +macro_rules! implement_invoke_tx_getters { + ($(($field:ident, $field_type:ty)),*) => { + $(pub fn $field(&self) -> $field_type { + match self { + Self::V0(tx) => tx.$field.clone(), + Self::V1(tx) => tx.$field.clone(), + Self::V3(tx) => tx.$field.clone(), + } + })* + }; +} + +impl InvokeTransaction { + implement_invoke_tx_getters!((calldata, Calldata), (signature, TransactionSignature)); + + pub fn nonce(&self) -> Nonce { + match self { + Self::V0(_) => Nonce::default(), + Self::V1(tx) => tx.nonce, + Self::V3(tx) => tx.nonce, + } + } + + pub fn sender_address(&self) -> ContractAddress { + match self { + Self::V0(tx) => tx.contract_address, + Self::V1(tx) => tx.sender_address, + Self::V3(tx) => tx.sender_address, + } + } + + pub fn version(&self) -> TransactionVersion { + match self { + InvokeTransaction::V0(_) => TransactionVersion::ZERO, + InvokeTransaction::V1(_) => TransactionVersion::ONE, + InvokeTransaction::V3(_) => TransactionVersion::THREE, + } + } +} + +impl TransactionHasher for InvokeTransaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + match self { + InvokeTransaction::V0(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + InvokeTransaction::V1(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + InvokeTransaction::V3(tx) => { + tx.calculate_transaction_hash(chain_id, transaction_version) + } + } + } +} + +/// An L1 handler transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct L1HandlerTransaction { + pub version: TransactionVersion, + pub nonce: Nonce, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +impl TransactionHasher for L1HandlerTransaction { + fn calculate_transaction_hash( + &self, + chain_id: &ChainId, + transaction_version: &TransactionVersion, + ) -> Result { + get_l1_handler_transaction_hash(self, chain_id, transaction_version) + } +} + +/// A declare transaction output. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeclareTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy-account transaction output. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeployAccountTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A deploy transaction output. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeployTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An invoke transaction output. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct InvokeTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// An L1 handler transaction output. +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct L1HandlerTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + #[serde(flatten)] + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, +} + +/// A transaction receipt. +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct TransactionReceipt { + pub transaction_hash: TransactionHash, + pub block_hash: BlockHash, + pub block_number: BlockNumber, + #[serde(flatten)] + pub output: TransactionOutput, +} + +/// Transaction execution status. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default)] +#[serde(tag = "execution_status")] +pub enum TransactionExecutionStatus { + #[serde(rename = "SUCCEEDED")] + #[default] + // Succeeded is the default variant because old versions of Starknet don't have an execution + // status and every transaction is considered succeeded + Succeeded, + #[serde(rename = "REVERTED")] + Reverted(RevertedTransactionExecutionStatus), +} + +/// A reverted transaction execution status. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct RevertedTransactionExecutionStatus { + // TODO: Validate it's an ASCII string. + pub revert_reason: String, +} + +/// A fee. +#[derive( + Debug, + Copy, + Clone, + Default, + Display, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +#[serde(from = "PrefixedBytesAsHex<16_usize>", into = "PrefixedBytesAsHex<16_usize>")] +pub struct Fee(pub u128); + +impl From> for Fee { + fn from(value: PrefixedBytesAsHex<16_usize>) -> Self { + Self(u128::from_be_bytes(value.0)) + } +} + +impl From for PrefixedBytesAsHex<16_usize> { + fn from(fee: Fee) -> Self { + Self(fee.0.to_be_bytes()) + } +} + +impl From for Felt { + fn from(fee: Fee) -> Self { + Self::from(fee.0) + } +} + +/// The hash of a [Transaction](`crate::transaction::Transaction`). +#[derive( + Debug, + Default, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +pub struct TransactionHash(pub StarkHash); + +impl Display for TransactionHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +/// A contract address salt. +#[derive( + Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct ContractAddressSalt(pub StarkHash); + +/// A transaction signature. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct TransactionSignature(pub Vec); + +/// A transaction version. +#[derive( + Debug, + Copy, + Clone, + Default, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + derive_more::Deref, +)] +pub struct TransactionVersion(pub Felt); + +impl TransactionVersion { + /// [TransactionVersion] constant that's equal to 0. + pub const ZERO: Self = { Self(Felt::ZERO) }; + + /// [TransactionVersion] constant that's equal to 1. + pub const ONE: Self = { Self(Felt::ONE) }; + + /// [TransactionVersion] constant that's equal to 2. + pub const TWO: Self = { Self(Felt::TWO) }; + + /// [TransactionVersion] constant that's equal to 3. + pub const THREE: Self = { Self(Felt::THREE) }; +} + +/// The calldata of a transaction. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct Calldata(pub Arc>); + +#[macro_export] +macro_rules! calldata { + ( $( $x:expr ),* ) => { + Calldata(vec![$($x),*].into()) + }; +} + +/// An L1 to L2 message. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct MessageToL2 { + pub from_address: EthAddress, + pub payload: L1ToL2Payload, +} + +/// An L2 to L1 message. +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct MessageToL1 { + pub from_address: ContractAddress, + pub to_address: EthAddress, + pub payload: L2ToL1Payload, +} + +/// The payload of [`MessageToL2`]. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct L1ToL2Payload(pub Vec); + +/// The payload of [`MessageToL1`]. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct L2ToL1Payload(pub Vec); + +/// An event. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct Event { + // TODO: Add a TransactionHash element to this struct, and then remove EventLeafElements. + pub from_address: ContractAddress, + #[serde(flatten)] + pub content: EventContent, +} + +/// An event content. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct EventContent { + pub keys: Vec, + pub data: EventData, +} + +/// An event key. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct EventKey(pub Felt); + +/// An event data. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct EventData(pub Vec); + +/// The index of a transaction in [BlockBody](`crate::block::BlockBody`). +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct TransactionOffsetInBlock(pub usize); + +/// The index of an event in [TransactionOutput](`crate::transaction::TransactionOutput`). +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct EventIndexInTransactionOutput(pub usize); + +/// Transaction fee tip. +#[derive( + Clone, + Copy, + Debug, + Default, + Deserialize, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + Serialize, + derive_more::Deref, +)] +#[serde(from = "PrefixedBytesAsHex<8_usize>", into = "PrefixedBytesAsHex<8_usize>")] +pub struct Tip(pub u64); + +impl From> for Tip { + fn from(value: PrefixedBytesAsHex<8_usize>) -> Self { + Self(u64::from_be_bytes(value.0)) + } +} + +impl From for PrefixedBytesAsHex<8_usize> { + fn from(tip: Tip) -> Self { + Self(tip.0.to_be_bytes()) + } +} + +impl From for Felt { + fn from(tip: Tip) -> Self { + Self::from(tip.0) + } +} + +/// Execution resource. +#[derive( + Clone, Copy, Debug, Deserialize, EnumIter, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, +)] +pub enum Resource { + #[serde(rename = "L1_GAS")] + L1Gas, + #[serde(rename = "L2_GAS")] + L2Gas, +} + +/// Fee bounds for an execution resource. +/// TODO(Yael): add types ResourceAmount and ResourcePrice and use them instead of u64 and u128. +#[derive( + Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, +)] +pub struct ResourceBounds { + // Specifies the maximum amount of each resource allowed for usage during the execution. + #[serde(serialize_with = "u64_to_hex", deserialize_with = "hex_to_u64")] + pub max_amount: u64, + + // Specifies the maximum price the user is willing to pay for each resource unit. + #[serde(serialize_with = "u128_to_hex", deserialize_with = "hex_to_u128")] + pub max_price_per_unit: u128, +} + +fn u64_to_hex(value: &u64, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&format!("0x{:x}", value)) +} + +fn hex_to_u64<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + u64::from_str_radix(s.trim_start_matches("0x"), 16).map_err(serde::de::Error::custom) +} + +fn u128_to_hex(value: &u128, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&format!("0x{:x}", value)) +} + +fn hex_to_u128<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + u128::from_str_radix(s.trim_start_matches("0x"), 16).map_err(serde::de::Error::custom) +} + +/// A mapping from execution resources to their corresponding fee bounds.. +#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct ResourceBoundsMapping(pub BTreeMap); + +impl TryFrom> for ResourceBoundsMapping { + type Error = StarknetApiError; + fn try_from( + resource_resource_bounds_pairs: Vec<(Resource, ResourceBounds)>, + ) -> Result { + let n_variants = Resource::iter().count(); + let unique_resources: HashSet = + HashSet::from_iter(resource_resource_bounds_pairs.iter().map(|(k, _)| *k)); + if unique_resources.len() != n_variants + || resource_resource_bounds_pairs.len() != n_variants + { + Err(StarknetApiError::InvalidResourceMappingInitializer(format!( + "{:?}", + resource_resource_bounds_pairs + ))) + } else { + Ok(Self(resource_resource_bounds_pairs.into_iter().collect::>())) + } + } +} + +/// Paymaster-related data. +#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub struct PaymasterData(pub Vec); + +/// If nonempty, will contain the required data for deploying and initializing an account contract: +/// its class hash, address salt and constructor calldata. +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct AccountDeploymentData(pub Vec); + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct GasVector { + pub l1_gas: u64, + pub l1_data_gas: u64, +} + +/// The execution resources used by a transaction. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct ExecutionResources { + pub steps: u64, + pub builtin_instance_counter: HashMap, + pub memory_holes: u64, + pub da_gas_consumed: GasVector, + pub gas_consumed: GasVector, +} + +#[derive(Clone, Debug, Deserialize, EnumIter, Eq, Hash, PartialEq, Serialize)] +pub enum Builtin { + #[serde(rename = "range_check_builtin_applications")] + RangeCheck, + #[serde(rename = "pedersen_builtin_applications")] + Pedersen, + #[serde(rename = "poseidon_builtin_applications")] + Poseidon, + #[serde(rename = "ec_op_builtin_applications")] + EcOp, + #[serde(rename = "ecdsa_builtin_applications")] + Ecdsa, + #[serde(rename = "bitwise_builtin_applications")] + Bitwise, + #[serde(rename = "keccak_builtin_applications")] + Keccak, + #[serde(rename = "segment_arena_builtin")] + SegmentArena, + #[serde(rename = "add_mod_builtin")] + AddMod, + #[serde(rename = "mul_mod_builtin")] + MulMod, + #[serde(rename = "range_check96_builtin")] + RangeCheck96, +} + +const RANGE_CHACK_BUILTIN_NAME: &str = "range_check"; +const PEDERSEN_BUILTIN_NAME: &str = "pedersen"; +const POSEIDON_BUILTIN_NAME: &str = "poseidon"; +const EC_OP_BUILTIN_NAME: &str = "ec_op"; +const ECDSA_BUILTIN_NAME: &str = "ecdsa"; +const BITWISE_BUILTIN_NAME: &str = "bitwise"; +const KECCAK_BUILTIN_NAME: &str = "keccak"; +const SEGMENT_ARENA_BUILTIN_NAME: &str = "segment_arena"; +const ADD_MOD_BUILTIN_NAME: &str = "add_mod"; +const MUL_MOD_BUILTIN_NAME: &str = "mul_mod"; +const RANGE_CHECK96_BUILTIN_NAME: &str = "range_check96"; + +impl Builtin { + pub fn name(&self) -> &'static str { + match self { + Builtin::RangeCheck => RANGE_CHACK_BUILTIN_NAME, + Builtin::Pedersen => PEDERSEN_BUILTIN_NAME, + Builtin::Poseidon => POSEIDON_BUILTIN_NAME, + Builtin::EcOp => EC_OP_BUILTIN_NAME, + Builtin::Ecdsa => ECDSA_BUILTIN_NAME, + Builtin::Bitwise => BITWISE_BUILTIN_NAME, + Builtin::Keccak => KECCAK_BUILTIN_NAME, + Builtin::SegmentArena => SEGMENT_ARENA_BUILTIN_NAME, + Builtin::AddMod => ADD_MOD_BUILTIN_NAME, + Builtin::MulMod => MUL_MOD_BUILTIN_NAME, + Builtin::RangeCheck96 => RANGE_CHECK96_BUILTIN_NAME, + } + } +} diff --git a/crates/starknet_api/src/transaction_hash.rs b/crates/starknet_api/src/transaction_hash.rs new file mode 100644 index 00000000000..7b00c492274 --- /dev/null +++ b/crates/starknet_api/src/transaction_hash.rs @@ -0,0 +1,610 @@ +use once_cell::sync::Lazy; +use starknet_types_core::felt::Felt; + +use crate::block::BlockNumber; +use crate::core::{calculate_contract_address, ChainId, ContractAddress}; +use crate::crypto::utils::HashChain; +use crate::data_availability::DataAvailabilityMode; +use crate::transaction::{ + DeclareTransaction, DeclareTransactionV0V1, DeclareTransactionV2, DeclareTransactionV3, + DeployAccountTransaction, DeployAccountTransactionV1, DeployAccountTransactionV3, + DeployTransaction, InvokeTransaction, InvokeTransactionV0, InvokeTransactionV1, + InvokeTransactionV3, L1HandlerTransaction, Resource, ResourceBounds, ResourceBoundsMapping, + Tip, Transaction, TransactionHash, TransactionVersion, +}; +use crate::StarknetApiError; + +type ResourceName = [u8; 7]; + +const DATA_AVAILABILITY_MODE_BITS: usize = 32; +const L1_GAS: &ResourceName = b"\0L1_GAS"; +const L2_GAS: &ResourceName = b"\0L2_GAS"; + +static DECLARE: Lazy = + Lazy::new(|| ascii_as_felt("declare").expect("ascii_as_felt failed for 'declare'")); +static DEPLOY: Lazy = + Lazy::new(|| ascii_as_felt("deploy").expect("ascii_as_felt failed for 'deploy'")); +static DEPLOY_ACCOUNT: Lazy = Lazy::new(|| { + ascii_as_felt("deploy_account").expect("ascii_as_felt failed for 'deploy_account'") +}); +static INVOKE: Lazy = + Lazy::new(|| ascii_as_felt("invoke").expect("ascii_as_felt failed for 'invoke'")); +static L1_HANDLER: Lazy = + Lazy::new(|| ascii_as_felt("l1_handler").expect("ascii_as_felt failed for 'l1_handler'")); +const CONSTRUCTOR_ENTRY_POINT_SELECTOR: Felt = + Felt::from_hex_unchecked("0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194"); + +/// Calculates hash of a Starknet transaction. +pub fn get_transaction_hash( + transaction: &Transaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + match transaction { + Transaction::Declare(declare) => match declare { + DeclareTransaction::V0(declare_v0) => { + get_declare_transaction_v0_hash(declare_v0, chain_id, transaction_version) + } + DeclareTransaction::V1(declare_v1) => { + get_declare_transaction_v1_hash(declare_v1, chain_id, transaction_version) + } + DeclareTransaction::V2(declare_v2) => { + get_declare_transaction_v2_hash(declare_v2, chain_id, transaction_version) + } + DeclareTransaction::V3(declare_v3) => { + get_declare_transaction_v3_hash(declare_v3, chain_id, transaction_version) + } + }, + Transaction::Deploy(deploy) => { + get_deploy_transaction_hash(deploy, chain_id, transaction_version) + } + Transaction::DeployAccount(deploy_account) => match deploy_account { + DeployAccountTransaction::V1(deploy_account_v1) => { + get_deploy_account_transaction_v1_hash( + deploy_account_v1, + chain_id, + transaction_version, + ) + } + DeployAccountTransaction::V3(deploy_account_v3) => { + get_deploy_account_transaction_v3_hash( + deploy_account_v3, + chain_id, + transaction_version, + ) + } + }, + Transaction::Invoke(invoke) => match invoke { + InvokeTransaction::V0(invoke_v0) => { + get_invoke_transaction_v0_hash(invoke_v0, chain_id, transaction_version) + } + InvokeTransaction::V1(invoke_v1) => { + get_invoke_transaction_v1_hash(invoke_v1, chain_id, transaction_version) + } + InvokeTransaction::V3(invoke_v3) => { + get_invoke_transaction_v3_hash(invoke_v3, chain_id, transaction_version) + } + }, + Transaction::L1Handler(l1_handler) => { + get_l1_handler_transaction_hash(l1_handler, chain_id, transaction_version) + } + } +} + +// On mainnet, from this block number onwards, there are no deprecated transactions, +// enabling us to validate against a single hash calculation. +const MAINNET_TRANSACTION_HASH_WITH_VERSION: BlockNumber = BlockNumber(1470); + +// Calculates a list of deprecated hashes for a transaction. +fn get_deprecated_transaction_hashes( + chain_id: &ChainId, + block_number: &BlockNumber, + transaction: &Transaction, + transaction_version: &TransactionVersion, +) -> Result, StarknetApiError> { + Ok(if chain_id == &ChainId::Mainnet && block_number > &MAINNET_TRANSACTION_HASH_WITH_VERSION { + vec![] + } else { + match transaction { + Transaction::Declare(_) => vec![], + Transaction::Deploy(deploy) => { + vec![get_deprecated_deploy_transaction_hash(deploy, chain_id, transaction_version)?] + } + Transaction::DeployAccount(_) => vec![], + Transaction::Invoke(invoke) => match invoke { + InvokeTransaction::V0(invoke_v0) => { + vec![get_deprecated_invoke_transaction_v0_hash( + invoke_v0, + chain_id, + transaction_version, + )?] + } + InvokeTransaction::V1(_) | InvokeTransaction::V3(_) => vec![], + }, + Transaction::L1Handler(l1_handler) => get_deprecated_l1_handler_transaction_hashes( + l1_handler, + chain_id, + transaction_version, + )?, + } + }) +} + +/// Validates the hash of a starknet transaction. +/// For transactions on testnet or those with a low block_number, we validate the +/// transaction hash against all potential historical hash computations. For recent +/// transactions on mainnet, the hash is validated by calculating the precise hash +/// based on the transaction version. +pub fn validate_transaction_hash( + transaction: &Transaction, + block_number: &BlockNumber, + chain_id: &ChainId, + expected_hash: TransactionHash, + transaction_version: &TransactionVersion, +) -> Result { + let mut possible_hashes = get_deprecated_transaction_hashes( + chain_id, + block_number, + transaction, + transaction_version, + )?; + possible_hashes.push(get_transaction_hash(transaction, chain_id, transaction_version)?); + Ok(possible_hashes.contains(&expected_hash)) +} + +// TODO: should be part of core::Felt +pub(crate) fn ascii_as_felt(ascii_str: &str) -> Result { + Felt::from_hex(hex::encode(ascii_str).as_str()) + .map_err(|_| StarknetApiError::OutOfRange { string: ascii_str.to_string() }) +} + +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md +fn get_tip_resource_bounds_hash( + resource_bounds_mapping: &ResourceBoundsMapping, + tip: &Tip, +) -> Result { + let l1_resource_bounds = + resource_bounds_mapping.0.get(&Resource::L1Gas).expect("Missing l1 resource"); + let l1_resource = get_concat_resource(l1_resource_bounds, L1_GAS)?; + + let l2_resource_bounds = + resource_bounds_mapping.0.get(&Resource::L2Gas).expect("Missing l2 resource"); + let l2_resource = get_concat_resource(l2_resource_bounds, L2_GAS)?; + + Ok(HashChain::new() + .chain(&tip.0.into()) + .chain(&l1_resource) + .chain(&l2_resource) + .get_poseidon_hash()) +} + +// Receives resource_bounds and resource_name and returns: +// [0 | resource_name (56 bit) | max_amount (64 bit) | max_price_per_unit (128 bit)]. +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md. +fn get_concat_resource( + resource_bounds: &ResourceBounds, + resource_name: &ResourceName, +) -> Result { + let max_amount = resource_bounds.max_amount.to_be_bytes(); + let max_price = resource_bounds.max_price_per_unit.to_be_bytes(); + let concat_bytes = + [[0_u8].as_slice(), resource_name.as_slice(), max_amount.as_slice(), max_price.as_slice()] + .concat(); + Ok(Felt::from_bytes_be(&concat_bytes.try_into().expect("Expect 32 bytes"))) +} + +// Receives nonce_mode and fee_mode and returns: +// [0...0 (192 bit) | nonce_mode (32 bit) | fee_mode (32 bit)]. +// An implementation of the SNIP: https://github.com/EvyatarO/SNIPs/blob/snip-8/SNIPS/snip-8.md. +fn concat_data_availability_mode( + nonce_mode: &DataAvailabilityMode, + fee_mode: &DataAvailabilityMode, +) -> Felt { + (data_availability_mode_index(fee_mode) + + (data_availability_mode_index(nonce_mode) << DATA_AVAILABILITY_MODE_BITS)) + .into() +} + +fn data_availability_mode_index(mode: &DataAvailabilityMode) -> u64 { + match mode { + DataAvailabilityMode::L1 => 0, + DataAvailabilityMode::L2 => 1, + } +} + +pub(crate) fn get_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_deploy_transaction_hash(transaction, chain_id, false, transaction_version) +} + +fn get_deprecated_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_deploy_transaction_hash(transaction, chain_id, true, transaction_version) +} + +fn get_common_deploy_transaction_hash( + transaction: &DeployTransaction, + chain_id: &ChainId, + is_deprecated: bool, + transaction_version: &TransactionVersion, +) -> Result { + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY) + .chain_if_fn(|| { + if !is_deprecated { + Some(transaction_version.0) + } else { + None + } + }) + .chain(contract_address.0.key()) + .chain(&CONSTRUCTOR_ENTRY_POINT_SELECTOR) + .chain( + &HashChain::new() + .chain_iter(transaction.constructor_calldata.0.iter()) + .get_pedersen_hash(), + ) + // No fee in deploy transaction. + .chain_if_fn(|| { + if !is_deprecated { + Some(Felt::ZERO) + } else { + None + } + }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_invoke_transaction_v0_hash(transaction, chain_id, false, transaction_version) +} + +fn get_deprecated_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_invoke_transaction_v0_hash(transaction, chain_id, true, transaction_version) +} + +fn get_common_invoke_transaction_v0_hash( + transaction: &InvokeTransactionV0, + chain_id: &ChainId, + is_deprecated: bool, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain_if_fn(|| if !is_deprecated { Some(transaction_version.0) } else { None }) + .chain(transaction.contract_address.0.key()) + .chain(&transaction.entry_point_selector.0) + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + .chain_if_fn(|| if !is_deprecated { Some(transaction.max_fee.0.into()) } else { None }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_invoke_transaction_v1_hash( + transaction: &InvokeTransactionV1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&Felt::ZERO) // No entry point selector in invoke transaction. + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_invoke_transaction_v3_hash( + transaction: &InvokeTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let account_deployment_data_hash = HashChain::new() + .chain_iter(transaction.account_deployment_data.0.iter()) + .get_poseidon_hash(); + let calldata_hash = + HashChain::new().chain_iter(transaction.calldata.0.iter()).get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&INVOKE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&data_availability_mode) + .chain(&account_deployment_data_hash) + .chain(&calldata_hash) + .get_poseidon_hash(), + )) +} + +#[derive(PartialEq, PartialOrd)] +enum L1HandlerVersions { + AsInvoke, + V0Deprecated, + V0, +} + +pub(crate) fn get_l1_handler_transaction_hash( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::V0, + transaction_version, + ) +} + +fn get_deprecated_l1_handler_transaction_hashes( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result, StarknetApiError> { + Ok(vec![ + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::AsInvoke, + transaction_version, + )?, + get_common_l1_handler_transaction_hash( + transaction, + chain_id, + L1HandlerVersions::V0Deprecated, + transaction_version, + )?, + ]) +} + +fn get_common_l1_handler_transaction_hash( + transaction: &L1HandlerTransaction, + chain_id: &ChainId, + version: L1HandlerVersions, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain_if_fn(|| { + if version == L1HandlerVersions::AsInvoke { + Some(*INVOKE) + } else { + Some(*L1_HANDLER) + } + }) + .chain_if_fn(|| { + if version > L1HandlerVersions::V0Deprecated { + Some(transaction_version.0) + } else { + None + } + }) + .chain(transaction.contract_address.0.key()) + .chain(&transaction.entry_point_selector.0) + .chain(&HashChain::new().chain_iter(transaction.calldata.0.iter()).get_pedersen_hash()) + // No fee in l1 handler transaction. + .chain_if_fn(|| { + if version > L1HandlerVersions::V0Deprecated { + Some(Felt::ZERO) + } else { + None + } + }) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain_if_fn(|| { + if version > L1HandlerVersions::AsInvoke { + Some(transaction.nonce.0) + } else { + None + } + }) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_declare_transaction_v0_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&Felt::ZERO) // No entry point selector in declare transaction. + .chain(&HashChain::new().get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.class_hash.0) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_declare_transaction_v1_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&Felt::ZERO) // No entry point selector in declare transaction. + .chain(&HashChain::new().chain(&transaction.class_hash.0).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_declare_transaction_v2_hash( + transaction: &DeclareTransactionV2, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&Felt::ZERO) // No entry point selector in declare transaction. + .chain(&HashChain::new().chain(&transaction.class_hash.0).get_pedersen_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&transaction.compiled_class_hash.0) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_declare_transaction_v3_hash( + transaction: &DeclareTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let account_deployment_data_hash = HashChain::new() + .chain_iter(transaction.account_deployment_data.0.iter()) + .get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&DECLARE) + .chain(&transaction_version.0) + .chain(transaction.sender_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .chain(&data_availability_mode) + .chain(&account_deployment_data_hash) + .chain(&transaction.class_hash.0) + .chain(&transaction.compiled_class_hash.0) + .get_poseidon_hash(), + )) +} + +pub(crate) fn get_deploy_account_transaction_v1_hash( + transaction: &DeployAccountTransactionV1, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let calldata_hash = HashChain::new() + .chain(&transaction.class_hash.0) + .chain(&transaction.contract_address_salt.0) + .chain_iter(transaction.constructor_calldata.0.iter()) + .get_pedersen_hash(); + + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY_ACCOUNT) + .chain(&transaction_version.0) + .chain(contract_address.0.key()) + .chain(&Felt::ZERO) // No entry point selector in deploy account transaction. + .chain(&calldata_hash) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&transaction.nonce.0) + .get_pedersen_hash(), + )) +} + +pub(crate) fn get_deploy_account_transaction_v3_hash( + transaction: &DeployAccountTransactionV3, + chain_id: &ChainId, + transaction_version: &TransactionVersion, +) -> Result { + let contract_address = calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + &transaction.constructor_calldata, + ContractAddress::from(0_u8), + )?; + let tip_resource_bounds_hash = + get_tip_resource_bounds_hash(&transaction.resource_bounds, &transaction.tip)?; + let paymaster_data_hash = + HashChain::new().chain_iter(transaction.paymaster_data.0.iter()).get_poseidon_hash(); + let data_availability_mode = concat_data_availability_mode( + &transaction.nonce_data_availability_mode, + &transaction.fee_data_availability_mode, + ); + let constructor_calldata_hash = + HashChain::new().chain_iter(transaction.constructor_calldata.0.iter()).get_poseidon_hash(); + + Ok(TransactionHash( + HashChain::new() + .chain(&DEPLOY_ACCOUNT) + .chain(&transaction_version.0) + .chain(contract_address.0.key()) + .chain(&tip_resource_bounds_hash) + .chain(&paymaster_data_hash) + .chain(&ascii_as_felt(chain_id.to_string().as_str())?) + .chain(&data_availability_mode) + .chain(&transaction.nonce.0) + .chain(&constructor_calldata_hash) + .chain(&transaction.class_hash.0) + .chain(&transaction.contract_address_salt.0) + .get_poseidon_hash(), + )) +} diff --git a/crates/starknet_api/src/type_utils.rs b/crates/starknet_api/src/type_utils.rs new file mode 100644 index 00000000000..93cb5c76cd7 --- /dev/null +++ b/crates/starknet_api/src/type_utils.rs @@ -0,0 +1,15 @@ +/// Implements `From for top_type` for all bottom_types. Assumes: +/// - `From for top_type` is implemented. +/// - `From for intermediate_type` is implemented, for all bottom_types. +#[macro_export] +macro_rules! impl_from_through_intermediate { + ($intermediate_type: ty, $top_type:ty, $($bottom_type:ty),+) => { + $( + impl From<$bottom_type> for $top_type { + fn from(x: $bottom_type) -> Self { + Self::from(<$intermediate_type>::from(x)) + } + } + )+ + }; +} diff --git a/crates/starknet_client/Cargo.toml b/crates/starknet_client/Cargo.toml new file mode 100644 index 00000000000..ed8ec389f50 --- /dev/null +++ b/crates/starknet_client/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "starknet_client" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "A client implementation that can communicate with Starknet." + +[features] +testing = ["enum-iterator", "mockall", "rand", "rand_chacha", "test_utils"] + +[dependencies] +async-trait.workspace = true +cairo-lang-starknet-classes.workspace = true +enum-iterator = { workspace = true, optional = true } +http.workspace = true +indexmap = { workspace = true, features = ["serde"] } +mockall = { workspace = true, optional = true } +os_info.workspace = true +papyrus_common = { path = "../papyrus_common", version = "0.4.0-rc.0" } +papyrus_config = { path = "../papyrus_config", version = "0.4.0-rc.0" } +rand = { workspace = true, optional = true } +rand_chacha = { workspace = true, optional = true } +reqwest = { workspace = true, features = ["json", "blocking"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"] } +serde_repr.workspace = true +starknet_api.workspace = true +starknet-types-core = {workspace = true, features = ["serde"]} +strum.workspace = true +strum_macros.workspace = true +test_utils = { path = "../test_utils", optional = true } +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "sync"] } +tokio-retry.workspace = true +tracing.workspace = true +url.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +enum-iterator.workspace = true +mockall.workspace = true +mockito.workspace = true +rand.workspace = true +rand_chacha.workspace = true +pretty_assertions.workspace = true +simple_logger.workspace = true +starknet_api = { workspace = true, features = ["testing"] } +test_utils = { path = "../test_utils" } + +[package.metadata.cargo-machete] +# The `rand` and `rand_chacha` crates are used in the `testing` feature, which is optional. +# `strum` is used by `EnumIter` which is used in this crate. +ignored = ["rand", "rand_chacha", "strum"] diff --git a/crates/starknet_client/resources/reader/abi.json b/crates/starknet_client/resources/reader/abi.json new file mode 100644 index 00000000000..86f3286782e --- /dev/null +++ b/crates/starknet_client/resources/reader/abi.json @@ -0,0 +1,25 @@ +[ + {"members": [{"name": "index", "offset": 0, "type": "felt"}, {"name": "values", "offset": 1, "type": "(felt, felt)"}], "name": "IndexAndValues", "size": 3, "type": "struct"}, + {"inputs": [{"name": "index", "type": "felt"}, {"name": "diffs_len", "type": "felt"}, {"name": "diffs", "type": "felt*"}], "name": "advance_counter", "outputs": [], "type": "function"}, + {"inputs": [{"name": "address", "type": "felt"}, {"name": "value", "type": "felt"}], "name": "constructor", "outputs": [], "type": "constructor"}, + {"inputs": [{"name": "index_and_x", "type": "IndexAndValues"}], "name": "xor_counters", "outputs": [], "type": "function"}, + {"inputs": [{"name": "address", "type": "felt"}, {"name": "index_and_x", "type": "IndexAndValues"}], "name": "call_xor_counters", "outputs": [], "type": "function"}, + {"inputs": [{"name": "index", "type": "felt"}], "name": "add_signature_to_counters", "outputs": [], "type": "function"}, + {"inputs": [{"name": "address", "type": "felt"}, {"name": "value", "type": "felt"}], "name": "set_value", "outputs": [], "type": "function"}, + {"inputs": [{"name": "address", "type": "felt"}], "name": "get_value", "outputs": [{"name": "res", "type": "felt"}], "type": "function"}, + {"inputs": [], "name": "entry_point", "outputs": [], "type": "function"}, + {"inputs": [], "name": "test_builtins", "outputs": [{"name": "result", "type": "felt"}], "type": "function"}, + {"inputs": [{"name": "to_address", "type": "felt"}], "name": "send_message", "outputs": [], "type": "function"}, + {"inputs": [{"name": "contract_address", "type": "felt"}, {"name": "function_selector", "type": "felt"}, {"name": "calldata_len", "type": "felt"}, {"name": "calldata", "type": "felt*"}], "name": "test_call_contract", "outputs": [], "type": "function"}, + {"inputs": [{"name": "contract_address", "type": "felt"}, {"name": "function_selector", "type": "felt"}, {"name": "calldata_len", "type": "felt"}, {"name": "calldata", "type": "felt*"}], "name": "test_delegate_call", "outputs": [], "type": "function"}, + {"inputs": [{"name": "from_address", "type": "felt"}, {"name": "amount", "type": "felt"}], "name": "deposit", "outputs": [], "type": "l1_handler"}, + {"inputs": [{"name": "expected_address", "type": "felt"}], "name": "test_get_caller_address", "outputs": [], "type": "function"}, + {"inputs": [{"name": "expected_address", "type": "felt"}], "name": "test_get_sequencer_address", "outputs": [], "type": "function"}, + {"inputs": [{"name": "expected_address", "type": "felt"}], "name": "test_get_contract_address", "outputs": [], "type": "function"}, + {"inputs": [{"name": "other_contract_address", "type": "felt"}, {"name": "address", "type": "felt"}], "name": "test_call_storage_consistency", "outputs": [], "type": "function"}, + {"inputs": [{"name": "other_contract_address", "type": "felt"}, {"name": "depth", "type": "felt"}], "name": "test_re_entrance", "outputs": [], "type": "function"}, + {"inputs": [{"name": "value", "type": "felt"}], "name": "add_value", "outputs": [], "type": "function"}, + {"inputs": [{"name": "self_address", "type": "felt"}, {"name": "value", "type": "felt"}], "name": "recursive_add_value", "outputs": [], "type": "function"}, + {"inputs": [{"name": "address", "type": "felt"}], "name": "increase_value", "outputs": [], "type": "function"}, + {"inputs": [{"name": "self_address", "type": "felt"}, {"name": "arr_len", "type": "felt"}, {"name": "arr", "type": "felt*"}], "name": "test_call_with_array", "outputs": [], "type": "function"} +] diff --git a/crates/starknet_client/resources/reader/accepted_on_l2_deprecated_data.json b/crates/starknet_client/resources/reader/accepted_on_l2_deprecated_data.json new file mode 100644 index 00000000000..0565cb9e3ef --- /dev/null +++ b/crates/starknet_client/resources/reader/accepted_on_l2_deprecated_data.json @@ -0,0 +1,383 @@ +{ + "block": { + "block_hash": "0x1bdb0100dc758de319624d4db608b09555ad1aaae8ae633e545475917f5227b", + "parent_block_hash": "0x180045c75e4b60df6d5a414263fa806f49e844d539c2ae1d5bd8bb89c916e04", + "block_number": 9243, + "state_root": "0x1e999d627c291e8a8df13c91993e6535dde78c22f0614012b67a71f0e9ebc54", + "status": "ACCEPTED_ON_L2", + "eth_l1_gas_price": "0x213637dd1", + "strk_l1_gas_price": "0x1a7ce8042", + "transactions": [ + { + "transaction_hash": "0x27022f2939d7548f429675590bf2d79f2100553b67facc2cf03d97b0f9e41fb", + "version": "0x3", + "signature": [ + "0x20c6db4af884677aa8ab908a564e978100c21341452d09fd620f7babe312301", + "0x2472600f0b29ebc1e723f62ac1a1e5892dea7511819a76f2e76546cb74fba75" + ], + "nonce": "0x24cdc", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x61a80", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "calldata": [ + "0x1", + "0x6359ed638df79b82f2f9dbf92abbcb41b57f9dd91ead86b1c85d2dee192c", + "0xb17d8a2731ba7ca1816631e6be14f0fc1b8390422d649fa27f0fbb0c91eea8", + "0x0" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x1527cbdc68effed3a36bbd838f561af2e4680443e420c596e79516d1026a009", + "version": "0x3", + "signature": [ + "0x282e6a75f66ea1da660e3f54360a56830e890ac6bc59e564496808403f2804", + "0x52cc09e0a2664f7b76f15739c89822ad46227661aaf2f2d4d9d7c26d52cf87f" + ], + "nonce": "0x24cdd", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x61a80", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "calldata": [ + "0x2", + "0x47ad6a25df680763e5663bd0eba3d2bfd18b24b1e8f6bd36b71c37433c63ed0", + "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "0x3", + "0x5b264178f50db9ddc8a7df8be419276da5a8e531e1e7e4cc5c39abdc525737", + "0x2e161f6711c5f773b5f53a4e637646917f7261bced3b929d6fa065bcd6eb898", + "0x4e8590878afe121fef5dafcd905455dd880f401c720977943fb94298a7e5dfb", + "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a", + "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "0x14", + "0x8", + "0x68ad936af09530a155349a5930ea9fb428c13bd80dc4a73776d878d4b88ed9b", + "0x201fbcf1c91f422b33394599162cc38a78b162f8f1bacea04905073d6681ccb", + "0x796ed12aefa1512540b9b9b0d52406007253c901feec5fc38b3b9c390104563", + "0x2c678f64b9fa77e6ca952d4adc0f31acb10cf83428ef3b0a8d7671e73b80ee5", + "0x2c1dc0540cbe0e26c1913c1af0ebaaf775a29dce054e9231be619b8afa1033f", + "0x7487c619a3d46ce9065e611ff42e43234bb3ae4f32293a311dfd8398a145d16", + "0x11820e1defa271835b0ef4e5b9e393113684cd545f5daf660bea751d87905eb", + "0x4d87494ac20afdc5382c43ba6ff91e2b2d76f2ff8a3ae70dc86726547fc5d60", + "0xa", + "0x27c1c9caffd5e2624f508fad70100967873ecee53e732060de1f5857540b8db", + "0x77298b815600e72786bc32f2e386eb1cf9b8830c19adf9d6d297beddd2f8fd5", + "0x26109c6b1267723ac03cde063fb2ddbcef669eeebf1d9a10bec867de0038aa1", + "0x296b1af725912551efc7a06a8103b327c2e0f547b63c111bb675c7fed62e755", + "0x258ef50780276e43e9b6ec57837b8d85f5e701d333cc517c8dec8aa82a93fcd", + "0x38875883c113025161307dc7595fea11b29064d7d91cd6ab92afdc9c97fae17", + "0x18f071b34c0456c933c317d5812721fe3f6080b61f8f041b332a95e06cd7aee", + "0x1a8fc337b3fa20e6f8fdde586b1d464d37c8b2c8249710d5dc2f8ea19c089e6", + "0x44608449442ead40f1ff072625c8e76ad6097d1c2d7375bb7f838095a9ef0e5", + "0x627c7b281fa37a37ae253ee5dd6563e306a91d6e61aba220a5f355a17bd3e31" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x4ba4c6567f00cf8b639fbd0271eb07bbca79c2f76217718cef20058f607cfbe", + "version": "0x3", + "signature": [ + "0x3742ecc586c241714e93e7784c1955d5422405b0d2677c69bf09967a9894b57", + "0xe2be6b32e3899dca731bc1615974a87dee5516d4daa4fb0fb9ff25a75153ce" + ], + "nonce": "0x24cde", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x61a80", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "calldata": [ + "0x1", + "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a", + "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "0x4", + "0x4c3cd89077d6a5020c14cba8ef0e1be1f4676f61bdc1a8605419d2989fd4518", + "0x2", + "0x25806976667362cfed50e4e63dd6354e539a8e3e31f8f3553286b5a15314bec", + "0x2f8ac85d2feb11c2f936b310aa64c7229505e3dc23570427373fddc38b7428" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x27bbcef3c4b9368994ac67a674154f2eb182e438a3e48dc47f55fd7ffcfcee6", + "version": "0x3", + "signature": [ + "0x63d88f604801d7801cd39e0faff66e5a373ce0776bde123f11022f1fb30200", + "0x1aed9f0c5f010e82dfcc56fe2c55efc3134fb08eb8def9f9a7ce2b8c37ab8a2" + ], + "nonce": "0x24cdf", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x61a80", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "calldata": [ + "0x2", + "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a", + "0x679c22735055a10db4f275395763a3752a1e3a3043c192299ab6b574fba8d6", + "0x0", + "0x47ad6a25df680763e5663bd0eba3d2bfd18b24b1e8f6bd36b71c37433c63ed0", + "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "0x2", + "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a", + "0x7743a703725faaef551c25787658c75132d46c75f136a0f8767582f32e4b5ae" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + } + ], + "timestamp": 1707496578, + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "transaction_receipts": [ + { + "execution_status": "SUCCEEDED", + "transaction_index": 0, + "transaction_hash": "0x27022f2939d7548f429675590bf2d79f2100553b67facc2cf03d97b0f9e41fb", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0xae08ac6b1a4", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 914, + "builtin_instance_counter": { + "range_check_builtin": 30, + "segment_arena_builtin": 12 + }, + "n_memory_holes": 3 + }, + "actual_fee": "0xae08ac6b1a4" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 1, + "transaction_hash": "0x1527cbdc68effed3a36bbd838f561af2e4680443e420c596e79516d1026a009", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a", + "keys": [ + "0x68ad936af09530a155349a5930ea9fb428c13bd80dc4a73776d878d4b88ed9b", + "0x201fbcf1c91f422b33394599162cc38a78b162f8f1bacea04905073d6681ccb", + "0x796ed12aefa1512540b9b9b0d52406007253c901feec5fc38b3b9c390104563", + "0x2c678f64b9fa77e6ca952d4adc0f31acb10cf83428ef3b0a8d7671e73b80ee5", + "0x2c1dc0540cbe0e26c1913c1af0ebaaf775a29dce054e9231be619b8afa1033f", + "0x7487c619a3d46ce9065e611ff42e43234bb3ae4f32293a311dfd8398a145d16", + "0x11820e1defa271835b0ef4e5b9e393113684cd545f5daf660bea751d87905eb", + "0x4d87494ac20afdc5382c43ba6ff91e2b2d76f2ff8a3ae70dc86726547fc5d60" + ], + "data": [ + "0x27c1c9caffd5e2624f508fad70100967873ecee53e732060de1f5857540b8db", + "0x77298b815600e72786bc32f2e386eb1cf9b8830c19adf9d6d297beddd2f8fd5", + "0x26109c6b1267723ac03cde063fb2ddbcef669eeebf1d9a10bec867de0038aa1", + "0x296b1af725912551efc7a06a8103b327c2e0f547b63c111bb675c7fed62e755", + "0x258ef50780276e43e9b6ec57837b8d85f5e701d333cc517c8dec8aa82a93fcd", + "0x38875883c113025161307dc7595fea11b29064d7d91cd6ab92afdc9c97fae17", + "0x18f071b34c0456c933c317d5812721fe3f6080b61f8f041b332a95e06cd7aee", + "0x1a8fc337b3fa20e6f8fdde586b1d464d37c8b2c8249710d5dc2f8ea19c089e6", + "0x44608449442ead40f1ff072625c8e76ad6097d1c2d7375bb7f838095a9ef0e5", + "0x627c7b281fa37a37ae253ee5dd6563e306a91d6e61aba220a5f355a17bd3e31" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x1e593c9539ea", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 2199, + "builtin_instance_counter": { + "range_check_builtin": 52, + "bitwise_builtin": 2, + "pedersen_builtin": 2 + }, + "n_memory_holes": 24 + }, + "actual_fee": "0x1e593c9539ea" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 2, + "transaction_hash": "0x4ba4c6567f00cf8b639fbd0271eb07bbca79c2f76217718cef20058f607cfbe", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x1e40677bb60c", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 937, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 24 + }, + "n_memory_holes": 23 + }, + "actual_fee": "0x1e40677bb60c" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 3, + "transaction_hash": "0x27bbcef3c4b9368994ac67a674154f2eb182e438a3e48dc47f55fd7ffcfcee6", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x23701c6984d0", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 1274, + "builtin_instance_counter": { + "range_check_builtin": 23, + "ec_op_builtin": 1 + }, + "n_memory_holes": 2 + }, + "actual_fee": "0x23701c6984d0" + } + ], + "starknet_version": "0.13.0" + }, + "state_update": { + "block_hash": "0x1bdb0100dc758de319624d4db608b09555ad1aaae8ae633e545475917f5227b", + "new_root": "0x1e999d627c291e8a8df13c91993e6535dde78c22f0614012b67a71f0e9ebc54", + "old_root": "0x655d778a3f6f39a1fbfb6655901362b194b2cfe1c4d069dad4e503834e39870", + "state_diff": { + "storage_diffs": { + "0x4d0b88ace5705bb7825f91ee95557d906600b7e7762f5615e6a4f407185a43a": [ + { + "key": "0x39c2ea930e610ae7f7510168463166814e6c1bebfe4117f087cae6c9b12c922", + "value": "0x25806976667362cfed50e4e63dd6354e539a8e3e31f8f3553286b5a15314bec" + }, + { + "key": "0x39c2ea930e610ae7f7510168463166814e6c1bebfe4117f087cae6c9b12c923", + "value": "0x2f8ac85d2feb11c2f936b310aa64c7229505e3dc23570427373fddc38b7428" + }, + { + "key": "0x7743a703725faaef551c25787658c75132d46c75f136a0f8767582f32e4b5ae", + "value": "0x7e5" + } + ], + "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d": [ + { + "key": "0x295c615dc08b568dce79348e5dd16f45bc6458ddb026f09e16ce03f3c68e12e", + "value": "0x1e0e5571d81bb386cfd" + }, + { + "key": "0x5496768776e3db30053404f18067d81a6e06f5a2b0de326e21298fd9d569a9a", + "value": "0x3d348cdbca2c75d667" + } + ], + "0x47ad6a25df680763e5663bd0eba3d2bfd18b24b1e8f6bd36b71c37433c63ed0": [ + { + "key": "0x20ffdf18dcee2495de13fa7f867042f40388b6a24526a392d34bfbd16be953", + "value": "0x2e161f6711c5f773b5f53a4e637646917f7261bced3b929d6fa065bcd6eb898" + }, + { + "key": "0x20ffdf18dcee2495de13fa7f867042f40388b6a24526a392d34bfbd16be954", + "value": "0x4e8590878afe121fef5dafcd905455dd880f401c720977943fb94298a7e5dfb" + }, + { + "key": "0x7743a703725faaef551c25787658c75132d46c75f136a0f8767582f32e4b5ae", + "value": "0x7c7" + } + ], + "0x1": [ + { + "key": "0x2411", + "value": "0x6bf4788bc26279b905437157f3e6d45a29321abc3998da3316de0805ad5fa71" + } + ] + }, + "nonces": { + "0x35acd6dd6c5045d18ca6d0192af46b335a5402c02d41f46e4e77ea2c951d9a3": "0x24ce0" + }, + "deployed_contracts": [], + "old_declared_contracts": [], + "declared_classes": [], + "replaced_classes": [] + } + } +} diff --git a/crates/starknet_client/resources/reader/block_post_0_13_1.json b/crates/starknet_client/resources/reader/block_post_0_13_1.json new file mode 100644 index 00000000000..0c63de9bd22 --- /dev/null +++ b/crates/starknet_client/resources/reader/block_post_0_13_1.json @@ -0,0 +1,421 @@ +{ + "block_hash": "0x4fb00421167b164f8392eb9b7ffee5d4fd585cf8e21035b9f64b29526aecb3e", + "parent_block_hash": "0x73786b02e70ee32bf4855ce687651058456093a146905de213dab989da301dc", + "block_number": 329525, + "state_root": "0x5b8950956ada2d4973a30dcfab366e6595afc8b0a5552517cd14fb1bf2eb75", + "transaction_commitment": "0x22810377061682d79e62285605b99c12fc7aeecf6ce5c713909d88e201909eb", + "event_commitment": "0x4a4f2c690f375f6ecccc37843753dbddc9bb4383905c7226cd1a4556d47a811", + "status": "ACCEPTED_ON_L2", + "l1_da_mode": "BLOB", + "l1_gas_price": { + "price_in_wei": "0x3b9aca08", + "price_in_fri": "0x3514f7dc" + }, + "l1_data_gas_price": { + "price_in_wei": "0x4e0b5cf03", + "price_in_fri": "0x2540be400" + }, + "transactions": [ + { + "transaction_hash": "0x9cd83df42ac151171cf2be447bb07714c47ef448f90fb2a29d8003ffc05357", + "version": "0x1", + "max_fee": "0x354a6ba7a18000", + "signature": [ + "0x31dd3d821097b19d67d581d07b6ab44a0e7ec399480acdb73094171222e2db4", + "0x43212ff00efc96d7426cb13f7796213b160b8b40d3c63576ef59459d8e3acad" + ], + "nonce": "0x8", + "sender_address": "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "calldata": [ + "0x2", + "0x4e18c9f8a657466bfe60e23e590fc1e60cb465bf6a8ca8587b6a35f3b53db20", + "0x31aafc75f498fdfa7528880ad27246b4c15af4954f96228c9a132b328de1c92", + "0x6", + "0x78e98d70fb53cd079bcebdb109c45d5919be8c4bcca88f938cb6e352bf6c30e", + "0x3", + "0x38f99ec96ae654cb3a88dbb4443d3be650eb66e61120e6dfecd85cc89b586bc", + "0x1dd8e057ca334c6592935fbf7aaccb036cf668a73d0b60775dae9dfcdc28f94", + "0x79005d3e9d691dea1ac2da70a37a6fb19b97cfd4845816e35d59cb9f1bb94c1", + "0xf469e4540aecc9e73f1d2d0e25502b020307cfe213c5354404ef279dcdd11d", + "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "0x5", + "0x3ae2f9b340e70e3c6ae2101715ccde645f3766283bd3bfade4b5ce7cd7dc9c6", + "0x41909f543f295cd42819243047f887f25095644903f0ed9ceacc841c3a959a", + "0x2", + "0x177bb4ed0bf95f8a93c340550ed5f9bf1563ea71f716602c3e2ab56c3e2ab92", + "0x6c671c42015ffcc2e4ff1d63159f94e1b8faebb90751b1879bfad2b879065cf" + ], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x16dc216ec3dd1dba1f8ec2db9da5cc7e349ef91c94f06e76204dedc3470d4ac", + "version": "0x3", + "signature": [ + "0x280a5fe524066cbb48c17d91de6aa15327d267a766309b74186af823252e2d3", + "0x4fbbb19cc01c575d7a55ee102ac7a6e90eb057dffdc6da7c9fee5a2e9adac53" + ], + "nonce": "0x3", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x708", + "max_price_per_unit": "0x46c7cfe00" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x9184e72a000", + "paymaster_data": [], + "sender_address": "0x6193c7376d223ae00c9f24f00905da596b23f1307ce5ab01c4e6c5a2eb2679d", + "calldata": [ + "0x1", + "0x7688d6bd38fe908104c5fe9da9956d53e5a4dace48fd9c776b035bcda90ddf4", + "0x10b7e63d3ca05c9baffd985d3e1c3858d4dbf0759f066be0eaddc5d71c2cab5", + "0x1", + "0x64" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x368c812e60b502eb422b6cd7e79c989e4418c44e96ef52885d010c805bb963c", + "version": "0x1", + "max_fee": "0x354a6ba7a18000", + "signature": [ + "0x6084e029cee15205d11734a210b1c84afc4eb80b700a56571a15ec33f70708e", + "0x375c614be78c24b52f4db4634e867e6eeea6faadc83e066e9f91c8d58959ba9" + ], + "nonce": "0x9", + "sender_address": "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "calldata": [ + "0x1", + "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "0x2", + "0x3b73e1773ce95172c5f525f29d4d1eb2b407429559bceaa7dec815deb6c0028", + "0x1" + ], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0xd027a2ecb11da22b82f3c214048fef16bbfd842c668e35e2ad95c0e25510f2", + "version": "0x3", + "signature": [ + "0x4753344a9de73595065d040a445a03838d5d53ccde410fcca8eac95a68f3251", + "0x1ba0f7ef78e977deb4b6c7fb8974b396e0740fb47d3782b6e76538e49453ff9" + ], + "nonce": "0xa", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x4c4b40", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "calldata": [ + "0x1", + "0x1305509ce387ad1b83a47c85a0ff3e82cb3be71f39e8c8753589f10f60ecde4", + "0x2fd9126ee011f3a837cea02e32ae4ee73342d827e216998e5616bab88d8b7ea", + "0x1", + "0x2fd9126ee011f3a837cea02e32ae4ee73342d827e216998e5616bab88d8b7ea" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x219e7355c8ece5480fdfda7b6a3019f49c27975d324e8e0728c2d78e95b7ae5", + "version": "0x3", + "signature": [ + "0x275179533eb45d70ae5a4bab1bcf267860522dc3d24a5c4e82283d1799b1d22", + "0x53d61d03ef8fa2ff46bf6d397ffe31eb05c530f74b59950b69fcbee2a668837" + ], + "nonce": "0xb", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x4c4b40", + "max_price_per_unit": "0x5af3107a4000" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "sender_address": "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "calldata": [ + "0x2", + "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "0xf", + "0x5", + "0x2b9b33cc1c7a113c74d307116418cb69fa41031a742d917d36f2fdbb83ab17d", + "0x15c9b83fb27785c1fbf812db24cc25e04703509a437143ad5b6e73129575ba2", + "0x4824f515c9f5414b21dcd39adbae015c51fb007b79eff92851df5c05072b6fe", + "0x64967a429861dc1ee34e4031010f86184e938ad2593c9db8e66a1a579566c5d", + "0x10673e66a28e64889629decbf97c07e0a5d345778c54307b47193a0c02b75c2", + "0x8", + "0x140626948f321601f052d2bb3372538c5e961f46e00f61330e04619e2a9f294", + "0x32426568e134fe0b8389c921c7a050076b78a64872288a192f8b11e1f35a3c6", + "0x446ce68e96931fd03c80d225404555d51b077fef740c5590600f68ae4762f8", + "0x6fa2b3ed33c07304a497e5e3a19056d803893112df0106af36baecf1dcb268f", + "0x12fb2c1e8db8530bb0d50cb0f8f746c17656dab9d07a5e6a12680971c2e4355", + "0x47e42785a3e11ff1408a884f294bd9588c2cda0b2621cf3e63f3a560e2fc563", + "0x68b14002234352e70f4f3f29a72c407162c7548b30343b75932b0dbec5840c5", + "0x4bd91309fbc94f0393c66f51f0c27cce48bff0784f44c77257d904bc621e931", + "0x3b73e1773ce95172c5f525f29d4d1eb2b407429559bceaa7dec815deb6c0028", + "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "0x2", + "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "0x53436cd27226d0b3a3fd9262546f29683c01ba8f22a28f9abb700d546fd9d7f" + ], + "account_deployment_data": [], + "type": "INVOKE_FUNCTION" + } + ], + "timestamp": 1707734016, + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "transaction_receipts": [ + { + "execution_status": "SUCCEEDED", + "transaction_index": 0, + "transaction_hash": "0x9cd83df42ac151171cf2be447bb07714c47ef448f90fb2a29d8003ffc05357", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4e18c9f8a657466bfe60e23e590fc1e60cb465bf6a8ca8587b6a35f3b53db20", + "keys": [ + "0x15bd0500dc9d7e69ab9577f73a8d753e8761bed10f25ba0f124254dc4edb8b4" + ], + "data": [ + "0x78e98d70fb53cd079bcebdb109c45d5919be8c4bcca88f938cb6e352bf6c30e", + "0x3", + "0x38f99ec96ae654cb3a88dbb4443d3be650eb66e61120e6dfecd85cc89b586bc", + "0x1dd8e057ca334c6592935fbf7aaccb036cf668a73d0b60775dae9dfcdc28f94", + "0x79005d3e9d691dea1ac2da70a37a6fb19b97cfd4845816e35d59cb9f1bb94c1" + ] + } + ], + "execution_resources": { + "n_steps": 8703, + "builtin_instance_counter": { + "range_check_builtin": 215, + "pedersen_builtin": 39, + "ec_op_builtin": 3 + }, + "n_memory_holes": 0, + "data_availability": { + "l1_gas": 0, + "l1_data_gas": 288 + } + }, + "actual_fee": "0x582630bd420" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 1, + "transaction_hash": "0x16dc216ec3dd1dba1f8ec2db9da5cc7e349ef91c94f06e76204dedc3470d4ac", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x6193c7376d223ae00c9f24f00905da596b23f1307ce5ab01c4e6c5a2eb2679d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x12d57417dc0", + "0x0" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0xa9fa878c35cd3d0191318f89033ca3e5501a3d90e21e3cc9256bdd5cd17fdd" + ], + "data": [ + "0xca46d96b37266650e0a8b79938d9300037337cad82ea4f45a921ad68b6a5f9", + "0x25e0bf0419c72c2f", + "0x0", + "0x25e0c0317108a9ef", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 6393, + "builtin_instance_counter": { + "range_check_builtin": 144, + "ec_op_builtin": 3, + "pedersen_builtin": 19 + }, + "n_memory_holes": 0, + "data_availability": { + "l1_gas": 0, + "l1_data_gas": 128 + } + }, + "actual_fee": "0x12d57417dc0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 2, + "transaction_hash": "0x368c812e60b502eb422b6cd7e79c989e4418c44e96ef52885d010c805bb963c", + "l2_to_l1_messages": [ + { + "from_address": "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "to_address": "0x0000000000000000000000000000000000000001", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_resources": { + "n_steps": 9817, + "builtin_instance_counter": { + "range_check_builtin": 229, + "pedersen_builtin": 20, + "ec_op_builtin": 3 + }, + "n_memory_holes": 0, + "data_availability": { + "l1_gas": 0, + "l1_data_gas": 384 + } + }, + "actual_fee": "0x20efe791d8d0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 3, + "transaction_hash": "0xd027a2ecb11da22b82f3c214048fef16bbfd842c668e35e2ad95c0e25510f2", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x12d222c85e4", + "0x0" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0xa9fa878c35cd3d0191318f89033ca3e5501a3d90e21e3cc9256bdd5cd17fdd" + ], + "data": [ + "0xca46d96b37266650e0a8b79938d9300037337cad82ea4f45a921ad68b6a5f9", + "0x25e0c0317108a9ef", + "0x0", + "0x25e0c15e93352fd3", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 5849, + "builtin_instance_counter": { + "range_check_builtin": 144, + "ec_op_builtin": 3, + "pedersen_builtin": 19 + }, + "n_memory_holes": 0, + "data_availability": { + "l1_gas": 0, + "l1_data_gas": 128 + } + }, + "actual_fee": "0x12d222c85e4" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 4, + "transaction_hash": "0x219e7355c8ece5480fdfda7b6a3019f49c27975d324e8e0728c2d78e95b7ae5", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x232438a37dc1e45f6cf278b308db7d1868016a5a6a2f6c4d3da746b4d13d891", + "keys": [ + "0x2b9b33cc1c7a113c74d307116418cb69fa41031a742d917d36f2fdbb83ab17d", + "0x15c9b83fb27785c1fbf812db24cc25e04703509a437143ad5b6e73129575ba2", + "0x4824f515c9f5414b21dcd39adbae015c51fb007b79eff92851df5c05072b6fe", + "0x64967a429861dc1ee34e4031010f86184e938ad2593c9db8e66a1a579566c5d", + "0x10673e66a28e64889629decbf97c07e0a5d345778c54307b47193a0c02b75c2" + ], + "data": [ + "0x140626948f321601f052d2bb3372538c5e961f46e00f61330e04619e2a9f294", + "0x32426568e134fe0b8389c921c7a050076b78a64872288a192f8b11e1f35a3c6", + "0x446ce68e96931fd03c80d225404555d51b077fef740c5590600f68ae4762f8", + "0x6fa2b3ed33c07304a497e5e3a19056d803893112df0106af36baecf1dcb268f", + "0x12fb2c1e8db8530bb0d50cb0f8f746c17656dab9d07a5e6a12680971c2e4355", + "0x47e42785a3e11ff1408a884f294bd9588c2cda0b2621cf3e63f3a560e2fc563", + "0x68b14002234352e70f4f3f29a72c407162c7548b30343b75932b0dbec5840c5", + "0x4bd91309fbc94f0393c66f51f0c27cce48bff0784f44c77257d904bc621e931" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", + "0x14c5c28581c68f64c9a3d86b919094a5209fe0ccb454f776b3be2c3968cd91d", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ], + "data": [ + "0x383ab0c2434", + "0x0" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0xa9fa878c35cd3d0191318f89033ca3e5501a3d90e21e3cc9256bdd5cd17fdd" + ], + "data": [ + "0xca46d96b37266650e0a8b79938d9300037337cad82ea4f45a921ad68b6a5f9", + "0x25e0c15e93352fd3", + "0x0", + "0x25e0c4e23e415407", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 9216, + "builtin_instance_counter": { + "range_check_builtin": 229, + "pedersen_builtin": 38, + "ec_op_builtin": 3 + }, + "n_memory_holes": 0, + "data_availability": { + "l1_gas": 0, + "l1_data_gas": 384 + } + }, + "actual_fee": "0x383ab0c2434" + } + ], + "starknet_version": "0.13.1" +} diff --git a/crates/starknet_client/resources/reader/block_state_update.json b/crates/starknet_client/resources/reader/block_state_update.json new file mode 100644 index 00000000000..4ba317a6e8c --- /dev/null +++ b/crates/starknet_client/resources/reader/block_state_update.json @@ -0,0 +1,43 @@ +{ + "block_hash": "0x3f65ef25e87a83d92f32f5e4869a33580f9db47ec980c1ff27bdb5151914de5", + "new_root": "0x02ade8eea6eb6523d22a408a1f035bd351a9a5dce28926ca92d7abb490c0e74a", + "old_root": "0x0465b219d93bcb2776aa3abb009423be3e2d04dba6453d7e027830740cd699a4", + "state_diff": { + "nonces": { + "0x51c62af8919b31499b36bd1f1f702c8ef5a6309554427186c7bd456b862c115": "0x12" + }, + "storage_diffs": { + "0x13386f165f065115c1da38d755be261023c32f0134a03a8e66b6bb1e0016014": [ + { + "key": "0x3b3a699bb6ef37ff4b9c4e14319c7d8e9c9bdd10ff402d1ebde18c62ae58381", + "value": "0x61454dd6e5c83621e41b74c" + }, + { + "key": "0x1557182e4359a1f0c6301278e8f5b35a776ab58d39892581e357578fb287836", + "value": "0x79dd8085e3e5a96ea43e7d" + } + ] + }, + "deployed_contracts": [ + { + "address": "0x3e10411edafd29dfe6d427d03e35cb261b7a5efeee61bf73909ada048c029b9", + "class_hash": "0x071c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64" + } + ], + "declared_classes": [ + { + "class_hash": "0x10", + "compiled_class_hash": "0x1000" + } + ], + "old_declared_contracts": [ + "0x100" + ], + "replaced_classes": [ + { + "address": "0x56b0efe9d91fcda0f341af928404056c5220ee0ccc66be15d20611a172dbd52", + "class_hash": "0x2248aff260e5837317641ff4f861495dd71e78b9dae98a31113e569b336bd26" + } + ] + } +} diff --git a/crates/starknet_client/resources/reader/casm_contract_class.json b/crates/starknet_client/resources/reader/casm_contract_class.json new file mode 100644 index 00000000000..711e201ad1d --- /dev/null +++ b/crates/starknet_client/resources/reader/casm_contract_class.json @@ -0,0 +1,63 @@ +{ + "entry_points_by_type": { + "EXTERNAL": [ + { + "offset": 787, + "builtins": [ + "pedersen", + "range_check" + ], + "selector": "0x11dd528db174d6312644720bceeb9307ba53f6e2937246ac73d5fb30603016" + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "offset": 4305, + "builtins": [ + "range_check" + ], + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ] + }, + "bytecode": [ + "0x40780017fff7fff", + "0x2", + "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473" + ], + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "pythonic_hints": [ + [ + 2, + [ + "memory[ap + 0] = 0 <= memory[fp + -6]" + ] + ] + ], + "hints": [ + [ + 2, + [ + { + "TestLessThanOrEqual": { + "lhs": { + "Immediate": "0x0" + }, + "rhs": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "dst": { + "register": "AP", + "offset": 0 + } + } + } + ] + ] + ], + "compiler_version": "1.0.0" +} diff --git a/crates/starknet_client/resources/reader/contract_class.json b/crates/starknet_client/resources/reader/contract_class.json new file mode 100644 index 00000000000..5d5ce9e9380 --- /dev/null +++ b/crates/starknet_client/resources/reader/contract_class.json @@ -0,0 +1,19 @@ +{ + "sierra_program": [ + "0x302e312e30", + "0x1c", + "0x52616e6765436865636b" + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "function_idx": 0, + "selector": "0x22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658" + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [] + }, + "contract_class_version": "0.1.0", + "abi": "[\n {\n \"type\": \"function\",\n \"name\": \"test\",\n \"inputs\": [\n {\n \"name\": \"arg\",\n \"ty\": \"core::felt\"\n },\n {\n \"name\": \"arg1\",\n \"ty\": \"core::felt\"\n },\n {\n \"name\": \"arg2\",\n \"ty\": \"core::felt\"\n }\n ],\n \"output_ty\": \"core::felt\",\n \"state_mutability\": \"external\"\n },\n {\n \"type\": \"function\",\n \"name\": \"empty\",\n \"inputs\": [],\n \"output_ty\": \"()\",\n \"state_mutability\": \"external\"\n },\n {\n \"type\": \"function\",\n \"name\": \"call_foo\",\n \"inputs\": [\n {\n \"name\": \"a\",\n \"ty\": \"core::integer::u128\"\n }\n ],\n \"output_ty\": \"core::integer::u128\",\n \"state_mutability\": \"external\"\n }\n]" +} diff --git a/crates/starknet_client/resources/reader/declare_v0.json b/crates/starknet_client/resources/reader/declare_v0.json new file mode 100644 index 00000000000..5cb91614d23 --- /dev/null +++ b/crates/starknet_client/resources/reader/declare_v0.json @@ -0,0 +1,10 @@ +{ + "class_hash": "0x5abf9436be774a4d4af00528296700d0181b8cf3cf85ccc556b441ef5876ffe", + "sender_address": "0x1", + "nonce": "0x0", + "max_fee": "0x0", + "version": "0x0", + "transaction_hash": "0x3ff2070e6723bb9b6414977324f916eb53b51f9691e5d9a4fb67160d048958b", + "signature": [], + "type": "DECLARE" +} diff --git a/crates/starknet_client/resources/reader/declare_v3.json b/crates/starknet_client/resources/reader/declare_v3.json new file mode 100644 index 00000000000..55d422c8f31 --- /dev/null +++ b/crates/starknet_client/resources/reader/declare_v3.json @@ -0,0 +1,26 @@ +{ + "account_deployment_data": [], + "class_hash": "0x6f6742127e27687640c7aaf566b9dc892c4493973076cb96fdeb418ae77c192", + "compiled_class_hash": "0xcbbcfda1dea5cc48d3c7ebefd50ecc4aaefabe7e5596fdef4f60cded0ea0b24", + "fee_data_availability_mode": 0, + "nonce": "0x0", + "nonce_data_availability_mode": 0, + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0xffffffffffffffff", + "max_price_per_unit": "0xffffffffffffffffffffffffffffffff" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x12fd537", + "signature": [], + "tip": "0x0", + "transaction_hash": "0x308104e126e1d6659ef499da73eeb88ba9f066a57ad75d8d27fa3ff420cded2", + "version": "0x3", + "max_fee": "0x0", + "type": "DECLARE" +} diff --git a/crates/starknet_client/resources/reader/deploy_account_v3.json b/crates/starknet_client/resources/reader/deploy_account_v3.json new file mode 100644 index 00000000000..58628af33a7 --- /dev/null +++ b/crates/starknet_client/resources/reader/deploy_account_v3.json @@ -0,0 +1,36 @@ +{ + "class_hash": "0x1fcd2dcd811e049eaa730b87038a68f39220a04986b43fe287d690da0df01b8", + "constructor_calldata": [ + "0x0", + "0x1", + "0x2", + "0x3", + "0x4", + "0x5", + "0x6", + "0x7", + "0x8", + "0x9" + ], + "contract_address_salt": "0x2", + "fee_data_availability_mode": 0, + "nonce": "0x0", + "nonce_data_availability_mode": 0, + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0xffffffffffffffff", + "max_price_per_unit": "0xffffffffffffffffffffffffffffffff" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x1b34d819720bd84c89bdfb476bc2c4d0de9a41b766efabd20fa292280e4c6d9", + "signature": [], + "tip": "0x0", + "transaction_hash": "0x60bc493f32b6a2ebc2f6fd67324e72c5104ca26afa9a1f61726caa1094f340b", + "version": "0x3", + "type": "DEPLOY_ACCOUNT" +} diff --git a/crates/starknet_client/resources/reader/deploy_v0.json b/crates/starknet_client/resources/reader/deploy_v0.json new file mode 100644 index 00000000000..d07a595910d --- /dev/null +++ b/crates/starknet_client/resources/reader/deploy_v0.json @@ -0,0 +1,14 @@ +{ + "contract_address": "0x264266d63d373b5287aaa0f62eb1a31a297024bf9572339c15cb84b7fb51939", + "contract_address_salt": "0x4c40ae2941a804d6941b1794c00d14bed375d19aab9c477500abbacfa58e7bf", + "class_hash": "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918", + "constructor_calldata": [ + "0x3e327de1c40540b98d05cbcb13552008e36f0ec8d61d46956d2f9752c294328", + "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + "0x2", + "0x4c40ae2941a804d6941b1794c00d14bed375d19aab9c477500abbacfa58e7bf", + "0x0" + ], + "transaction_hash": "0x166ccbbb1356303eba0081511df1a1ed6c59c3a36c4ed842773ab277586c372", + "type": "DEPLOY" +} diff --git a/crates/starknet_client/resources/reader/deprecated_contract_class.json b/crates/starknet_client/resources/reader/deprecated_contract_class.json new file mode 100644 index 00000000000..a7dba496b01 --- /dev/null +++ b/crates/starknet_client/resources/reader/deprecated_contract_class.json @@ -0,0 +1,47 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "implementation", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "offset": "0x3e", + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + } + ], + "EXTERNAL": [ + { + "offset": "0x56", + "selector": "0x0" + } + ], + "L1_HANDLER": [] + }, + "program": { + "builtins": [], + "data": [ + "0x20780017fff7ffd", + "0x4", + "0x400780017fff7ffd" + ], + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "main_scope": "__main__", + "identifiers": {}, + "attributes": [ + 1234 + ], + "debug_info": null, + "reference_manager": {}, + "hints": {} + } +} diff --git a/crates/starknet_client/resources/reader/deprecated_pending_data.json b/crates/starknet_client/resources/reader/deprecated_pending_data.json new file mode 100644 index 00000000000..634f62bd25f --- /dev/null +++ b/crates/starknet_client/resources/reader/deprecated_pending_data.json @@ -0,0 +1,214 @@ +{ + "block": { + "parent_block_hash": "0x76fc47eb559b3a167888021394d83d707162ad5d92c15996c3aa7ac98369645", + "status": "PENDING", + "gas_price": "0x59682f03", + "transactions": [ + { + "contract_address": "0x3b3ca08150f47c715bcd3493e5b7fec3732ded1b884f8513bcab111f8949e5b", + "contract_address_salt": "0x1b551a2d45a5413d0b9fa8314b0fa12766cac44e4707ac30dd14677c41b2a3b", + "class_hash": "0x6ed527800ce2621c354e50d57cc1d6c0b6e3255a0eee04470254823417fecfa", + "constructor_calldata": [], + "transaction_hash": "0x1c60d1088f403f3ca990e12131e71fed086920dae52ccee3e5e80e1bf19dc0f", + "type": "DEPLOY" + }, + { + "contract_address": "0x6d0a7c29de4ea81d1b9982c04f691320a6b65eef9d6ea847b4b077a0305a24e", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x1", + "0x7394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x3", + "0x3", + "0x6d0a7c29de4ea81d1b9982c04f691320a6b65eef9d6ea847b4b077a0305a24e", + "0x3635c9adc5dea00000", + "0x0", + "0x34" + ], + "signature": [ + "0x628c9d4398de3686311ad2d7cb90792a30070155e26b3cf98559fb0a387393b", + "0x7762c61f244f76a2ddf57ecc8c117d6906af827db8796e16ae3e291c31b75e2" + ], + "transaction_hash": "0x6e81d0030bfae36fc55bf682f96dc2d103ee02f439b10c8e9af6742e7d7e2ea", + "max_fee": "0x148b1ed190ca", + "type": "INVOKE_FUNCTION", + "version": "0x0" + }, + { + "class_hash": "0x5abf9436be774a4d4af00528296700d0181b8cf3cf85ccc556b441ef5876ffe", + "sender_address": "0x1", + "nonce": "0x0", + "max_fee": "0x0", + "version": "0x1", + "transaction_hash": "0x3ff2070e6723bb9b6414977324f916eb53b51f9691e5d9a4fb67160d048958b", + "signature": [], + "type": "DECLARE" + }, + { + "class_hash": "0x5abf9436be774a4d4af00528296700d0181b8cf3cf85ccc556b441ef5876ffe", + "compiled_class_hash": "0x5abf9436be774a4d4af00528296700d0181b8cf3cf85ccc556b441ef5876ffe", + "sender_address": "0x1", + "nonce": "0x0", + "max_fee": "0x0", + "version": "0x2", + "transaction_hash": "0x3ff2070e346", + "signature": [], + "type": "DECLARE" + }, + { + "version": "0x0", + "contract_address": "0x55a46448decca3b138edf0104b7a47d41365b8293bdfd59b03b806c102b12b7", + "entry_point_selector": "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "nonce": "0x0", + "calldata": [ + "0x2db8c2615db39a5ed8750b87ac8f217485be11ec", + "0xbc614e", + "0x258" + ], + "transaction_hash": "0xfb118dc1d4a4141b7718da4b7fa98980b11caf5aa5d6e1e35e9b050aae788b", + "type": "L1_HANDLER" + } + ], + "timestamp": 1658396103, + "sequencer_address": "0x46a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b", + "transaction_receipts": [ + { + "transaction_index": 0, + "transaction_hash": "0x1c60d1088f403f3ca990e12131e71fed086920dae52ccee3e5e80e1bf19dc0f", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "transaction_index": 1, + "transaction_hash": "0x6e81d0030bfae36fc55bf682f96dc2d103ee02f439b10c8e9af6742e7d7e2ea", + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x6d0a7c29de4ea81d1b9982c04f691320a6b65eef9d6ea847b4b077a0305a24e", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x6e81d0030bfae36fc55bf682f96dc2d103ee02f439b10c8e9af6742e7d7e2ea", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 754, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 16, + "ecdsa_builtin": 1, + "output_builtin": 0, + "bitwise_builtin": 0 + }, + "n_memory_holes": 25 + }, + "actual_fee": "0xdb2148b8ea5" + }, + { + "transaction_index": 2, + "transaction_hash": "0x3ff2070e6723bb9b6414977324f916eb53b51f9691e5d9a4fb67160d048958b", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "transaction_index": 3, + "transaction_hash": "0x3ff2070e346", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "transaction_index": 4, + "transaction_hash": "0xfb118dc1d4a4141b7718da4b7fa98980b11caf5aa5d6e1e35e9b050aae788b", + "l1_to_l2_consumed_message": { + "from_address": "0x2Db8c2615db39a5eD8750B87aC8F217485BE11EC", + "to_address": "0x55a46448decca3b138edf0104b7a47d41365b8293bdfd59b03b806c102b12b7", + "selector": "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "payload": [ + "0xbc614e", + "0x258" + ] + }, + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 137, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 6, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0, + "ec_op_builtin": 0 + }, + "n_memory_holes": 22 + }, + "actual_fee": "0x0" + } + ], + "starknet_version": "0.9.1" + }, + "state_update": { + "old_root": "0x0465b219d93bcb2776aa3abb009423be3e2d04dba6453d7e027830740cd699a4", + "state_diff": { + "nonces": { + "0x51c62af8919b31499b36bd1f1f702c8ef5a6309554427186c7bd456b862c115": "0x12" + }, + "storage_diffs": { + "0x13386f165f065115c1da38d755be261023c32f0134a03a8e66b6bb1e0016014": [ + { + "key": "0x3b3a699bb6ef37ff4b9c4e14319c7d8e9c9bdd10ff402d1ebde18c62ae58381", + "value": "0x61454dd6e5c83621e41b74c" + }, + { + "key": "0x1557182e4359a1f0c6301278e8f5b35a776ab58d39892581e357578fb287836", + "value": "0x79dd8085e3e5a96ea43e7d" + } + ] + }, + "deployed_contracts": [ + { + "address": "0x3e10411edafd29dfe6d427d03e35cb261b7a5efeee61bf73909ada048c029b9", + "class_hash": "0x071c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64" + } + ], + "declared_classes": [ + { + "class_hash": "0x10", + "compiled_class_hash": "0x1000" + } + ], + "old_declared_contracts": [ + "0x100" + ], + "replaced_classes": [ + { + "address": "0x56b0efe9d91fcda0f341af928404056c5220ee0ccc66be15d20611a172dbd52", + "class_hash": "0x2248aff260e5837317641ff4f861495dd71e78b9dae98a31113e569b336bd26" + } + ] + } + } +} diff --git a/crates/starknet_client/resources/reader/invoke_v0.json b/crates/starknet_client/resources/reader/invoke_v0.json new file mode 100644 index 00000000000..5bec71c01ab --- /dev/null +++ b/crates/starknet_client/resources/reader/invoke_v0.json @@ -0,0 +1,29 @@ +{ + "sender_address": "0xef934e6c63a9acba42dd644d1a0c1af5df01eeac1b9f82320b53cfacd40890", + "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "calldata": [ + "0x2", + "0x13c56add3ee9699228614221602165185b49f712cae90fc20c608d7ecc1521b", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x0", + "0x2", + "0x69202aeae73af1c685003f68de5edd3eafcc702e3b1125c5e24fe6b6ccbc0e6", + "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + "0x2", + "0x2", + "0x4", + "0x56bc75e2d63100000", + "0x0", + "0x56bc75e2d63100000", + "0x0", + "0x1" + ], + "signature": [ + "0x5d543c91737a46b9baa7c342e8b58f62ad438037dd63ac56cf0c64de7e6e21e", + "0xde8ce74586c27f66b89dc000f973a8efdf044d9b5587666a162e6db4111646" + ], + "transaction_hash": "0x706deaf73bc99c4a2026a7252f21e3c8db0946ac2221e2abe12a9f3b78192e0", + "max_fee": "0x21a3e1b5676f", + "type": "INVOKE_FUNCTION", + "version": "0x0" +} diff --git a/crates/starknet_client/resources/reader/invoke_v3.json b/crates/starknet_client/resources/reader/invoke_v3.json new file mode 100644 index 00000000000..f47b4eeafc3 --- /dev/null +++ b/crates/starknet_client/resources/reader/invoke_v3.json @@ -0,0 +1,35 @@ +{ + "account_deployment_data": [], + "calldata": [ + "0x0", + "0x1", + "0x2", + "0x3", + "0x4", + "0x5", + "0x6", + "0x7", + "0x8", + "0x9" + ], + "fee_data_availability_mode": 0, + "nonce": "0x0", + "nonce_data_availability_mode": 0, + "paymaster_data": [], + "resource_bounds": { + "L1_GAS": { + "max_amount": "0xffffffffffffffff", + "max_price_per_unit": "0xffffffffffffffffffffffffffffffff" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x2da4d93784af6b4427c32533dd7e5780c9d642c3a3348f6adacebc97edab4c", + "signature": [], + "tip": "0x0", + "transaction_hash": "0x14df307294262b17b20c8949fd3dbd8f25a9bd47548d00d89ca93977e5836b", + "version": "0x3", + "type": "INVOKE_FUNCTION" +} diff --git a/crates/starknet_client/resources/reader/l1_handler_v0.json b/crates/starknet_client/resources/reader/l1_handler_v0.json new file mode 100644 index 00000000000..08966e72477 --- /dev/null +++ b/crates/starknet_client/resources/reader/l1_handler_v0.json @@ -0,0 +1,13 @@ +{ + "transaction_hash": "0x5d50b7020f7cf8033fd7d913e489f47edf74fbf3c8ada85be512c7baa6a2eab", + "version": "0x0", + "contract_address": "0x58b43819bb12aba8ab3fb2e997523e507399a3f48a1e2aa20a5fb7734a0449f", + "entry_point_selector": "0xe3f5e9e1456ffa52a3fbc7e8c296631d4cc2120c0be1e2829301c0d8fa026b", + "calldata": [ + "0x5474c49483aa09993090979ade8101ebb4cdce4a", + "0xabf8dd8438d1c21e83a8b5e9c1f9b58aaf3ed360", + "0x2", + "0x4c04fac82913f01a8f01f6e15ff7e834ff2d9a9a1d8e9adffc7bd45692f4f9a" + ], + "type": "L1_HANDLER" +} diff --git a/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sequencer.json b/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sequencer.json new file mode 100644 index 00000000000..f5449be2518 --- /dev/null +++ b/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sequencer.json @@ -0,0 +1,157 @@ +{ + "block_hash": "0x3ae41b0f023e53151b0c8ab8b9caafb7005d5f41c9ab260276d5bdc49726279", + "parent_block_hash": "0x0", + "block_number": 0, + "state_root": "0x1f386a54db7796872829c9168cdc567980daad382daa4df3b71641a2551e833", + "transaction_commitment": "0x0", + "event_commitment": "0x0", + "status": "ACCEPTED_ON_L1", + "l1_da_mode": "CALLDATA", + "l1_gas_price": { + "price_in_wei": "0x0", + "price_in_fri": "0x0" + }, + "l1_data_gas_price": { + "price_in_wei": "0x0", + "price_in_fri": "0x0" + }, + "transactions": [ + { + "transaction_hash": "0x3fa1bff0c86f34b2eb32c26d12208b6bdb4a5f6a434ac1d4f0e2d1db71bd711", + "version": "0x0", + "contract_address": "0x7b196a359045d4d0c10f73bdf244a9e1205a615dbb754b8df40173364288534", + "contract_address_salt": "0x45b0cbcbf09543933226c808aa58c84c22c98388d29d90408a84198bcc0aa3c", + "class_hash": "0x10455c752b86932ce552f2b0fe81a880746649b9aee7e0d842bf3f52378f9f8", + "constructor_calldata": [ + "0x187d50a5cf3ebd6d4d6fa8e29e4cad0a237759c6416304a25c4ea792ed4bba4", + "0x42f5af30d6693674296ad87301935d0c159036c3b24af4042ff0270913bf6c6" + ], + "type": "DEPLOY" + }, + { + "transaction_hash": "0x154c02cc3165cceadaa32e7238a67061b3a1eac414138c4ebe1408f37fd93eb", + "version": "0x0", + "contract_address": "0x64ed79a8ebe97485d3357bbfdf5f6bea0d9db3b5f1feb6e80d564a179122dc6", + "contract_address_salt": "0x46cf52b3bfaa8e223983f8b65fa6e9d2ae331954a284ca4c4769e588a2f3eaf", + "class_hash": "0x10455c752b86932ce552f2b0fe81a880746649b9aee7e0d842bf3f52378f9f8", + "constructor_calldata": [ + "0x5cedec15acd969b0fba39fec9e7d9bd4d0b33f100969ad3a4543039a6f696d4", + "0xce9801d27b02543f4d88b60aa456860f94ee9f612fc56464abfbdeedc1ab72" + ], + "type": "DEPLOY" + }, + { + "transaction_hash": "0x7893675c16da857b7c4229cda449e08a4fe13b07ca817e79d1db02e8a046047", + "version": "0x0", + "max_fee": "0x0", + "signature": [], + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x17d9c35a8b9a0d4512fa05eafec01c2758a7a5b7ec7b47408a24a4b33124d9b", + "0x2", + "0x7f800b5bf79637f8f83f47a8fc4d368b43695c781b22a899f11b5f2faba874a", + "0x3a7a40d383612b0ad167aec8d90fb07e576e017d07948f63ac318b52511ae93" + ], + "contract_address": "0x64ed79a8ebe97485d3357bbfdf5f6bea0d9db3b5f1feb6e80d564a179122dc6", + "type": "INVOKE_FUNCTION" + }, + { + "transaction_hash": "0x4a277d67e3f42c4a343854081d1e2e9e425f1323255e4486d2badb37a1d8630", + "version": "0x0", + "max_fee": "0x0", + "signature": [], + "entry_point_selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "calldata": [ + "0x17d9c35a8b9a0d4512fa05eafec01c2758a7a5b7ec7b47408a24a4b33124d9b", + "0x2", + "0x7f800b5bf79637f8f83f47a8fc4d368b43695c781b22a899f11b5f2faba874a", + "0xf140b304e9266c72f1054116dd06d9c1c8e981db7bf34e3c6da99640e9a7c8" + ], + "contract_address": "0x64ed79a8ebe97485d3357bbfdf5f6bea0d9db3b5f1feb6e80d564a179122dc6", + "type": "INVOKE_FUNCTION" + } + ], + "timestamp": 1638977893, + "transaction_receipts": [ + { + "execution_status": "SUCCEEDED", + "transaction_index": 0, + "transaction_hash": "0x3fa1bff0c86f34b2eb32c26d12208b6bdb4a5f6a434ac1d4f0e2d1db71bd711", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 29, + "builtin_instance_counter": { + "pedersen_builtin": 0, + "range_check_builtin": 0, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0, + "ec_op_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 1, + "transaction_hash": "0x154c02cc3165cceadaa32e7238a67061b3a1eac414138c4ebe1408f37fd93eb", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 29, + "builtin_instance_counter": { + "pedersen_builtin": 0, + "range_check_builtin": 0, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0, + "ec_op_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 2, + "transaction_hash": "0x7893675c16da857b7c4229cda449e08a4fe13b07ca817e79d1db02e8a046047", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 165, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 7, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0, + "ec_op_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 3, + "transaction_hash": "0x4a277d67e3f42c4a343854081d1e2e9e425f1323255e4486d2badb37a1d8630", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 165, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 7, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0, + "ec_op_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + } + ] +} diff --git a/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sn_version.json b/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sn_version.json new file mode 100644 index 00000000000..98a4f01e72c --- /dev/null +++ b/crates/starknet_client/resources/reader/old_block_post_0_13_1_no_sn_version.json @@ -0,0 +1,109 @@ +{ + "block_hash": "0x701aee1d390ab6e780e2bc179e544e4f3373f153c07ffa63ec6fe20b57ab898", + "parent_block_hash": "0xa3d8ca14d847e677462a65829b349a38fe3f921f93c208ddbf50f3acfac54e", + "block_number": 171486, + "state_root": "0x59a3850f3985d6c6c34b551e558c3fc707f752df53c266eb387b3d23cfe6575", + "transaction_commitment": "0x5df7360156f828b4e4df4775c5409c8fc794b06e32822948279ea6cd8ff4333", + "event_commitment": "0x0", + "status": "ACCEPTED_ON_L1", + "l1_da_mode": "CALLDATA", + "l1_gas_price": { + "price_in_wei": "0x59682f08", + "price_in_fri": "0x0" + }, + "l1_data_gas_price": { + "price_in_wei": "0x0", + "price_in_fri": "0x0" + }, + "transactions": [ + { + "transaction_hash": "0x568cfd2278a1cf89b8fe80d3e19da135b1d313e514b63bd015bf5a22851defe", + "version": "0x0", + "contract_address": "0x5f1bfbbcf8b6ff245e962b386d5dddf6405874d5eabb0f9931f423909ca46e5", + "contract_address_salt": "0x33146533ca75702f5b71aa8e4a6327af14ced70daf1a2066fc965524147b28f", + "class_hash": "0x590267e2a8bdb5a5c5c6b8f51751fc661866d96e6dec956f8562f54ecdffabc", + "constructor_calldata": [ + "0x104e9b1ebc4eecf6fbdd3eb345195e018b5b5da47659d862d798d9902f984fe", + "0x690523e438501f9c9b408269c158013f8c60dd698b4fbbeeac9718a0d1e8878" + ], + "type": "DEPLOY" + }, + { + "transaction_hash": "0x63334023b88eac991734730c1ea44a27ebd3b4a0724a6036366d0d7c522e0bb", + "version": "0x0", + "contract_address": "0x27bb67bc0670bc7709d14f2a51ab89471ca30339a44a2795a87951e2f3c9ac6", + "contract_address_salt": "0x5569985cb92e31b277f35920ff3403831156d6f8bd3c3456a0e7089263fa11b", + "class_hash": "0x590267e2a8bdb5a5c5c6b8f51751fc661866d96e6dec956f8562f54ecdffabc", + "constructor_calldata": [ + "0x74eb57094e1c13347ecba6a9fd2b1b23ebdbba8633f2c72c4e97704a573cd81", + "0x2bcc79d6c349a81eeadf4133c1774553db2a33bbcef87e066bd4eb743f9467b" + ], + "type": "DEPLOY" + }, + { + "transaction_hash": "0x689a029835b5145a7920fd551d28bb4ca520b798b2a95ac192ae6d56be1deb5", + "version": "0x0", + "max_fee": "0x0", + "signature": [], + "nonce": "0x0", + "class_hash": "0x2753ce06a79a9a9c608787a608b424f79c56f465954f1f3a7f6785d575366fb", + "sender_address": "0x1", + "type": "DECLARE" + } + ], + "timestamp": 1654504622, + "sequencer_address": "0x46a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b", + "transaction_receipts": [ + { + "execution_status": "SUCCEEDED", + "transaction_index": 0, + "transaction_hash": "0x568cfd2278a1cf89b8fe80d3e19da135b1d313e514b63bd015bf5a22851defe", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 29, + "builtin_instance_counter": { + "pedersen_builtin": 0, + "range_check_builtin": 0, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 1, + "transaction_hash": "0x63334023b88eac991734730c1ea44a27ebd3b4a0724a6036366d0d7c522e0bb", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 29, + "builtin_instance_counter": { + "pedersen_builtin": 0, + "range_check_builtin": 0, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 0 + }, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + }, + { + "execution_status": "SUCCEEDED", + "transaction_index": 2, + "transaction_hash": "0x689a029835b5145a7920fd551d28bb4ca520b798b2a95ac192ae6d56be1deb5", + "l2_to_l1_messages": [], + "events": [], + "execution_resources": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "actual_fee": "0x0" + } + ] +} diff --git a/crates/starknet_client/resources/reader/transaction_receipt.json b/crates/starknet_client/resources/reader/transaction_receipt.json new file mode 100644 index 00000000000..ced8f9c6a93 --- /dev/null +++ b/crates/starknet_client/resources/reader/transaction_receipt.json @@ -0,0 +1,53 @@ +{ + "transaction_index": 1, + "transaction_hash": "0x4586cb82c15ec15a123ba42279aae105f2304cbc1f992f8360ab1b1eb0f718", + "l1_to_l2_consumed_message": { + "from_address": "0xc3511006C04EF1d78af4C8E0e74Ec18A6E64Ff9e", + "to_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "payload": [ + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ], + "nonce": "0x26fc3" + }, + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ] + }, + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 673, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 12, + "output_builtin": 0, + "ecdsa_builtin": 0, + "bitwise_builtin": 0 + }, + "n_memory_holes": 22 + }, + "actual_fee": "0x0" +} diff --git a/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2.json b/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2.json new file mode 100644 index 00000000000..f9de0942f4d --- /dev/null +++ b/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2.json @@ -0,0 +1,64 @@ +{ + "transaction_index": 1, + "transaction_hash": "0x570ef4df9300824aee9c2bc1f3f1280b96a43dd67a5b4bb19ca2d2450cbad99", + "l2_to_l1_messages": [ + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "to_address": "0xc3511006C04EF1d78af4C8E0e74Ec18A6E64Ff9e", + "payload": [ + "0x0", + "0x8821d9ce3b90b4d2f3578b8ac909e2fa9eb6530e", + "0x5543df729c0000", + "0x0" + ] + } + ], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3031a6941b698fd835f6126b8a7b1089cc641d19af2cdfd6fa0167a8a4bf32c", + "0x0", + "0x5543df729c0000", + "0x0" + ] + }, + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x194fc63c49b0f07c8e7a78476844837255213824bd6cb81e0ccfb949921aad1" + ], + "data": [ + "0x8821d9ce3b90b4d2f3578b8ac909e2fa9eb6530e", + "0x5543df729c0000", + "0x0", + "0x3031a6941b698fd835f6126b8a7b1089cc641d19af2cdfd6fa0167a8a4bf32c" + ] + }, + { + "from_address": "0x3031a6941b698fd835f6126b8a7b1089cc641d19af2cdfd6fa0167a8a4bf32c", + "keys": [ + "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" + ], + "data": [ + "0x570ef4df9300824aee9c2bc1f3f1280b96a43dd67a5b4bb19ca2d2450cbad99", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 1446, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 35, + "bitwise_builtin": 0, + "output_builtin": 0, + "ecdsa_builtin": 1 + }, + "n_memory_holes": 23 + }, + "actual_fee": "0x380dd17c8400" +} diff --git a/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2_nonce.json b/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2_nonce.json new file mode 100644 index 00000000000..45defee2fab --- /dev/null +++ b/crates/starknet_client/resources/reader/transaction_receipt_without_l1_to_l2_nonce.json @@ -0,0 +1,52 @@ +{ + "transaction_index": 1, + "transaction_hash": "0x4586cb82c15ec15a123ba42279aae105f2304cbc1f992f8360ab1b1eb0f718", + "l1_to_l2_consumed_message": { + "from_address": "0xc3511006C04EF1d78af4C8E0e74Ec18A6E64Ff9e", + "to_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "selector": "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5", + "payload": [ + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ] + }, + "l2_to_l1_messages": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x0", + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ] + }, + { + "from_address": "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82", + "keys": [ + "0x221e5a5008f7a28564f0eaa32cdeb0848d10657c449aed3e15d12150a7c2db3" + ], + "data": [ + "0x26ee727ad466d4255a76f4676eaec72adb3e30e14461952a2062b3e87cbdc7f", + "0xde0b6b3a7640000", + "0x0" + ] + } + ], + "execution_resources": { + "n_steps": 673, + "builtin_instance_counter": { + "pedersen_builtin": 2, + "range_check_builtin": 12, + "output_builtin": 0, + "ecdsa_builtin": 0, + "bitwise_builtin": 0 + }, + "n_memory_holes": 22 + }, + "actual_fee": "0x0" +} diff --git a/crates/starknet_client/resources/writer/declare_response.json b/crates/starknet_client/resources/writer/declare_response.json new file mode 100644 index 00000000000..5870d1686b6 --- /dev/null +++ b/crates/starknet_client/resources/writer/declare_response.json @@ -0,0 +1,5 @@ +{ + "code": "TRANSACTION_RECEIVED", + "transaction_hash": "0x205ea2b8f86259db2d191895e8af9b186bf2aea05a5dbe28721b7840113f217", + "class_hash": "0x32ba0c2c5aa132c795a7ffa58057c36283dedf7bc0bfbf5687ba52fd317f56d" +} diff --git a/crates/starknet_client/resources/writer/declare_v1.json b/crates/starknet_client/resources/writer/declare_v1.json new file mode 100644 index 00000000000..6e014a8854c --- /dev/null +++ b/crates/starknet_client/resources/writer/declare_v1.json @@ -0,0 +1,828 @@ +{ + "version": "0x1", + "max_fee": "0xde0b6b3a7640000", + "signature": [ + "0x240b2aba04732c2ecefb28141122549891f2ae62573c416b690658baebbe9e7", + "0x199fdb72392e77d78848c72949d130ffa78d1aeabe49be9c8147919e0f7a2e7" + ], + "nonce": "0x3", + "contract_class": { + "entry_points_by_type": { + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "offset": "0x270" + } + ], + "EXTERNAL": [ + { + "selector": "0x5fbd85570830519219bb4ad6951316f96fce363f86909d1f8adb1fdc836471", + "offset": "0x6bf" + }, + { + "selector": "0x679c22735055a10db4f275395763a3752a1e3a3043c192299ab6b574fba8d6", + "offset": "0x2fc" + }, + { + "selector": "0x7772be8b80a8a33dc6c1f9a6ab820c02e537c73e859de67f288c70f92571bb", + "offset": "0x29f" + }, + { + "selector": "0x8692275a885fee8890c5eaa075cc627d4755e3a1c8a2f1d557f7f97743761a", + "offset": "0x516" + }, + { + "selector": "0x8a2a3272a92492ded6c04f7c85df9c53134cef398564465f12af3c9c986d41", + "offset": "0x655" + }, + { + "selector": "0xbd7daa40535813d892224da817610f4c7e6fe8983abe588a4227586262d9d3", + "offset": "0x5af" + }, + { + "selector": "0xc3aec03fe455b8a64bf01ebad1b32252b107e07bc075631c513bb581ea3ee4", + "offset": "0x6f0" + }, + { + "selector": "0xd47144c49bce05b6de6bce9d5ff0cc8da9420f8945453e20ef779cbea13ad4", + "offset": "0x81f" + }, + { + "selector": "0xd5e8843577a4b0aa2c4408c543dd466ece9a2611a140c26c004169cb123e43", + "offset": "0x72f" + }, + { + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b", + "offset": "0x84b" + }, + { + "selector": "0xe8f69bd941db5b0bff2e416c63d46f067fcdfad558c528f9fd102ba368cb5f", + "offset": "0x567" + }, + { + "selector": "0x127a04cfe41aceb22fc022bce0c5c70f2d860a7c7c054681bd821cdc18e6dbc", + "offset": "0x782" + }, + { + "selector": "0x12ead94ae9d3f9d2bdb6b847cf255f1f398193a1f88884a0ae8e18f24a037b6", + "offset": "0x41c" + }, + { + "selector": "0x167ac610845cc0ab1501b38169a7e50f1bf60602d3c2a961b30987454f97812", + "offset": "0x597" + }, + { + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "offset": "0x4de" + }, + { + "selector": "0x19a35a6e95cb7a3318dbb244f20975a1cd8587cc6b5259f15f61d7beb7ee43b", + "offset": "0x5f7" + }, + { + "selector": "0x1ae1a515cf2d214b29bdf63a79ee2d490efd4dd1acc99d383a8e549c3cecb5d", + "offset": "0x36d" + }, + { + "selector": "0x1b1343fe0f4a16bed5e5133b5ca9f03ab15976bb2df2b6d263ac3170b8b6a13", + "offset": "0x67f" + }, + { + "selector": "0x1b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d", + "offset": "0x2c2" + }, + { + "selector": "0x1cad42b55a5b2c7366b371db59448730766dfef74c0156c9c6f332c8c5e34d9", + "offset": "0x3cf" + }, + { + "selector": "0x1de4779362d5ca708d55fe1d4d499501b7f692730d2e01656e9180708985e07", + "offset": "0x769" + }, + { + "selector": "0x1eaab699414d786ce9dbfd4e86815f66680647efd13f9334ac97148e4e30e82", + "offset": "0x3fc" + }, + { + "selector": "0x218f305395474a84a39307fa5297be118fe17bf65e27ac5e2de6617baa44c64", + "offset": "0x62b" + }, + { + "selector": "0x26813d396fdb198e9ead934e4f7a592a8b88a059e45ab0eb6ee53494e8d45b0", + "offset": "0x3a8" + }, + { + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "offset": "0x4ae" + }, + { + "selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "offset": "0x436" + }, + { + "selector": "0x29cef374bfc7ad2628f04d9a18ac3c3a259c1eb3ce3d3c77bbab281c42649fc", + "offset": "0x7a1" + }, + { + "selector": "0x30f842021fbf02caf80d09a113997c1e00a32870eee0c6136bed27acb348bea", + "offset": "0x340" + }, + { + "selector": "0x317eb442b72a9fae758d4fb26830ed0d9f31c8e7da4dbff4e8c59ea6a158e7f", + "offset": "0x24a" + }, + { + "selector": "0x330a77821de972bb6bd8a5eeb87efdf645a609a3057cfc0b3de7bdfaf887c85", + "offset": "0x487" + }, + { + "selector": "0x33ce93a3eececa5c9fc70da05f4aff3b00e1820b79587924d514bc76788991a", + "offset": "0x57f" + }, + { + "selector": "0x34c4c150632e67baf44fc50e9a685184d72a822510a26a66f72058b5e7b2892", + "offset": "0x69e" + }, + { + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50", + "offset": "0x7ca" + }, + { + "selector": "0x3639fffddc860618a5a5cb4e4c1562999b4b0ee1c648dcdecd1a905482d6ac2", + "offset": "0x7f1" + }, + { + "selector": "0x398cb6c6170250c323a37586d08047d637f53b06360fa0268de8ee3ae3e52a2", + "offset": "0x864" + }, + { + "selector": "0x3d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3", + "offset": "0x387" + }, + { + "selector": "0x3dc5da2d6d1275aeed57f43461d31967b0fed58bfe739b4ffad4091e89c4b03", + "offset": "0x5c7" + } + ], + "L1_HANDLER": [ + { + "selector": "0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01", + "offset": "0x54c" + } + ] + }, + "program": "H4sIABqSnWQC/+y9CZMct7Uu+Fd6+GLCkkdqYl8c1y+ColoWwxSpISlfe2xHRW5F1lN1Vauqmotv6L8PMmvLFQlkImuF7rXUnZ15sJzvOzg4AA7+58nDYnKfPPnTzRPwWYDcPxACu3/gk29unsTBKlDC/qmkEcCVQMjH43H6v/Sv4DNc/wcBEW7/oP6XrJ8SAHBaB/Uk/WtUeAo3T+PNU4HY9mn6zfop3v4RIPUQFf9YXygqVDMuyGmopgDBpjLjvfTN06jyFGyalH8Kdk/jfd+oJpFNVWKx6c9dj2n/GACWa8OmmkVtgrHdP+G2pmjbqlxNm3qyobd2lcv1AGaQRSxS/x2zhBOO1O+Yk13/oE3/yFz/7IGQPg0KT9HmaVh4ijdPi1Aim6dVKMl9DXkBSrT4x81TVnxq1QERkwylzeaIy213XHnzSYQhEernhBH1O+XoejqEqOYC1egxl5VGi9pGp09lpdGi0hV48zSsNFpUuoJunla7QuzrKiuNFh0bzVWjyVb7qb4JVJpPrQHlmONKRxStJcsZxG3phaqV/2hdNYrVvyGnjCpI4hOsIEEpZFTVQpKoasYM1bLm4NUqmfWT7TVKlB2Ks2oRVdWYg+NjjnChcCcZV5iDqg9p2m/21cK6auU8pI6VpWmPjTMFq2pTVUX1U3X8jmpNV1RrYiKdIxc5qSZXP0n1pNqfYW1Fq34osvBDrZSfsldVjVDOUnNzSr4Q7YNlIhWOGRsfkVgpOrPBFaZGXBkn9VOtIeqIVmQ9wdgrt+aPppOk1nrBLtMYJLdCcjWCIJt9bP4HHM4w+s+xhqgca5nUBVv8HqQaNljHeokVSkX5duHdRLUAuJ0N5q0SCKlWqTWSUBAJSiIB3k1sDUeNJuLo4hGs5m8tM/s6k2UZNYG7ibx78CSxDib9Yj27PoBoo5diz4htr+y7f4gW8iFU4Qg9kea7QKcZPu7+T5KjZz1mD6OZWGwpVNN6oemZ8CTsbqwtcKjgJS2YQdw5eEnt+9BqgNmZelEnvv4pqhsWdKWggry4LI/mB6q4+LQW81uHZqx/imFOblSRG4qy7YtNGGaivNCx8gygEdRKD82gUXATA40hHBe+2PZMqPmC29dyQBtmww1g8Edth5a6p76bS/BPDOAfdIB/0Bn+oQn8a+0/0oC36JOLWljI2qeBobUzlpA+rVnWWT+FhxufiiHiosMOawPHpDYYjGqDwbgcDN6FvkVt6Fu0dxBhbV3R0RUdoJcjoguCcz0P6p7axa2ymDMh6+Ak3sSvCBuniyQV9Qe1gYugVtFBraKDWvckyLWp26JGGtdXVYdp0O2Sl7k08wP32EyCHQQgrjH6G1+05MdserbsNaEtJ0Fd6K3ZJlaDM3XeYswloAzACEHOMWEcQoJjoroaxKGqO1ekUuMOREEYYxJKFJEgVA0cxwmI8H5YqWlPrY0ZorNjPdctxpjDokTEHiWHQwk9U5TsF5wNUKLFAzRw3CMTPCjhEMdYsnEcQikSqTgoMUnImAdUokCEQgSAyoTQIARJyJKEYiKJQjyhITgJPAhmMvkFWcg1KS+HQNQ4+wsbdxhFJwYshk4OWCJAAUYcBRIRieIkZhFQoIoEjccyohhiEiVjLAVlqfMyVgZnjCMZScFiAk8CV2xsYGfCE7QzZHwmoxEMFQzwOAFjEkAWJjFNKMQ4pFEgxwAHIaSSszBE8RiFLEYMB8on5yAUIQvgaYxGNBx0NMKDVRyHFigJa1ESVSKyhdkB4rl5QGWXpQZYYB2M2dQImWMxPs4yZoKpQcgkMKEEHYexoJQDgQGFEkEZhiSImVTEgGysBuoowQyPBZNAxnAsAjVwj+NIYEb4vnPltpfy/XcgRuBWL77GDzkFRsD4ZBmxiefU7obIL9z2pIumlCH6m7hiTYSDJAJqJCGUhiJgJBwDmIRBDEOMEEUhBDwBPIwApwzDSJEpDKmASYCThJwEa2DkjDUWIzBiEkYhxzSEYozHaRQJhwKFseTKfQsZjSEFygYxAiFXvabsDiAxTABTI58ID7tcGOcCpLWOaN0i+QCqClm+wASahCQtA5U25x4OtEWmhZYH6nsat+yI2E4BeWVSM0RthL42GT4sno5p7dNwiGWVw6ztRXoTX99tB/LaaBU1omkqPDjBElKcSIDargKGOyTyflNUN/T3WNU7HHhoZb9adWd1Zb81RHUNsXlab33xdvlHtD0doivGLdSvOYbX0EF7FzbptS94u4lx43aCwjm2uHYTY30FQWO1w1rLHtdx1AIgmpYOobm4PQbUFIa0eVq3l2nzlFSe6nZU1HGiw4hzJD8lgcjh1hsNJ3Q4N0R0CydaoTyElwcvHa28FhA2w+HwA5+QBr72sWJdpYBnvR/Lj8R+Wpya1U7CTJ/WuwFZ80jt02B4YBT6PuxhxvBBzBjubtzqD84dd4AOTWZndk+HNnl1+97DrmtVDUtHBiuJNdsXc4ISXaytqZoozAF3wONTRIfz4Qs0JKEGXYbDrPkMSTu+Gvl9DcuBDIaR8vMxjsYkkKqWUmCGJYiiGBKJYDyOSBwRCKIxjlEQh+MkoQmCSTROImFQuWPNZPdbfOv9imOGQeIAnlAYJJaRszCIBfQYJerFhPEAIhzHEAv1ksQhDrn6ZwzTEz9UsgglGJExolESjCUkjEmhui3S7s0cBzFiMgrT2LkUIMGCMzFO1BMWglAGIcBJgtUkmkTjOEFJFEUJlTwSnOz2xjfUOkYYRQCyZAxDiIIkImG6gSuKQIiDkDEUJqoFccwVV5RQBORYlRHGBAUUEP1GsfQDFieYJFDRC1GUBDEN4BiqWiEGYyUtTlfvxyzkjCLIScKQ5KouhGhPxJF05UX9RmKJOOJcFRIJrJqNQAQlpphQHErKVCcQKISQIExXpngUUqxeGG7dMrC3FdqVCCMXYAiPJik4tj3GU2eOIBl82EzYYdy4+iG1zv9358YddPtQNIaOl8GRyaYi7GotWNlrZfZEmDqTAcZxxCI4lgELQqEMDEAJxTziOBFUxsrgj5UnGnEwlohyGIansKcoGkcGM/1ThM5uuaceOjoTGhtuGAsAI5JTFKghD4lQ6RfJAFI1XCQJFzAhAYmwGqb4mOKxBONAYBInauCN9qNSYaEfHFi5STTMdtWox3bVgdaEjn26GNnHRUjnuAhyHevIjTXDRkCSsfHQGdcOh/Wz0RMK+g4/iYI796MuRSSy3yNqYyyH2OOCy2YkDCrGRbUylAOsvcantPaahHGXLTy1mTIMjIvtKlGryRnCYGBjg5G497UPYTBOaiCLttknD7NOebS1R9odVY5WJg47DB0MP7G8hIh/Z5N6NDOZHHrpoAhNZuGsnebSQQ37xoOxJGzZzKmpjXZ30hBVlcfpot0BbbBrLzK30RYpnvoGI4dgs+w+S9LMnU5oeDILwWizSVE6GPYibm8sTDJfDVBVKGsngxus0DCUhIAEcSFkgBkJo5BxEUJlsGUSxRATHkRxEkfhGLNEpOetx4LyKKIKBqzL7huLics5L//b+IFDWAh42MMQyvjqLaNmr9Jxx3tNRqr85vXcAa/aP27TQg7HZMBdbW5Ah10EjDG8MGc6uvTZ4dkG2iOKOp9OAN1PJ7Rs/q89ndBUlV2hlarASlW05xBq1lw6HJQwDMzoe2VbFV57ioIdYJ5iGCis14nNekOdTtAwjBadBzgyVDeHAWlZdq1pVQiYTBIi4iRCHOCQBQQSGUdjGYEQJGOslEfGUlDAYsoZYUEiBQM0HEsIeTGxXDG75QANlEltA6t+Kaw9gx/WnsEP96e8q2fwYQ2jzM/gYyN5J3AGP5TMfocF1KeezFbXt9MBfNiMnRGQhQKRxfh7Fkva4gRH2rqrCFBl7IvdHhLcmfzEuJ6app1YvOg8VtXP1mENebesDM3wRN3JhfV7QIbyHW32oWiqPQRxguM5jfCYTuNBWaWt9gCU2yYjPvM1SG8DDmMDgAHPm5O/JAcZ4Ik+znriq6201krYHI+2sUly8DEdRwbLj6z7UerDRdOKZ5jZJS3btAVdO9pPohXUEApEmmnLcSYoffcGt3XOtj9Z3U7OMR125nroxbF4rM+sdarm2X1XBNHuJrDdCZ1xYdVU48A2RMGtUv/2TVKu68Qhtlsig90ciUmik8Ns2EQWx/OOtbnT4nheZJFPMbyiMwZBsqfxbnSuHA5KLnMv5Zhd2ebgAfATc48fj58e+CEePx4/3fETUo8fj5/u+JHM4+dy8RN0X7Xg273hQ2RHosOuuPCEDrfMGdqfyBigC3dniWu3w/OIG0ys8UmtH0uubVFC3V0FcIhQwbGCAnF06VskzO780eb4GmzbYMzRCW/R2OfANT+NN5gljcXeN9jxcQ9VRhxasEO2K2TaJHAI7dI7EZHzuBL7lM9Xad6CSzdvgx9jCUAwmOhSIuuod2a/4EimkgkzEjdBTTck7XgfH+S00qaO6BiTOHSsk030Ys0EKjQpLrs7vS9osPax6tWHcGdHqPK0DpNFeEBg+c9wW2aCk5gfysJ6azL2noNFgqXLyMh2KKzJBNhD/sDZPWSCLix2CS82donqblqj9vu5B94RHjaOUpHjUepgTi+QV3QjmrO9hIe9+yxBV+LZHoz4R3RKIpmchf05KMSD7brcSZmhczmQeRL3M4ZXFqRryqweGQWRBrArLDGq2ACO9u4y6dplvHLgLHG99NvW53LA2CewX10ZUhNErwkZ2Gc9u+yg4dWZrSFAF1VOxoxrT8YklafV4zhg009R5SmpzTaUnkepZlRPD3vJylNeznxem2aoSB1ePgOW3zIlaj/ZXq3U5mIVvwrKBdUQuLRASo3MDYoOe7umREhbH8x1jRigPlB7QAcSpLsTbYj6CN3Id+H2lvg7MnrjB+mPofn9m+e8f5OfazYYGQYGp8ENL0cyv97ivDNM2FxI0iHzyjmlqkBDXy44aBqIs6WtKDmVnraetp62p09bwl3R1lPxQqhIeuYGMHx6SrtddHfJHDQxm9DvHh0bJIIdolLoUm6N6XG35nncGjN4XE6gcZd1mLreGyIpx1h7FCw0GOyGH3NLW91FXV8lYPi+orq+SoZb7uLEQkmGTpQNUdxGq+BpRUaT6xu9D8NaTC8sBsovMQb6b/U4fJxMV5PZ8smfbv755CGJk8UymaXvL4LZ+2QUfUiiX9Nfw8nq02SZKTCJRvOH7OMPk9kq/fJ/noD0+/95Es0Vp/508+Q+uZ8vvvwzePj3zZ9vlsn7+0S9eBvE8VdfpxKCKEqWy0k4TUbLaP6QrEtfroLFr5+CRXIbBZPF/Daa39/PZ7fBdDrP1tN0f9+8lVZqPJ1/Gq0WQfTrZPZ+FAerIKth8LB7mP3+fjF/fFA/AfXJfDxeJqv0l9/TlifjZJHMomQ0ibPW/f7776lgiIqN/Hg/Us1KFus2fPU/f5j94U836pPbaTL73b6dqs+ihy+ahq5f2L7XoamovalGZacNzCSs+wWVlD+7+fbPN/Bfs7QrovlMoetRAWn+8EXVR8EB3kzGN7Ob/30DbpLpMrkBp95TtEdPlduvvoTbbsNVOH2erDZoOnn8MB1VcIkqyy/LSDF09CGYxdNkcZv9kvaNKmb11dZA/Hn7wzc32w8eVos/pzjK/W7UM9lPs2S1bfvm+2Wxe5reKtavS1eRfFfBNgCZ1SPfCak2Nn1NiL6vp5NwESy+jNKHJ9jV+ep16Wnqpqfz1Sh1NN50NGXmHT2awu3zE+/zXE27dD9z3/25GpU0QTaaYFKviTh5mM6/nGDHryvWpZ+5m35eV6DUrXTTrbwF4O+TVaYg5fIoV26hOuoEu7hayS7dLdx0d7Uypa5nm64XuL3rl8lvj2kFTr33K/XsogDpTgGV+pR0wDc6kKBdB6GaZfw6mj3ehydp2MtV7NLzELjr+nxdSr0utr3ODYzOxgM6dbNTqman3ocOLU+pPiUNyO28FhBT4K8m94kq8v7hpLG/q2UnBSDX8N9Vp9T/cDuBhhC2K2D1ebScvJ8Fq8dFcqK9n69ip67H7ro+X5dyv8NdQKfF4i9X80XwPhktkiA+wT7PV69TfzuapebrUe5rtOtradbXnxaTVXLCnZ3Vr1NvU7e9nVWk3N3buSrELd2d3E9Wo+Sj6toT7Ot95Tp1tKM56b4W5V7ezkMhoUaGezIbz0/XZqe169TP3Km5TqtR7ujtzBTSlvnRQs1rA1VsNA1O0j0s1K9TZzuakRYqUu5utuvuUiRgvJjf3zSFlYPVh9HjajJd3kzuH+aL1Y2SnCxWSqGr5H2y+Nes+PtXafd/DKaPydfbP93sHt383zc/v3nx093N//XndGVm/IfNt7P5avSfZDG/GQeTaRKrxu4++f1GvXr7B/t4uaq3Llqu/nxbKr2T4mSPVZeaOqwbndFvqy0GB9ZWsNcUuPmvP2fqCnaq+q+b3FrhaLOgeBvOH2dxpkGln0xbwe83k+XN/HF1Mx+vPxlYa7NOixzAkb5mt0HG262WuOynpVQj/5r9a/a/bp7PF4skWs1Ur91knX77r9maPX/evLfn2DdrJX291dZOkesP/ivT5S8//3z3ZvTd619efZ9q7H82vFprazmJk1Rjqw/JWms3/1RdhP74R0TB17d/2FQpmEaP02A1mc9uxvNF9vK6IPXkdr0W+GHy/sM36wXS+SdV1Xjy8X4e56ua/vj2xxc/vPt6SFyoeo/CSSfXAmE34NhUIeuSVCy0qnnaf1ukWny1Mxy7ib8sTfz/183fksVk/GWrvsf7h1R/CgaztfqTtYqXHyYPN2Gy+pQksw0Svrl59v33GwzdqEF5jTal+dzjteHIPShj8qu1LIXK3EvK3mSP4deZ3K/QzR9vdu9twJ394V+zm80/ua/Vuzf/e/PaNzf/+tf6pT/M5ov7YDr5T7ILKX19EwUzZWRVu24el0l882my+pC1OnpUdJutbiLV8FWQbmT4wxrQk+VoqaRMt4vamZFT4or1N1/krgzaa0+/xcVYv3RbaVEnfPecETbVJeuWVD7q1pZdV2cc3C6glzdkbHSSIqOqkQ1kzlcb6KS0ofoyq+F2wR+0eIyLLw8r5d7vQzLbn7YD3LOXP//47Jub7+7eqX//8OLu5fejjXEoiXr4svpQO0SqwSme34+SaPQwz8bK+g8L36zmo/DLKlmuR7Hvk/FkpizfzTJRBiAdx0oylT0IVn9Y3sTJQzKLU6OgLGNqAVI7MZk9PK7UTGOevfWnVODNzVfKbL1LrWkcK5FrIct0ZI2TVbK4n8wmy9Ukut28jL6+eZHK/xAsYlU3NbrP58uN5GVWoU8fJtHaLG0cLWWnVPmpW6yEZPX+8034ryf/enL7f1RhX90HD19tG/nNzT9TQjzcfl4PtQ+3X9Y/3K//89v2D7/dfvn311+vjdxy+3B5+0WJLnXIVzlNfVPUYVoX+3E80W31SqLb/eYzWzJJKzLVlnt7n37K2it4m5VIDV78LX2RG7yYVhBtnUmMWwIPSwXP0b3q9jRSpPQ/hYeYFG8KbJkUb9+qqWQXxeJ+AXtNbcobbrZ+E24L+8TJNHkfrJJD7LlRvylq7xd70iV+NTtQpcej1iCFycfF1nTSUOe4vn39ynt3tmssDFAHW1RHo/tgMhuN0jeKP39aBA8PyWJZ/V3J/BikLY3UjHjVbU2WFENtFOk23zFMjtXUzEVePEbKc+jUzOKqP9e2srxl4nCt/DxfbJXZya+jxTVeBrXtLC+QH66d4/l8pGqkyh0tEuWrdYqnUGy8wZpzeKymZlams2/BzDeRC3I02GZmsS92WWFOgqm2rYIdz+bG+/XfdDTv1ebighLFukZLeDQQq/qN1kGeLo0sLjDo24iOZpPeb9vY3zJxc9ZKAY7VYCV48WU92erUyIL5Rdpd+xDA4xrg7WEkB7ql5sd6AJXHY+x+ztGpmcLcYYIQoOMOr71W9QWwADLk4qhNTeP6o6lq67RHg5nFyTRIjtre3udlRAHIiOhbi/lRW7veRN/fSEmbs4cSn0KbA2WvMmX3b7z5vABidjRHUrV7vuy2WCiZxTQPYgmOqmA35yZkcUDSxikgObLVcnZYAQJg02wsjt5sFxulAbJpNEPHh7eL/fmA2LT6eDPgkqr7nAdhFi2mmB3fE9lukU3DkZPlStXzS7eWF6yZaGm5OC6tF+mUWLVDVa3bwRNg0ViG5DFDO52jHLB4vEMfyoGMH81oLZLocbGcfMwW3fu012IWwcHRpv+TWbRIgmXSp6VF10Pqm0ro8c1UusNoFCwWQTfrhJCFaiU7kfau14f6NNsC0WnKzmM2u3CsfflltlLexyQaLR/fB93GYlQAORXa1ktAj+599DlfgAsjEtHPn+TxRqSssaqhH9Wvk/msW1stnGkEKD4dWPfLHwFxMfIj9Q0XR45zpatII0XixyDnZX5Id0V3m02Q4sRRy2cEMTqyh9n3EAspoJzrUQ7p0cxX8lm5X6vERYuL08VmG5b+IZrfP0zSCMzWkqhGg1uIbrMUc1nds5alz/NtmaRbESfjSbq+mZa+/dvtd+usbd+t11Wyv8VKk5NZto0727pUv+0s+2W3HlOWo4pcfVlXI5hOguWT33Ode3sXvX7oXWJeSFtxP2eLY+ZFbTcv7j7VF/DDs5dv7yzEh/P5dPORXvCPwfJD747KC9EX92IWJ5+fzeK/pS72GijjR2XAZ8F9AVHlF7/JmBduwTVJ/5r9tHfCUuxm1doWP06mq6z0j/vC9iyovP7V5z/dpJ98c/Nl/cPXT35Pv15O/pP+HecatvYfiy376cvz7dpDWtD21bRhywfF36a3b58t3us6ovxmsSdyFQTGFbz94fXr0du7l3fP371+kxW9PZbBGYMUcg6wpJhhIaSUBHGMqBr2oJSMAc4hwogLJlGa4lIwjAiVAKX5IdUzRCVUj2C+u7IdWY2VeXH/MJ1Ek5V5PxS+cNEfb9YrCGnhJUx8ncdz+t9RnO7PnmT8aBL39sX/d/f6h9HL188VAQv9C4x75e+v34yev/7l1bu7N2/rdYXSHKOMYyY4xowgmaoOYcmRhIKBTHmCCEw4JkqdCEmMEVazEYQwoEwgRgGiahKKzHW1znBpbifyeTH1hiFXSHEhT1uYYfI846LH83lW4EOUrfamHRMnkXKxlJuVDeX/zokaP84iLQ6UNAt2794u2bpKxNjI7OWIAM2JkNbBno+Vr0otKG6Hba38H7Pq5c9zVj6E7a1Gdq1uNgGqz7fjQQdbkMputgfQmHmFFIXdOFEQYUyJTapOc84XU3wal1PYFLjjIBeoHwfzYi3IWP3MCStTPzl1XbI17M9tmG5yhvIwJ+YwL7TJnuXNn58Z3QsNcTz0F2R35v3b9az+eWLB9coxhcJv2VH6xVj5oQXhena+e/Ps1dtnz9+9eP1q9Dflh6j/2lRnvrzdH1etk9VSuirlua0XYNwLBektFfn8Io0edjO6m4/1JTTvFN47I5RUDOGT5LN6aRasD8ToTWJjEW1GseXD7hMzCw+luQ6GZsxQQKkx21T0JpbMeqLcw+x9c9NsY1GTjbWYyjb3lgtr2Sy987xpvzy54wukUvYmTCbThCC5F0sY2lfLNSHWZVoQoOaDcxi591V3hb61tB5oK56l22GOMt4TcgXB7cCreb1XoCyeqJdG65sVzOxQ9sUQFqjYNGOUaz5zgfXmEQEeZERA7XSy7Vo3pCrK7E6tweJLu4xICt42k9lCNqX0W7Nitsm6Opa0/Vxf2OY+nPQ8nc3SwPqrwtf6cg4dkKseEty7wQj3MrEV0W1GtuGDkjE58SBAtRGGBrXlw3NwH6pNcGHxqlI727z8efUdzlm2Z66E8/LJ9hao799uBXn51Z7wrnF6XWgyV0tT/DZ94p2BSv84oUVOXmdCFHN9dI78tKcR0Y9Cm3tSug13m49bS8jO9ewnrRjXzCBKm5v0rN/IbGN84bUSGdKUVdZh7eA+NYTOOb+tpyHfa18/2iiltRHIiY2w4Pq2b1zwfCurM8fXaS5ststsPtEzarurxmQLxm4HTgumiu913m6wE3PgHTe7cg0pVP9+/2a7gN1OWB/crSVs0g9ulxmzPKa2y4wFYcYw2r/cv1MzWbaKrX50JnFvi3Gj2Fini/tF0f2R+EH1DbKwBOn7m48MmV9NBGrn1DTmEzUsv3BHSDd/qiDCstj1bRn9yl3LMCx4X+DGuNA+xmV9x4YpuXNvd1mJMN2t2omL67rZmquar/zsra6LnI6wa5Hdrds+z0o34uUEtLAul5toRznZc7U8J7SVeeVXu4/qOUmmJGn65BwYYmNCcu10AvOcvO4YzwnJD6y7TT605fvaAx47DCNI+sW6a+W3wrn5o/IOuPQvo9QRcb68XV8JU060f9ybHb3b4gTEtZI7w7mw95nJfgbUYOtzw35nC4NpsVu5ZYuyZaFO5xP6HcItSqsk1+g22lbE6MfcuuwtfQveS2ovu5QjqHvRJUEGJddt++1YdllUe+njh2zN8MFmiXyRvE/TjyyWJQntpVXTEnVvbFVWe/nbY9vdS91KMCprf21orwL3YtpLLe1Zkwj1Mro7kW2mt/Rin9U+i5FwX6qh0W744JCj974KTm3+Xmxnyz9Y2Gii+rrA+JY4ev79NuBV3+08DhdEHTimXijbEMzN37jpAhceZUFgZ2QWpBwEpseKcBbqcNgoZ23Rh4p0ljIl7devmeg3ZS0KbrUmNW8faCwrFW1qAzRfHXJUK9XDiekoiuxsPA57zrEpiUz/gvPSWuowf79P45KkN+UYDLqVj9q40vBB57GnKs+QAy0fOqyQC1hXpdaexccQMsmgBBIIgdX/MSqZkAAiBjHEGAguKACEUAYZIgxjAgiiaY4FSSViRABEARQsu2RHR49qfTozrSJquN3X1bLS+H5u4ICwyxpZvVh7Kuy/Klvh/GvVgxGa/VBVRhtFz3se6LSLqjd0RGciV78+hw3CDe0YxnpkopspS2wpe7h1tmrZg2YGqMs9mvMzCejlZ9ZIb7MajZ+UMZ5Mx6PT2DBdV2VDcrd+eg7MrmuEC1rXye08DFdX/+xJXJShJ1bhupc9owBmvRiVF9tGpeq7JTSt5oMluymUbUiG5m8OOWkr1MIFjAsCm/GL9PituUDVCsS6m1jbkFyJoAvJe6LYMIK+dBdBH8z8L23j7cvjx9uXBvF2G4T3DrMfNqp36EBe4caz3EKUhL1oVBDbRqWalzsHAYqyDGGv+ejyNkYXG6td1HqcrmzXtYrSO5Ou5j6vXKhAyP7gLAg3QmjNF65Sgm3rOVJzh2R3DtTkeFFaqTT/bzU0gdo/Kn6ADaw3MQFXsaNsOKj58pBjUE1dXAxGNWIdEKTumpk9V0hPf0hbjjltGj8uqXW++pAsRp15VPu+K5vZ2BBrhLcKOYe5tb45bvlSV4ID6uSuPtkzhkPkiDF78eZEKX/jIrakxFml9FHvu0/oU9tEa+Y0fXtehMm1wi1PcoJd0aNwU06OJZS5ZEm+FEuyVD89Uc4MtMZjSbxCd3XjX7OIM6RhoTEDsLEgvycpdfe+7E+NAEYcUFNTlhlBWwX0m+Nr5Vvh2ljQhR2pam+9OzroShmOFJ0OZW0umi5noFkPe1K77JhZr0+j+ePq4XFlyrRCUUbUqvmiEoiIE+sh7yJiD8W+sbEDmi/9aeOmbtKFD1cZNlLZ22t1Ns/Wv/7R0oYUC+5nNHKZnda8RshBmGQt1ZDC+1d7nqrMbuwqxktGy2C6MqfxPmXXqBulawQMRu+s3+x4Xf3k4MHETSWa6VJWYae4+6YUF9zIDomVBj/EmSuS7MRbsKX0zbFps6lUlittl+m1K12qfMN9+EY0A9GvyZfiy9RqWZq1jyPcnBF7ndpTuuHbs5mDlltxEOOwL66fldinb1tnuCEOgqaZTCODkHuz3yxyLcgGezVfXLJ7qB5nLa5+gTvWK3enZgcHYN39ziama3E9qVDcgbvZTceBA0LsJJuxovR6CZfK8NvtYE8/MDF9a3hZu40Duom5nrDidsNnB3cXcxVxB/W9zH54r804sVlt5rg/6svyjbBf/1FJccnnhyRK0wFXqu9yg2l9fWxwqP/44GisVMcZJiuSXSGzmJVkA86aLHw9wLkrwhKfpe+aIFpswYD43NenG0Qbvj8iSvc1GgCoe+H9sVqTxWaTBZxzN1AtlmCM1LrPmoA61D79psrYolT3+VFAWqqQU4yWZDuAaN1WrI09JdIRSEtlmMO09sPjAbVcHWuoagUcB6zlKrmFa1l6f8DW56zaIBZAN4itFGIM2YYvj4bZan1sQdsi4SiordbJKWyr4vvjNp/rbI1WQYUbtG5EG2O08H4jMqP1yvvgl9NXqmUL0NrvziZKnG+BUxBvhfaD7ofJ+w+jafIxmVZCYJA6iAmX5RuBuP6jq8rsUN8PNtTRf3w2/Kk0wxmJKpL7MamS92iz40hA1zuO8iUZ8an6Qf/F14vYbVToGBtyNX/o9xo19NIBtxoVynXH6nJ+sc12XeRgmGwoxprdlW890bV91JXzjTI8/ds7zNkI3lSAQ8ovv8xWyqWbRKPl4/sgv1YmAHfM+1JZ9uSvFXC4Sx/aK9SZblpBZ+PLaps0DCvKpfSjxiIZpXempFfF55hAiQMm5EQbAb/yvtuTyHHysPowDAryNbchRON3Z4P/fAucwT0vtC+666/xAZK6wLfFHT5NXxzYlne6vaftS+8hNXWTQ0o4uU8ok7X6PPqo+nqdvWgX1IAOdpLvJRvRofx6U2A7X1vnjMhVwoYOTZ8dfHElVxFnaMvJ7A61T/P1ScBdAkF99uz8+63oqbzbfc9xXtSBr6wolG0KvsZv3HSBEwzlBToBUOlqaNopM3VFoBXMmq6IfjKZxcln97apUnYXgFzDtdLVBju9Fqgq3g2iB7uEpVDKkS5hKdRhl6ZxzV0k+3I3FWjF3f0Hh+duVnYX7lY/9H52Qy+1EP6r9QJExvuOxM+KcUP8w2YvrS36YKlM84WXbmCnpLcdMLqFvemL7pbANDlwHnbdAW51QXvbl96CNHWTc7+352Xtn9OTxPnp0/oKYNIvbpWX2kac6rt1lMlOr7YSZyf0RfrNs1n8t7QXllZKK9THkA/N31z4CdFwsvo0WSbuzoh+txbY6ZhoQQsuiFYQaE+xT4vg4UF9qiSll0XsbodNM9xXOSe6nvwwKaaRhOYf28/7jWS3McxeyEAVbQZUjtSbXSff3OQ5+6cbe1Z+c1Oi5HZ7S45x20e7Y9rbB722wxh1xjBkuN2+Fo9SjNd5jjtuNjOqwVc0qcAomWUJtBaZrge65ahUkcr9Rgg6sQP6uyyaX+5NH7N7J9o/clSRPrzdUOg0mNj1NotaMZZMW5dhAejDM+ljuo67ZXJu/ieYAzoVhJuRquaTnoguSrQimOZTp5W6ykGy2AU9CVoUZkXTIgOsOXNoymZwqJ9/Cox6k7Yi3oS2DR/14khVpgV1Wz52XLGLGCurzepFyao4C1JWMd6BFwcn5j7LXC4khGpyS+ffNGTl/gsjPpZf7wf4nDQbDjZ95qwyVzhs5pvfj585QTbMzEHXihKHZmOcPMyXhQuzcd0NDLkTJmZM3Mg1YWHh1V6g30qyYF/tJ04qcYWs2za9F+O2QizYtgWxMdwPzbJ0I/CX0cN8kj/ILDnt7YbmBJtQrfJ6L6TnpVlQrvEzZ5W5Qurlm9+LfnlBFhTMI9yKDwen4uckelwljZvqIRH9WVlXhhE/mz/sR45auTacbRcwQAUvYsJY37R+HK0VacPWWhJ0JM+hGTye57LZcNA/AKsEmpBz91ovpKdSLIhXeb134RakOllOpe3oxaBUgAVfUsgZAbPIhVx8o+a6VGNwlghmhpq6j0rbRRaFa+41m0XyO44H3QytbYIda3Qf9+VQSbZm42Y9VbZZCPK/d+VBqS7NrIBGrDi0MX9fwOB6XoT7m/SdWBO2lF7uhY69LAu4NnzkqCIX4UXtm9PL7u/FWFj/PUYt8Nw0EkjUdSRoEG2F8HMfFZoa0oVsg40QTSUcb5xoqlGv0aJJ6OBjxmQWLZJAGZ7K5iZJeo8cReEm5Kr7ohd+SgItsK370mWVLmJIKbWp17hSkmUxuJTAbIv+Q3NvkUSPi+XkY3aGrkpAhnsTsKYEExY2ftYL93VSLfjY+rnzyl0EM+sa1ouedQItOFoH+k5UOTRblWrj0X2yXAbv8zQFtP8GqLxoE35W3++F/YI4C0Y2f+euOhfBwUKLepGvIMmCdQXw2mH98DyrRjEAdsAxiyjG0mEUY9klirEcIIqxvKwoxtJNFGPZJYqxtIhiLI81tcsS92xX2fMjFgK92VSQbcKomg96gbkoz4JZmg8dVqjHwtCZbpootr8XJYuiLGhZRLwlQ5qCjBBA2DHKqJFvzRnX0cbH6erQAUdde7oyeLDAo66U4wUfdbXqFYDUCT7MSJVZxW0u1/wVJVK4Ga4KBRjzr+ar/rgqCrXFvuZr11W7CE+xpl39x6eiPNtBqgj2Lgw5Hkd3V+uo3pksV6oeX/KJohF3SNeasuyY2yjAEVPq5Hfic6ugASt8YSyva6IjwteJ7sT9OhL1JOHxLMKnyerDKFgsgrwh4E4Nwb4IO/6Xv3PEopzYTmxv+t599S6M27mWOaJ0TmInJufA340zR+btGk1V+nLmmr75kjqwuPq5S7YUpHfndLOYwSp7iQwvNNAl0QuCu/O9QJpelDsO+7NrYdUs4jHIuRIfUhgULsXg0pEN0JRnbglahTigmK4Ma6tgLGzgil/hGb72TnFgVXTirW2LjpIOaH0UOxMn0+R9sEoqF6ZS7OLCVG1xxnal5qv+fCwKtbUcmq9dV+1abUOxF/obg6I8W/YXidKFXUfi98N0np81IOJo1rCWbMHh/esuGJJJs2dt9TNnlbkcL3/TIBeUywTZcy0DrRXEs6TWpUEMA+QS67siLEFf+s4V4PZiu9Gg4Xv31bs0Yuxb5oohe4ndqLIHfzfONO6sQBL32VmhLaYri5zusyhfTXqUHRf6BvZk97D7L/SFHXkbhr5y/Xdj6OUf0sFrJjDmDgjci7eXSlcnLD0EOU+RkwNR8RgMzFyOXI4WRtw4nZlcY7Ll3u4PnLUwW0jXfOWqKmcRAzEr6C56/bAvyKl7uu6r/k7pWo6tK7rmgQ1pjkPX+zQj4sckn5wQAu5oC+NeujlzS5844MxeojWHGz51WqnLmRDmGuWAdnth1tzbg9qaBkdhYZpOIZzOlfpmjymsclwkrtY0y2UYM7L+w/4UqMi1ZadewAAVvBymVprWn68VkbasrZCgI3mOzODV5F49CO4f8iTG0DWJd8V04HHpW5dM2YvuzuYGGcNU8xI5vW+dS1rvpXZn9p4c3Xl1NH6naFDmJX8P+WZlRWB39C6WYsXuuk/dsKYkuQu3dSIGqeRlMbvUODfELgntwusSKTrT6XisLgVR88M2pQ55XSrHjtm1HzuiTVl2J3ZrhQxU0QtjeLl5jjheFtuJ5WWS9CDY0Zi+TH57VGXXDuEEcHdUrxRkxfWGr91wqCq8C9tbpAxV1cvie7V9bghflduF8VWy9GHa0Ti/+jyazMa5SwOgkA6ZvhFvxe/CN26oshXZhcu137qt1mXxdtsqN2zdSuvC0S247flwFD5+mLz/MJomH5NpZcUJUkdR7nIZxsys/7A/DypybTmqFzBABS+HrZWm9adsRaQtbysk6EieozB4OgkXweJL5XiMNvd25+Mx+dKMeVz9qD9FCjJt+dv8seOKXevJmEIn9Gd4QZwtuwsE6UCqo7N6lLvtNXewFjsKcDcU1Yndle/d8ikvvg/nG+UMV11vCYr94dYo5CX3sQ95qvVj6vGtxvLLbBUo4kej5eP7IL9/RWA5gOkoldfNftQKcczKchm9LIlW2MAVv5xZgbaZjk1FWXwve1EmmQOiHsVyLNLU0isFhyh/MQF1tdEtJ97YLlS+6c+mvEhb1jd+67Zal8PpfKv6UzgvzZaxeXDb8+FIfGy4DhthV4y0vAu76SsX8O94C3bb166rdq0+vMOrsmvk2bPZ7pLs6kdHYfTq8+ij+nUteRelQ47O/++lG3O5/El/tuQk2rK46VOnlbqcsTXXqP50zAmz5WIO1NY0ODQLP88X6+xW20O965vAef9t4HnJJvSrvt8L5gVxFsRr/s5ddU5xyDST+936k73owRhd6LBedC5IsuBygRp2TDoAixu+VOCZR+t/7+kMzHMJtItt4LLph7YsMpCrZ7etgAEq2Mz3Pc9b2WFQji1NGkRu7MLts5cvR69f3RUlfQuBGh0AR5ICSDmm6idBERAEASgJxQAjCTjmBACCKKVCCCrUJxJh0qUWRZNjQSKt6bIi1bYqW4OpqJ6bfWLUm141BdjRrFFAKWXH57ZUHev0GurxF1eJOCxq3InIrYJKXZAb9do6o9OYWOgT2LtPmm3H5/Tvoy/bXCrdzEddka7MyHw+vf1BibjrKePdm1/uDLKLdDIDpihrNSaDskw9/pzlKyq9j3TvZ+govo9171dfJ+2kp1YAb86p0VUReRElLTx0pLdyaR/mk9lKyf45/W/WoN/aOt5G2L1ZN6f7kYpv0u7F5nTG++lsLdB8HK7UxWbobZ7XdEVMXsQBeLu+EdCMtjkd4T46+msSRcGvPfupKKTUU5NZukWuG79+zQSP1F9XSbGUt+mjrJ2bPXiFAoSzAvIDNHPW0Wvh5rxoq2YPmvw8XyaTeD7rCYGyGIcgeNiI3jS/VJIeCNhpITkw9MJCrXRzNJjUtQci3k7eqyo8Lvo6PhU55UH3MRz9mnwxNqTbq9OHnWzEk/RUXxSlZ4y+Vz8/y3407oOGz0tNt2n2wyL5WJc7UTOQzJJPdV84H0uSqOKXdZpvlzwzY+Bm5R/Ux1Alvk3/8vxx8XHdu9tPU1wsH4IoMf789tnLn3981n22UhJmMxGu+dRRLKso+bu7d8UGfks4kxBATAFnGHPJKcKEcYmlFJBSxhGCBFGJufpVUkYkEFykfyScMCyQAOotiEVhNLbsq7/cvRr9vVAvwQnHktA0TRwAnDNGqCqPSCE5JxghILD6DXHBAKcYIyKJgJCqiiD1A+BIMCEAYwD1q9Y/inigiDHVOwhwVZYQGKhiKKeUqu5BqgqYYkBUhwEC0pqnbRAQE/WntIsQohRRwTYngTtWq1OoRSNiEKS9fvP93Zsi1CTDTGELM4UrIBEEAkoAFbYEUnqjElIisnuNO/ZLc7ila4SlKN9RbEUJVSYviONcHJLB3nHInVhry5P/7Dzm4TmMEluMblrblUR1n7sj0Ea6JmFw42pfuZd6YH5TC6d4j+eP4TTJh96FI8ivJXdBff7LwYDf2fEt1LEHXOskOEXspoDjg3ZTEae4zeeZRtIVZhuzTBt9NaSRvjeOUv/WcWavpQjtgL/WvNlWX5c6d7dJws2CUz4VdY/Vpl3Vj086bfpr1IVwt/f2Krx/Ug/ULIo7ThZpopCMrwUqb6v55J9RsFx9NX64+X9uvvqWfv3NZl3/3+n3wcMoTS3062T2fpRuickq934xf3zI5KSBrh0qfv89bw92JRu1+sG+1Q9POpOuS8dw1TGG8g/cd7/Z991vh+07crJ918FgLt33HQasru8G7DTUrdMmy9Fvj0E8WiTLSfxoEya+D1YfKp/bBbtKnWmuuKoWTnNryYdg+aGyUtgphllaKzTu5KwG6b/Q3vHDvd2+vVQ7x6/83Wkrbl3RTs5Y0/elBqdvuPPG8ltte3hjubpr/LFsMbnfjp9cQY4mOW0LmabqM1gQzatxCYyBu4TGyyxLZDx5WWLj3TVLYrzlY0nb9nzsX2XFV5nmVV58lbdzV1jhNxuY9ru9zMxtbouYjXnNytrtCrMoKvvGuqRguUwWqxGiYBRO8snA6g4C/zqbf5qNlAuxvh78ia2RrynRzto3CijRx+jmtgoooD0oSnX58cVffhx99/qXV98XqkExZBJCKTDEkjFMJGSQIiQQgRBBzAUGVvuH68ruNKq0Cipfi6e70O4gXex+EaOulLc/vvjhXUGHmAClL8yYREBiQbKVGswJA5xgyJlAEBLK+mrR0bBVJ/qXn3++e1ODTiiATBeYJMFYzTIopQqgGCmgEsDT5gnKAAIcE0xhum6n2i0ghpBRRDgFUPUKQYwChnqDOE2w1gu8mQC7UMfa1JVmVv/cTUv/rf4LLQIeuO/Es65Z0/mnXt2Sfu+2V47dI3sT37VP1hIc9MqmU/DXx+qT/LqRYmXvyVhRdvchumHtKDD2bcOBJ2WlyvYeQvXLSEccPafJwAOnu2WlvNRZ/ui8gz0ARdndgT2b9QG2E43OZv3hOpudKFxns4HhOpsNA9fboKsiAtuRKKODg5EIuByJZrPiYMSBY872Go9yn5/FkLSurwOan+7AtK7b0GQfaniar0b/SRb5iw2yGaBDwG9K6IH5goQjx0l2lemP6VpJjrbt1BY0MEa3xQwI0x5zppIIy6GKMidDFey9plvMPbFjrezP2bxgS7JWPy2xNF6uTDj6x3UFF5HJCLV+eZrMBj5xUWxdN9o3i3DF90IJL+fzhx8W6zp1qeH++8PosburUaj2APatIN+VYSsITa81m8wele8yf/iijEZHlVXE2PriVfsWPFj44Hm7hvvatdstq+37If3SrumOwmFODfvtdD4vXPyckzYNwmSqk2RyVtG0cw3PPZ7Owm9nM79I3k+WWRKq9H6j4MFk8XKqJh3p9w+TNIn7dBJWpdgsZxY/Hj9kOSUeIhc12QszqpC5uP3OadLdBTEuztAvsZTXdww2L87Oe+go93DNaR5w1TvKpu6T5EW5X60HY/MKdR+hs59myWpvjrOTz8vbt3evvh/9dPf27bO/3I3evR69hKO3dy/vnr97/UZPzLLETfJAvcQWdjbXMpnFP61/eTd/Cd9+WT7f3q3UoYL1wrrWbanEjTa/jVbz0RTmtt2hTjMXi7JaTYa1rNJ4p/6SvwfW6Hx58GU6D+LRhpdmI+DmI5Nh8I9246BND5hasM4yy97EPuWm4czDJsxjU0snswubAgcwZjWllDvYgT7zIhu01LhHHDW742zrjpv447jskH+zMzmY5oso7Apg2V4J8k1uoLIoBZq5/RW7qwyf6rzbZ99/X7e5pXtKRyKkJVC2Vfnp2d9Hb9V4lI5QL97d/TRKsVg89tO6UahJds1+PYvN9aWvLcekbR1m88W9ev8/Sc0V3hI52TZoXLT1ANUiqbwupP7mPj5uXqeuA4ahxEMvA5lXU7tP3HqTuHm57oaN5jJ2oOqtzEySZawqY6iDkA3pELMxb9lkmVopN720kWV5ABKiuqBe1k+wcz+hAfppeb+drLjoqbU0W0yRAfqqq0OwnYg9T3M8P3/96t2bZ8/fFaedu3EYCIoRx4RThADhiAgGJeSCCGTN91256t/P5+ldQtHKSi21AsomOvntMVlaZKYzKuXNRuomqeODam5inp3TsIiNWKtsnVa179vXWznlSVQyTaLVfGE8QY028upntppJ6tYZGtUXqTmukzYmpVPNpBi3f2VyfuePdmkI7DDRX3MbQRW2rBp6Beiymq6qneJk9a2xLd8r4/SXZ+/uRpnNqjdVEDJOJQFMmSeMABMIQ6kmKmmyrK6malfuSzj68dmr71/evWkoXVlJoiZQAiDJkSDZzn/K1CxKCoa5hFAwVReEutfk55ev/1FfuDLOABEmaHoEA3YuIXmYzr90gtrm08FM8Vp+uxFmfYTXmF/ZHbCFGnfvU2cmN7vlKz35aWxsy1Z6tAxMcxl/s4Fe2mPpzSjdjG+NBENDnE2x0+4bjRfz+/0WtNZzlTb5YE0B1Uf59VZbP34Csy5tNv3QSsABIsb7bimmbzUL7DQncLWK7WzrcPfTi3eju7/dvWpwmSESgAOJQZqkEGPKieREdDXKd/eT1d3HZNbNhuy/7ms/fk2+LEeV3VBQ/4EhNFK2pkisiNcYh0N7ZX+5ezf67uXr538dvfrlp++avABIiABCQuV8YEoRBgASLDhAmND0hKBgXXGwL//di5/u3r579tPPDY5ImipUAswxYihNeirSk5eqLpRzwSXi6r8Uqgd9apJ6YaoP0pDy3du39RVJa5H6X1xArNigpoyEIKr6RzGDMyogQIzgXrXYTl219WBIzb4lxQwIQImERHlhqvmSA6hqlZ7JhBKp2SwQvSrz9u7//eXu1fO2XoFUqvqosrDqAalm0qo7KFY1E0gq55XB9E9pbWgKnD4Vevf30YtXP7xuqAZWJSOJpUJldsRaVQPhnsW9ffGXV8/e/fLmTk8OJFiaIhgArlSh3HOEOFe/SN69/GT13XQe/frqMbVwnSxlScRgnmyxnHaPFroopMaz7T4Vq29B/z534un2irW3dJ+LJtb7c2H6ymi2R+9h2/lucq86Prh/6NXEvZTBybMramD+5MoZhEKVdjjp/9MjUrUfHTVUR6dVAdUHa3AadUsWz3ITsw7tLAoZkk+FkoajU6kY12yqbYWLvj8pLtV3optmNgQaspfswgzOWrsJcvSlUknMoGQqljUgncoFOSdUfUvc6OC0SNXQla6a6jKC56rNb1MFzKLew1RFzpDkKhc2HLuqJbmmV1NbHOnhpAjW2JvOGltPseX2veNw7N3nF7PxvGsjN18Pyad1EcOxaCvfNXeK9e7VvyfFk1J/9WxYPSdWn0eTLSr7AWhdzh9dNn93u2D3tu9FDMucXTlD0idXSA2HsKPO7k2kiqQTYVO1+1w0sWGs2b5QXcPSnU8tAP5AO2levvjuzbM3/1hvpGnb1UIwQxgTijglML3Oj3OQ3qKHKOBCUsoplFmWVsIgo6zzmlKhUvWrSQhzBhDjkmDEAYQ8PbEAGeu8teflJFwEiy/PbfeG1n0/mLXJFXJ+WxBrKt+zo4+4G+Yath6+ufv55bPnd6PnL581rV8iSgEgACPICcGYC2UbGEh33DHWebnyTfIwDaLkeaqVThApCDg0OJyY5bZzwHuLnC6fp1eoMoEBJlhKwKFkgkpEMFf2ufsy6vZI1pu7Z983LOECICRgUikepFpn6ZkwIFAPM7wt9L/fvHh314S59JJYyClAghNAQdpWxhiSHHdvbPORZlv0NR9o7oXDppO/sMvJX9T+UeVAEzYwNqQ74teHLN4km0PH1r2e+36w8TdXSPv4i3qX4NTPr6l7z352NfxawdqNea3p5d6dUT8XGChlYFuV/nsxWfVq01rAQVWbOxPlOPdOS9yiUz/Vx+Q+qh/W+08NOyiK5o+z1ajzGZj74PNonJibd83cFFvPTXU7rlVzZstg7SRXvSfNTTbRh2AyG01i4/tsZvP0lJvzK20aNZ+lG4jyJ9bWJyCpi+Qi9aXYH9vWiHG1fbxlDgQ7zYGQ7RxoWLek2H2dj5cbiDtqKpKGCupOle+PC6yPl39zs3lmn3jJsDYOz5rXF9AxO4mBNMvEJIhq70w1zktCGtOSoMasJDzLSsKNs5I4PYMc7w+dZfXsdodBi/juxjT/fdmKNoQJQK8TVbD3iSrU50QV7nyiirQPwN0DUxs19LbGdXJOwwxvatZsf8vY6Z/io1T0AMZ2I7mvla0RY2leNVdBCBvzypvMK5ON5lVk5lUam1fu0rwm95PVKNmdH1sno8DIqY3dl9HdzpZllEhZf/oM2Jw+g9anz5DN6bNhndJc9/S2gU2yTsMO5mo3SEa8uoIGsHw56X2tX4MoSwsIMXLjYWapvGttIMSyxcekxkawWEpfK5hmca2cscnqnB2xc2cKywV1N4j1krrn3jUvqLeB0Us8DTNTqWOzscm/5s7pqlRgACNUKaOvKdIKtDRIGfNasqwZ2SPQZI8kaDRHODNHyNwcgWHMUfGM0tqKAjiQSdoV5sIqlYQNapj2ZTm0TQ1CT8087avZZqF2bw5hpPbVGNRO7YtxZ6rqZdq6TwA6MleNiYMhIO7sFXJtr2pOgmW1znabuLVWxaL6Gas6WQPZqlJRTkyVTubpWKpSLTUxrMKLbu1UqRIDmalSKS6slEakpZHKuOjARokmE8WZMwslnBuoukXNtR9I3JuoUmE9jVSttKHMVLkwN4ZKK/WETFW5nscIuNdWZCiDVS7HicnSCbU0WnWZkTs5VrBxHsjd+VXQtdmqP6W4niED53arUlo/w9UgbiDLVS3NielqEXs6tqta0WbjVXnXrfWqVmUg81UtyIX90ku1DWQBNwZMNtkvgZ3ZL+nafOUPlG7ukkTOrdamkH62qiBkIAu1LcOJXaoVdjrWaFu9Zhu0eeNPN+bHiV3Zp23lBrJKW/EubFGdLNvgFEGOfKjG/Q2QUHdOFB/AChX3K28CamIIU7Qrqbc9KkkazijtC3JlmRoknpR52tdR4yflN8dvt7XuHjrc2Fqp03CmaV+GI/tUL9A6gi4cGSncaKQgbDFS2NxIYZdGaro+wpzF+nK3k7rdfJAvpLttqkrpv+/1Gs4NFPqtt5ltlnYaJrZQv2MfGihUZgC7WpDf16Y2CrO9ypS72c9Fm6wpIc5ODNChbOloCpUlmsXT/J4uIgczq7ny3FjYikBvbPt0oVO72yj49ExwvqqnZI3z9RrYMOeLcmmjm+Rammsi3Zjrxt23lDkz10733i7WqVlG0S65yyag4NZKF4rpbptrxPS0yE64XqxWbyunEXcatq1YwWEPAhTLGsBKFQvoa5uapVlHDZtNErGakDfuF4G0eemC2EYNne4Y2dzwO1pss89sAgjMqVHKl9LdJlWl1NzBftj8toUq9TZHzdJOwxoV6tdsjDKcu1tnLZQ6gFkqyO9rlRqF2RolyBwZpcaT8BCBFqNkESUkQxilT7tUPpsKk0GsUlZMf7OUE9PHLtXnAho0KVSxBc7MWI2407Jj6woO61UVyxrQfK0LcGW/qtJsDRhq3s9GrQwYbTZgzecsqa0B6xmaU7/Nl7eZ4oLZanm7vqLyx2dvf6zczlhMJGmu9nIRWY7gnfC/PHurfnn7rngfNgQA9Cjh9au37978kuahHN2pcv4x+vn1i8brXiGVgACAGIIIcYElBRgQSBDm6t+cYkCB+g/kJM1hnL0nBABEEMg4YARRRiBFkFLWvcrf3z1/+ezN3ehvd2/evnj9qpg+s4/YH5798vJdey+APmVkF5vXKlKCXorMXdVbKx72w0m+V2rlM+BM/otXL969ePZy9N0v3//l7l05KaurUt794+e7UQ7+rnBUKePu7+/u3rx69tIViCoF7DObu7I7d2/eKHvw4tXfnr188f3o2Zu//PKTKrUIV87SZLwcC8kpUaRn6n+Sc6yYLoDSEyEAAVdVyNnaN+nlsyXw4fTCYcnSW3cFQBADpmwQBunNsoJL9X9pGl1lighjUAophKoulZRJBASjAgtX9Xzx6udf3o1e3hWtUnrrruoqpCwgVpYTYJEmk8bp1cBY1Q6mOY2JqgnAaW5jifrW5rWqg3JBFE+LvcQpSu/ilQBiCYWqjeozAGWP4v5+9/yXd3ftNpNBDjhNgaI0QwkVlKleV/+SqiMYyn5TakOQYTVAAIa56jFVU8wRYaq+FGOJBRAC4u61/eHubqRG0ldvf7h70zCY9jMv+4urM6QOYYfTIta9roa+9aXHQxSzNcH1ssHun+4l/PXu+fNnf9UU0Fv0m9e/vPo+E95QiuhXTO5CiTpXpI/k/BURQ3h9r17/XODs6x9+eFsaab/tMXy8WrPg7eiHN69/Gj3/5c2b8ugBe1ReMfgvauT+8e75X5tY3EN44VqAetzQXn3/9u75z8rg/RWmk4X6Eggn2EkJqbVYazjTxN8bikvvqXdV3N8b3FuEHRXy0y8NnECAUOqmjFd3/11fhnIbUK8SKjcfDAKxF8oPeKb8tjfP/pE6I6PvUlNY1DmSRDKOZI+J2Nt3dz83GvA+YnNXMwzSPYVrGAYp4R9vM9v93bO3d4MMcZkb8+x55gQ0kMFdAXWjG+wpOnXBWr1GhBHjgAhKEAUCqR8lRpRL5TJS5fGn3qByYtXMU3nOCDMkOFcePuccCgikIJwhApn6qs9wkzn2zxRQtnEHgzAJEVD5rhKq+kCofH2W+vhp7AQyptx/oiYEVPnC6QwFQJ6+q9xiKRARREqq2qmqzGTqMjupdxZ0aK92WiU1QQIMqTmSqqfqNqDsoepuIlR9lIuufgcYqtpy5cpzNcNjRE2slB6y+iLls6spjIKei2q3zykQk6pyWM1ApRQccdXjUhLVnSCdaQjV1WpSoVqg/qYmpEzVVk36GBFYTTfUDIxkISzIJbED8ypZ7o8Fpwk7F0kUrJJ4VHvPVFblWH0ymQWrdfJ826uq8iHqYDoJlg6rl78to18tcxdmuKzs90r1f0nxUL0vzb6+DcKGqnLTlXM9Kl4n0nH142SavFePyjv4cd8jRval26zYdZXuLwyIVk511mFxsW8px1pz7FDvw29Z7VBJJ2uYHcq1X9rsWYjtQQQs3GxtxY0Hu7Dm9Knt5laMe694Fju38NtoMlsli3EQJdtrlZ4nxrfKdRJdzZR9QvstjFv0Tj0veIfbEtIOWz4ETjSSL+Q2DTQpv/qXpjsH1XwEMoiUY6zmH2rqovx5hjFH6RoBTCdhmCqHn2a30QoJKMq8fSRlul6RzlvSlZ/Uo6Y9rINZS3qMKeYFODmd3K38NISmURVUk16qtIMkxQSk85f0kmCczhuRmo+piSahGCu1cKDmPupnwTiTMr3DFEM1UcIg1RlCGFI0tK5c+AH2BR1Rd2/unv/y5u2Lv92NWgjHGSWAYomAopaaUjOQPpFYKYwACNXMVQIgqJplI8oZ5JioWStC6s+IAMnTPRdqUp5GFuTQSnS9c6pbLd62sIJjrkyVwFmcgqYhFJnO8DFBasQWHCojJtWfOMaSE5iGkDDhyn6hVAWS0XQxFqo/EDh4hw7jWhkV/e7u7bv1zPe/X7z7cRMeru9QJmE6FjCgzLtCnxAIEyh4tmTOJIc8XawVFHBMMU2jb4Ct194VcoXqUQKxVPYJU3zgRq13c+japhysFANMGUeirCbh6QYGwCFThlFQmY50HKY7lqjqg3Q4xJAxmKEGqjcgT/EiFD+ZGLptago62jsu67NVELuehdtVZfghuFSUq/n5iXqAueYebMBsKLL3LDqdNgWz92qe9SGJfq1+eGL9fRpj274+zUMDHNzSTKfzSB+bzLpoG5jM3t981SP8aFS36o2k9vHTooyha5zmkinZbSzBUez2rirD2+1SUa7s9iEu0O7b4INZ7oYir8Ny7xuvC6L2Sv/Zt2JHNOGVvEv2VrIgYmgjWUg8sKyxmPw4FrO+XsObT125/TOlnN5d9U576WAG2KT867DGDT1xGk51Q+WOaJ4VIqKHLxYu9vqD7XdDW+NFEj0ulpOPyagu6ND7FlVnlRreDjcW6sqhXSbT8ehS7HFdbx3MGLcWfh2WuK4bTsMM19XsiDa4zsukx/EyD+hYLk9gXn7CFuwITuRV+42n5iqehHe4finV9qfJ6sMoWCyCLzn/ix7H/6qr1fD2qrnUo3pgqh5p4nTj/Znq/QNvzezeuwezfO2lX4cRrO2H07CHtVVrNo34wKZxrY+KhRQnYSHzlTu4oawWfmn20tlO0iMb3YKmjmV7mytxlSa40B0naYkLNbQyyL/n97OP7oOZosFaJfXXVLZfXmKwxb358u+atIfBQ0fBOCcYUTeb8xvTKQ5/D8HQmbNZ89XuwqaAxsuzBr+XefgrCLmju3tA4yWtg18DCwF0VEQziw9xx9EBEqQOn8IQIzekhqz5xroDXIp3gAzazMnAA2XzyAPdDG2N1Ibc0eCJrUrI5fQ9RBnqv9BJORK56a1mftfZ2mBdAuxcAsw7HRANUALKlyD1hw4b1o+TaPQwV57l7V30c/pfo0o0UkdXCWrTzE4lkEM1E4NaGzRg6XlNY9RsPZjV8dLGYXu4E6z/zibxq9ViEj6ukl0EJk7Cx/f7i5Mns/U0Jj0oP51H2SaI9TQT7P6+nnWqDl+NppPZdoa+fhDNpxsHOpnF+T+nv67/mBFyMnt4XI3Gk+l6ySn9YTulfvphfp88XX4IPgS/PlXqVJPUp2Hwn2T6dJT9Z7T5EwGMwyCGPBTq/2UwTjjESRCTJM3jQsOny2AWh/PPT1UtHj9/u/2NE/o0+ZxEi/l89XSkZluT2Wj0dLmInu4w9DTD0NM1hp6u91Jnj9ZTtQ8KSJv52LaLql2C9V2CC12SKf2cu2Q2elBT1cnn0Sz5lLZwmWEuxVcQqcnrchJOk9Eymj+sgafdtv7kG6Nt7anw8XT+qcKB2eN0mtYJaQBL9dqhBe0QcCmAPa5CsEYhsMWEwJINkeelknQvqBuNZLtKmxWSFZT+C7Xrg+j00cIQSL0+XOuD6vTBS/rI5jh5hfCizeLnqxBV8wf1wmw1yg2v/yx3SHmAzdyKfIeUhlhy6R0iWhgrCv2BxHkz9r8/qMrerBZfFJFuVvM0E89iknxUjz4kN5PNcslNsHj/eK867uYP6ffpSscfbiazPz35915E8vlB1SmTor7cBdxrvzgJM8F1ZoKVWSFKKGBFVuBrY0XFbpZowS6BFo2YXiTLx+nq1BAtdIi+LrN2EvqQGn20qKOojTNzQjZHOpyoY38uxOj8SKtOINQoRZaUIotKkWftq5+0VnRBBlQei3FRLahoufA5q6Wbz46p3mcX547UluE4XtaOxbq4IkQt42ERVVnu5LPuQkehRefMxxbMR1TH/IwFV8Z8QrTMJ/zCma9kOfHCncOaWAWhmDYIhb3/504xVtFBqteL8HpxphemGwdaBmt0aYP1CelFF1RALauzCHu9DKQXpNtHgGSLXoozWUIuRi86lx+1rI0ifllBlzqPHx7f40e6uT6GLfs9YEFHlHqL4kwvupkYbuEOLu0roFdhUXDb7iR81osiZxNEQLrZVotPXzL6pxg9zCR/O39cPf1VfDt/WH2bvvIt+o4+/+675+zbt+++JYiLgEQM0Qg8DSezkla3R7RSxT6o1ix2T0abJyMl8nbxOEvbutSDYxrM3u8FTSfh00XyfrJcJYtlT8OWSr7dSk5zW93uJNdhRfN6lqpw/DBS3Tp6MNnjppsVEtGyGEzE6e9zOxUM5cWkNiaXurYbdJqyPD75pkPG3Hag6HYNkBZTQ/HJO5geJm5gIjxMPEzaYSI9TDxM2jd8Aw8TD5N2mEAPEw+TdphoD/RUliZLm21ocb5MiQdKZ6AYLfkT3LLzlpzBZp+L0ght2btJS5s3qVdIL1tqe0Qhl8jJ/JRC/UdGUWDaEhunxdi48ATth4fuQegDD7S6qHTFiJT3AJWsCPEe2eV6ZNQGKDsPrGG48SsYlwsUZgUU75ZcK050qxQStixnyeIeCyw9UM4GKIWrzdpxoos/Zzc5auyJZD5idBUoIcCjxKOkFSXQo8SjpBUlyKPEo6QVJdijxKOkFSXaM3YAtKxkrd/ILWX5wMnACyeiklWnlGBBsNM/93hRGlknUNedeATQR42uaTFLtuwTkcX1f+EpeqaLWZZjLdOOtbDtQHvJjPjVrMv1yrgVUsqrWZUBx3tlF4sUYYcU75lcK1B0yxSwmsG2nKuzlBSH+vNZ54mU0RSOPqheVI0zyAINtaBpS/8FhY8iXR1kkIeMh4wdZLCHjIeMHWSIh4yHjB1kqIeMh4wdZLQBu0pCvcriWCmlnl8cG34pprx/F5evWAClIwH+IMnQOmlLcAhLGQ59EOrCl8cglG2DbTG3ovQkvYAFMruhVxvXrpiUyloZwn6t7Pr8NWkFmsqyWXkg8v7aFYCGATvQeOfFY4Zp10UYb734jp/+zXceNPWgiZOH6dwgnyrTRrUZa7slwecSuniEEI8QjxAtQqhHiEeIFiHMI8QjRIsQ7hHiEaJFiPAI8QjRIkQbWONt+S7Xb/hFtwMuulUSGZUv/IWlVEYYep0MrBPetuzFi8te1JvSC18IzaLFWkTQ4klBT9IzXQg1HWm5NrJcsSCV7S1lE+KXIy7PG+PICiN+lLlCiGhvhAflRU1Wcg7Xb+Q24PjTXueDkfTatvSnZDEK4nihijLAC7XCC22BC/JwuWy4aC8aB7QlHrB+IzcE+XjAwHNPVM0uUeFwKbuE35MwuE5Ym1ktpnJifvZ32fEABNpuVwfFazCkJ+mZxgM6jbpCO+qWrQkSenNCfU7yC/fSpBVe/Ohz3XARuo3QCJXDSqx05GL9Rm5sYh4vZ4WXZfLbY+rC2EAGWUGGtiDGTwMvHzHawCSGbZEDDP2gdNhZKuJtfiUq7e7whn9oneCWbBXrF3I08Ws8Fx45wKANEcB7ZxcTOegy8GpXeCoGZTfONlkUv7Hg8n01ZgUZPwZ5xOjOGiBaRgwrGxlahIzwg9R5QSZUHsqvo9njfWhyilpIK7TQFrD46MElg0Vqo5OV6+MrgYPSBfLUm5ahJ6kUtOqkOCchPpgzuE5om1GlfnPoVQUOaNvePlra2+dJesaBA8sxV7u8U7El5SRsFWPiYwYX7aFhK7T4keeqwaLLfYMqJ4pZGS2lE8WSeLSc1+aU+SyFxso8tiSZFWLaAOPnfxcPGG0wsnJMrjI7LZ2TY/4M1NCz08pxaMTLOik6CcR7lEPrRLQtLAvgFwavKmLARdtQW8wsIj0izvmQgv24q13WqdiTcgqDikHxZ1wu3VODAFhBxg9BHjG6PCm4ctqVkSJkcOm0qz+xfpbRptXkPlGv3T+YIAZbIYa2AMYHnC4eMEQLGNwSP8ClpBj+uOXgc1Up21akZDGmQzyLB9YJbjvSjktH2r27f+HxAwxQGyKQH2ovbMeB1bjLtONuZaefbDEofsPKxXtq3AoxfgS6esDoMqngaqqD0jkFXDq47s8pnBliVp9Hy8n7WbB6XCQGcIHACi60BS3+oMJlo0UbmmxNcYBLKQ78SYXB56io7QILXE5x4H3KoXXSdrwUl46XSr9f9MLjBm0pDnA5xYEn6RnHDWwHXe3qTsWYlDeWla2J331+4T4asYILky2Dj99xcNlwoVZw8a7KdaNFG8CuHoQq5VPDpZNQ3C8cnw9clqv5InifjBaqY02gIuygokeKT6B5wUiRHikeKSZIQdpodeVi0Eqsq3QxKPXLYUPHuio5GGB5vlFKwoC9Bzm4TtpWdWhxVQf7KeCFxx8pa0NE8cIE4Ul6pvFH2wEXaQdc2WrcS5bED7iX65thK6j4Med6kaKNUPOKx1gOIvGix0h89oLzg8qnxWRlEnBE2oAjbwtP8+L+R++2XDBSuEeKR4oRUoRHikeKEVK0kWnO2uKNvHQtpT/uM3Rsi1f2oIKyTop7ULFfLhhcJ7zNoha3oEI/97vweCNvW9MrJUPz5wrOPd5oOuJi7QkDb0m8c7aHijY2LVvDSNIvPJ4tVpL7yWqkRrTZygQo2nijbJvvST/fuw6YUA8TD5N2mDAPEw+TdphwDxMPk3aYCA8TD5N2mGgD0bI1EC1LgWh/fnTooKcsB6Jh+VymhH7Hy4F10hY+kj58dF2BaNkWiJalQLRHxJkGoq2GW6KNQnsz4t2yDU50IWhCKjgp5exdv5Fz330+pLM7PT2ZjecmSCF2SGkBil8PvVig6KLQpPXicVK6eNzP9IaeVRBCW1Ya12/kZnrezA+tE9py58X6hZxKfCKKy57pESLahljhE99eUoo10/GWa8fbynZS2GJIfAj+Yj0zYYUUP+JcLVB0izWEsTZ3kTF/vvFckbJIHqZBlIyiaWB02R+FWqy0hKcJ437991qQgjxSPFKMkIK1SJFtISQm/am1w4YrGGk5tUYY8afWDqsT3pKTff2CX+W7nhASawshMeFPrV1ECMl6xNUu2nhL4p2zPVR0xwdgy35fiE7eiS9qK1PKVlX3wepDrZp0VrdlZRzCS+qROoMHjQxeJmQLzlRsEb6VP98qtCaqU2fz1eg/ycIkrEV18U9Y9mBLmQBh0X+F4kKgeyK6YbrEyLCNQ2ewXe2cdaMN8bXt/CnqBrErMPkEtfnZ3ub3wu7MBLXacKNouXSqtJhOzhi2ZtGCymmP8lbP0uofvPQOacn3SuRFjTm2sYtFMHuv5gwfkuhXu/hF84eHGfaMTId2r+t1AeOEtKKLUVSvaSjZr/ItDdAb9OvqEEr0vKXFCR6C3qCfg0GfmmRaYrqYVQUYsAUZwFt0R2rhNmq5bL6ekFZ0u7/aLjMr3WXmvR9XWuG6AFllgaZ8j0lpgQYT7/1cl/fDW3b3lpIKQ+69n/OYzhpaD2hjPTDTWw9+bWSBLWxhl8CWRowHJ4tqXYj3yizeaSmGeHNjYW5Qm7lB3tycAqqpFar1LjgBV4dqoUe1vGhUhyeLal1srO0uoZIOfWjMpWJ025UqlwyWFYN9HGYwxegCZBCIFvdm/UbueAq4gi0xbSnHIPB7YnqBF1EwCicmOb+ELhZQySdYDpyV8glevHNe5TPFLXzmF+3IfJi8/3BoX8YC3MitbfZRAafawVbaoS3K8XuwnSqH+HHBYlyAuOXI6/qN3OSI+HHheODWxW7sdYmRNz0utaPbCCLb9ueU7pA4Z910ND2YtsBVXLTpUdg6YcsjrCxPmyalNzwulaMN5UDackoEQnpdx0SEbEknKOTpZ4p1a4tZG4GZPyhyhjtrzG2IhFobcmX4ODXlaONBbYNvaQKHfFoL87QW68uQ3WW1WMtrSWqxKXQ2X9wH08l/klEQx4vEKK+F1IU/UMs6KEI+Od0AQNGtKMGW8wEIepW4U0n3Ba3DE9kqQQ0i2gw1Pstxd9z4GUWnc4pAn4imdD8K8mn+exm2c5vPHN6ccps8GlCfRwP7VKzDmtPq/UpEbz58qj4H5qOR9J/Ph+baU59+TPIT5Q1SEIA22VEql0PI098xfFEDAmwbEKAfEA43IHw5lwEBAd1eLT9r8yOkDyucFUBhC0ChB+hlhRXKVXh8UCa+VAFVrcfF7OZjMH083xAFAlb5+iohipJH6i898B6p90hPkebaBJB+fPMhih1StInlUItrSJG/qup6oCJtoCK1SPEXnV4yUqAuAx/CeqSgMzgL5JHiCim6TYeItiCllEETeqQMvpcMtVz+g8jpnwo+881k4PfTpLIutIAraVdLqQEwOP0cxd7qu4KKbt8hrkw6SuuiuORK+r3mlwwV4beo+rWks11LqhizyriHTj/DlV9Mupg9qghKl0Ovt6cXPPQiYAMVb9iuGSo+jOORYoYU7dlR1mJUEPNRguuBij+d6Kd+5zv1Q6LNmJUOfGGPUD/1G9Kecht7SqDWnlI/9A5rTyvmozwXL5sPHwYfcu9fSrPzYbouaO7HJe9k76GCgR8UzmdQwKTFycbEbwj3g0I903WHkXHLtp4yrvy2nkseE3TRXNpyPQ3lp58JUDPNDyerT5Nl4iZP40aYJlXjtrjNf0ef5wsTBekOHNOWuyGo8AoaXEG6KDerhC5LDjgreVXsrDVkdtKNtSTDoOys00d36RPWknOVlfKdg7Mnsm0Ib0tKq/Bd/UcnaEN0yx+ssp+25LAxcNbXGjjhS3lyVCIMEhdCmOacWinURl9OG+a6qPT1mcATVJAumEhacraTs76rMoncqCaJNFpRhSTRKJ4/hiZXqiKiC9gR0nL3GCGnf7bbSCFGIwLhLaMk4Wd9KXMRny2DwYOTYcAplKGHsofyZUBZFzKr6K5FdciPkr31gW3yHO3upGjIc4S9QnorhLpUiPQK6a0Q5lAhmHqF9FYId6gQSrxCeitE2iiESq1CGPAK6asQCl0qhHmF9FYIsjJZUK8QHxzqrxBsczUB1Gdexn4e0l8hxKVChFdIb4VQhwoh3svqrxBmk6q0vAG1lKuUei+rv0K4jUIw0isEeoX0VoiwMllYa7LgZYfJqxmzqT65sbjgMPli9PnkAuVUurQufsrQWyEM2ChEzyYf5HCgD12Qg7Vsvmbcb7cwUkcQxya60E2nGW0Zahi9kBi52e470bYjUVzPAvVvhxp3DXFMPI49ji8Ax7rgTUVxLXrz0c2eytAFbjjQOyoceEfFpS6EjYEvhwhKBv58t7sYGXgOWww8h34n3bFwLD2OPY7PH8dcF1ThLfevlfXmHZWeytBFVHjLbUS8eMII+p2HPZWBbJRBtcrwXmNPXejCApy0jLac+E3STrVBbbQhtcqAftm1pzK4d0SNHdFyd+zucsq/kAsgQu+IHgzHPjDgcXwJONYFBiqKQy2K8zOqftoQ0EYbFceRnn5+0bPShnZKVUkjXPYcxVmn0Dg9bRAbbWCi14Y/V9dTG8xGGy3U8NvveypDN6kSoOWEowAX5H2dgjaEjTYw02qDeEPVUxvSihtQrw1/trGfNqRu/Ua0LbwJ6KcbTrUBXWrDj+I9tYEcasOfoOurDd0WZdF2f4NA/vicU20QG22UT7cI5M/OOdUGtbJUWGupLvzgXAWc5V3gJXD6g3MHRTJzaVf8vome2uA22tDzyB+Z66sMob3AquUAI0QlK+9nB03qmD+0awMD/XVipE0bxG/wcqgMpFVGJXMAKmsDXNPBL98hlQ6h+vURiOgF7VS2vXwkY6Hd1SN1n5yAmcBWZgJzPSsIvzJWwDZa+IMXB4My8VD2UL4MKFMtlK9qaD4BbTBvWCwMC2nbPrB+I+dK82szLP/zJNeBFUDJlokylpczUZ6NHlRnTT6PZsmntH1p98Dfj0d17qnuqX4ZPoQ+NlrJdAPLUC5ugITo2qAs9VAml+wOL08LytJD2UP5IqAMtWskFc2hNs35bSL91KFdJSEty7nrF/yJDWfawF4bJ6QNbTyV4DZt4AvaM3QC2tCGBEnb4nr5wlSvjX7aYF4bJ6QNbdSG0Fanil6QO3wC6hBeHaekDmmlDor06qDereqlDgTs1NHCDuYzKPRTB7IzVi3sYJ4d/dShn3SwlrOw6zdyY4f02xavatsi4W2uN7+gPd9Xu20RMSur3TKGQnllpIBtrGCXfMDrtJDMPZI9ki8Cyfpp/1UNzCegDe1tCmUWiVLuz9PP75NJ/nb+uHr6q/h2/rD6Nn3lW/Qdff7dd8/Zt2/ffUsQFwGJGKIReBpOZiXtZT/NklWqwAfVmsXuyWjzZKRE3i4eZ2lbl00gyItJcXCvVB28T5ad0bAVuNX5VmARFk1v3S5TvW1+G63moyk0AAvWJVmhLcQ9/dt8PFZcYgV5rHisGGIFe6x4rBhihXiseKwYYkV/PqocJMblmGgxZE88XDrDxWjaTlrSCxV3QxDs9TGsPmDb3q3SvVd+/tfPntqG6ZdfllEwndoF6us/Mjty1pYop5gnR3qC9sND3aE38PvJDrbaCLU3Jd41K6BFGwVuCzxCdm5bv3JKU7+tkmXatFnaPauncaJ4roxuEo821tmJLtVvhXJua8ppVLHJx+rZNHmvHo3SXw2UTrR7mlomb6UsbNyr/CxUDr3Kr03lyKv82lSOvcqvTeXEq/zaVK4Lp1ayTZXDqaVsU5RcqtLNYmuw5T5KeHZXkgzZXYi1GJTihJDTS7Yopx4nRC0nsFFxYUWIS1aWkyDeCY4Fumhfha2IaelKvANwHkoXNkqnXG+jsVf6WShdWin9isfly9E51QVqy6N76WxdcXCHLW5+8Liav09m+W5ft2OkOjNZjIMoefpOte/5VgfLZDX6GEwfk6eMjLkgKIRAJJxxwCTiIReIgyDiOOJCRpSKiBKCYYgxlQkhBCYMJxEKBBN2/nrlBB3Q7i06gxMWOqQXfturouqFflAFTlP3cfvyze7lm/HjLEq7s8vRAx3CGypnTpGm1uWB5lba7Q62JuzTBVBxy3V9xYVUIjz9PP08/azoRyzox3Tsa0tj69nn2efZV2Kfds+u3vWEVjkMKuwLFu9HD4t5qpv54inFYxgwiCWlOMRR+g+lPIoII3GEkzEBCIpIucp0HMVYJsmY0hgzIMcAMsHifgxDeoYhfm0MUxOXFCq5sGYQxwulqj94gtkRjDkjGO5FMEECRCgkERxHhEcSC0BpJEMRUkoDNaolUOIIjxOSEjHAWEJOBMEokJAx0XMIw/qzIWe+pcwJwTJEeXpZ0otbhE7KaaKQFQY9v06VX0Zd1naxFu1nbM3nEoRLEAcBgigcJyJQzovqURRhrp6OQ8kkDWmiPJswDjBX3cwSHgXjOAQBgVS97OcSh51LtKzcjkZbW1674ustvmuLL20cKqb1qIaLlqtBgHI0ljHCQRwlMaSBCGg4xmOkxggWjEEEIyABRDCA4yCWEFGOaYAJYRKh0JN82NGgkii9PAMsJUo/yQ1Bp3pEptueo7JHA3XZb/z47Mfnwjh7lP1ZPi451CjPbJbEqW5ah7gf5K90kMct83+7Id4PKX7Ktx4MdqVtY+J+RDjAiKA72khaTkMQq/vZPNP9QrGnX4l+Nknj9LFVSjz9PP08/azoZ7NLCur9XOC3SV3phKiS6IVoY2zI22lvp40mRLkVsFHW035KdIhBgVoEyXw83XPd088p/XR7j/wCo19g9AbxLL1kv4nEA6WTRdEfzR0u6DwOAQvjMUvEOJARH4+5goKMOUQxkYRDFoJQGY4QBZwhJng0DjmKJY4DwIIQSY+T892x4G4S57SUfeMeH5TfVGqaavDjYnaTobc19413Q1vcUGGxIRJrxzIK/VjmnR4PFA8U7/R4nBzX6VkEs/fJSHVM9OvAjo/DkrzTYuq0SGcpj7yJ8SbGs8+KfdwnHPPs8+xzyL7pJFwEiy/ZWdCRFRV99jHPRc/F0+CiT0XmqeipeBJU9HnJfF4yn5fsUGzzScp8kjKfsuYwXPMZyzzZzitjGZVRzGA0jmkQJzQmGGAWBEiKWMZJGCZqCgIkwUySUHk8LIBxkqBYwChBArFg7KccPmOZN/8b82+TvgxJna9FhgsygCAgguFExIFglIlxHIpIMC4oZ0jEFEacqs9BIGlAxgTHjIfjGHPAWUQoZp7xww4NgrWMDYJZxaP86YKLOV3gB2ufvsynLzulIV+4y2UG/Yjvc5nVHkoqrj9lFwH68cWPL+1H96fBcjn6ECw/+IHh4APDWaQ084T3C85XwMWzyG/muei5eAVc9MnOPBcvJ9mZN9o+2ZkfIdyOEGeR+cwT33trV8BF3YYmv1DpFyq9dbyIjCB+M4oHis8I4nHi06D5NGgn75Pa5EQj2oGNET+weQ/IA8UDxXtAHic+J5qPqh3Gg/EJ0ry98QHuU6CiPN1sae+PtBsBt1EReyp6KjZS8b0N+044QZqnn6ffpdPvdHOiefZ59l06+64zDVrb3Xklhvk0aD4NWleCsVPJxuQZ5rMxGTk7PJbjCPCQgoSycCxoLGCMJGdjDGRMYx4jFiCUCMFlwhFSj0MCuPKIcIS5xN7ZuZRsTN7md7P5NpsDDnz5557mlCYAjseCk0RKBAISywiMqWQYRZTFHEQoEpzGCCIQJojASKAQo5BJGccxhZ7mw44H/oJnv7PZj9B+I6JPwXSio7x0lnWJ+0HeZ12qjQDYDfF+SPGTvs0Z4m1p2ymcHxEGHxEIAKebbskz3a9lXTr90OlmWPL08/S7dPrh002q5Hdy+KRK3k77pEo+qdKhBwVyunmUPNe9T3bp9LPafcS0u49Er91HXAEzhgIESTwGY0UfSegYIsapSGQc8BhKiDFCOIbj8ZiMlYMmmRQgDiOhMNvT78JSSzEi/FH0ttvzivPjfrdwKsqGWIgwCkNVTxoyBAWUQlCYjIMgRgEXMFJwkAkGNMB8HIQUqt6UIMBQksDb2wNnZsLazEyyFxgkI4QDyCBnsfp3HCQCjwkkEYlxgnHCFS5YApIxk2GE8VjEBMoxjGQowVjN1jwYXA6++ZQxy5v52HCL2fqz9bg0UmU9Bqrpk/8kzU62i4K0S93F5DeLxG9js3UehKuzARR4C3HhFsKzypRVum0jfs+f3/PnYxQX4TP7fd0eKP1zeQ2444sKxhmjEgBEeUgCAGMSjVEQjSUPgWBAcqrm2mosHwOG1EwdxHEwZjDAFDAc+km4z2bqs5merRsKgcXkDmvHMgr9WOadHg8UDxTv9Hic+ASmfjl7MKcF2jgtYMCQtF/OPrPxBmsHHOoHHD/gdFnpVEYhXVn0i5CDmXzkKjeu9yo9yb3DZck+fLKZqYM4PsqRDtbGPubZ59nXyL4dbE3YR083M7Wnn6ffpdOPn2xmas8+z75LZ5+z3ae432EFQQJEKCQRHEeERxILQGkkQxFSSgNFugRKHOFxQtL8ugHG8v9n722628iN7+GvkpPNb6URqvC+nVk/q2TPg9exztiW/5KccZKT7/6Aku0RmzaaEJvdaHblTMZjiRKbwK2LQr3cAi2M4OgsKGXOtDCsWxhKUqZ+RhTFVRrNy/aiS032RbrUJ7k6kApQBE+RAYRkDTNRWpYCoMlgeEFI+TtnXDofhUgGHXPZOVngIhXTiVyda9GlJsZ/A+Mj9KtK/ZeRu3KJsTJzmR0HUEJKVNEkkQCDc5pFy1y5vBQqMCpxyYyUmhsZmDJMgQ9k5KRKTR0qM3ao0PlMBeWkSt3PKY/dqlLTIU+q1HSkkCo1qVLPeyLwflWpydIpj3Xt5if7VaUm8yPzu3bzU/2qUlMVB6lSE0+TKjWpUs99KOh+VanJ1sknu3bzIwk8SjASIZIEHuWXqDt/vHPwckHn7JnyMatksrNB56yjBRs1YBRWaFCeeWmUxwIoVEaH7DVGy6Njynm0hBOSwCMJvLW6obxjCTw6y0gCj4BCTg85PeT0kAQeOS1/OS0wmSILUQxRDFlfm/Vht3pIDyl8fni8+1faLVVWYMfs0B7Wl5Mdkh2+ssMfAPgUixT9aiSRSZJJbtEkVbe6SWSRZJFbtEg9lZbSmVovMgHjxgvGpMlcSmc0ZzxKlrmS1pqQlTCpvMA5hdn7HFEqbq2PBYnRhPNsjddtTSBpKT2m9/l7dxbZ21vtbZvaZUN7k3V7k6RdRko2ZxraRlXMyNJWpmL2o4tHDDH7cvnQwRiG0ioXmOXJZCZiWVpVrh0SjHOYA1rBnWReRGaiyIkjz4IuHqRnRqdAOQVEi7IZVuszxBxheaFEufBo62KWgRfjQG7AS821EtGXL6MQWirGM886y/KD0oYgk8sMdMiJDJ80zqgFYcYWBDq9qXaY1M769gH61T0jF4AU0OjAoesiaaH1dF5Mp4o2eU0/WT9lqbdokh0rpZFJkklu0SQ7Vk+jWi7SUSMWp2sVKar1dWR0rK1G9k9e3BZNkvTWKNlJJLkhERIqciHIdC1H8iPEzKsaQIghNTZSY+vRXZUtumyietIpoJOOnCOCDEGGnCNCDKm2kWrb4s5Nv/ptRDsUHd+iRfar6fbyqfeXyj/vnt7t3MOD+/e8NQ6IIyaJ2FTlQSa5LZP8EYJPscmOVd3IKMkot2mU/eq6kU2STW7TJjep7IZjJRIDYxOclKZI2W0ag5tO2k2eZXBYTqhiT5FbF72NoRxxQWXBZBSZ8WC8lmilsFrZACYkQOkYd1bkxLwEd57BCVk1OElSiv9XELUrn5hs7e22ZqeKzDwPZTrD1tDaJNF5K4KSoEJxLE3KCVUwjEMW3kULonxubVhWXFirgrfl5MvOOK7OszVV9yQVHW57WyM7e7OdKdbSeFnruxSS7IzsjOzsJ3aGvaiVkvPYeckSG7ngfo8uEe9ui3cvJ0JK95Wz+b2WtToy6bpFK0YWTZ4UWdpPLE2SJ0We1ClLpodg0Icrpg/BAMS61+xWD5dsICIFAyVQQ2ggr/rIqy7v++nfra41ue/9OxVV5ZJG+9KM2JaPsO1hURAgsS2xbXp5ITXQnsVkpoXJxi4RhphMjDDZoSAwULaZmOwrkz37ZMRmZ7FZrQwExmquDk0T6YJPYVWytJ9Ymm4apKar5cRyjhJ/ETSzWivngnUyGM9Qcp0xgUpBRkgh8xw9xBCKrSbIPjGFKoIIwXOhqMSfJqmRuOCM4oI/tGKfMzc2Fbs1HrXmgQWniyV7DZo5k8AnlTLn2qNN6LKQ3KdyqvIgBfIoyIpplBo1FU3oBvQ7S428ABqmRmcOyf7TNLXOjowJx6kh2T/ZPxnlBEbZ8UA1Mkoyym0aZccj1UhGhWaqEZHT7YqGqnV3anQ8VY0YgFy5bRolzVWj1CfR5KYGq1HRC2Gm6+EhP4TMrDL+BBkarUaj1fp0WU2L1JeuZQSQ2rU2NTSt6vgoJMeHHB9yfAgyNDaNulKm9ln6HZlGnEOh723a5GqGpj0+PXze14UuUMsgx0xTNk3FIdPctGm+BvIpFrqeEWpkomSimzTR1QxUIwslC92khW5zvNrQ5p5rU35uc5KR8AiNV5vU7rY5ZW1odxLrdmfJ7kj2dCqT62XYWkLOJJqAaAVmVTxIno2RyBzzBoKxMXlUTPKC2WBE8joxw8pBCE5icOk8k1O6anKajjrKZkxhbraXmWtkbmRuGzC3jY5eI4+y89FrRL80eo0uMZPRfNMENmGqlj1GhmTZ5FiRxaluZh6SwZHBbcDgNN1k6CbT3ehDIl8afUhooNGHdH1es29RzQE2mpkRRLqzTkAk0qUJiERorwlNslqWtXGqH1J0gqITZHAjBofdzOojgyOD24DBiYZKWS5qpbKXHrxw0ETinRcJteMyZ0zaYLAaALRTThebtDJ4SDGxvA8wFhtlQno0LuTsrdBOUhMJTe4j+crl5CsPjFlCRCl09Am9Y5pblY3KySihvEzgciirnLXnxZ615TpZ5ZLRGMHY8hokY6YBftS9Nr1vINcyx49cAxrnRwcRzZ2gqX5dniNquuF+ltiA2IBMdHITNasZ9UcmSia6SRO1qxn8R3I/NP+P2J2uYzQGsM+jBNhqpgESH5C3t0kTRZoNSMlVIs3tTcqhIhuCzhoH5hwgZ94ZFoQcGhhIAwO7dmd5J3MDqap7Xd6QrHpDypI3RN4QeUOEHJoiSP0yszgyYi3DBImBKHK+SQutVa0PNY1ATqpp9Ph0/+AKQf/LPdw+/Xlffs3n/Ud8vN0fGk02ZIdRwcH8JnvehLWTHvSE8+hTcXgfHtPH9pvyN0PbY+fbf//y+lF++o1f9tW8pwChVnZqRmrazMH6WtkNECSrAUHyhYDwkB672/9aTePRssrasmp9qWXtY6Vsw0ohVFfKXPVKITQcLoLXDhdpFuOUIzE3FFU1N24pf3x6/vhlm84TjccR0fgLn/fTXX3fcJPtw9CxgRKHJZOHlAh6OUM/kiwXdVxpch++I4C3KFMvZrB9rJVssJYlrjJvEryd63IYU2g0axhRHjvMkqDq5bT4yXVxxZdMrOrXk59FftZEZDTXZWI7ZHQB17W90qR3N1g3jeeoe5dLOsIwZvgDlApyhL9jwLRoMi5l/X0slW3Ri+Wyql+pgDzhUbsePikfhMdhjozOlbvCD8V1PAH8vEksWfEq+DV5XlcM/tVFDU81AWgxAcOqJmCX4/9jZMk6sthC7tLdx5i+dIeCqoh1N0bbx1qJFouBusfE+WIWwyUfqSh4eUXnVU9X1ZQJwyIPPii/h8MqDy17OR8nFEztw8plCyMehRH0DHfItyFKmjqiljoXv/2e/b21OzBUQ+bd2Gwfa1WLvdCZQ2cOuSzXBR87Bh97/S7LjP26MzB4NSRsx/yJwXaLqz7tBLSs1WKm0cdacfIMiNov4xkgjMgZ4WFWT+BS15zrPz+E6LCdaaWpitPAf6TlNdDSxcOiLSH66r1qR3/PSUUhO2y4uGr485HUDx46DnKpENc1VGGdagRNEbOj8KnpJUmCw3yOGGJrUAGzFLXudq9+0+4pffjEusOEbrkrHWHCdoMJOYYJ2SsmoDtM1KLFqOqVenioUar4dV+fa2EZHGtZwUPzUUiVeqPRZhxxgThSpd654P/z4e4pnYB+yVrQr0QV/dpSqd71on91pXon20At2MxZ/bDkh50NyJbL4uHIfW2IrG2U6p2MglqtXj9W28liiZZjA+pOExfL2YyGkQEKL6+gCQrzpUc4H2Hcw7CTYVSrdykrly2UOIwsDChxwWK9I0QNs1gDSAm+pWK9k9FQiz0eLfFQRmuwxJe5KnS0WLplsZZiuE7WqjrPUozZrphJuKaPxVLQslhHVig2ZYUKWxbLVtfq2q1QXUV5QR8XtTfW1qhqbc10seX2VZUjpnKYmQF7lRHbldRTnGzwV1FQsWaDPwqnw4VO5+0Y/KalfE62/OpNrpet72Stahc5cdQFOJi+appCIG+cNDDBoh2sk4v/csUmvq3VKYtUu8GJIaBwUEYpZFNe4sxVOq1Mj4/1m/MLlc00U7U4irYPqsmFbToAJwDh+gKnZ+Jfsxb8izr+lekQ/7yOfwWE/3XXlZxrAdBiAZpVLcDIDi3gSKaKX0imaosW0E9tybl2UIs4CjXiLh4WXoJa3gyOsDU8CIbYYjNh69LVJefioNaU2aHBLrRKtRCUPBpZMMj8yIFEs73WVVItq6RYdZUu7F0uuErVNgi6z13ylDiKbEI9lTFdxVfz8h7Zi6yai2bXfFteuD/6XIs3LRZPN9iLWny/ycv1W/xVZTHPNXrbYvR0ab+o0febwFy/0V9nJvNM6zfsusIrRzAdzoUa4BQthVeecQAtV+KhbstWAgcGW1ZJwjYDB4Y3rdLS58hCi1SN1MHIIh26BSCvdZGq6ixDph+6pofW1lrGnr6UZ/zo3t8OHvtWC0iOSx0V58ozn6L2mQmNAqULkXGAKAU3hnvDePnTGJYUc8iRCRZ0m1e7wkwfjqhhnDcOrDh0u08P93sE3j/cohRMhxgYWJaVU2X1TXBeZR2tdVpbbo0ve8OUD14oEYJOGJMVIgWZRW7bDDWWu1FNrROTORfvimvxfu9b7ENJeyN65fbGu5wf/28SR7c8wOPTw+fw9O1nv9nI3/58cJ8+pYe/5fuHKdyYr7/u8fjvbyER3UAiQ88GzhtaeQhWqUUMSWB2hT2SdN57C1GpJLWzhS2CYdpYwYCpZCMEVAaUlcqYzENCcx5YwVTBOhahX4I50NSoQyJRRy/Usdt9+/ndfpWff3JXHveIQ0bf7/mnuuOQqvzT0NCqoOUE2tlA2xGAbAOAhvW8Z8qM0CHU9MzDEnQcJGLMlLtB9nyZQ+hH7us6jx4L5L6ulDmGPX7mvIgEMQe5r2/kkFrcuu2800Co3aD/annDKQS1Q0iedwgxCN5JzEaCtFaVIyhqppmPyUDO3KKByKwqX0ThpDQpl9erBDmiYBjyedFXVQ2+IiyGn/vcHWIExe7XF7vnIxvDm7T76DA4s2dqSKyM1ewEQE5lKBmyAZF9AAjZ7j19LwQylkHrKFTMGBVIxQrPJp5DYtkJ550FSACO+aug2ZZ8x5mpFcrg1I4S2eJ82OpRIqayEI9BYnAY0ZkcjLbgrOHMqGg0qCDT/jwJPCq0XFgQEdGobIS3JmcRzrSQNbT8D2/DouoWEnV1Sl21ToeV8klTWcnIkcumwq1VRjgjk+VBG2QgggNRyCPF5ETyKBkybp102ivJTQqR2yBVdi4DSrTn4XYNGgoj7vThzhgkQumTUKp9FCtllKo6bdOdSlBVA92piEdmvFN1RCO2xTEx1VzfeXWVnKFjSWdEnnW2MhZ/Q1kbTILsUKFBw2PSQoHiXAdtBSu8Ur7JbWYo1Xk00n+fyRGL1COY0KyATywyE4sMUn/DdpxxKnn5ic6oRDFGZQMrKRs44pKhyPyAS5q7QIlLluGSKysjUKzaJDjinsjzwn10yzmPU4yucQoyTZyyHk5Z/1WnWGyLvuXi29rRwsmGUBPUIk0oyOYXsvnvcPrv31990nP6Sjht5lKb+bE4Jinffdl9TH/uH3u/sex/yxNFS98jJWcvDq43+W227rVNtS1OGpXBgRM5iah10Cym5EEx5rNEpVXKKliTpNcBXA5aMcEdSoPlxm6RnLYrz5krZhrYhDKzfbIJViuzOSc6oYz5XHzSkuqiHG2vjMKrfqOwxCjrzJ2vk1SATVcoPNlhCCrahDllU1giK+3QOJ2QOyFMzNw665F5bRkYk61SIjksl7egnLExBbk1SpFVrm+WlSZKmYlS/N3Tn3eP6ZropKX1HvQ8sOUcksuI2QhjgveBB5MUjwW2AJZ5oQtrWJmSDdI4QBHK92OSQnKhIbCt0Ymq1jZoopNO6SSF3f2nayKT6iCrkaYD0bSddN25WMtBlUyMIDLp9LqTnp4z6I93/0nXwieiIQ9sa3ngsXpaopNL0YmpFvpZJDrpmk6uhUnkVNoulg7AxStKlodTrbtWsZH6bHWo/8876PXgeqwn+OUVp+ui3L67/1Ce9p175/64Lc8S3qVb7/6T3t/unv/Yff2WYEqDi6C9Kf9Yl5MGnlwUiQlQ0t8+Fn7y919uy3N8/nLz7W9ayGJZKTzc3z/dftvplze4uf/8dPuHubn/9HSzf8kN/ip/+/XX39TNP/55I1AbJ4JCGditvyt2+rPV/fCpfJqH71/Zff3KrvzKXx4+f9x/1se/3vnnv+bDfXmTl1z5Y9OeKF5vGVK8qYVh3VMHpxjO8J1r7k+y8VptkRqZXqEG2bsOWsuP4IS6iqexarvLjw1yMT6UfV4WBaYFBUPSHMCAQ4cwGKoiDGlFLw2D57Fiy4Kglsjvj6bnXyCEFn+I1/0hJTqwkjU+sxgBoph7otKiM0sXsAJssQKlqogy0KEVrOGZV28FFxjiuYAt1Hqf+tujBRZI9DItg6d9i7plKnC0STsZOE8MWdj/t7NBCgyi/M9K6ZM1ad9eGnzKUkhnlGqLQ63RZT4qCKwGCMV5bb+Bg0LmGUYRNVOZ7ZffGuvRuX0zsGfWQISsnLScO5OTsFy7kHh5eWyMCh4TfJXfocOuX17NL0i9HiXuvjbjFCXuhrbe8PTZvf9xbnKK39+qjfRyp7xsWLnxPFBbVJ9fH+Y7QYvuQC741SPPKxW8xgzLXN2orzcFOJhiycWDK76cSDxppRNIH30CbbRB5bQOLFnUxkPIpmwP0wGFiDmHrK7ClDfU8tjIIaYHieDXeJ1VHniNIb65mlCJRDbc6NjIIraDGTiv8Trr/Js1Rkjn6zwlGtl2d2Mbk/AmOc8qZoU66wocdXROCpFQKKHKTaYQSeEOg1lyIQIzzqril0jJUjIMVXLlohNMNClazpg6LyLafynJsTJwXc1TaGKQ7lX3jqttxsNo336mKxqBbgTGKbEysSoweSL988iwXGuNwXjeVsmx9JZ2smhiedVOsvMrUeykjexdrbORHFQHSp0Equ5UOl9vyawNcZSuWlt4SHegzkkM0p8yJ1EIJatO5RDThSInsUh/apzEIpSraiAS24EK5wGNzKnAeQU0cikFTqKR7apvtlGIYB0ob76G66yqm1dAIZdS3SQK2ariZiOBQAdqm3SV6U9pkwhkwyqbjRzCl1fYJArpT12TKGSbypqN7CGWV9UkpHaoqNkIo5o4q7Ij5dH20JPlHZD0UbHTkKX5eamvx7Ku7ve0+5d7uH368/6bcOnjbUzhfdOjajESaNCHFwUBJDJZV4H5cv/wfT9Owb5qwT7WwS+hQ/DzOvibY1cE/p4V01rhr5uon1fhr0yH8Fe8Cn9tCP5XJ5XWagS1qgQ9lgoY6nJ30KZ+hKzhGTBEFltaY/buY0xfFkZBLaXcoa0usEQSWk6LYQ3g4LSwHZwWUo0I2UjV1Ne6iOj+4UI9f/xvuvdfM7Zt5CFH1kTL3o+lWqK6Mbu9hJXVmp+OdmfYiD3YnQtLLy21RLWwuT5qkRmUrOlBk4zs4MSWI2I4Q6Nb/MT+wha2EtFiJctz2BJLVItt0NHX/dFHLsxb93FsTbTakAszfOvPnwpRDN64PM7nh49/e+4E78kVqoWnjnb5yBVSW3CFqsELPuYK8f5cITXmCqneXCFY2Epsi5Usz4ULLJGqitJQvvCSBo1HEdRBph7hPNGCCZdX15PdWjfpE607G9vuN3ST1VXYYu6UIb2oufO6uSskc+8j/9xu8P0kshVvsXhKCl/U4pWoWry2ZPE9pdzb7b6r9L0S15a+H4IURRWlaCl9r5RsygfUs2bQIwo4VlEwQ3hrtLD+ceGkkFJNkZB6vLBPEJj6gYUdgGDhcJiqBo27cwCWWCFLicE1J5RO649ZYT3W88WrZp2m9+HBlLfbE4yuaWv0t8lLrBA0NP4Oxw/zKccP7wfYJrTW6Jgkj4mBRSe49ojgguchxGgNoi//ZoAQTASZUuHnzKxLbbIj+mjo12DvB4MDGU0fvuD0YTPSQWm6n3xyRdOHu9qM654+/Byu2JUX7L5ceOxB66nANzmEeHXQ7wUuooMpxK+feeYxxCtsTZ9Jaf9gU9CgUCYoabWGDMkn77Uszl02kKLkVglgxftjqGRmrriDKUmJEcqmlF1KV2HMG9J1b2UR2cMc4gPEzjuIeI1d/jPp7ROPbFncvZVIVAejiA8QO+8s4jXKJcymuU9MsnGB91Yy0ZPdbQCmOf+4lWi4CFDgqvRe/VDoQhPWMBVy+U+wyfiQbApJm6y9CT6hlZ77cl22xl19+uZ4LnF9XwQjNiGd94szScvQmeF4k8NWcYmUapl1HnE1PAKG+GMFA4lfR9uvI0pviVCIUIhQiFAmIhTDiFCIUIhQiFCmIpSqUF93+9vLqrUM44BaSR4KMvtF9fT/+/dXn3TYrljfSTxPjIB2cpKd/FickpTvvuw+pj/3j73fVfa/hfmhJVFOlR0dBqSr4WicxlebdwgKVdusLBptWpLkVNbRIYlgtfCWc2IRqrW5PI00pcepqqPL5pWqiygsEQmV2szCJS0Jcqrp6JJLJLvMgHriEiq0OZlHWvLiQx2miwCWc0guI2YjjAneBx5MUjwWwAJY5oW2MVmZkg3SOEARyvdjkkJyoSGwrbGIqk5E18QiPbJICrv7T9fCIbaWChcjzUiH0ogI5Iks0YpU5RAjiEP6nYn+4xb9NdIINqRybS2VC4pYZAEWMVVhD4vEIv2yyFUQyGRKHJZOvGVrQRYGUk2jw/CRW7HhTSnqTrTQ8v39KSujWlZG1hcGr2lhdMMdSNauQGDeyj0vwoK35YFvpfQQhItBe8mDdCaKwPneRXEsOSekEohqz0vSupgtz+WbMkgFlmuTRRPzGKwzjzksz7JzSwEdCC4eyQHVys5GAD0YMUQbN8fGzVJlVrZiV/yj+5h2Lw9xCgXYqdyPMwUJ0XKuyhWkIAYw5JAROQjHIQH3+x6AZKWT3nj0Ggyiw+x9zNKV7zht5XkYgjqIUC6Kor3W9YXrvt+AHc1qIbThCqOqVb8KQ+C56K0XRnSlAZo0/ulYmORYGO0eefmp3fNP1dUnV0EY2FLXbKp5O04AvThpsBG9MmDn6UPTnlyANMbqhk68YfRAF9XQWOOJRoQx7w21B/zUImJHg5oGlxvZNK+a0DPBcYMjM8QBKXSxAh919/wJ13zu1NrvRqSgBxgll2h7p47aorR+77CZTVn/pMxL2YdaSqq3tVx4rWwHar97Hp5V5Hd9/tvwgbWuRXzfXlmz3wpIJnNmIWvEQlxGpeACyLIz0gZrmBVaxpy1DntRVMZ9SNw7HTnLShgF18BtG+s1Oo0soCUnMQwxDvaRE0LXX0VzImxwugE3Z8GGZwxaOy+SNUplEHuk+OLRBxRWi+LG6ZCMZswbrlnSGXwApqRxnEcl2LXHCObR2djvxKx1cNd/xPSurnEiT/DJRti8fRDWMzoxacsRmY5MWwfl2lYudbnc8ZjMkGL2QYJgUoBH4z3yLJxLpjirhS+8sBvjiUtJaRBRbE9A40SmEA2OaLU25u3tZdv2Q7uSyiCioEvrz7lCdnL7ABVtwlxowgJkpR0apxNyJ4SJmVtnC0V4bRkYk61SIjlUTAfljI0pyI2RxaW0MIgsNqeAcSJRqA6EL57DFHPqXayfKC4ld0FEsTGRixNpQrcU5vOqLLWky8fqFS2IJranY3EiU5gGpuDVhK4QxBSrV60gptiUVsWJJGGXl6ggYK4NNVirxNBH460GE7kOj5bWC9Lj0/2D+z3t/uUebotD/+m+rMTt3YdP79vGhi3wkDGFtoe09Yz44exmVFMv5F/IfHr49zMm7/clug936V/pGZ/7F9+Fu6dX06yqGZ7WvNAbQf7Lt0/zwy/+4mJ8OAXj0IBxwWvwaS72vQzG53jILWB8LDnxhqzGskivFUiZkRSFOc8JmAbpdqQkwJ43WK0BRRVX8bGb/RYNPTAL2OOyi1PL1+Gws5APs/uHrYUKybn5aUm5Gq7lIOP2XVXkjbIVW/Vv/ny4e0qnIF21IF2JKtK1JRfnupC+Gi/nZLxXMydd7NHCC2RbCAHqRx9fxhPkeqxS9+UVp7ea3767/5BuH9+5d+6P2/IsBdi33v0nvb/dPf+x+/otwZQGF0F7U/6xLicNPLkoEhOgpL99LObi77/cluf4/OXm29+0kLfpSwoP9/dPt9/27uUNbu4/P93+YW7uPz3d7F9yg7/K33799Td1849/3gjUxomgUAZ26+/KQv4sDPXhU/k0D9+/svv6lV35lb88fP64/6yPf73zz3/Nh/vyJi+V3o9t/KfrPiUesnTzuPOL0F+tpr2xEH5Zq+ashfaGugwD2pve4X8bgjhUIST4Aje8b79jf9HoZ/drUayjZZWyuqzTO3kdLBC2LNASzLXw+lRr3c2YXR6Gh4S+wgVSLQt0ZGHm+i1MtyyQra7PVVqY7SyZtsIL7mmFFnYkegf2AtG79tUcCcHi4VOCvbq42PDNP38qNjN460NN1C4DbIJ1lkHcjGEPg5UDw57mlN2GYV8gDNhu3r2GFEX1dtXDdi+8PrXLlT0SFRqQi23TbJlHx5IdjbIeigSypiL7RcKLh0v1vADfInwpNOpIj00fennFqwXRM5XTnc5xP+8LaWolmWK4z/Nnev7lp5hXTbHCypFM/iCBJ3oQJeejquS8KR45GZh+7sIuCoCqmqkaAYAiAKweALXYCrAj1eWhgiI7PGK16REDw0vH0YkCS2Pgw6IYqMWP7Fg9l10BCfAREuCLk8D/WxIAEqokwEZ01RgjCKweAlXtsh599PmXSLbcRWX1Koo9XEXtSEHOIOg1TUFOc9AL2Miw0ZcXnF6dvcD9cPlakDNgr1pgj3XcS+gQ931mca4B9z0UO5+BfN1E+LyKfGU6RH6faY5rQH4/xc9n4N+0+YQjt2zowec5gtaRDu8QW3zpe8EkjV9noMASCggFilVR0B9hz79C1SkBlPbrPKRwWpvwGjPOTI4Z52EiD+S15lfb60a6yNKqemyuv+2df4XEFsfqWairENnDjwbqaufqtYFlQkHtN0tW/fXEtx6DxOAwojM5GG3BWcOZUdFoUEGm/fi4wKNCy4UFERGNykZ4a3IWwZ93gq0gTj0sdK2q8Es5yZYwa1xQHLUui5xB6/0A1QjFZfImShY9CqFUEKgsgubKasw8Cea9BBuvwow3NN+njT/UZGN+ANgEaLXKCGdksjxogwxEcCAKWaSYnEgeJUPGrZNOeyW5SSFyG6TKzmVAifY8AllDxH/Eax9I6SIxCA3+uSyF6A6m1r5C66zDa1eZOTmKco7wOnkhNBPo8jRiJpv4AWwKHlEmeEjGC1FuNIVIHBZ+8C4VdhHSRvAcvOfRg0tKR5ZljsIYzYWCwj0hXX8w7igKXN+V5n444pGtTwFpY5Bq6W93W9nFmulatSyvBxv5eTqiZN1TKp//9++vPunIeAuozsGhfVxgH8tdsJDy3Zfdx/Tn/rH3e8r+tygztAyApjDmVgbGv9qRWadUUGB5Xc6YbsliUgxzM3PkiT8orHwagTRltimEuZ0J80QhFFU+mUXU35cfOP8KsLPOnb8CDrnU4HnikM0OoG/jj5bkNiVA1HYm0hODUE7qBP6oZbXHGrcGfUZA7HE1g+qJPbY7sL6JQAxrSNDaWoIWyPu4nvH1xB+bHGPfRh2w/DR7wml/U+3bQFSdCNRSWAKtIPq2iruyDukhu5Bu/79///Ztob/cP5Rf/Hn/rcdbJbI2Aj0wk7TSrJw92pdn18wFve8ksUFKE6QQHDzn0iYhBCTFU0BnlGnjeGBjOhFw2P+OOHu34teX/O372v0tf/4Y9p/oTK34v7bgJ1/+5fXOnIIw0eDhiGoNmjAEMYLYDyCmGiCmagjjmhBGCPsBwvRUdbQSz2raL/6SMNwloYWRjGmmU7mH+ZCjgXIpE5oDiJil9wIw+MyMct7rXPDmpcz+TBAd9XcNQMTFYn37fylw3H2M6cuuvGD35f96w1FLvBBq4ULC0aZxVOuFkHUcScIR4egrjmwt/DgcqYGDYPnhSA3BCEiXDT7KkXoWeV4NZ4Mr63TZIydTVEpLDRC5Ra4Ez0mH8oPRJOPAKOl8FslE5YVz6E320YqcEDfoyo5EJXe7b8Txw8ToWukFJyvPuuTNzOnkHQJ6axikEBNGC4kZ6TAlBK2YR6mCjr5c1bIs2EatneXGZs6UYuuG80lPLfhYMntwkTYdSkI+/+ab+89Pt3+Ym/tPTzf7l9zgr/K3X3/9Td384583ArVxIiiUgd36u4+3P13bD5/Kp3n4/pXd16/syq/85eHzx/1nffyZGOXrX7PXo/zaGfLYNmBzZBq5otOg99NgkaEM6w3CWN6Qq5C1XAXSYbLkYcJHLhZtRwlRV0+O7PfFdzE+FKq4DuYRLWV+vBa3E4LQTBmGH0BMtUT0qjd/SRAjiP0IYk1JrPqZzChPuqADNYzMgqje/ZD4YEUO1Ks44O75s16HC2UaLm8Uy6DzrRlihtWSWRTApAAmGf10YqCUrOl3s9rqtuFye5U9Uz5mlUx2NuicddkrGzVgFFZo2Ot3S6M8Oq1QmWJtXpft5NEx5Xyj2j9lBs7wE+dJJbQPtZp0sPQFXI6WHhxe5czLRm2IM1vVjWiz6ICjA275A25Ms2q6Q27Cd+rngJquv4/MiKIuP0IY77SDNN/fz51LwFFg4ZwDxjsDVtmQU/Ake+0XJUCtE1C60+5QwtM68dQ0yaoqcInTE5TV6JwQOjshmQSWEvgci5MbpHVeYWZKSMV4tG4vO8pT9BGtUVFw55hQ6wYU1bJTKuhNNAysWIbnzGQQodgMj8wCi8Epm7T0yRaaZtGU60gxrELNQSJzEmLZQx6N3iANUwl7w5FhO61cpxOj/4J14qft1qmfRi/AJitP55KwS1ccwF6L0QlQ6wQU77X0nIIw/Veck9FvudD8RIYRvdaXE3rXCSjVAChUtUt7cx7qUBpJBxciGOZSzKygSFghM6DS0iQbnY5ggXNEHiHnLHI5x6yyBU4+mAj63OMJR8CDtsPqraouu+TnSVWF4LkxPnhfcCu9QjBgjZGQsnMRnTYQyo7YxJl0XGfnJbicLHMcrHAbcBdgTF7rvFmBh/thlRCagQKtYvl3dMnwLArPisgT50mXrVGJpaysD5znwrJgMwTrLcu2cejaGsj1dQnt49/u84kKVC8/tnv+sV15h8/u/Y+nbEz6RtXQ7mEx8EN6/L9ODgczlfa+ZIT9y2N/cbxYak2jfCTdFy7ZkUaVFt3tUVP55wXSZtIorZS0jKHUXjgGUYSMLmSrPTOKWS2LQ14OhLJZWNx5FqPLChyXTHHvKK1P/Wfz9p+d5k4ga2k7qxKjkESMHcQraI/o8KLDi3rLVhAYR5js8Dkz+EGB8XYS41UWk8RiKxgVcBioLSaxD4yuLoaKk7Wm0uFLCduCp1qNEYAesrcYLrE+dLpJdYlEKZqeGlm9kh+QNXk/kxnxOqI5Z81D/koaz7+2sYEdRRNviBHekJbEbIg3NsYbPVykF+MPWeUPM7K5zy945dmZHhGJtg5JrmaC5E9xcdzGsxgeVBMejqMIh4AQukdAcFMHhLBLA+L1WLwOQKEJFASKISgMgYJAMQRFrVSsR19xqYXi1TwEwthCHV6CQF7vQmFD8129tf3MIc85CZvQWqNjkjwmBhad4NojgguehxCjNYg+7q+LCPs0jUzJ5ZSZdan1NrhKAh0pPTyzMuBwPwIHhcwzjCJqpjKTAoM11qNzMTDwzBqIkJWTlnNn9vvHdbm08fLyaFuF73VdbGsYSUG+usYSfdZ2MAjeScxGgrRWeW/LMmvmYzKQM7dYNoNZVb6IwklpUi6vVwlyRMEw5FVvR23Y9cmdBd97Gk9qXzjj9y82pPvlv/98cJ8+FfY//vvbTggxWTuDIQu4pAV0hRo52XR31RqCTl/KQ35072+PHvzWY5AYHEYsB1Yw2oKzhjOjotGggkwuRBZ4VGi5sCAiolHZCG9NziL4MzG0xrziUU7j0KbldJsjuUk6KKG5jMi1NuX/yjr/3BwZAhbD9rm8IBUHRBojpE7BMxEzSAmRqysx8PKdx6eHz+Hp2ynzbcn+9tUm/5bvH84vjW55m66YRTUwS723VOnpwKsFJMeljorzvSR5itpnJjQKlHtS4QBRCm4M94bx8qcxLCnmkCMTLOgzwbvGzKOubo4xxCz9MstYUm+17KKn655QZ7m7UUfnpBAJhRKq+CmFVgqTGMySCxGYcVYJtFKylAzDgt3ixgQTTYqWM6bOjIesIRU5eGRratvxEv0kQumUUF7fz4sdjCsvHt+jv/1Mh6zSIgnARa2eVSJFWWcurOTVGxAo4pX18MqP83mrj9FZ4hfiF+IX4pfL8ItgxC/EL8QvxC8X4hdoarNYfpu7Wrwm/exaBQ8KYoIFmeA7qP7791ef9azmV9rQJTf0Y3FcUr77svuY/tw/935z2f96oIyW7DwlgPstOasWTkwZ8HbSqAwOnCgeeNQ6aBZT8sV5ZD5LVFqlrII1SXodwOWgFRPcoTQYIay8GpBy86fySlNuns1V9eMwacsRmY5MWwcJ8l70xdvIZIYUsw8SBJMCPBrvkWfhXDJCow/ghd0er2C1kK9Z1JSIZUZi+ZRiWdj08bqYpSUvT4UlHRfJi0nV/olZqOjnfHIx0xUrT3g0goo2YU7ZWICstEPjdELuhDAxc+usR+a1ZWBMtkqJ5FCxvSSnsTE16/dfAbnIuksJRC79kou/e/rz7jFdF7G05OW/7+HFwcs5JJcRc2E+E7wPPJikeCzgBbDMC134w8qUbHhW3RGhfD8mKSQXGgLbHrEorO2NJmLpmFhS2N1/uipakU0znVltpjMCXYYW7ICo0ooRRCsdX4bS03NW/odtxKtllhY5CFvLJYMiYlmOWExVisAiEUv3xHI9nMKnEhCwdCB2UZ/SA6iqqhQoh47W8G6N8hBZcnkO56hHupdfXvEqWg407PGywx4Bj/oihwyFhxXAyq5KuHsBHW4XY3Gaf//onj4/pN3TfZPZVwuXetysxVesmjh91u6tKuHZw8w/u/4Fq8VsiaOJoye6sR1VZg9Nj59Xc/P4dP/gfk+7f7mH26c//zKB25jC+8ZHZWOpCs6aQL/uQ3DhSaGTMZ1iTT40x7oPLU2HVsXrVtWcVSOrOrCqaq1Za4Xa4vYATfagWN0etOzQHhSv2oM2ZA+XnHWy0OiSs6wCq1ahxi4QqiktMI9RsNFTgjVJW8+kQ98TKqpB3R5NefEVq4Yu+FHX1fAOwwd9V/z6V0w1rZgS9RXT6vpXrBrsoRvnhecpHyWzBlmewViJ5u7cKRd4bATG0HgM3ehXcKM3LfZPd+ML2z+v279Csv9eYg/tDNBrEMO2UACFAy5MAUOndEAB2hIF9BVuaSeCfkM3ml1f6AbGRmoMUIuWQjcDVEDTtfoo7bO9QITGphWTcvOBCM3bVmzxk2fxBatFBymwcOnBtGusFwWOY0uNc48xpRjO+UxQj3r3t+eLL1gt6I0jI2xxyhG2nKFjSWdEnnW2MpoUlLXBJMgOFRo0PCYtFCjOddBWMGt8+Sa3maFs7FNapf9+vRNsj+tD6kcIB5pge8H5nZ1txwYm2F5YV/qsI8JucobtCm2gR/QYNpmqJcCbNVl/+glurTLCGZksD9ogAxEcCLQ8xeRE8igZMm6ddNqrfSt1iNwGqbJzuSAA7ZmgWkVd8LC6ZtqD7oRNCinl6OxeZJTrHP3eCXRJYdA6hmL2suxGMsxwFwGCQZWUMTlk0E5Fg/FKLH9LOpdncQ50MOX252ied9rtOkuvhyGluiQDI8ohAczFWQenE8IU0wPaY5AYHEYsl/VQvHpw1nBmClo1qCDTnnoCj6o4P8KCiIhGZSO8NTmL4LcQFB5uEqsPfwJJvEOzAhblnBZ5GKyOeBaCwrfzskvd8wTBiV3WOWLuqsJ/pk0saPkt7nIR1fJj5ogVrnTcHG3s2sbOnUUlTfMW6AazgszxhQbR/XyL5tVvpEvmyi+ZLQlgSg71zzeXGlBHhEMJvEkYx7YUDVBuaAW1cRcaXEeMQ/m7yUgHOhhk93NAzzvQ7hpI51ID7Yh0aLDdJISDHQy4+zmY5x10dw2Ec6lBd0Q4NPBuArrhHQy+o0tV/wPwiG5oEN40jCOXH4hHhNP/YDwiHBqQdzbXqOUH5RGOVzAw7yyQ1SWC1YjSDHDVVPIzy+A8PdaE+fKKV09taCjThYcycX1UKzxE0uGgLClpcF5dJOWxbOSzdM0pZm6azJyPmLnoYmKWHkvJcb3MgJCfgqEw9UPZ6iWBYJuAcDQ6bQCEMc3iZYAg7Ai3iKWB8Lxdy8HAsmo5Qo9kPfsKYdMKyZEFUte3QLwbna1keXG3mAocbdJOBs4TQxb2/+1s2Os8ifI/K6VP5UaSgszBpyyFdEapxqvIOjnyeoW2jvZjxHcBSUJbFxQZ6mw7rlto68WNuGx0oelMkJsU1loh5rtAi+pAXuL7A88sJ7HK0NpRa0S1CFbKCTbFKFMWmxsWiwfH0AbLUkCWuA1BCx2MxxysjNJDiuXrMbnEGSBqyZQLV2LIG+rraWIQ3cAgvFo8KdRZB07U0TkpREKhhCrMwZWXLhjMkgsRmHFWCSw3EJaSYaiSK8QSTDQpWs6YOhOnqwjYDW2r6vQaTeTRvTbEcTxz3Gf99jMdsYjpRnKGIhnNncbyQu3gRCOz0cgwGr7Ci29bWmX5Le1h0QCWl5AhK78SyRjayN4lYpqooUUFkKIQmxGA+WtL5q0/pMDQugJDICab0TBFaNlh0pYjMh2Ztg4SZMg5exuZzIUxsg8SxL5u36PxHnkWziUjNPoAXtjt8celBF2IQDYs4NLEILKDiQt/oXXeCQtXUVNxIYEWYpBtC7I0kYjqQIDlL8DOK7hyDSRyKcEVIpHtCqw0EYjuQFDlL7DOK6ByDQRyKQEVIpCtCqY00YfpQCCFwqj9CaIQfWxYAKWFQZAtL3hCBNKfwAkRyDYFTZq4A5YXMCGcdihY0gSiah+ugLEuCgH9CZRIPhL6e3nFq6fWJFByYYESgWPhWDFoWjYkUFLvJv+9xcx5k5nzETPvot/hCFKCjUBKX6dASRMQqpUbPVrp7CtUTSoJPqJMIdpKZ9e4QLoh6iVrQS8wb/U7C1V/fvh4+/2xb4WKWdisbLm2lkMRrAPIwWMyPljNI9osABIYZo015UBOQUqHBrmxXjtopB4YcT8HfDl/R/LLAv3teXGOu5JrBcUjAOdN0m60g9Pu4CyVxN/3ZFdOrfuYdi+Pcgo12KmupGdqpKDlXJnMHUuAIYf9lHEQjhf8cG8Ng2Slk9549BoMosPsfczSle84beWZYJKyjiYlFkXT/xUn5MLdPW/HEGctwkeqKnxkCEQXdsKPjHrYvzmIDyg6L+Y8L0YbBV9+6qupVvVxVsQgLWNyZLWOUVnC63xkwobsPmRAdp6uHW3OJclkrLr0xLtJPzRSjZk1Hnxvry8lrJ511e0HTrXI21B/HwaXo4H8viQwzXcqHcVEhx4DUkhkTS7u7vkzrv94qnVQ2ZEoNZIjRYfTazCpXtSm51V6W2fm83rVplfpIFyv2nT//HpFatPzKPe1ZHq52aTe9ApR3wVabAd6078vpDe9ykrJuZSe/toUa3XinvMokomOh+yc9l5zFrIJijnDZYhWBNBWl11yAsW+mNKUO4IKVtkrMeQNyQq1MIhg29SbvopbyKX0pok8SG+6jUWgqdZ5+W3tYtF4B3pMvy+kx7TGqMMwKGd4LShnDdEv6TFdnEREQxRZmCpgLQH2iloSm1CkOhAnJhR1J078+0K9xhRFWBl/6A7EiX9fSJz4GvjjUuLERCAbFiduYhDT4MdWO1DeLutFDkh/2sREIHQXPplDbAfaxL8vpE18DSRyKW1iIpHtahO3EIhkHWgT/76QNvE1EMiltImJQLaqTdxEH9BS0V1NHnGKol6RNjHRx4a1iZsYBBsYhOtqT4ggBrkecWJikG2KEzeRB19enJhwuvJKAFkXq9RjEgxCN4kPkTjxRsWJJRuLx0pG4sRNgqLlmR7+vft0X37VKYZenQZ6tD1HQr/D7dGrEF1tXCPdtEYdQHiBNaolXYh6iXonOsT1WBnRyytOF4UhJJ2PJBjRPJGD2lC85jN8+NafPxWuHLzxoaJjL76Aqua9jnYZdX2bubjCc05h0xoJHDEFuMY1Ek1rtDxbLLBE1Up7iWO19hI3ACPTtEZHrXHDNbpGHOk6ZYsxUxPXz9ga6WayMn+yM9M+Mfa8xqAoSDlGEXKZiDn57m0sx5sC9nwEm11MOFjnU1+BRVVbSlobURawhfr9o7/9WWCJ5Db15fRYfviQUEBfrb5cI15UBwpzrx55bo25Vfp2MzXsv96WEAv7GoOW+ZBCDEkHIRxIMAKiZZEpC8B5sFEpEMxD9jlrELlsjCoXoisx5w31hzfyyHQd4gBsCsRaZYQzMlketEEGIjgQhTSKM+NE8igZMm6ddNoryU0BNbdBquxcBpRot+DSDuujq/tikIiE+sQvzySm6cK7/Ib2sWymFjDmdce/bb4y2fml60Nrs4SxvpXYFPenrbzQVs4yVLiRILADDTCCVYcqYK83Zeayfrrnrcw7My1NKHSf6JFFLqUFRjRCt7zTeUR0II79GrEzy2NfAY9cShKMeGTromCNVCI7kAV7DdqZhcGugEouJQxGVLJlabBGGlEdiIO9BuzM8mBXQCOXkgcjGtmuQFgjidTS4GIkDS4m0jmm8EiPImFEIpuWCWvkEduQzbW1bC4oopFrUgojGtmqVlgbg1i2vFoYYbVLvbBGIFVnf0o7MoPu5RWnh9jm4Go9ppCiWVMZzSKtoYcL9fzxv3VnfnBP79rsRbGR3hl1uCLYX2/TWGD7DRHxKdp3nj+f/3z3vlj84ynmVi3TOdqno36F4UaxVTQ5Na+SaFolxJFVEte5SqpplZa3+UUWyTSdb0e9C4PzTfTQIKSOcrVHewtzy/st12TajIjqnKGjtZVQX9uV6JM0rhIwBm3LpEaWSV/pMvGmZTriF9XWlrvaZapm8RWOnVVtw9lXu0q6CUwL0/6JugrrPGL5GCIHXTWG1CCmN4ea70a3/M49/jfSwxoiTNdADxcIqLTLMHUVnCmE03Y1gBFnDro8yY5d0AFW1dKXxYf0+Pn909JggGqKpUMGWGaVoKEkRtYqYsC8NRH1wim3B89+Ww5mmZ1O0hoTUSi/P6mTYGjRxWwT80YmKZVgFq2yXpVvZo3RKpP3TQFnHmOqfoqBnVuh6IB4j1SKaj3JI0jnTbrttIvT7+Is7cgH+7IrRH0f0+7lcU7iicnGW4nzlMustSI6jJ6zWFYHrOXBo87RcZM1sMw1L68BzTxIySPnSYgckHlupc7+TERpqEPK8EUh9e3svWyK+lwsiZZJrao6Z5HAdGkHFMZymtAkwUYHyPQHyIg/vvtqmy9j6H546Vszm7R0hqjq0aQJuzOTy1EpwPAaNpiFxGiDOiOXsXDSiReYzjilmshpPBHf3rZKoD37YtwZrmoZkaFANgzOqkN9bC4JVfOeVUfabkOFBaRIytoc4d3zZ7ySQ6uW/bAj4W4kP4uOrB+hCtkmRxb0D6LZRhY055QQelAbP6SgefXG11k0NazkqPZISj3NxiBYFxMUsw05CuOlSsxym4olm2x0UlY4xXMW2iqnFVNC6AQ2OSOsNFxciVlvSYuunVCwAzm6Q9jOK0i3ziqrYbaj3nPNiE9Ik24+SuFNfUXLb2s/K9ci6Ec230fwahi7MrqWVS+bTBtDZDwfpaiGgpCh6zOELifoXpkiRjueTAeas4dw4hmD1s6LZI1SGYRhVnieeUBhtbDK65CMZswbrlnSGXwApqRxnEcl2AbyK/OM0xhEpmfVvdnCAdX7QI12MrEtk3koZtYlmVxqqgaxCcUy2+iEswZft1r7/HYJWmKTPmdrEJvQ5bmdUKC7y868IzaugVEuNWKDGGXbQzba2QQ7mLMxCJ3MOmnjGtjkUpM2iE22PGujnUt4S58nr47KlnTXua6BG8QlGx+50U4nLW3jvJrgFoLo5LoGbxCdbHf0RjuTyOWnbxBgr6XagNd13M2Y0JhpktHqRGjscf/EH8pPut/TSYtULclQY+1pyjad3ytdJMFokcYXqRqhOpKVPWoHGOrKXqe9ifoIDj2WF1CHE5h4B1LUYkQr5FCOUPAO9YKff/PN/een2z/Mzf2np5v9S27wV/nbr7/+pm7+8c8bgdo4ERTKwG793cfbn67sh0/l0zx8/8ru61d25Vf+8vD54/6zPv5Mqfj1r3kWK34B1mObG6FhhJD0wFni3ano1qqVGkucFrFy2WTlfMTKZQ+K0npUJn8AKyGXFrx9ut+5GB/Kvi2Nh6orerSyitVXdiyDs9az0TR5EEcy0QMPoguZ6KO9PdIW1G2hlstbzW6XP+12S1uMbbKY5U+4JRZJVktM9Nj0Fz1o0ZDXuUjYku3CanianaWUwZFnFXVmJpvsmItoVAyoNMaY7P4LJkil0GGOnjnpM4eQpAtay8yzaRSoX6WXMXzmumSxPGs/AgeFzDOMImqmMpMCgzXWo3MxMPDMGoiQlZOWc2dyEpZrFxIvL4+twT01Nlx3sB0XDji9bTumLaNfUkims+04RUhm9Nz+9hO78os/u/c/zjFO8furgpLff+9f17lXjvhlg8TNh4PYpIrSCsHfDWLkdGW9b05SvX7oW49BYnAYsRxRwWgLzhrOim9hNKgg0173JPCo0HJhQUQsfkc2wluTswj+TOisIUR51A5WbRSQcpJ9MSqlnGMxWmUTd9oa9MFaqVL2aFOIZfGV3Zs7cpukSFA2p2wUtzqoJOWVmPSGehibuaRFIp3zSZtb6GpybjGvqRYgcOKQLjnktZdcTOCHIeI1O7S6KfOw/AZ3s3C1gCOv3wQGI+kEmf7CpUe1sWtY30tsmm5Le3mpvZxl+ForSaiWnk66ZHQZw7yQfs3BrsxbNkpXv/Vd/RROpsU9URjJYdKWIzIdmbYOEmTIOXsbmcyQYvZBFuqQAjwa78uFUTiXjNCFcMALuz0muZR4DVHJtrVrmrmEdyDDfQDaeVW4ryKzeiHpGuKSzSvXNNOJ6EC45gC38+rWXAOdXEq3huhk07I1zVQiO1CtOcDsvKI110AllxKtISrZsGZNM5HUMuViJFwiJpLnpMBrl4o1RCTbFqxp5hLTkOm1tUzvWIcRUcnK1GqISjYrVtPMInZ5rRqCa59SNa1Y0lV9Ea1GmtReXnF6m9ocjM3t2PX+5RWnS0mSMMQrYYiv6fBWYQg91hF6aLRakjBEvRn1+XOlD3flX/8qz3eSsUOTsYsRY5dddLnrEQ2YIbI4X7rL/Y/078ddecMOAIFNgJCmDghlewSEYHVAzCCKdQIgOgADbwLDsZrEIRiM7BEMcoQd1OLs8Bzx6IMdRBMghgNkh4CwpkdA6BF20KIHQHQAhmo+rUP3bql1qnbB6DHpT23WKIzylnUyHVSODZ575uKxIwZVdQJF6G9quK2OoxNndYaKWO7N+1qaLMBEmRSCzSr7iF6a5CGU5ffW2GSdV6i8AcuM0y74JJ0U4czdWNjbPa0b8Nl1vK5JZ4080hIMHdH0OU9EJoFgQnqLOSEzJjPLpfeKxQSOCWUZeogmWyYDK3/PMWUrFfPBiOALpZwJ1zXc1o80r6qD2yUQfXRDH4Pm5R/EME57t+cf6o5FTMsI1mrbpkQC7Xyg7QlC0IvYHx1Eo089vIbhwPU2U+4H2fSFDqJWLbiOzx9OXuxqyUPwGnkoReRBXuw8LFIL2LcdeZqOvI26sZLisiuMy/KRneFNE47IutcUJ0/MZVTZ5rK8wKXChMA5KBGVLU5ZLj4cBqG99yJlBwY1gEDILLAQZDzXZVs473sa2T4nUSeJk1M0vnZ6qF7uMSJD5s4xp3IKCA6kjDpZyUPkIjqngxNGSFaswrCsUCcvsonFilBaRHemUayhOmbWaDyR1JQkNbjH/KBm6LR36/QeozuJxhNom0DbE4RML9F4Ooj6isaTTV/oIGp1lvs9fywjL3a15HHRaDyRB3mxJ7MI9BKNJ9Su1Y21uMkhYZ1F4JccEvYW0PAO5oQNUzjzjgpbZeP6XCr+w62ByJXx2TOOXqqgigGrKDRaloDlvV2HvZ+ZITBgxZrLX7yXnCNKkzHDldj2hiTj30IqgiqU1tMVPzQxVdU/s8QkK5kZdmUFS7ZWbCKHR/jgGiEPzY56zeaeZlMlFQDyT9bEKm+tc+iJTTSFbdcjzTG8h2KdTgQ5KWuhk2uL45penJRtx3HfRiuyTiuavJQ10UozpXRHJ8DaFDeX39ee1g6Xn5RMdn9Vw5JpO9cxL/ktbCGolYlamSjut6b9oCtON/M7h8w1r8r/Fi4457SaUUPbPD5ESzs0FWz04kNAvf32cGOQEUVSJc18lNLSI4tsnvI8h0nbQhBMR6atgwQZcs7eRiYzpJh9kCCYFODReI88C+eSKaTjA3hht0cpWE0gck6c0iunfEqxGG/6eFWkohsio/UbnKCeWbrBEZXMeYPriUjsdM0Dk52BoKJNmFM2FiAr7dA4nZA7IUzM3DrrkXltGRiTrVIiOVT7qJ4zNqYgt+edSHaZifZEKZemFH/39OfdY7om5wRa+qmHwxovhdzik6TiqWA2wpjgfeDBJMVjQS6AZV7oQh1WpmSDNA5QhPL9mKSQXGgIbHucoqpT1DVxSrecksLu/tNVMUqtt1qMxFBE035SWPZyjKKrjGIEMUrn89R3j3f/SVdDKrwhhmJrIRRQxClLcYqR1Yn3SJzSOadcDZ2IqbQ7LB2EHRSrdoAoORWioBlRz/B5f//77vHp/sHtg57p/fvHW4PIckxQzh1ZbswZ0CUNzjCusohcFpzpcsfGUL4QnQJWDidZ7tcokkjJiDZAGRwBlBkIa/O5dWGe1+k85PxytMr17/6yB9FJ8GmRVeV8Uk1Mws8V4Mc24EdVBe8twWdz8EE2WYqaA+Fne/iZrPmLI8Fne/DhDSHjofcjyPvZPH5kA35UNeNA3s8G4aOmursLeVZ9Xs4cY2SeeXTZaaYVWBG0UuAtj4HzkFMOLLqEnnshmE02e5PRepO4gDNBg6KOGgEdiAEfbPH5qiSXA9Vkg1LEebro0mbUWmYUTCHTkFKWRnMMBU85uozeMWBB7cssUHqHXAZ0MUhtY4wmngkqYeugUtgbqHoFVIvWDdSkbs5kKQLUdQCKs17m8Gz73DvtqdmYSB4jG1/exi83kmctfg+vjkUYoliYKoqVJRTTSQVctGCqToxnzmshSF0JpCQ5P6txfvSIkqduemKy8LOd0ZER6jCINhrakN590fK+n/79doeU3N9v50pV6LwZXLqHiSUj9dUwkO9Esvb+rP3wR/6yvO7spxblBDGCxMNkHidXn1x9AFFtcR3L74nzqpsIUlcJqabZn9WU8WQVB04745IAn9C6YLPIKnCvDddhL8WgjQ6OSYgRXEzW5P1FUorIedwXULB1VxycppZqxxraX17xytxHoui37+4/lKd95965P27Ls4R36da7/6T3t7vnP3Zfv1XMXZdlB+1N+ce6nDTw5KJITICS/vaxGIS//3JbnuPzl5tvf9NC3qYvKTzc3z/dfoPtyxvc3H9+uv3D3Nx/errZv+QGf5W//frrb+rmH/+8EaiNE0GhDOzW3xXw/Gx1P3wqn+bh+1d2X7+yK7/yl4fPH/ef9fGvd/75r/lwX97kRQ/u8byhENVmGzmRrSiQLKcUOPNRGJ8jy0KoFE0AKZ2KFsBh4NnzFLSzhmnOLdvvlQGL0l5zdc7Lt54e/v3sRd4XJ/Lp4a684NmjvPvw6f1duHt6zdcVGcA3aQeuomZItAzyrevRIRKqN1dzJlriz1CNPyOVTC8mNFkV2eKWDHum46oScnwesbrec6alNrWuLKY1wXF754xuKI0fnjOCzplOhDPEtBoEZNjTnzPjaa2uecJMpohBl/TtHTOSNRSnV+ewUvpwdonrekuTovj0TBvT1BUEQDTbXSz0ZM3xBs/iHB3zNeTSJEzVKEcmsUXPo5qKNUOZMxw2HBjVdNwtMiidEsidXMuNHUbchg9tD+9Cc5nqNOm6txxPP/59ZynzfeWE54/87u73d7v35Xnen67FJ3kTJYgRSlCcfHaihCumhHm91mWpodpJZvTYXuqmxoZlAChUHYFqLgSeVoz8XMzfCzxkEzw4q+ND6h7xoe0IQ2FX+OgGG9VMbIfHwLKrVc0nWDayWvawaRfkla9Wy2S3of7mYAqTPkuQfPj0t1pAclzqqDhXnvkUtc9MaBQoXYiMA0QpuDHcG8bLn8awpJhDjkywoBvJao3O+Ug35MBpFeflN6A44mEffHLBSe88BhOEwgAgik8OkDJaLL465yikFqiiFklpvt+upHPjdnR24l2sPWrMBe5Glf4t7KJaZryJag2RPE+LzFups/fWWK+0VclYCSg8U0Jlx63xMYgCaYHlrlmA7bUul0ofy7+sccGnM9G7AnceR+KVg3QiIzLpurN6v961287sjc8XZJnJ8jgKCNXrabK7IKKwF40WOrfGHtoMt2MQhDJTbgdZ+JXLc1yQUwT5wmvlFMFrnKIlcQr5wp2wTC2P0AhrS7AmZ7hASjdAqu59EaQIUs+QmqznQ56n8McgeCcxGwnSWlWcoqiZZj4mAzlzi2Y/TbnAiKFwUpqUy+tVghxRMAz5zByDqqcYcDlA3edeoUMJqxUnrBon+hk6Luat7tNVgzFmWoMJHG0xAone6yhEuWCmZxViZ6MJTuWyL0oytNZHX+xHaSNlUFwza6LHBFfCvlNOS5+4ZWPLyUvdkryEqh6HEtMaTmEyicFhRGdyMNoWkzGcGRWNBhVk2h83gUeFlgsLIiIalY3wxcSyCP5Mw1ljK4OoNrJLSczWN7PVugfWTTMw2QRkgeQvkb9ErLKcv9Qfu3DKOq2moWLoUzJT2w9onzhN9DIvvWwzB6VFgyQLVzVNFuDk0szNOlJVWccIYp31ss4Vejiqqed6+f3ubwVNww0UahdQJG5Ymhu+o+u/f3/1Wc8piua0qUtv6sfi0qR892X3Mf25f+79BrP/9cIfpqnLh+Kwc2HtTe5fNY+BE984nTQqgwMnchJR66BZTMmDYsxniUqrlFWwJkmvA7gctGKCO5QGIwSL5PttJkxuoKXug82ZjXOYtOWITEemrYMEGXLO3kYmM6SYfZAgmBTg0XiPPAvnkhEafQAv7PZIpj6WhHNimb5Z5lOKxZzTxyukmZb5apT96ZtmeNXXFJZoZt3ZuXUzDZ+uvGjiAxNUtAlzysYCZKUdGqcTcreX3svcOuuReW0ZGJOtUiI5VEwH5YyNKcjtMU19/k1zWzkxzcxM4++e/rx7TFfIMi1dp8OhpJdFMeeQXEbMRhgT9mMRgkmKx4JiAMu80IVMrEzJBmkcoAjl+zFJIbnQENj2WEZhdcoWsUznLJPC7v7TFXKMbJj0NQzNDCZ9Ad2ZFq5orHLM1Ml/4pjJ70zp6Tnz/3j3n3RlNKMb0tS2lqYGRSyz8FhBWR3khsQyq2CZKyOY6SYR0jHZTR1MN+iqNq7bIz/5SJj60FMWHXRzCz7m3Lf1c9++u/9QnvWde+f+uC1PEt6lW+/+k97f7p7/2H39lihHKLgI2pvyj3XluAWeXBRpPwlL+tvHwlr+/stteYzPX26+/U0LWQwthYf7+6fbbxv+8gY395+fbv8wN/efnm72L7nBX+Vvv/76m7r5xz9vBGrjRFAoA7v1d8Vsf7a2Hz6VT/Pw/Su7r1/ZlV/5y8Pnj/vP+vjXO//813y4L2/yksl/bLNdO9L3gGygeLmqMUFLzQJ6/t3fPtwpxm6rJVFWjonQy/48ODsm9fPyitO7ES8/zeHbj+xcjA9l8/uABjRBA20dG130WtvhDAocRpLt4RAKIZbGRv78Mew/zu4xvU/h6b4T3sAmcBxJvgzAMabSPYuuOGMjTcwvr3jlJsjFieNb/8SFJgS144I34eIoUTDAhdY94OLoSjVUnGeD6lPVCy76wEQ1tdefI7jgStVahOgSQ5eYKVygNV7gkfGxleZzj8Na8L44fOvPnwqVDN64PM7nh49/+5d7/7nHe2ctR9Ljbi+4VKYXIcmDR59ZRfKItlSdtVBsa+pZWViIDLDsSvnTQbaOK5ElCumSxOhM0hKTE5hiVjG68i3QwfiYvPEuNu5GZ478aW3i373i6yrqbWeUFmlaXs2AyvMGEXmuDAtOKrTMcGtjMFbnPUekKKUyKrHsnXVeODCcswDcJqnAOe0FRHMmalcRlmgadyYlsUhXLDLQuPhJwOb0d51LT6eVVJCxqYabnanfRRhuxnBnSIJuhprR8dTVVDMy7QseT62ykv2fSJzc3NXyyMjIJ+IRcnOXIRUx3ZApivhs28+Vmxwu1Vkkd/HhUu24Ub3M+zhMCMw77GOVecxZReYOdycW9zKZrBUPQiaROQ/O8wQos/UWucDApQRrTLFol5KIOcmgfPFYrVHaXomRb03CrJ1ddMutyU6K38NjSXCFSkkhjCleTMzl+pTdvk1Ei+LaWIMqhmAYt4JnZFbr6HPO0WTpXVIynengrKHWedgTW6UTYMQnK5LDrhSFn+D4Dn+4S6oxvcz8kDmzqB2DcnsKVmjhiwOcHLPSp6BAOV8YRioTi0OMGhBTluVrWkhRfOEMZ1LNKmrnh44lViNmIDWRzXrIptZlMM42xz/dJd1Q2cN64sHHkk9VvY+Xvh2im7X4NlcbHwbWMlMIajOFzozqbTs+/Ea556qTiWcKPhPJLEIybyKYPskFm6QZlt/izpZPdDI/iIjg2oYH0Y6uZnJQO20oasBZZwNO21RyTv72Nc09ODSWeZXJtuBtnzOSnDqxvh4tupeJdOTA9DuOjpiMCjnewC2ml0F0A/zOOoXuGrjlolPoiFxoBN1b2MU2xNLq9y6BdO+iexcRyvz3rr4oBaGXQXOHEJ53ytw1OCwXnTJH/EIj5t5ALtjLfLlD/M47XO4ayOWiw+WIXDY/Wa6dWngvY+UoiNvxTDmiFhoo9xZ2kZ1MkyNy6XiUHJHLxufItfOK6mSIHEG35wly7biqK3vr0Vka+jC71UProxwK+8Cwyk8eSvtwoNkLl529gDD0ffjgZoVgaYJcszx9TJ/e3//7JEM3VUM3YxL+punmO4vUMozd1l9e8crO2eKTft67x8fdO/f4bmE02Coa7BgaDm2VYw9oGGvXe3nFqxK87gYJ7h7d+6dlgcGrutDARoABs45cOxEYaqRZ/OUVr4BhOwDGiz95/7C79NC4BmxUlZ4BxrABHZKGHnVLDh1cyXrExsK4wCouxmQ2Edq88Z7GAzUskqguUn/u8RJrVAtyII4dPnh4+AhzlWukG9JXspa9AvPWQNDLsLLbV0++V5NkloUkkTuvfZRoLBNGMBP3ZXwmQzYsBpEAkxRZgBTWB1BMsQAZoXG+nK4HgoZhCZhd3fZgntuRMGmtD3ZkmNqZTXC0h2fu4Xydry+7siun/n1Mu5eHOYkhbCdCxcrrrEOMXqIVUtrAMDuWuLRJGVCZOe91EhzBe+UxW8/2SpHJi6yzYL7RlRs2kOvhCTqY4GYXxdMimn9vhZRomRZ05N81ncqEqXPD32Pzr4f3MEVHyLxHyKguzstP7Z5/ql40vmJKaanwVPYylT6E4LcQDBuTcmfnTZGi7bkswZzcklK/xHTFJtXhUY0n4tvbUQiwZ16Mu8KUaNCGhKo2JJeEqDlPqCMtsWEHJVIUZV0u8O75M17FUVWrEB5JvAOSZ0UH1RGiulG8+wqlWaXuVnlCYb0TAM+TLx2EzJJLpmyCsVKwjFZyY1FxH5Jw2TgdpHfBIJYdCDK7aOy+alcIJjXjPrHGkFlfZQAnz185zqlfl9jZ6RlG0aRypidt7D9EblkDZa0SPoNVoRw4MgngBZo5cgXcZe6kTjpq5ZLX0RhVzqEALAolFWjXiNw1FjcN2d3UiKSZ3YlIZiOS43FSYxVgb3uauUYxNPCNaUguVVWhlSF8L4bvXtBkW1KVWE1VMjq9Zp0iXx/AfeZ2kHXPc3o1i1yt4pCSQE7xWmlF8BqtGCRaIae4O76plUe0nZtGEcC37hVL3klNKIPgncRsJMhyinlvo2aa+ZgM5MwtGojMqvJFFE5Kk3J5vUqQIwqGIV9bluE7mmbMMJwEGDGduqeYIqfgMUgMDiM6k4PRFpw1nBkVjQYVZNonFgKPCi0XFkRELJ6PEd6anEXwZwJnFcIHc06g+LotGaCsNPrs0AepCuUL4WxMkilumXJWmGK23lotLccsmXVMegSNsXzPiiux562NN2ggEtkyxplPqnQ9cGScTEqgTwGylsWFYcV74UIbpnXKTIJTSqF0sqCWQblVCVO8GV+8HVAqONMI1RUqKhyV3ZqqkBAnAlnDXNUfSU6c4NP+9WN98YmabAaTOjOg6MBJbl3iLJbbD/r9PHjmvebSm7AfBK+99wkdKwySTQQfLJMKfE5ZR95aMLNCTY4jP7Gu1AySGGUVjDIiW3LShfkHv6EvnqEqiNUEfI/r++uD4cESz6yDZzYT7jUNvQbDfMZgghGlSWee9yaqOuSoNbHNStnmbKbpi2UUaxJ7XX7Pe1k3pAL7lRXYzztLns7Mxjrlobr+YeEdMEZH5tUNM6Qei1cnSks+vjqJAgSZyhIMpkWNwQxFMnsdDPLSU3wVJCK6GepMDhA5QOQArT4+oBp6Z4SpIxgIwdc3X6gBS2ayPD1Vqi0T2K5WdeIkJ9Ss88OofHCFNNIiZozs8nXIDpMu/FCgEpm2DhJkyDl7G5nMkGIu5ALFsRXg0XiPPAtXnGOhC+uAF3Z7NILVfgLOiUd65JFPKRaDTR+vhUh0i4R1VcEaybNdhEe4mLQ4nHikixvzGqkEpuuNmuT0AxVtwpyysQBZaYfG6YTcCWFi5tZZj8xry8CYbJUSyaFiOihnCuMEuT0ukXVPEYhLeuQSf/f0591juhoeaSkrqZfOT4NYziG5jJiNMCZ4H3gwSfFYEAtgmRe60IWVKdkgjQMUoXy/uCxCcqEhsO3xiKqW/mnikS55JIXd/aerYRHeInjFazcbToHWRVhE42XGmxCLXLiW4Ll4+PHuP1dRTqBFA5FwXVXOo6KkRYjEVEvFLBKRdEwkV8EhciqdIUun3qbrB3R9FrQaOrbD8+i7JtrXE6mHNlU51ASBYa+IbBuFfvvu/kN52nfunfvjtjxLeJduvftPen+7e/5j9/VbgikNLoL2pvxjXU4aeHJRJCZASX/7WJjJ33+5Lc/x+cvNt79pIYtZpfBwf/90+22jX97g5v7z0+0f5ub+09PN/iU3+Kv87ddff1M3//jnjUBtnAgKZWC3/q4Y6c9W98On8mkevn9l9/Uru/Irf3n4/HH/WR//euef/5oP9+VNXjLfj202y+XY5HUBM09ef7HZp4d/P1vr/X4SycNd+ld6tty7D5/e34W7p1eFZbWUf2OdwMQDzXduv2zlbU6yeF21eD02/V13p6eDXI1UKLy84pXBs5nQ9VNc/FAuZlFYVOXhcUxmCU1/tcB8iGU+lLXnh2CWuDgsRjQ/FkVIVfKdjwla8A7HevAhrPnRUx/iWtoOEDKm1rAkSEy1/oOPtRTwDlsKuB1zXfihJpRkPYKkF4BA9ZwZk99CO1B96AAggo0IRb+84vQ2oMsD5OvG5Yf7D7v/pIf7XsCBVfbo7w6x6GJVtYPpEkyX4IuIfqlqmXFrOPG7w1sMKT1kF9LtP8uz/vbtwR+/dZLeQg5SY7YRuYshRZDOOOkzzyhBKJdZgP1oVUBwkF20e3E5Lh0XQlnENmXqI3k2GFYyHTL6mNTZIsbzRnj8tRWNxyCOnN1i0LxtVhXi+avn8Osb/e37Ov0tf/4Y9styfu/IX8/6+VNh/MGTHgzL7TC2ZGRTNFmMRJNVhzJkvMp/Eoj/iP9Wy3+n912fy4E/f6dF+Us13T/gKBBwqBGJqofb6VFH+QguFfQWBe0FHdXMCR8zf45NikLLgENDHRxaLA2OP9K/e8FDNWXC+RgeDrVhoEuyMDhyiOml8TDUGVoUEdUUSYcOwpKLZeEKD1s+GuEZKEIpOmx/jI5qKFiMketwma/clGrNCaK+VOLwFDJvrQd8iU3c/ugj3AaVsjQ2ShWFEi5Jm3zxhwLEYJ02aq+ga41S3ATP9X6ei0nIyn9kY7yCRjWHoziDqocZUM09jvAgjnM0kvC/f3/16Ub05uSkeru0mVNt5sfdp8Kxd192H9Of+yfdbyz73+VqPb9vz66w+n1Mu5enOok8ZCdDS5XXWYcYvUQrpLSBYXYs8QIwZUBl5rzXSXAE//+z967NkRxXluBfKesPO1IPi+Xvx4zxg1ij3WnbnpWZSPXO2KgN5k8SpiqgFg9KbJn++94ACkBmJOCRno8Ij4hLk4lVYAKIuI/j97pfP8crz7L1xCQN0SeyzoJUak/yPi72NyP5NjIyO2lg7a7To80RHxNbNVR3rMgHIjC4zrzTTQfEWPt8nwpXl4lWl0HJjcfvejw5KO/kLgFkajgQ9ZnENjGmj8KenREqWTxvEgT91Cb27H2EVO6B2gSaIkti5fKpEGom77RbjDJOSIVIHaUlkbrDmSYwxo5azvqtDe2T6jHcqJlpKX3x8I5LWtc4KZ3EDEzk9yIZCzNc1V6PscbE/V6Ca1yVv1kOQbIyZX2PuFfMSOSmsRtpqPF28CEoJ3ydUvKzvHnbB/yiyk014COijIYoyxSTrwOeGkY3Wgx0g4E+WaA3F1ay5uyUFc9OCa5nZ13PzMBRtjmlOzDNx1nPTqE82PKypbFeniu+CF7CF8MQX7Bebhd4SvMadSupURjpWDA/xZVtpWDmyXJvLFGBM5u0k4HzRBgJ3Z+dDVKwIOAfK6VP1qQE0RV8yrDyOaNUJR/uHG+a0QFqPlpFKzvgjsCpYsQTFkXURGXS2d8a65lzMRDqiTU00qyctJw7k5OwXLuQOHw81tITz/LAeoAHrzfnfdx+HKHBO8mykVRC2ee9BTNr4mMyNGduGTiDWAVfZMJJaRLkhlOJ5sgEYSEv7TTvGXX3PpN+KSHC3b379Lo2wil+fm0L9HgZs83lgdJG7jlg/A/EZ3ORg2fX8z275gP+OfLKHDYUR4oyFdPFmJOmCxSCxAHOpuw0p4E4GZ0RUlOuPREpMGkNUzqSyD1PNAqmGVWQKDwHSY1aCPKOqDuLYwzViw0/neytOGn2eBYkC45FBi1SMNpSZw0nRkWjqQoydStO4FExy4WlIjJmVDbCW5OzCP7I7JmF9kh/gSyKaUuJ6NY0upWYGmeNMaWJhbqCSeBZAxZMCClTF0zNIYyqqGJ4MaSFPQ5hnExKMJ8CzVoCthCAFS60IVqnTCR1SinolqVyllCZhDAAMx5giCoVnKkM4RnqJ+0UlaS4+0WZQoxpGmP6Z8yvaU3tgTYv39YoxlQNsBQrcXXkRJajTnLrEicRShXmGU+ReK+59CYYzkl3JykxRwBVsonUB0ukoj6nrCOnlSE8QzGuHYyRpIgxBjFmXhgzIFy2V3Hzyk9oFHlqGEe4PekeQG/SIHOdfKQphhyoVFKoQIiBiKYxRsspzYIZHp1TxiWvorDaMGGUNVqkXFvdzFCeaed8hhTPthlH5JkV8hSkrIZBZ+ebG8Ubi6O6cxnV3cEbVexuOWGINzOrdFY3sctqKGn6s+nblDQa776MPMrHivUOVwTxZ+74s9RdZFY1eFVU5jr2nMpZzyiDtkpkTR3PzkieKeGRJ6FMZiklBbATRXCcac0E4BP1wistHPyxEndmqCWzK5RWVoo0AnFnTrizrbszDDPd5xtFlZoJG1bkixUC74mMiyqWFf1BsZuaFar01ZvmfcWAiSr90+nd25wBa8YGcBKmLfGrPkmcKN2wpMSif2Y9qTTnAUimK64KiyI5GaW4gTJxIDcXXfZkgyk4Ij5xw1E8vGenTX0njcrUUSdyElHroAm4ylNFiM8S/KJSVgH6QOl1oC4HrYjgjknDIg0zv6eOA/wVCMNJzRYGGfGSkGNJW84YARDR1tFEM805exuJzDTF7AFIBJGCema8ZzwL55IRmvlAvbDrQxhWnLblHCGmaYj5kiLkcrpaHsbQihq5KN03NOSORcy5d03FSS9YIMRgJ34ylGGnu+582qWSqmgTyykbS2lW2jHjdGLcCWFi5rY7ESZeW0KNyVYpkRxTRAfljI0pyPXBTHmmX1GEmaZhxl/e/fXyNi0PYqoYFfSIMQw1VnKZsWyEMcH7wINJikeIYUot8UIDkliZkg3SOMpEgP8ekxSSCw2Vz/ogRhWPfzVCTNsQk8LF9ZflAUyNAESfToGdSLERW6XT0CsUAebEQ2sIMCdvldLdw2zJq4yYs8aYGjUQrovkxjh5OS3GmOJEvmWIMXPAmGXBizoVOa7FJRLHIbZjqzhsI8nAPQ4mSdWJ2NRjkY9//hYMdX17ebeXgYrCBXLoEprsbefrpdlHkCr79CdqdgwkF2cghgFUtE9pB5CJPmcX7QeQ0M1d8xRyQNBEyCpFk1EmhOXQvTbZ08Mca3m9u/n1YWG97qTVby7TL+lhkb38/OXTZbi827h+UJooqhxDGjsJRFUSSFpOAq0bTAJRToIhfVVMgv2SoDjzUjspM3YayKo04ANrwdDwxCRpoEkxDYzENDhFGgzNZRww0DF2MqhiMgwRDQrT485qMa52eON7gcXtSIH1Zjg80E99pb2bMBbKbTobqg96ZpVscV2ErdrHoKS8j8FYi9miyAAMy6mzJV7mPGGaSFKXJpOvamPbp7QXgV3rWA89y00NJocoKmSPokIueYOg/6vvv0C29X4xPM79zdW7B1aERjYaJK9BAOxVxkKAObSyS0CAM7SF9UjQTIspRQ0a4AbeWGgwh/3dJaDBSfdK63GgjU1XWdx0bdDLY9tH1UwQs+J033EEu5onZYKwxGslCTcmw7+STTRn65nnIUVjovPZKEZ5VI4YTjspJU/hj6TySsLODiMb2GLkDSoK8OI8lDhO4CFwqhjxhEURNVGZdJyA1oAvnIuBUE+soZFm5aTl3JmchOXahcTh47F2/mlnlVDlRYLyBt1RnK6Uekba7Y25Yx/t9gr6v3B37z69Pql9ip9fq67nPl/fX51bcaZmTTCnGsmUBmP+nDHfQrDYBlSjvz7vyELRs9zpHIsF7NklUA4EEnTINoArrFAxS0Yk41pyJWy02WVLIiQwIwksRpQ0XDGvnIqB2oXk8IqopSrAQ1WxSRVZV5U+NlK1oMlxqaPiXHniU9Q+E6GZYLLDDU5plAIaE+4N4fBvY0hSxDHOiIAIX8Em6VhEuAgea2Z0qQEQejI6uiPoVJ/C1SojnJHJ8qANI1QERwWUGikmJ5JnkjDCrZNOeyW5SSFyG6TKzmXKJLMr2FjdlXzmZadgAYLEc+cEkBoWqIENHnpUsyu89sJ4Hmw0SWmWAjOSSWh+o2c5WSKUItDBCGullYJpKZ3RMWmjVILIPXL/cwYTljvYwcuALjViR+MqHG8MoA7vmW19YztoUiXwY8+4e4+nKfVwUtYNowbhpHU4+bqTPufNd1V3WW56n7Zgs9IhNi8fWGwf8DOBOT4dbcTf/2njXQdmEWiRzAzdOL4boR8EZL7828VV+mv33J1LyT8mRAXTgBgKxlNj+idPDhmX3gfPpea1K1R1qI1bmKuRNkH0wE3lYfjQpAExUQSP1kRLEDzwVHs//KANSJM8Reu4aiRLwI9zqZEgfqxVgKQGO1gDmiNPkTquzMgSsONcMiOIHetUFqlBjiJ7wsAsnTiR7iJ2La3phyByrFYypAY8ZMURrC0dwVKF2LEUXRDEjjVKgdTARgPqHxikzQl+1ERQmTx055bVDstk75ZVCzw/hA6NU5LenvRAcHz4+fozPO3P7mf3lw/wLOHn9MG7/0ifPlw8/Ovi638SRGnqItXewP+sy0lTnlwUiQiqpP9wC2jkr//2AZ7j/m/vn/6mhYR0SuHm+vruw5OTH3/B++v7uw9/Me+vv9y97z7ynn0vP37//Uf1/ocf3wumjRNBMRnIB38JyfmWdT9/gbe5ef7KxdevXMCP/Pbm/qp719uX3/z2j/l8Db/k8Zz6tpIQaGfE1fQjyYwZSQuQEHh4r586b8LPTzdP49x7Zb0pZn2DvprYYKZMHmuHeJDstr3U4u1VOoJBgEaAPhXP3CwLFEUG8EIRZMudhC33GMgrank16PKp7cVboc7jXnUbWVpnmVwyREdPLAsyMc48445bZYyAZYOIbJUVAOuBJSUkfKpjUToSsuQAZGmG1HlnpM6TQzsJPXcwi9R5Z6QRa8wdy6bOg5+Zwl2KI10FPma1kKsk1ZthNrQYPKoBkr03nn9k0r1ZNkxj3TZ7y0VU8pwVd5oEsLuOVjED9UbIklKefGYcYEBEkbwyvPOKMJQKkeFDkvpsF5LzK7rsdAzY6BpKHHvSSMa+5tgpoCKyUILQMjdOi50Sd6H1sak6x53e7w3a0JLpeTAQJxbJi4FunRdPxjEowhrgzcB4a5xH4y0HjTtFh63mrFtNy09G33z6fS3HkracMWg7ibaOJpppztnbSGSmKWYfJBVECuqZ8dCPZuGgSxWa+UC9WCHUnIt1A7EGWThOADaiAbGJt0J5XPGJRRwZn4mlA8EGWTtOgzeyARaPN/uoUVk9loA352L1QLxBlo/jsUY1wPrxViSPywKyBKw5FwsIYg2yghyLNLoBlhDcHW6dNQSRBllETgA2dnpWEcSa1llGEGuQdeQYmBGETM9CgkHcPCvJMRFWvE6u+nUz5/3LlaJKanKUS8BMD124ZrqKNQAvwR99CV7JgXuOj5/YiCSBLCV73hC+Tf/ffffL6hK/fKm6QXc1YLOiBN6DSmPxIrqqOglchslKZ02I1IjUpyL+mGWlovQQZGikK5mWruQw1FPFhaI9rzdgMr1O0pId4JIDwKUlkpackbRkxx+q7A7OkLTkjDQNjbkDSUvOsW112IJhV8lbMsOEaDN+KGmJumTnFUZmL5ll/zT6nb9dL4172Nps8q/xVtlhqEPXyWGyiDbn/BwmCDBIY3I+7GFVZ73Tu75RM4qGyEwQMJbKZ4KenR2lyWFwolpiNcGoa5/YZNdH487iYRc6+y5Ut0Rv8ko8j8pwsgTMOTvDCYIOkpwcizqmJZ6T3YAel+pkEQfN56Y6QdRBtpMTAI9tifDklRZrVM6TJQDP2TlPEHiQ9uQ40GGkJeaT3Xgel/xkCaBzdvITBB3kPzkKcmhLFCi4lTwDFhSEHCRCORZ1eENcKAg6M6BDQdBBRpQj8EY0RIqCoTwHXpTD4qx4dV0P3YF7/MRo1/33Cxdr+11AP16s3X5qgRfuz3zhXu/cbrX9SNoeLpMEqVH2vIrswfB/ubi7/AxfcJ+/7JX2xbvbLTprcosVFRI1H7jtrvmsaVEOMVjpPAoxGjH6RKv9PGsULYYAQyApyrSkKAdgHifFRaI9n09uMNoKIYr0UfFsmdU6SWmE9dZQkgOLnHCRuy8o6TjPYCVHHKFeM8uSV5zqzAw7ErTkAGghIcpZCVF2/KHK7uAECVHOyP/QmDtWQojyjNxjXfA8ZMHgqyREmWFCNBk9oiU6lN4LjEyGMsu+afSrgjs+4gSiyCiTu1kxqhnJOXqiOcme8O6mTkxQD0pjnbZeRkYFDRSqFQl/ozEtJO3XeAntELypEaEU9Iz1G7Y39WNJqkyEYhFcZkuD8lLqLrdSVlUnu9M7v0kjmoZoUBAulkmCgn6dGQXKAUAiSEsEKBhxrdOf9D007sAd9p3z7jsFbYn6ZCeWRyU+WQLanJ34BOEGaU+OwRvWEulJP5jHpTxZxFHyuSlPEG+Q8ORIyOEt0Z3043lcspMlQM7ZyU4QcpDq5Ai4ES0RnfRjeVyakyXAzdlpThBukOTkYLCRLVGc4GZx8wQnCDZIb3IM3uiGyE0QbpqnNkG4QWKTA5HGNERrgmHcPqnJITFWvHiuTX+vu3+r8OETrV1ylv2qX/efWlbdvsPr8sdfl+9TGHDS98k2hYFkSGmy51Xip3eroTKS5cvXDXprepMVxRINGbivbsg25pgVWIwXgwxhGmH6NAv+LMsUQ4cQgyKrybSsJgeBniguE+05fXqLyVZ4TcZVQN+BLTkAW1ogr8k5eU3M0CbDtjs4RV6Tc9I4tOWOlfCajCxbf9B6oddJazK/fGgzfExLvCb9Nxib2GSOrdPoVwB3nDSuhESzmb/GG2YHQU6N3CS3J41m7HCOHUgSZWoThJcZc5s8lbtLrZUVqTrfnd7zbVqRNcRsgmixUGoTdOzcuE0OwhLRErkJxlzz7CY7Lhp59A6bz3k3n0q2xG+yG83jEpwsAHDOTnCCiIMMJ8dBjmqJ4mQnnEfmOFnCsfK5OU4QcpDk5GjU0S2xnOx2VuPSnCwAdc5Oc4KogzwnRyGOaYnoZCeaR2Y6WQDinJ3pBBEHqU6OwBvbEtcJ7h23T3aCeINsJ0dBjqYN0Z0g4rTPd4KIg4QnB4MNa4jxBAN5BpQnB0VZ8Vq62bmWbvpXNHvX0lUDl4klGThVYbLHP0DxMv2ZL9Mb1fdJP4WN2vaJQM6TPe8ZP1IdXd1/9ulmr5wv38pu0FPTmquoh2j00CV2PaYY8vTWKh08ITQjNJ+KMWSWpYkxQ2hhkOdkWp6TasAzxeWhPYdPay3bCr9JVFlR6Ea1ElZQ4kyWOSrnrDZSmUiptNIk7wIVNhKeqfecsZyIVi6QRI6EKzEAVy0Kmy+I32THH6rsDqaR3+SMfA6NuWMl/Cab4D2uIP3+C4ahqyQ4mWFCtBc6rCVyk82nH5nYZJa90kTa5l8dBFWhAIM7nQyBmi+5mLNJNhAHTT0UI5DsLPNMlDTRWOGVtlIKzmKinrFgFpLt65XNroAZfrJLrApbmrGHjoqwTynCykzJTLZq2+VWx6Lq+HZ6/7dnQdUQnQlixQKpTNCpc6IxqcYP0xKFCcZa0/QlW+4Zd4QOW8w5t5i2JdqS7SgelbJkCSBzdsoSRBmkKzkIZixpiapku5YZlaZkEafD56YpQZhBipKDkYa2RE+yFcnjUpMsAWnOTk2CSIO0JAehDGuJkmQriselI1kCypydjgRRBqlIDsAY3hINCe7/tk1BghiD9COHwYxsiHoEUaZt2hFEGaQcqQYY1RDdCAZw41Qj1dFVvBVu+yM5vG90uz2VI1uQxuP9e9O099SUq6pZolFuIFs1cCHV9i57c+Th2OMu7MPPvr27vnHdpj2k6uXtHfziX/dKjuINYssHrv09fmLDY6bFMNsheujFGScjxdmbEbIrf9hGdBRvTO/YmZuBfGbzuWB+hNkkoVVmmx4F27Aar1qn5cA6rVuU71DFGczaPbhn0jVwX7rJLqQPP8Kzfnx68Fuolh7IKz7QHKRm2UbGXQwpUumMkx56YyapUC6TQAOxhDIodrOLljKpuXQc+mvLWN2dP9on2qH9Q7ptnh1qG+TZOTA8XlxRuWbZIVCw242Obq40GhoaeLn48vWXvXu21bt8fxU60xw7ntAGkImqmmqgpOK8hZKqH55iID6Vnrqkuoa/3+zwUjYXK3KB9Xc/WLQuB4sRWH+/Hh1F+r8dO1s2sGiolVSSpsps0y+1TViN1kzg0mIlW31zDStZrGSn7NPEYHwL2tx+KidsYFr18RP706QhpeNB7Uob8E0XV0nuBjjXAwGOleQb0VEaR20SSNowmyiabaCVf/zAxnntWqxWPM/HtXay/eeRq/afnqt2KROhORstkrWMOBFtIFlaxVmQHW9hYMFoGRllxCcmaDDMc+aVtTFGSStPx4eqdo5Vez+8d2j6drBsW0tAzaqSPN3e80zYxI+C7xr9bjzSwo2ABW0ETBvduGDigrmuA9v6hfOET93GamuWdlrMyZCqz+MnRttsWsxpMbUL3OPbGYcz5WBREvf4Xo0ORoqbVe0tWG1Yrbwzaoa2+EZXf23DaqLdw2KsorGKPut80xyvDPGdLYy+pftbGHhWvNizYibb3eFD9Eb0HhW953CRZAnoPbRxg7tHhyB5UUKiwahpw2q6GSVYHZ2TQsDypYSiznLlpYOFLEsuRCDGWSWYlZKkZAhTyRGjgokmRcsJUZXYN8cdogUrwe6sRQNLEZeoBHtG4cvG3LFsJdinTdQRWEOOWirsKjVgZ5gKzYYQJ61owb71FiNrws6Tc2dMPaU3HZWTVpDkTELeAwCYLEM0MVhps2KRs9AViN4HG0mSKQsRpXCJKCOd8dm5haDA2oR7joIf2oqyxptRPa7CxiKoRHTRUcYg/KDURjsQVEOGL+RJyfC3q2gjg8iUupgAcBQAjEwQzzEIFbiXMVPf9fWaBkp5SNZr7pImSdugGPxZH7nfMoPprZ2ClBaRhkqCUDNLuerBkbfhHv6NH9E6GvGa08+iwIxQuPs79hW2okOoYQhHs4SjQ/BnLoAjqpgNp/d1u5ZUFVIEtCRFwATiRGuM4X//p413HTiVpaVDWY7ObcW5V1DupHz5t4ur9NfuuTtHk380hyumpkHFnd9ZnEwXT1LYmdrWcRUjcIN+CbtjNUfMjExxPuhY0pYzRnQk2jqaaKY5Zw9gIzNNMfsgqSBSUM8AhBjPwrlkhGY+UC/s+sCHFWcBOEf0mQf6fEkR0jxdLRd+RM14Ah47zWQqr1ijCovwg8eD7SAQPd2A1JkWVqqiTSynbCylWWnHOtVJxp0QJmZunfWMeG0JNSZbpURyTBEdlDM2piDXh0CSnFHTHBFoNATyl3d/vbxNC0afmuEEqqeIas5pcpmxbIQxAQodHkxSPEJUU2qJFxpAxsqUbJDGUSYC/PeYpJBcaBrI+tBHFdW0NaLPTNAnhYvrLwvGntIoghjY+hHbG5oUe69GRjOL2GMEYs+stLZfvzK1DPiRFcfptnScThWiTxvoY4rjs5Yh+swKfRYKPOpUtyotLqfNzfE0F226SJIhBu5APX5iY/e8hetAXA2R7HHVnooGHaJTpD06RbVkErKTcaHcpIvUvRn8rr3ywRTzwQzmg6kapWyJNabSUpJUWYqzgXCWy7UUq7LU9Hk/maFE1WIkBhYjaVavmuBi/MoY6LTSVmYus+OUKgFRqaJJIlEWnOsIeohTPCXHjEpcEiOl5kYG6BeJoj7UvbUaYgxUyBjYC29GB3CA9TbLKKomnFPmvha7ivtFVA6BvGxPq4ANXT/uh+SalO1rw0NVhQcfiA+hWowPPQRZZOr4iOnL3c8thEOx7W5wKZjMULZdMn0srrC4QuX1HVOLIeZrJlB5fUZs+pWIrYr7Qmywie9Hx3J30BSrslQDeTSZpYobQ2youWK95sos11ALlBdvLRFQXhyVQk5ZmprB8N4+ALAW9cVb1hevheyGJcWxw8UOFyXFcZHERRI1xRtShapdYc3yjub6+aAG8sHg0dyb4WGLmwt9S1s9gDzL3V3QtMpSDWD0ZJbiRUvZvqVU31J2e4xwwZaSVZaSZUMteGtPK5QVx0p6cZX0nsPxc7yIwPmQxihHXfEFn4RqjVLiiNiI2POZ1l8CYqOW+InQu7hr1GCgTGYo24piODeJcZng/2w2jidjJWVSyMCTj0QJr4lQlHHKladMqxA4kUQQRqXjWapKhJvj0PZyFcN3VxxVXnAYQ8Xw88kkt+aOZSuGP95rGIFroHJtMHSNEuFzjP2mooa1ogq+8eDjCoHPlHpjTDmYTd8wqPNkTCErlQOjXZERqHDc6Kx1DM7SEB1NARKb8EiYd5x1LDaKB+pYWkp6r01apBZXeCty35uxO6rC9zJYFM4qtYC4gqz9B2CLWKWO9yzHp0bW8UZAQenu82COrKlnTHGnT+DO68igI4sOoRqrmNmATp9WZMYbdqqKgm161zZlPNOIBDcm/7JUt9GfMxHargQMS1rR1sYIa1VOe9MzozKv4zb3TLeiLG1FNHsrdsfUyV4EqpxVJxthBaWxa3GFtaKGjdVKswLYiCt4enYAtPBWZK4343dUZetFQMtZla0RWlYvZl0LK6IV/erN2B1VsnoRsHJWyWqElZWrVNeCimxFmBrboGa1qBFUUH66Fld0I4rTCCvNikwjrKxaV7oWUUwjUtIYtu2qR9fGVJEtkcsBIjLOZXMKA4zQAYaVx09s7JHzBmlpHn7y++v7uw9/Me+vv9y97z7ynn0vP37//Uf1/ocf3wumjRNBMRnIB3959TaTzecv8DY3z1+5+PqVC/iR397cX3XversHIc7nz9fwSx6P2G8rmVjUwPwy74l4C4N62GVyj2c29z3yHNC4mOcNemd8ExX1e7geYojRc9R1rrNQaf8VYRdh90yDM+qkV12GuPRuUri/ub38JV286GUIJUjm2rqYZeAQa4wb6qXmWono4ctMCC0V4ZlnnSV8o7Sh4xDIhOqQ6yjiqB1i1aujE14Dq54YIvAS2xPcCkV3GhXdqVuRZFX7wgfaF9ki6YY66Tkmoh+iX4Po14Kayvjopaqasn4i9Gs31oK8oxiq3nhPlFJMriLfLWTp5kwSJnUBoVcQEFKWA0JZDIjngDBV9Y3k5fpGNRkQWpcDwrCpA+LBX5PGQXGbvr3lf3QD0aKWkegjJ2d9C20jJ5cLNFEVXRruuWDXMauuY0/BCjUkrdSroZrQTN/BL1mGLyFQeaZR5Zk6yBZVq9oOp6wYtR+YxkTqpAu/4As0ka4y0fTYMr6FbA1xB27IYmm0vNJonqclXAzNZQiNEk/zk3iqgm9WHG5qMELGtxBtRtQpWQ5oTlTgzCbtYP3iiTASuj87GzpNIQH/WCl9sialIHPwKUshnVGKHYlpc9ghXbCo044/BpaYM+fi2kWdGnPHskWdHg8RznsFoG5R4KtUc5ph0LcRLqIBGaeXHnhc/aZZ3oQZi3L0xSnRi5A9ZKeLBuJURsqzoCwRk4hySWhlshJamyC0EAFyN2RDhBSZ6Qxl4UIyeUWMlnUQIhtQbHqJ1nGlmhYxjXouHkCEkHWzzNXBiGpGKAV3M6rJtYvHJ/RwsguEkNEEUvrzcHNsfnXVZOX0Pm3DanZ6SRTM84VooaAjWxdBqcIGThtQP8GYak725MUl43IF4e7QzNo6zhoQOtmI1lEVTpYAIOdSOEEEWbG0SR2E8AY0TbAGaU/MBCEE95f3RxHRgHzJS8SOq1uyBBQ5l24Josh6BUvqEEQ2oFTyEq3jSpQsAUHOJVGCCLJWbZI6/FANiJJgH9OeGgnix4plSOogxEyvP4II0p7wCCLIOhVH6sDDTi81goHaoMZIVRSJ4r1cyQbu5crtQRM9i2u5r9A17GWqoviAHCTVlHRMko79EmmmTz1UG8ledWRRqOQ8KcGrUkIMBJeiLabEPJ56/ilxBo6NKVOjyAvWoLumtJVc3sqqycDkzeMnNmZvbAswMsQ0JnvUiwRX1vOkRJEzTw5qBvX8xJaNH6bKWNPH9IS2kmRxJRuy/yH7Xy37n7QDoKAoyrG0XF9LWoVjipdxzLTQxCkyVOmqXs1oppZduE2f8plUOA4NDLaCwNi5Vd4LDCUxMHYCo7hZtWNiPWDiESRPpjRWuSVvbvWc0lQaRTuwNl1sbbqfm5UemrlXPfFt3cK6KocsLcfWHELRjnHB21RVi2agWrSixahmdiCsxRLV2w6NiCJ/SoOIMaGtFEVRDix91l36zHRgQA2diiiFohzzE+U4FMiLm2YNxsqUtuLrFOqYZTG8YKGO3a3ssjsYCnWcU7OgMXegUMexc/SHLg9ylZIdMwz/1gJHNSDe8VrXPK6MxyzHPcfiznzNPTJERwUxVpEQWYjRWsa4DjZw460LjtvsUwIYMI4SGaTxKmhqAjTT1Ai5kDxfEWXjoQCjG5D2eC2CxxX5WMSM47mI8RBgkI7tOJAxFSAz0P7Ro+pfSymXRCXpuovIIiULkEITIzxJ75XpNv9lDFxbEiRJAepj6UVIGqpfwbQ4NmxnMFi2U1WSIqxQThBXZqQB8sYM3nB7vfWNbcKMXae+0CI2YSkvOoRKLF9QamgiYNF196Om925r9mPTyw8hCixOiAhdOh9JokORQzQgToRx1rBM0WvOGZd4DHe/Z7sxpWUD0kWvRvCoIkZLgJdziRghvqCc0REAoxoQNsL6pWWJIwQYPF07DmN0A7JHr0XxuAJIS8CYcwkgIcagFNLh+GIaEEV6LYLHlUdaAr6cSx4J8QWFkg5FF9uAZBJ2SC2LJyG6oIzS4QBj6PSCSogvLUsrIb6sXWTpUGhh08stYfA2Lbx0aGQVeSlnqiPAB/Yi+wIXQ3Rwk5DfPPzk99f3dx/+Yt5ff7l7333kPftefvz++4/q/Q8/vhdMGyeCYjKQD/7y6m2+nM9f4G1unr9y8fUrF/Ajv725v+re9XYP2p3Pn6/hlzye0N9WKlLsHKOKfiT1pmg4ijuUGUQur8JNcrepItlFVbKLgWSXTUid7AxnyYHAYlPzzZ2HmPiAcCjS7LaYsRPZSVepKeFqg6vNaaCsvwvZf+ohBn6MpOMjaUiEVLOq8Qwk6Z0Qx80Cyx82tPr0ApQpLH++hkORa3fHsFwMZL5ZaPljaZWdpgfIicxU3knhQ2bic2SxPMBMohUCy6ijc1KIxIQSijrLlZcuGJYlFyIQ46wSzEpJUjKEqeSIUcFEk6LlhKgjJTnnsLwsmMByxx+q7A5GkMDyjAx+jblj2QSW45BrHLA2qFWyV84w9huKGd0AceX2Y4/MWTnLQ7qxrlT3PMON0sZmlZ3oLgoQ64nkyYnkk/GEyGQFpHUQArK+u1SVGeXOeWOCy4TQpST2ii7sHoAoVSRyxYsUQmGHMvLgebEkNhpxZB60TocQxzVb1tqqfefpnduM6TSh0xM6YeovicsJvTkLGqcDoII3wOCE0dUmeVPPL+POLWMbOMM2UBPRAGVTP25HZWtaAp6ci60JAWXtRE0HIIpsQAKlF7jjqp8s4tD1TPRMiCjIzHQIqKgGSJl6sTsuH9MSQOVcfEwIKiunYjoAUHQDLEz9fZRRCZiWACjnImBCQFk199IBcGIaoF3CbdlGGZcQTtZOtlSPKJRMz7OEgNIoxRICyorZlQ7AEjo9sRKGbKucSgfEU1GAzpCBS4Bm29h6FncAH394d/j718u7ny/czY37dS9bldlodL830P3I1FW3z8a5jj3LpzYDUxiPH9iomyxyM50pJ2RVToiB6FKsxZyYxVMvICeGDrwOOCmbNDdUcW1tz1+TGksvbnGlA8985GX0p2e6AK+lm+xC+vAjPOvH7Qff9sQHAdW51Vo5F6yTAZp9JrnOLFGVgow0hcxz9DSGoEJONPtEFFORihA8F3U3dNjOiHRvu5T1hqRJg/RQB0bKi1cqYXyId+N5I+Kl/ZlPZfNyG+brL3r3bKZ3+f4qdFaZbSlkFlcK0YFnplVPjAiGCDYLBBuqQ0+HYo0WruX7f2aIGcpsF666he5o5+S2v29oRBVV5flp527Tp3xxHu65QwODkeUHhuTlwFASA2M3MIrXXndsrGXZxkYtutdlvCqNdokct/NIiBbzyLKyj+3keQT+aiV9iicL7RVUk9qqvKumhmyl5khbebCxdAM3eF5t40a+xzPH7puVN4jZcXQR28w9OTmSnYjSm+x0SipwYihXwSZuTZAiO2ZDICSoronWEVAJ/GMp8RIa1dqBoMaWuD3pWmC9WMzFnYMRpRmyKS0EjYIoZ2OMgUqejOApC++S1hCglMtksxVKEueodSJQ1sWuY4RlKd2RIbvLW74dsrxBBGGmBCGSIIS0AiF9dqmbmwt41Dp2qa/f0yiO2Apa7SK1jqQYtqOFbWthxEkr7Oy4HA0+tRnYgzWn9Afm9XmWo2ru7qaXIc6wnJ0tfghewg8lET+wnB0LR0pb+nXrnrIYt+utZ8U6FSX00K0ePY0o3PiKEgdHjsSt/vlO7w/4h1fNpuAKcXI6gWK+GHPSfPHRC5mYY1kBzgYmfBKCOK6ljF6mIJ0PRiQuSY5ackUiIx0AK+a9YdouBHpHZFLDU5+hxUU1IFr0erKMK120hHso5+ISRzBD5upjMEZX0KSUCyTBsEDCAgkxZeQCqTlEsTWb+2Vt2uMOmS2lEI0qSdcxo4iULPS/NDHCk/ReGcq4kTFwbUmQJAVvAXxESFoQ6JK1OBJRZjCIv1NEkiKiUE4QUuakj/bGpYVheNn6xjZxRhA8RJzNIeIO0IiiQ6hiCDSzEmJc3NmiKF2ukgNni9tXQyTHxmhkeFGmCC9GIbzMDF4W0h0JXsVXMb1rmzOgnF7rFUFgeYqv6NMZ6b4eDB66AfVXjLSWNWBf9c7IbMt4njbb8zRhGtCDfT2Gx1WFXQDCnEsVFiEGtWGPwpiaEzY8I24aY86lE4sYg2qxR8KMJA1oxr4axyMrxy4AZs6lHIswg/qxx0AMbUBF9tUYHllLdgEQcy4tWYQYVJQ9HGBYA7qy2Co1rS6LAIMas0dhjJheaRYhpmm9WYSY1avOHowucnrtWQzfthVoD46tIqu3HWJAt3z+OrSPvqswWVFvypKh4Vm7rd0rW6DBmOlTi4HSygqUox01NWxVasiBIFO2xdSYx1PPPzXmoUpbmyKqKOXUoNtasBld3IpLudq5sNKr3LmqmmseB1b0UEHYo2ExuOKeNzVYMTX0EH1Hz19Dt7sXgie8ymjcDAT5KtoeJaqMNj0wtGAztbh6mA48Mz2OU7dSmnjTIR+88yIx7bjMmSVtWLCaUqqdcppIbmXwNMVEsvGRS66JkJ4ZF7oJaKFd3UwQk0MKxds3gLlGhWJryyAhiECF4lk0MUXKMEuH1gLaHA2OIGTgQv/jJ9YpVFwdH2Z58UEHRG0ePzFavzbv+CjtEwrCBsb+Hj+xcdKzimJS06LRdi6+877RemTWchVGK7d6zRUkLZhMFuNMDplMLkDot9pmqj0RgK3eaFwtgFl2tmPK/jJjlApCeO+zNo56p5SUNDPvTNKBBZ25A9foFJ1TQgYupSHBgu9MzqRyLsvSwR3yOtZNlP09cj6jGl/0OpkO7dAls37krk79F5EE5dLq4cQ0IgKM0dsgk111NNl1agHPcnEaVQsY03vFWsC1MGIo1rizhZGzSgIjjGCNWw8nrEIZeCB8LYbv2otcI1oRmsZwWkI4yVXqTe8cDKjyucAQw+Jy9KarAwhPnOZ/S2dM9el1LxstiytuD7GOytjQLB6jCHV7K45uT4t6O3VGlaSe57WzaQQOEOGQSf8I4DGtCFRjDYU1FNZQretU1+KLJeuUq57jPYzJ5KoRYFC1+rSog8fd8znunky8GmEHNaxPATbsZFLWlGEPtVQta0QblLQ+BmVEFd3J9B5u1Y6qOYFrRIbF6lyja+cnd12NKKY91WuMuxmIX285aVy+dzy5m/3JnbXtSWFvR/SoithLgJ2RFLERd1AY+3DgMYS0p4+N9c4cZLIReFAt+0jsoe2JZm9F9bja2UvAnpG0sxF7UEL7CNxh7Slpb0X0uILaS8CdkQS1EXdQV/tg1OHtyWtjpzUHlW1EHRTbPgZ4ZHOa24g7c5DeRtxBBe4DIUc1J8SNwTwLPe7qSNNFDv6+bEF/Gv3xE/tzxKDi5Zu6L3TgktTjByaQBZq34uWnS3/jbn59TJHbX6/u4B0vw8Xt/U/uZq8EKQ007Tqtfyu47zU2I2WPY01HSZXp+uduOwGvV2Q6VmW66aGiHcuJouXY0IJGezzRfEWmU1Wm658o7phOrMh05VWCD+Vr3TD9kizHijL1kg/d4ZS8ffXTh5/8/vr+7sNfzPvrL3fvu4+8Z9/Lj99//1G9/+HH94Jp40RQTAbywV9evS2Y+vkLvM3N81cuvn7lAn7ktzf3V9273u6hu/r58zX8ksfS67ayUG0MCA6bLiyOQwh9YjXhW/DUL+7TffpAnBNG8WSiM0oqk6M3wShtpFbMREmDlvDtxFkJ3bXgUWmfI9dEqyAkV3VvTQa0g+l250zt6rWDBVVDYL3dPBo9qz7sdMLBpd/y8qz3XwDye08Kz39/c/XuISGabwAZrdohUQM7JFo2SM52Wg49BEMEQ1RSbxPMWBWYaV0GM8tb2DjdiVFWDlLFphbMDp/c7e3Fz+725yaDpDhps2NuPWBuLVfUzcoq0xk+AKcr2i1musp00y9E7Viu6vIjNr5Y682h1ttvNgA3CBvcINSDG4R67JOCCY+yT7UjUt2uNLNA8fJBsB48k9OrPZPjrMp0DWRaO6YrnwSbodXOrPZMjis8k8Ml9/w7N7McLxSMDCAH6/UWEqubGZ338Br1ITw5wW56Od30PE8zlwDIQ4dUB9Oc1ADzCU/K2kHz4mBeg5HTjuVKu8r9ETDGSgyyghxF5K6cTEownwLNWjLFiXGaC22I1ikTSZ1SUKU7qZwlVCYhjIsGFgxGlQrOHImBczgE3ZmlL14KE/IofwROFSOesCiiJgo8IFiwxnrmXAyEemINjTSD3yznzuQkLNeAEhw+Hitvf72yJpXdwW2D7ihrOen5CGu35o59hLUryPLD3b379PpN9lP8/FpFs405gRFuER67Ygi6Rqn5OWZE22HEWpH/Lb3JuCLAM72JOybfe9FZlHlhhUrCmeQyVI/WxESiENnJ7ha7ZDyFzBVRlBpjrQgmGR87Pg1LpeELQYS1EYofDUW8ZrKmyO6r9PmiWwuaHJc6Ks6VJz5F7TMRmgnoigCFOKVRCm4M94Zw+LcxJCniGGdEkKBXsEk0KhUzQhFS/Z4FjkSNkic/KY01bskcLSBcbHkoU4g5s1XYe3Wgf3H9vay7CTe519u2pm5Eew+RY+EKfOjguerwHY0xthU1PozB2WjyFV01KvMjbqQtpXOVpBV9vnJ0j6nStwggOqtKHyIRavWdHopoK4p9WBPNR7cPoQi39M+CRqwVDb8yGo2p5LcINDqrkh+iEer5nRyJeCuqfsXoHlXbbxFIdFZtP0QiVPg7MQ6JVnT+sD+bj9of4hBq/p0eilQjyn+IRPPR/0MkQhXAk4KQbkQLEAN7RoqAR0dd+d68GJI9Y9uVuKAN8EQ8XHveyhbTe2oht8NGIXHVmYmrmBxSgWOyiqEWZQ8f3usn8Obd3y4ur/L1Xului+neoJOmspQqyoEwPQiMugpi5mwphpba01IcLbWnpQRaak9LSbTUnpZSaKk9LaXRUntayqCl9rRUufLsszSzfqfPtmmaxXItpYss6nyIyo5vU9lJslxDFQtPPiSezXsHU3S5hirWnZwNGYrN6kLnMYYqFlN8SN6Z89nKsdcaqlghcDFkqN75/YIjqrjs4U4l7lSeRh9JD12uevzE/uCEkXR0JPEhanCuqga7UUBgSiQ35bK872umy87my63LDauyFDcDacGWayleZanp8WMyQ5ULcz2YfHo1yaerLLWbfNuWkmK5ljJVlpIDhpKLNZQtr3xmMPnMWpLPsipL7SbftqXkcrekLK+ylBww1HJLBCurBrTEwIBWG8pqs3xqMbTzLtYoPzRZXhRPcxv01WSG0q3o++hsnKDd5UzJdQ6KWsY8cVQFkQwznmvplfWOEa61diQSFhhRglprs5T2SJDZoa/ugQzq+5xV32fXH2V3MIb6PmdUM2nMHcvW94GfmcJdivBg4fr+akN10sV4A+4fgxa4dt2wq1T5mWFeNBQ1lpBWRH02HnxkDZ9Z3poZlSV20zcm25DBJR4cE5gINjDnDUlRJUmtSClTnZxwKUMJwm108BmmwIXZ2qgcWUh6r41ptBZXaCsKPZuxO64gzyy3TUZlWkRcQbK+A7ClhptPqiLLEsMdkpHldlixUKGaIaLMRV1nuE1eeNNtCa867Zk+JJoynmxEaQdBY1nCOujPmejo1AKGbkU2ByOsVZWcTc+MS36EW1UzbSdNKxo4W7E7quTNElDlrJI3CCuocFOLK7YVQRusVprVr0FcwR3wemihpBV1ms34HVeMZgnQclYxGoSW1WvP1MIKbUVqZjN2x1WWWQKsnFVZBmFl5UIytaDCWtGNwTaoWZkYBBVUhanFFdGICAzCSrOaLwgrq5Z4qUUU2YiiC4ZtuwIutTFVvvYsBu7zCiGqbvSiXstKuet2fMJJ2SeCo17LHpf3IdV/gezvrL5Ptusq9tAGfDSVoco0q0NEakLNVtamzk6MIB0tAvEIS/o8C5Eh2ilhWmf4WTJhayXUFQW8GnT1VHZirfADOe9VME5BG2o5t9SQHI2MJGhJrJVM2Jy5ytGb1J3hKQ9LhQodAQQhUdUKHO9AlBiAKCWQH+iM/EBiaKtA1B3eID/QUTwojbljJfxAX3F7jJuJlauEWCUb0AyzoKWgka2QAb0898hcQLNshEa9+rbhGi66IoKwHFXS1iaeWRYuJS9UYt4SYj1PRnIXpIeSA7Lcy0wSdSTEYIxZSG6v7X5VJaioClDh9qSRi/3KsUM/ZbIOglAyO66Op5J1YfWurjpnnd7fLdnONsLDgXiwKBoOdOc8WDjq0ILTVkg4ML4a5eDYcMy442vYIs6yReSsFQaOzcgdlYBjCZByVgIOxJTV829UggpvhYF6I3THJaBexBHtOdk3EFSQfKMaV0Qr3Bsb0Tsu9cYScOWs1BuIK2tn3qjEFNkK8cbmnsqovBtLwJSz8m4gpqybdqMSUVQrrBu4S9sq6QYiyuo5NypBxTRCuYGY0irjBmLKmgk3KuHENsK3gUHbLN1GXUSJ4nVp2V+iWP8SoeTNXc2lg+efvWM20+AV7/0NFdOXmwTGSPHisPvXss8dIPp34lVvwwR5MPa4oxrTp/QTuOVhqHSvVCxe55Vi4Dqv7AFfC5fkH+4DbqViH66lrsrFk8XWm1ERrmN6RYxvwrBgVWHBBuKC2xbion83nen+U29fTudy6ri4Bb+Fu+tGoIJXxYSg5ZiQTcSEHdKUl7axmHi+LgC/tI24EFVxoQbiQqsG4uJBsrdI2fMs6ruxxjQRF23EhCzGRHvF34SmKqolYlsx57Ziz4eeY8MrFBvoDRSroulAVqeJcchUbcqIgRjVtMXMmsVTLyCzipPKtfPNE+aErcoJzcvRZUyLOTGLp15ATgwN2h4woTtdZkhSVeDT/uiK3KaGZU3G2M7GYS/Ipt84fGN8YcK4oFVxwQfiQogW42K3qWBVF2ZHi4s2QqK4l9wgsE9oqmYuQ209+sj3oWZZobDyXBU7joBjmyEJLEsjoQzcAv92NFvHlciSCemSZNGZpCVLTrAUs4rRwX+iOhgfkzfexUp3NLaDux8XzvN26LIuQdVDSs09qAGiVXpU1HquDAlOKmaJ4dbGYKzOHUikKKUyKpHsnXVeOGo4J4Fym6SizmkvaDRHRu0czqN2ClBTQpEjedYQRU6NIj0urzdO6vb/rQ/f2CSoyApy8yJ3kVQYw+PGcGORpFqhycflafCpzcD+iDmlPzC1z7g81TKpt78iGSxzZ4sjgpdwRCOOYJk7DaiUjv/qFkONOz6rrnMVWaXQx85Wrirv5DKxbKGP+riheCIw0xMBPuAdXnWWjAvEqS9YU1LklqJUnjBfqM5dH6BIMi4CuipwVgZXOeEYjdalnJnRkDzwRZaohLyx3AnpqbfeJLYQ2B2Rtw4Ph/ZYXVgrSlLb2TKumNQ8LxyPSeGOWIZk4QegCz8ZXzil5IQBbJURzshkedCGESqCowKgJEUokJJnkjDCrZNOeyW5SSFyG6TKzmXKJLMrGELfYbgquscwhBfkDR8dX0QFz1W5+xIMuy/svhBSpui+GgMV1cpBYiLSOAF1CNPUkCiy45EF4TzLIrHAM41Uy+izUsxxSZXjJieIWcoi4UcfJM6A6mUHU3gZU6RGTJmPFOYbpDh74MvmNzaJMboGY4qnQUIfhzE5JO6D1Yk4bRkPSlkrqCDEdCoFwRGpBMCPJsKFKLpiJhGvu3kGHQhNR2LMHHiDdkBGmSLIWIogMx+QeYVhaRhgnr+pSXDBSaj5TELt7oKpouDjkepsCC7jVjCLnYxSpckoOVDByFPOs+DWSz3IlM+KmMI2aYYgs5wtGE2rWFemd3Fj5uOtKH8jErQr/r3tm3H59PFIf65HbrrmNjmeGTeMLWdVAUdwwQP9Q9ClSl8TD5BbxpezCoIjvqAm+IEQo1qRBe8BzKjK4EsAmLMqgyPAoDj4AeCiW9EH347fcSXClwAuZ5UIR3BZvUp4PbSYGp4kUuRJwo2XxWqFI7SgXPgh6GIrblJQWbzHjuiyWNVwRJeVC4dXA4shjWiHY+i2LB9eH1fFERG1owAs+qICuqokHoUUTw3sPpptaQyuG5T6e/jJ76/v7z78xby//nL3vvvIe/a9/Pj99x/V+x9+fC+YNk4ExWQgH/zl1dvqgJ+/wNvcPH/l4utXLuBHfntzf9W96+0eIoOfP1/DLzlITVCTIeEPLVGkvFoW49Olv3E3v+6f7GUBETMkILLNxMdakHjTQ/QHj5/YyHYyub7sJ3d7e/Gzu/25iZjgVTGxI+vcCwquWwgKNiRQrtmKBMqrQ0JUhQS35ZCQTYTEEI2B0Hxl+uTVYSHrVo+BsNAtKJJpMSRPrsWK5MmrQ6I0BNBi1TedpUrHDtixYMdyEn3FObbrQquBvkMr1D+fTv+8Guls1Y6SGAhRTVpMrFk89QISq03589qUsKQqJfoH2/3gMrrFlJjFUy8gJVpWP69ODFrVP+yInz9fjGpI/HwnxHbEz3sxtnzx8+qwYFVhwQfCognt852w2G0o1Hq0z6sjorhL3SCqT2cp0YrOyeaTjyxzMsviZLnC563tDa9a26IaUOQ6adBmec61YN3zNYDIXGnPqjFFrVL2fBEh3FYg6XWqns9ycVqw6vnKFqfWVc+rYcRijTtbGFmQ6DnWuEvBFEYIWafmORa5J48kukrJ851NXFXewz2zkM7kkufVYcPwJGCeJwELFjyf5Zj4yIyJW+liWOBeKGUYJAdgK/EykCy5j9y54HSEJiAanY2nUnNteYAWgWvFRHYsM7kQzEW986aWFt6K3PlWroyrdj7LaetRaesRyJAZvRpaRDNa51vhO67U+SwHzkelrUdsQWL0enCR6xQ6x64LAQV1zs8DKVUSxPykXP49SHEyKcF8CjQDdihofJzmQhuidcpEUqeUYtJJ5SyhMglhXDTeWEaVCu7Yo8MZsMXsIAorKxBLjogyH/m+12h19sCWl29rEV3MOgXOZ8k7tCtwXtxcoUYjvKC++WTQgjNP85l52t34KpKfM2YRWlDdfGqIoWSd4uaL2G5hgpTFzbE5Qm3z6aCFVVGqTO/htqwnWlE2RxhoVth8yzXjEv3j6f1MD9iobEXWHIGlXVVzRBY8u6+HFtWOpjmCS7uS5gguqGh+EL7oVgTNtyJ4XD3zJaDLWfXMEV1QzrwaWUwrauZb0TuumPkSkOWsYuaILGvXMq/GFduKlDn2Q+0qmSOuoJB5NbQw0oqOOUJLuzLmCC3rVjGvRhXaiIg5Bm7DGubVUVUcBTFkYJT18RMbAw0toDgxAxoXj5/YKOANSgKeWRLQ8IEbT8aghvlR+hYXn+jFw0Bautkr8YuiIIYOuYu2J2duxJCcuRGrlTOvDQ9RFR47N4x68dGEsrmRQ8rmRq5U2bw2OmRVdOxcEulFRxMi5zs6wrsxrVYscl4bIapueRmIkCb0zo0e0js3eqV657XRoYvR0Vyt2ITNilcOsefBnuckGDfHjl8YO2Rp2yOnQBX0iVTQK1GPk6r9KTkQrYa2mGPzeOr551j7gui12UGrssPwcpxZ02J2zOOp558dc9FGr82R8glHe35rwmi8RfmDjZcYWQlhlqC0XE3k1vaPkP/+QJgR66RRmuUO+YLlkdeAJ0vgTaqFF7lKpeRFRHOzMaXWKZo8yyVrwaLJK1uy5iSaXIsoBovg2SLKgvSTsQheJrzYdUopYxV8xqASZJWqyjvbwKq8C8zFelSVayOI4gnD7E8YFqy1PMsR1QmZ3DYzh2fwEQOojYEzaBGc45E774iKFhoKbxnXhjDmhBAxcuYD8YHrDM700GbwhYAyyi63uvawFhWYNzNoXDHmeV7znIppG5EOmZ2PwB7epETzZlCPq9Y8y2nYydi4EXyQ/PkY9BHr1HDGbg5hBuWcxwQatU5l5zkSZ0yo7Iw4gyLPp8McvU6951mysUyo94ygg9LPpwEcnNyaz+TWhCrQCDgoCH1a4LHr1IZexDbOiNrQCDwoE30SwJF1RBPTO7tZQ/IabYDS/jsTCBONEXr//Z823vWY64YcfduIb6+g1kn58m8XV+mv3XN3fib/aA1UZIuK9Bh5cxCn3/TSuGIOOM00/3kCqVqUrEfkmYV6PUIPzjIdgz26TU17RJ9ZyNsj+qDS/ZEAZFoUvd+Mawowk1g3cmApzUo7ZpxOjAPcmJi5ddYz4rUl1JhslRLJMUV0UM7YmIJcH/xIMpKCOMLPOeHHX9799fI2LRd6bA306AlimnOaXGYsG2FM8FDVBJMUjxDTlFrihQaEsTIlG6RxlIkA/z0mKSQXmgayPuhRxXkEjdAzD+hJ4eL6y2KBRxX1GIb096pGn7HlGuvyWhF4jEDgmZPi9cXt5X+kZWIPqzg7t6Wzc6oQepqAHlMcirUMoWdO0LNM1OGnojqzuJK2NrHTWqwVVZdtf43rD5I+fmL/2d5RKML0EKnF4yf2pwlDZcqjlSmtHLilareHxIVYsl7iyQSXwvU9GB5e7N5BFN5d37iHM5DuKOR2r/QvymrbQfnyntdaH7M9qel0lekEGwh4viLT2SrTTQ8VzVhOF6firRrMV7XafNW8ynS7+apWm69aVplODlhuTUGnq8prNVBemxYEu2f61HooSjWKCU+SIqaYIu25rR3L2VVS4u/iTxl+uF02Jf6xYWRIK9zEpTcZmaB4ljtfo168KjorRKuFMcwSH1KIIekghKOSGkGjJRFaQEo5DzYqRQXxNPucNRUZ3KWUpgtBhLXd6zkaimgzVMXF8B6Xr3iWBfeoV7EQi/Ciz+nBiNX17pP7uW1rikZoKBArFs5FgQ6eKyHF0RijWmGlwBicDTVF0VXjTjphH7uU0lG3QlKBQDQfpgpEIuxiTw9FphXV22J4jyt9uwQoOittBUIRclecBY1sKwQWxQgfl8ViCWh0VhYLRCOksjg1ElnSCp9FMbrHJbVYAhKdldQCkQiZLU6MQ7QVegvcKpoPxwXiEBJdnB6KeCNsF4hE86G8QCRC3ouTgpBohPwCA3tGDBhHR13phqMkO+ckPUR9/MRol0P3ihqmh27vP35i46kl0mCclwZDkp0b2qofSb3LsgZ5MPa4SneTvnxyIT0Kju+V8KqY8A26aUJblY6QEWYQZs6kz14WLa29svr0TBeQR+kmQwZ8+B+/fnx67Hx9/cFq5pwQOjshiaQkJepzBAwL0jqvWCZKSEV4tK476uMp+sisUREqO0eEqntbyobel26PRdMGigpJzI62bD+yzPbhiJ3VAvZyh/frL3r3HC7v8v1V6Oxy/KDjy7PefwG47T0pPP/9zdW7X9yn+xZXTltVKmteLpVNg8jDi8gjJCIPIs9ByDM053M69Hn7N02GHJSQqpq7H5X9moWxFqNSqoGoHKuhe3thSp/yhYvxBjzfRlzQYlw0mPcT2ooXbWXLbDmPH9hIoUWbSlap9WGzgUv+SZjG1ODUhhJIPzzuhgglA8BItznEBV3ytuupmtDqonXCxaC838uG1k1WNWk1CjruxHS/bd0JajJ16fngrouf3e3PbRSepWuaLWLGhKaqubiB+ydYTOHO3Goia+epOe0j5fZTa4U7c2/+ppqy7IRPPd3SQhe4LbiTEooPpITEbcF+XBS3BVsEnQltVdwWpHyoku3NDy7aVMVRPyoHm6qe5I1csq3KDZIaCiu1IlNZ3G3GMnaCtm6Os8mSmiHoMK2rceB+7DFwyUjVFJEYCGpNW0zFWTz1AlKxTWGc+pyguMeKJUQDuDWHmc0l4NbQ9h3uIe4NnazYqLYXKhOaqrRV1McvxkpE7YIcJRumnExKMJ8CzVoyxYlxmgttiNYpwxrjlFJMOqmcJVQmIYyLxhvLqFLBmUqUm+EZPx1YTo5c9LfdEThVjHjCooiaKHCAYMEa62Hdj4FQT6yhkWZwm+XcmZyE5Rpij8PHY+Wd5t1FR5XXHCYadEeRWEHq+YjqteaOfUT1BtbIi4un73i+F/4ae8spfn552Xz6uS/r/sYYzAh34+tXCLlGXck5pkBjcaNaEZLcevRxlSPnuSE7qjjKtndSill5ASVeolql6FPiRvvgWRYmEJKs1FKqznmCJ+00c4qyYLK2LGbmFpLka5PYqEcX3Yw25HYAjyoGOc9N5lElTxBeUDfjEHxpRihjO4BHVcZYxv19SgbgH+sXVMOYBGOqblHwkwq84N7rkaDCTBFUJEdQaRhUNrcDIRNevYk2+507XjdVM72bGzMfa0SjGsFgaaLU6NHZqFDXw4ZoRXYao6xdnelt34xKII673rPtGLlsRUkasaVh6WgEF9zzPgRdqk7scVe16WG0c+pBI77glveBEKNbUXzejuFRJZ4XATBnlXhGgEFN5wPAxbQi4rwdv6OqNi8CXM6q2ozgsnqZ5nposa3oMmNj1LAQM0ILKi8fgC6CNiK1jODSsLYygsvKxZTrcYU1op6ModuyXHJ9XBX5JdkObUBvVFKyHnGAQp0O1Ol4JXXZEFMp4yvS6TgFSUgXDvd36YCUF1UpLwZSXjVQvO2G1w67az++liuZcXhgFAl0G8zgaa1VpNBlYshaYo7MRIdby6yTnGiWcLpgdqIdf6iyO5hGdqIzUrM05g5kJzpJK3rwKiHJKgmKZpgF7YUObYCj6NWnH5mmaJZ7NmNdpnndQQyqwEycd96GwLN3JFLuOIWKRESvPIH/7GSAihEyPOVMiHM5KMNV8tZKvZBsX9GdjcNhhq3zov8i+hhVvOhvOaIKXvVvAmTqDmWm93R7FpTTX/hHVFjgnX906pyu/R+OH7qBm/8Ya01f/n/dPeNOxGAvOede0pyM+PbUW1aOJW05Y0RHoq3roITmnL2NRGaaYvZBUkGkoJ4Z7xnPwrlkhGY+UC/s+kDmXCwAiDJIBHAkzNgG+G9fD+NxKXAXcfZ7JjIAhBnkAzgaaRRpgBLg9UgelxVgCUhzLlYARBokBjgOZWgD3ACvR/G49ABLQJlz0QMgyiBDwDEYwxogCcD937Z5AhBjkCrgSJgR07MFIMq0TRiAKIOcAYcDjJyeNgADuHHmgEOiq3ueziAPr5Yen+vvI92q6KLt9jbd3L3738Hd3v0mf3n3n9/95r347Tfvcvp098+//fd33717/R7Of/3zVff6A8/JmLVJMlj7RFCSqpC1gYdJTAVDOM3Cu2ipAFtpQ7LiAl4meMuVzM44rl6e88OHdx+7vV5wrbt78C/E0E93P7+7vH13dX31/ir9BDH7S/r2z1dPr9TbIe7exd3cXMD3wcPDz/vhDoLs4Ufdf4HXS/Fd7zveudt37l2XDZ/e/eJuLp3vrrlfv/tLSl/edTfaf3GXnx6+6DLE2sMP7X7c5/Q5fPkVnuTxW/s/9budr/znd/Txkf7v7ie7DTCF37Z9T6n7qemu90WInS+/brsKvvrWW25/6kQvuf1D/8tj/Ow8ErzpVxe8++eHd378Kb/589U7+Cfe3n33yot98/hfASm+g2/++jf4Ed9t/Kjf7hmPUhAdusuQFsLNKYhBE5xXWUdrndaWW+OFZkT54IUSIejEYrJCpCCzyKeOx94cbrzM+fZrgHZeroicjzcJnLu9FO/GyvMvgR/1kPHb5n5K+8cf+adbWMzv0ucvEBbdYn57l1x8d53f/Sf4qf+pixH3y/UlZE36Ar/7EXbh7TtKjPu7hwWkg9zukR5+XL7+BCDYfexpgvgWHvDrz+/HySuB85atvkbSPt43yiTjI7cuAmIC6KigsiAyikx4MF5LZqWwWtkAcZEok45wZ2FhJV5St4ua2w+5jTC7afraW+396EapIIT3HiDUUUBzJSXNzDuTdGBBZ+4EkzpF55SQgQPqkwBI6g30FPbMgbv91mcJW/gVbwXtc/3w7ZP1vu3qh2+3K4atv11ABZBuMiw833YA6X5KH9OnT/OI/BfYY3sGj+VcGQgQAiEdcsiMcVh0OXSc3FtDaLLSSW8885oaxhzL3scMwU+T01a+FvdQ5N/fXF384j7dp6eggK89fuHbm3T7nAH9Tz684c4X984EThi8h+7eIetsZTQpKGuDgerGMcUMMzwmLRRVnEMxbAUBTIf/yG0mTG6UFK8E2eVVTH+DB+wn9qnTmcPDQ3WWickmO+IiQFMMUKuzCKtN9wUTpFKdJ6In4JvMaUjSBa1l5tkUX+Lu+sLFCC64HeNNTGJcJvg/m6FiS8ZKgM0OgJKPRAmvCbgC4g2QiDIA3MCJJFCEUul4HnBHTF8AmEZ4Ca8YSUzrLJNLhmgwumVBwlsxz7jjVhkjXKREZKugGmAAuQlgFj7VFdvFl4A+OQWou8Z0SrLcG0tU4Mwm7cAbPBFGQvdnZ0NHDCHgHyulT9AZdsVN8CmD3xysM6z4Pg85O8ZLZK4hhmiKAFlUKilUIASyndEYo+UU2ocu12G9My55FWHhNkwYZY0WaSBHILI+Xf96kW+uP1/8R7q5HuF9BFcMFm0hoANyAuBVsey6DlwLWMKtYYAAXVdkBc+MWA1BmHOOJkvvkpKp+D7P69p4QQap7YXxPFiAYEAucIyRTEJPGj3LyULeKwL5BD2dhKqKaQnBpQGaIcISpFvxfR4cM+K7xES6zgCqQWqiTIpRm1X2kXlonj0NxhhYKS1gM0AF1FTQPxinHSQNrJwinLm8+kv69extQfc75t8VPFlq/6ZAZCgNHCy5KnfQ4qiUUUNBxEPkAsBFBycMID1U3t0WBQNMEtnEbDOTljFXhpnuD93jnD+EJbUuQCPAoaiFgsF5FkwQigVKBYA9pSkzyxy0BJwJqQXADcCk0rybEIV66swhfPtYZV8EKLPPHstbvwy7htcdsH//IHmmTlEO5QIHvO/+kVIHiC4Roc7LXTVnoOMkUEVAc52gkJCRKwIFN1VQ2O7VNz9i/cmzQsMjJgErrYSlRzrIYksjLEBSu65GggVXG2gRKFHJwmLMlKHKSij3Mg9poLJ72YIYIb0Bb7rinwkCtaqmnZGN5gzqaZ6j6zYC4CWC6kalGKQ/FOWBuRiktlAtmXjq9H4tn3FPdaI91bdyu3J3devHbOyzvvrj99xxlT4qni2DejZJaYSFMoqSHFjkhMNCCl9Q0Al2q1aARZhQr2GZgnKeU+jxDduvtbq7/Aw47T5/GSMTEyXceEGIBJB4KGrhVaIkmStprQlZiW6bUUBj0m2k5Mik4tZ6WG8l9PX7oOFt+pQvzgWJOZOowdKSiWCF7lp0nRyx0AsGRZXz0H4AAkZDAXIoY4A08DV4eAFNYqbluv3+KnQr2QW8Abjm+mYEhyjiaCSUaShyIvw5W8eVyPB6UNhIFrsdUsmgEWGddkMEsJSM6mB8TN54F89c+Tz/5cxFzzNBx+yL+E2L7V/IK0ed5NYlTiKDDs4zniKU7ZrLbp3nnGhY/RODSGcUKnjqg4U4pz6nrCOnVf31xa37dDdGbJ+Gm+iNl3rmbxnlTaxnlEGLJbKmDgDfdHUlICdPQpnMUgKnQYqK4DiUOpC9UJZ54ZUW0GKT4ptA2zfGK3iddYjRS2aFlDYQqCtJ4tKmrmzspry8ToIz6r3yLFtPup2drmHUUCT7+n30ftida1NdPWx7+m73VhDoEyWHCFLcQ+nsMkRcgIoyGPCOIkFmiDDbTZUIQaQm3Cdybgh9mu24vhkPTl/5nQuA1jcsuT/Mag7BHoQlXisJhZDJ8K9kE80Q7wzawxSNiVAwGMUoj8oRw2mHVp7CH0k5j93n6/urMXBVC0EjtFKu644ClTx1ck3dPErSulsNuEw2WwHv5hy1TgQK7yaUY5DzUPOV3+LrAd0IrxFciNQQB5UNycQLwKVMmdLSQDvrdKSWcs4Yjx3pgMieEqusIdEHWAD1zvKwhSDdrwLQeXyNHZw6FxRpwBtBuzs8kusMBallzENVp4JIhhnPtfTKQoNLOHjKkUhgTSFKUGsteMbueRYTQhdpU+ybG+FgbaMQUTkIHSw3RMpgoRSVstuJU4laHnhOott1gdbIUi0gOpmzsKYbs0//8GD3kz+4DPBI1MWUoMDuFuhkoZwOQgXuZczUd7zi4DlKAQUsFF7wNgQWwKAY/FkXPXMNgHczhTssPK0kKoHpAaJE6g4uNE0QXknCMm4o40bGwLWFpY+k4G2UXoSkBWECeo7iW232cWO8ixJCE6qoVhH+P8KizrPo9n+hyOI8aWOkSiRlSKBu38hESJtMIfgsyTbsHvRvXhjYzevqcUBIUREdix5K9BAgziHQPdM5Om6gKIQOWkOjDPFOPJUSKkMoDaHpZMRzK3X2Bw0i3H+6OxdWOSaFgSiHJtpIQro+GgpvHzL0zkEwoTml3Umf9wIqX5+JUV2JmBW8oJSb7/NSmvR2qh4mEi7cVbz4W7er9FBp7BYsd5+/vGwPPZQo/8fGN24UKK9DBrwx+fdefMKPfPhy6Zvo699Ei9/EXv8mtn828D29A+kbjFPQ7tsORQ0Bv8hIgpbEWsmEzZmrHL1J3XVT5aFtAiizDKqUqAzfbyX5Jd3cdkXb+bMb1ixlIcV9pvCcVAL+Cgr5LXLkinKXuZM66aiVS15DFaYyAzAmEaoYgAQ31OC+XhiO8l4e6kgfPDQZALpQNxpqAapoys5F5jRkE5QxFjp76aAocN0wXnfC7Di1wpWLmBeMgkd8LdvfPybMV6jbyJU9Ht1zZUiA7ptZKHOtjQE6o9zRqqQopTIAttk767xwtNuBgNewCZzhnAZIiAPt+bhu8A8Q251yQ8tt1eMkj/BQWqnsurlYWOmdZ52mSGbdsKS2JvsI/2dNdxBeXgh3tpDP/0In0kN55YX6MbX1fF/jaWuinj9N1P/zb/+9LsKiyooaBkkNtT0l8JQyQ1PlrDbdHi2l0nYTCi5QYSPhUIR5qPdzIoACgSSyH4j5T9fQKV/df/ZpjB3bqKNzUojEBEQXdd2Yquw2GLLkQgRiHMAcsxLqrWQIUwk6R4DyaFK0nJDy0Nh45VYiEnoVbh3TsLhEAWkS2UOSZHg1KOEhurSMPneTfFxS1ZU5AHCUMnDVUPZfxzTqu7jMVLbZJwkFsWIJundIIBGVFVC65G4gTnQ7qAJQGSJSQ2nDaCaBhCAjP/dk/Ag7PsvY4anf0UlUECG9BdRgxBjwNO86HxITdUQoS5iHpSpbIgOBv+eYspWK+GAgMMxAnfQ8kDNCCDOoD5gJjFnBsvK863CMZMQRDxVERz/kmeq2FShgjYAaKXUbUplT16mKJLxstODLRux0l432PfpOGUoJHyyEmdOW8aCgfIdunBDT0WcFR6QSsHJoIlyIojurTATKKqgfNZQnaWhnYazz1a4uSszabngTmvJEqGWw7GnPGCRSNxAUoQpkrKsFCYWWA8oSmRJU6AAlbqAE2exv4VUe7f0qBD9LJ/5L9y2/u4r/1pXwt1BRnbpxzFBvZCei9CY7nRI0hcRQrgJ0INYECQs9swHAMKhuT1hHbniUwtKHW0IxL/qyzXxWwu2bhvv4PXMWI3QM0CGA46GEhvYyaKWotzwGzgOEdCDRJea5F4LYBPWSycx2WwiC7jXZ8cYc5BHZujud+OF//Prx6dp0vr7+II2Ct5CWECah8XSERhEycyFb7aG0JlZLaKShEc9EMd9xVEQHfYfrdka53+iw/3z12D+/g3759rvXDwy++e3hT6ooYZl4yLdMRUiJ8kggr2Jwyibd3VbIGkptE4WFDHVBh259lzTmpKGi1ptP2pn1N5s7mN887Wf+9iG4P3163m/+uib0t5+/63/h63qwM+Xy3f/5hz9c/PD7f/39xx//8MdvnkDsq/u6X/3dK03ixsrzcKG+933f7X7iGMMKMJyASq47klbQDlumvYYynoARedDGBik7bBOcQuUkbRJC0KR4CswZZTYNC891HR5YAj49nUj/5nFh3n3kr4tzZ/GHb/vNb98K+N3vPfxtrYYeXwgNMSKJpNBGUt/VrSnIhwl+CHMBJSyP1nXMlDxFH5k1KopuFFxsNJidqwGYrv++QZ7+9Z2+6SPtP94Io8fP//bd3/989Y+DXulv3aZcd16Vbm5X5Mmt13baSMj0FJXSEprPyKGkUoJD4gf4xmiSgbZUdaNqIpmouvk75h92qAQ0NmwqZPiff/jjxcc//On/+fH3f/yhXYjomTp5xyh7vBsaYmLRUuiVpGMpMaqh92NShe6WHCwhD/yLuhunNjZzohTpZc/mz24njbInysesEtR4NujcUQBQGzVlsLZAWd6xaMO6CaWAVkwZCDKvwQ48OqKcZ/a1NbHG+D+m27vnJ4M3fFxDP9DkGGRuioTSkMABJsK6nQJlsCIa6GgT/J0TDnEeRXci7gjUKrAC6g7QdJoqzH/33/7bxb/97l//9PvGYvwNMy8cRN94awhlbWXmMjtOKSyBkikATtFdC3eu2/QmDl4RQtCoBLWfkVJzIwNRhkARHHqJ/fyDx8/qN16wqaT+6ekU+oOU0DTn3N1LtRbqVRFtIFlaxVmQHUtPYMFoGQFziU9MQAsNHQbzynbjSZL27P78gye2+8YLtttgvPHEawKAl7eGdIAGVntJklS+u6prKBS+WsHCbaOMOjLlGEvGaGi3GIMve0E0mIZ3EzB8qtXl//r9j+2vLjcp3N/cXv7ycGzz1eBCiW6qxbqYZeAudtNE1AOqaiWihy/DYq+7TiR3bBYSvlHa0AlZZ0IBnVIv81/5FRNjwGsvvabceu39Y4i5m/nWwRgARNudxFoOaxIRgHpJwdtLaqA9yYFZ6DglJFmEQg/6lI4YREyVZX/8/cc//fGHf/m331/Mopp7zfRNFQC3z7hLnBMG4ttEiG+pTDd0FGDNNBIeAyp8GrSEbyfOSiey4FFpnyPvtiCDkLy/H/Hp0t+4m18frH9xe1A18Hz14wQY8PKeNAepWbaRAdaFFKl05oG9JjNJhQJUCxRyoTslcDR33H9QL0Avw4VQ3Zxv7z1vGyl0Xl5QaEuie2iOczJOGahhIoO1Eb6avVVWepk4NMjRcW20V0kH98DhIyjEHZ0qtX+YwwL6YmZYBKOiIUdYEZOMAhpeBVa3JnaHuD5BsBBATmWFNyoqR2NKrBu6TMxABZP3N/NmKu3kxncvf1yKZde0Nr+8dVPLwiOlRJfef728+7k7pnK/fhBBd5w/EOXBOhmMh8KB68wSVSnISFMAEI2exhAU1IU0+wSdlIpUdNOTOzvWr/2OiUH01ddeUzi+agCfMze247Mznml4ZRKcBt97TcEGJlEAu5R5d9puE3MZqgGfvOW8I/HicbJa8cff//Djxcff/eu/Xvy///Ljf7/43R//+Lv/1TICvmr8lmHhcRr764NK6NKl0NGnjudDc6uyUVCAKKGg3ngg9TYuQ5eeSIY2XSfoOZKBZ6XGwmdYI1Hyw49//NPHH2cXLFuuWDFibdnBOy8S047LDKsUGCBYTSnVTgF+SW5l8DRFiMeOcBeWsm7EkBkXOu1joZ0sL1ibv6qtdWvLCKMCSPolXd19+HTdm6b/oKgkOaXAoesQBvpGkqGdStEEKqVT8ETUddPIgA5BO2sAP7glRFBlqGWbNybT58u7i4df85unuc3v6Dfvuj9DRj586WEG6GnGdDdNLy5eJoUesvLlC917HfyOhjGSY6LQTQEO2kyZS5o6A31BFhBfIj9sV7IAX4hOdZNYXFJ4PZFESmZjmXw7517e8NVce5npefpYN8/zhGL9H9UbTtwjbV++p9Y4TkOXnQSUCsxC+ZhF7m5kasN16EQ5oQ/tZg1pjN3dTWtyN7gkwWo8Uui/ieilYhcF++VcMa+eZSu63Znby5+uHPg+dey0z2ewJ9IS/TpZuKHT2I0S7t7CkBu3MLppwGeVg/96+CucSKjw6ys8i8Dt9QLiFC9wIuXory+wO404/BrsFK9hlRHOyGS7JZgRaIscFcxysLUTyUOYMwIBJZ32SnKTOqK6IFV2DrBEst618U0N873egW7yCT78qG/D9efP11ePf7nw95ef7i6vbr/97+725+8f//LPx73xiXRf4I2fUHkj57/ZtMA3Pa9+s5Fp3zyH7Df/f3vX1hTHjqT/Ci+zgTeYRffLTDARuxHzvPs+M9GhS8omBgML7TP2Ovjvm6ruolWXbjAYTNbBJ44NVerqL6VUfpkqKXPgU/Yu5TMEjCLVffkio99UkrOeI3lJ5kx2yKz1JQmqZ8KphsOsPFdZCOwRpyKauKJSHA5pI9yjRpTtfnuGDAmg5OCZVhyj+RxrWvIARiRrcxKOa9Q/cMzVV0P1ra+BmnowlepHZRyo0ezqFzQ6utgUnsldzq3v7XidDQZvPCfPxqPZds1Z8/Pdcbc5+2xux3b3CvYP3+vG/Kubb38L15usZR83m3axP5Ab/nB3tP1zenr0nxddVSHYfqLb97vVu81J7d1G363qbGmn3+Y8PInOHjUm20VpSiyzgUyIVbYvlqmxyHZDDEYuXqJvaTOzPtQSfDVRSvSZ6YLhS4lJc1VnL8YuMdaXcwEDa5QrJh7VT2CNJ2Bejt3fCETLzm9f8UaFsVyKIWSMaesCbU20IYA5wMgOlDWuGGWtS8oqlbqqG47VFIrCluj8o+36Htv8oFW/O+4eeDaXvJ+C8f4tXNYCahsepWTCh8DJGPIhbGLmfAh+uaHAUM7FEMFQLEp0MESOvoPjCmkBXfnia6rxqJRgDL15m5XJRWTDtWHZMpAlQT1kGGJAkwacBxafTwpPjwIOOvtH95nOz/alQN+2mb3/9vmm68HB8QAyjDOFToRzpsCrMcYeVFbqLKStC5jW+BC7TD8pCctELNgA0OvSziltIUWmcuFa8yzNKzhV/Ruw+ZwjJ226rrP9J50pTghSLsEUPp1Ibwb7Moh+Khgdqm/So51yyZ0WJekuCyTI+hoYuI45ArfO1g1oOEYMvLAuoifgcq3YkYRCS4VhoPm1NP+QBaMcNg5GiQyBN6CpUHcDmRYvNMCXGia2Mi6FORqR6HBGhuur2/M1HUvUAyZihXq4pCxQD3qp1qeXbyGWpxeHntWJMqMTmmwqPiFSX9eftGAaA2stjfLZl1A8yyroWvtYWWa0k0ZEE0xO/OXfUBxwY++O2/qvZwdqw54cbUpGnM0Wknj7HisCufm2ur46vyTEEy1oIlzRQibFFy3wpXJGK+NCeKMViQ53tKhTroXJncA5nFCTEtTNpIFr7hTPyBvM1MoZtfq3MVyxyEssxXJVELcxlr/gKsfd8du3618hfVnD6gauL0J9RVQPEhKy8LPwhTCyFjkL0ae6nzywzGWQPCv8L6IpxdtBo7bU1VUohTG0PMmgVwHRe22fqxJ3x83RzL217E6IKgcVJp0FT4tTZ0Wg84ZgD/6FMOescHQ4tKafJGPnO7DgavYfXiz2GUI2kELiGmey9qguGDlanUvNZhIlwq5FIWUMNktWCx2bxxP93f3Zl+NJKLj3PCIiXMFlVwxho5bH998wiTA/PEpeIna2g1rqRvF60M47g5Nb1dGIssgkFHpn3uBMBmdxgjtZK60VjqaoxvFBojzjmqlP1fpHgiVFARUwHYPfoV2Ged/lIiNjJHeQiZiOJt8bpTm5g+29RY5BG1Yz+QaZSq2XFa1kqbiE8JzUGJ6qxK23SP+hltqLzrp63DV5458faDzwlvwJRHYv3U+ks12P0bFlDealWTQ6Tur5ZbqBgB1AzBSPcBOxx2PUNfGbL6YEVTub+ci07FZwwUXGNHj07HJSynvDcRYUwWUIESUMBQUrr2Ld3vQCyqhDSbHcCDsdwz0GvgzrPZKKjgmfy35Jxo7PgSdizOegozcacJI6b1jKopbD8kJIm3ySLvqQgqx1FcHVrK+cacQfTbLcJWk4d0q/wsb1thL52YEq5bQ3gM4NDil2mBOADkXMol8GT8yJRoksatdtaoHpyJMKOdmoZdLBZZUkMoSHwCAEpY0SwtTR0jVruZcFb6LJMtxL64qalkbaF9D+qcvhv83ANY1uj/74l6Nt1q76Z3R787Fdqqn29/ucSt83H3/QJG2ajTI/dYUdt9maxkXBBynX+rbT4uJ94qb5j28/V7OGTczGFvkWWa/Ze3tjsndq17LJxTVT2nwfttEDzva1qxPj7pHatQuE614zhRGOVww9EMXRaPGSosD4Jnkrs/BF1UOPjnnnnQKGvodGZ0VI56MNe+tdvGvau6ZVTetS8vXbjU4Dmqpap1N757JQJuIFC6h6XlQDBiw6DRrtGvPCm1rdHlSpafgMmjP0AeYyEfYPP6xxXy7W70r3u1K6DNcXV98q8zPPEmiMraKNWQvnmXIYAuRckP7rSXCWUy2shAEKGjutPDpjhmGAwIvgcyq3efQBhduT2/Jd9X5PqtcdIK5+4mlCx1lj3K5NVqZWj/aAvr9IPCcfrDM1oKmvjSUG09LaGKMDjCEw+HEYfrYbvCc62H/HuzK+K+NOGTHMyqvPONbhI6GlpgFqImtMA8yk1i8GyJ0BKAX9rGw8yGC9E+j/e42Gq2azTxgkJOO59l7ImpEWOAbJGDBLX5M8aP38Fx3rq31rXrs7b39Va9CpdFaDhrCXsQw0kInO+s8tvV03t9R23dzS3HVzS3APye3S9pDcEtxD0mDGYAOxSAx5larrLqlWrBYMpE/JKptcFCV5nXUtCYHXMwSQjAthNTMhvfiGBtLvtIaLXWTs9xC24D5k4LXUcalFKtAHZB6dPl8XS5wF41UwEjXYehNwjhqlLLqDEFCxtJPqFfJgP2l7+qMWC5+ws2/Ye0QYcASayub1IWxS5D2EvtTzwaPl/mVQ/q6sUL+URsy2D7FTMlFD5PQm/BA/Hbd9DvxiJzMdR34GfK5ZV12xRialQRUpU4gSkCWKj15IJZLUmnvnRCoBcOgK6GSiZw7J3v6EAxiTmoPj897jEoQz1QfHeWPGDU52pfJmUhu393Yt97UiEkdsKob31cOuLm/Pb9fotX6jyD1zYpCjoTkhiDLSnCgUyWlWjqXx1JyQFClrTo4C1niThY4417N1RafscvLaFyOyFAkCQ2VLqISgoSiFsykAM04HFzEaeoXt2FfrT3Czeojk5ludHFE/vzNbjJkgAzXoyRFPg50o3zQSUKSZFv7S2KUtcE+QVFr4OWIEJIIoRnqRhIqgFAvSap2jRrMTYnIKpGYl18SaLAumHQ6XiNEJ69/U0R4UaS7S2V7u7s/cI8cngxLdVGllIARNdhmIQJlkBoKQ5ZqhFIuknIGIZJlnKMU7AVEhoJpyeoWB2pfQxKWfam9Re29/UBRSZHRIEIKUdEicRb/+PSj5osjskKDUKO2QLO8Jpp/NOBku4CN+6+ZAEC2KGWG3qM4epyW4kE22JjN0q3kOKgjUhgClCGfRLuNFAVzXs031XHrk0ddzTb+2plq362vvi8rdPbSQe95NvtgryRnluu+d/2hvDNvONXvKuFLyFYbI6TkHQ/yL9gaGoi6J/oeSEeP77eloakTUgaZlqTrIFE1UB5zYElqPelFmps9jQNC+VMdQCBFLQH3QxjKJgQPOTs2M9MwErxwTKXpvNWpZ0cwHpqPgVmS859Ur1SE5Gr+4X92Gi/VDG9m6Rt1n+5KXq4Mu4Z528094zKdPnnoM4nACi6ceghinPaBILjv09Fhmh50q3ewkIMk7DfzFEdBONpJM1CRjkZyFiKNRgpU4T4POwSltubSRKUhCe4cDlFmWdR91VsIKbmqyg4Iq58wrvKV5ec7adkpXn/P/4OZq/LHx/V/Kckf/hG/jhnjpwbOiz2DGh9LqPJUiuwlJjBg3mA1yIAcXlcLJj5wS0DarGACJRmmfeZQ8RpkjD1AnT9H18KizUhmONJTgmXT4uBWKv6b/vv7hFYqNfPQoc4N70YtHGxGXRKYbiXB6exeSkcJaJMXCra1ZXDNX3ESXNctRKGVMUsJ4jIak8VYUCYrFqLnPv3IN/WQ3ec/uf6LyGqbvflIeDHw+x79+g0tq505b4FkaF0tkUkRtklGhJsOzwjPgrPDMfLIJJzg6ZBztqcBfUNUlRgDaFVH48xcC0GO4nXNY+uudm3E7d/fkaJ+zs3Nu5pwZQofNmpGiFPc2sAny9w48sWi3Rb4kbt6JRYwhatrtiHbjn6vLL58j3BDjiQl8SjZoAp6eJZqKYND7LFVlHCvAIORSHHY2Q58VY4zoeEZ3tNQUMNl5FY31GkUSGdBAieSez9bw9RrSGpu1uMYEO9uICONO+pwYB0zxL4gJJsKR5YP1+We8ED5fk6WEnQQ0WWGHnzIx7KQga6caERZpqnbyLcBaRYk9rpzB4B+nMbeClZIjs5LVNYSqWhlswRHxwfqos+CKJ84j0/gbz/ATPZB7UHvdj/sWhHyPKgnc9K+FTrmWpRgZLEuoBzZ7I5wNKRXNuYRYhIzRq6wgGierlijHuVIFG2kei/+J/b1nd+74PuG+JsfEIwGoEfEIPk0eHglBkIbHEiyMhUfiESTh8WaBd1Z4UVaY9DY9XhiLQI4ZxgIQ5YaxGBTZYSLD0vhhLCBBhriF//0Cl+k9cHgdipjpbnIcMZWBGklMJaDJElM5CNLEjBAL44mphASJYv11dX5Zrgjaqx45NSvV46Zpm3r0qAQJfQMfUc8T9qlPIiBOyAY09wqgcAtBBSgyOOlzwDY4xT0v3mcT2Cvszt/5E2mTNeOh3LAPfoCQR9KPE0HmuIe+ML7o5SLGEp/OP35aXcBvcEFyb+sEPiW+mICnRxoTEYhZpCn+BZmliXDUbVOSwqPOaxGjzUohKrDMGpQiuxRMkVIYzYT3MUeUxFindTLSMu9yFMBfI7Vjn7QLLi5mN7pPGtSjO82lg+2JuCgX5/Em3HyjeP58AJ0SmQyA0yOSAXwnkozKGCcQrDeZRZ1Y0TJmGUIKNkvJ0GQVF7m2EvkmGWDSGqFKEEXoX5zc7FHnhpef2GwwpIs+IDmQdEkexEAwYt5Di311wXHaXeYLcocy9klBlZoGMhTkKQElZXTspIcQJBr4GBiOkLel1s2zjgmBI6NylhghMJTTFlV01MbJdzNPsqTePnWg7bS0kvxuyK4Veqm818pImQJvv12uQ1qfp9Xtl48BeVBE5ZUB1FRkkmAlBsnAMKwuQddB1EJCKtIww5EJvVdIIA49cC+Sr/mE30oGHoJGbzIUdF2SsShk/ZKxIMTZaCwOsXXZw7IslWnGghKjmxtYQX2lepmAmElrkQt0wTRCKMaUJFBfnE9cBelssTan4HnKOH/QfAGTmYkYpKgKaSTqGkYzb74Yaobr9aeZVHNrKlzajhYlvmlx06OXFj0xNhlAXxB5tHKR44rri5Bg48iTY4sWOy0L1CKnaINa/IteZhmKuiyr1UpG2m4BUp2JKtT8eTgEOQKgnxhTFEW5xBjOe6u1qbIpCTZYEQwXyRXrRS4iEFjBpuESrr+ufkPRz68uiXFJA5wSkbSw0QYXYKJkg06hB1lQ+QMaJ2VARM+YjxKcliHpqL30JkddcL4ElnJCSvmJR4+2kPbu/N3ep6fT9Ji6AU8sWGiRL4h1G7HoUO7XmoC+btZH5KfCCWVcMtpbiyoEEWK0modUHGqRRsuiOOoYmiKDBiYoDwBa40ggbJQDfm265mZAz5qf747PLzN87VLdfx0brubW27dZg7EiwmVDzF4LJxXaHIgGQSB2i9bTO2ZSwR+5BxcTeEhg0YOLKBcIr6NEs4U6Fp7tODwumvivzYN/JKAYiEmKSwbIlxrvDYRcCOcMZHrzhNNvskZreIqSX1+dX65PMRi42H3zZfgMt9cY+h31DY6+//2yGttanqXRjP6hvXJsn310/vn66mZ9dHl18zlcYF/2C/KPe8hG5tv+KT3gGwh5t4H8Xzfna5h93gF17R/ZaO3Dj6ihYf/B+rP4e/8hJNCjKtn3VtX+1D793ydseYfk9ce/HB1jd2xI6EPft/XPho1utyTUX63dsfnq8cVJD28b3A0w1p5rmX7LfkOS/xHcf03/U7ViAr0fnApmToZ6fXytHd5Z9N1IPx9+5wm8DPQO4Q773ePnHarV+7x7U/POCOXRDdI1SGMYyTln0Qs3WhktrNZWVnby3AprvLLoW1ht0MpbZ5XU6D4pjO84XlXcNOrS8xN+xxn+/+HXTtPjVtlrIar67/GHP49arVaNzq6qB81q41Yvjvv3sYPpgzz0iIfxxz6M14ftHte78kNubH7787TtyAFqf51pPXX0RldmPjPTWZvx62Kuyb1HPYEfeAKf0a6NZ/BvM1930usCOgYnH36hmX1Y9QaGZq9+9aXYtiJvS6Rt5jXe/scPP5EffiIfPLHv8A8/YvTX/7rauYn7HK620bvx/3nGv1te6A0/Tf9rIkKrjyjMcb2z1djNLVL+2e5rG0G3k/LFhfthD24wmfd5ce+T+Y1MZs48k0o4Yblnjjl01JzTRlruLNMM7zFmtVCcOSUN+nzKKKeEkqIWH/Ho0lklmHWOMzt2bKo7h1/RyfW9/j1ZMb2rbeqRlsorHfZ+UehvQ6JqnzcZ+Y64Wufxlf3Kn2B+5sm/e/C787lk57PVjRf3QJ9NJI9UU7KO6t3d3f8DOF4L4TWbGgA=", + "abi": [ + { + "members": [ + { + "name": "index", + "offset": 0, + "type": "felt" + }, + { + "name": "values", + "offset": 1, + "type": "(x: felt, y: felt)" + } + ], + "name": "IndexAndValues", + "size": 3, + "type": "struct" + }, + { + "members": [ + { + "name": "key", + "offset": 0, + "type": "felt" + }, + { + "name": "value", + "offset": 1, + "type": "felt" + } + ], + "name": "StorageCell", + "size": 2, + "type": "struct" + }, + { + "inputs": [ + { + "name": "index", + "type": "felt" + }, + { + "name": "diffs_len", + "type": "felt" + }, + { + "name": "diffs", + "type": "felt*" + } + ], + "name": "advance_counter", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + }, + { + "inputs": [ + { + "name": "index_and_x", + "type": "IndexAndValues" + } + ], + "name": "xor_counters", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "foo", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "test_ec_op", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "index_and_x", + "type": "IndexAndValues" + } + ], + "name": "call_xor_counters", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "index", + "type": "felt" + } + ], + "name": "add_signature_to_counters", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "set_value", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + } + ], + "name": "get_value", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "entry_point", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "test_builtins", + "outputs": [ + { + "name": "result", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "to_address", + "type": "felt" + } + ], + "name": "send_message", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "keys_len", + "type": "felt" + }, + { + "name": "keys", + "type": "felt*" + }, + { + "name": "data_len", + "type": "felt" + }, + { + "name": "data", + "type": "felt*" + } + ], + "name": "test_emit_event", + "outputs": [], + "type": "function" + }, + { + "data": [ + { + "name": "storage_cells_len", + "type": "felt" + }, + { + "name": "storage_cells", + "type": "StorageCell*" + } + ], + "keys": [], + "name": "log_storage_cells", + "type": "event" + }, + { + "inputs": [ + { + "name": "storage_cells_len", + "type": "felt" + }, + { + "name": "storage_cells", + "type": "StorageCell*" + } + ], + "name": "test_high_level_event", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "contract_address", + "type": "felt" + }, + { + "name": "function_selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_call_contract", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + } + ], + "name": "test_deploy", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "contract_address_salt", + "type": "felt" + }, + { + "name": "deploy_from_zero", + "type": "felt" + }, + { + "name": "constructor_calldata_len", + "type": "felt" + }, + { + "name": "constructor_calldata", + "type": "felt*" + }, + { + "name": "key", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_deploy_and_call", + "outputs": [ + { + "name": "contract_address", + "type": "felt" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "from_address", + "type": "felt" + }, + { + "name": "amount", + "type": "felt" + } + ], + "name": "deposit", + "outputs": [], + "type": "l1_handler" + }, + { + "inputs": [ + { + "name": "expected_address", + "type": "felt" + } + ], + "name": "test_get_caller_address", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_address", + "type": "felt" + } + ], + "name": "test_get_sequencer_address", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_timestamp", + "type": "felt" + } + ], + "name": "test_get_block_timestamp", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_address", + "type": "felt" + } + ], + "name": "test_get_contract_address", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_block_number", + "type": "felt" + } + ], + "name": "test_get_block_number", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "other_contract_address", + "type": "felt" + }, + { + "name": "address", + "type": "felt" + } + ], + "name": "test_call_storage_consistency", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "other_contract_address", + "type": "felt" + }, + { + "name": "depth", + "type": "felt" + } + ], + "name": "test_re_entrance", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "value", + "type": "felt" + } + ], + "name": "add_value", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "self_address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "recursive_add_value", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + } + ], + "name": "increase_value", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "self_address", + "type": "felt" + }, + { + "name": "arr_len", + "type": "felt" + }, + { + "name": "arr", + "type": "felt*" + } + ], + "name": "test_call_with_array", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "self_address", + "type": "felt" + }, + { + "name": "arr_len", + "type": "felt" + }, + { + "name": "arr", + "type": "StorageCell*" + } + ], + "name": "test_call_with_struct_array", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "test_library_call_syntactic_sugar", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_account_contract_address", + "type": "felt" + } + ], + "name": "test_get_tx_info", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "expected_version", + "type": "felt" + } + ], + "name": "test_tx_version", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "code_address", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_delegate_call", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_library_call", + "outputs": [ + { + "name": "retdata_size", + "type": "felt" + }, + { + "name": "retdata", + "type": "felt*" + } + ], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + }, + { + "name": "selector", + "type": "felt" + }, + { + "name": "calldata_len", + "type": "felt" + }, + { + "name": "calldata", + "type": "felt*" + } + ], + "name": "test_library_call_l1_handler", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "test_count_actual_storage_changes", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "test_replace_class", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "class_hash", + "type": "felt" + } + ], + "name": "execute_replace_class", + "outputs": [], + "type": "function" + } + ] + }, + "sender_address": "0x43eef75848203b37363edd1e44e4121b49c8d4adff592c21b59566f5b76562f", + "type": "DECLARE" +} diff --git a/crates/starknet_client/resources/writer/declare_v2.json b/crates/starknet_client/resources/writer/declare_v2.json new file mode 100644 index 00000000000..28e01d365e3 --- /dev/null +++ b/crates/starknet_client/resources/writer/declare_v2.json @@ -0,0 +1,80 @@ +{ + "version": "0x2", + "max_fee": "0xde0b6b3a7640000", + "signature": [ + "0x130f50422046d324c0a44170402f0bff6854d384cfc3d9be9ce4179d37ee7c4", + "0x9f5c9cfc060ee34f99bb295a613bdb00e0ea091b43837867777f5c854d3dc3" + ], + "nonce": "0x2", + "contract_class": { + "contract_class_version": "0.1.0", + "sierra_program": "H4sIABeSnWQC/8y9WZLsuq4lOJWy/K4P9s1Y6ouipDHk8IsACRCkpIjYN2+avXPMdnh4uEsUCYJoFhb+v/+l/rf+X//v/9N+mP5Dvf02flg3Pnvc/ad346cJOlwhBu9sSMEHG47lmy4GHa0z0YccanTt36v/JYT28faONdbbcVeno4ntkjH339cRettupaOKcKs7jiFY+mN0EW5j6Q/6KNdRorlivvJ5GJ9ivZ27r/b6tlGpw6joi7/SZXPxoX3ApWCqO6K+A41ojOC69GUOfaR8p+qyv41SV/sZTEzFnS7a9t5lgrlNPLy5fJuMmr1xVaU6huh8uNoAzzE8XcOZVIqXUsEZ166czWmS0eUM13GGNivl1MUe4dQmWXuWcIaklc3a6zEzof+I3lqaQ2tSOn12Ry7On9of7WnrEbOytwr1PFQ4TLzVUVLSKVzV1buUnKyK9ciRHntZsLa2d4T5HQ9iUjyOdLVRKFPUmeoZzuuwztX2DFcNOZ3uvnON2jhTdD5LdTDPTmdzKJKp3C6q7vv2td0tXLfxR1CpSVC89B21uq0q5bruJlvtEdq8wBhzrq4tsR0PbmMbRAq1Km0vk0IubVmrD6Wc9bI+Jn+k+7jzbepRbn27tobGWt1kT52uDKHuPyoLUoaHDbxStGDuvFyo2bZxHMm701h9eqeszdeVyqXDcejU/ljaqO4raR9NaTIJi+HvsWB6PH321l8lKJuya7Pv9VmO4zyOfCmjnfbhbnPWlkbltjptV9iz6mRMu8/RhLRf4yZBGgMfv+bDHk0y/XG2lW0Pc9zVF5dd1k3k3HWfZ8xNoO7Utu3tTpWybwtztIs3eYvjImOl7W2aEF+16GquI8Y7xRza0oRUvfE1tvc0iM2Vj8uo9plkj+syWrlqjRnPqsfILDzedWXlm7i3D9/+0vFu8nLnEN2lmwTqerdNetlDpfbIbbzJ5WqtagMci6XHCH3bTCCbIaOM6tDELpa2aLT749GEu1qdXUjWH+rMZzbVtKcvuWrXHqzcysa2Srpc0RXdZiAlk9oPN3aBHvds2/pIru2k67xdW4YmYqaJ+9keodywlQ57gxI4U7vK0bbw2WbMwy4otikIUkdja7XN1PSAAz0Hysrp4AL85pvUjWnXQ0fa00bQBuU+rPG6qYfzzL6Y3OYtHLd2yafzMu2xYmmr62xuY2/CfvmqPa1lu2EFJdzUcIKfIY2nIpHUsSk8c9orntVepy/3Fa9yOeXPu6mepsGb8Kj2TD7Wq5QmoKUmmIImabS2TTf7Jk9Na8GzgR6HV4EU+Bnbh4v3Od53E2R1t8k8lVVniaFN7VVvfblb26ZRnC2qaG9Ax+Zaqz5oy5BqanqDHiGf8WyjUq5pM5VjuuLRni839a2bflLxbuKoo0+pjeloc1XbswbjXJtVdUVa3fHz9qYdBU2O9KXb3WtpUpmTOUKu6mxKKjWhaSrUXm2tQ1JNvq+cD5/bJJRsSDWOn23aQlu61B4ql+rPYlw54KGOto3aBk1tA7Y7qtA0XdCnqU39NmVoS2qCOK5R5tHWnhnkBQ5ag4vo3+SmnQPp9Tsvn20rqoyy1cF540L7xTUZN75toqteoHHbo7UR17aeRp2nb8vm7Wmu87rOStpMn7UdSDlb13Rwuttp0KS7CVO5yumuJv+plqYRmv5oJ33T69WkJsShnY9t7oZ6tcWE0mTQFGt9WxpXmjaITWsW1/RtcUrVtqqlaYzaToAjmwsOl6tN3z2e1mp+/mDJLmhna41Kl3YItjsrVQ6tj1CVuXM7X1CrNTmHZzP6aKZIVldVTWH72vQaqSzSg45voJvBMm5La30F70s7iZogNEmztbQN2N7LJYPwtXPiuNvJZNoWrmeT+hxrO9XTmUI7pMOQwnmikRpvB6Gz+jib0rlUvkpuyvPM5bzs2UyGu4loUwYRDIi2NmCZuKaij3bmtwNwSI6lx6B5GlNuWbHV3La3Oo5iNWyeNiEnKNR2eJUbN1/KV2h/jO4+mgI4vW/GXLMcQiyVRk6K7QLF5psOboJGZ5Nqn9PH5bOvyVzZxLOdxqEZYUebo6ybatZtmZsmM5cFqyI3cTyONns5t+Nh3OAihVVtSq6ZTaF96D6aLKSjKchyt8mtupi2Budd24iP6kAbHTDQJoLKNWkmk7LJY2xSHVxt5zfYq+k8XTu9XIhRhWYdNtV9N3m5tAPd0pRHEx11mXo1ASRLjk62oK9LwTnUniY4bw/ftnxbrRNu096ytmnoNgHFlnhFezdDoclkO3nbFjvJRF4MYQenGRwLvh8SZAo7+9OnedM3ees6Hk7Cnz4Llllb3GYPhQQf1vZsJ4pLl7FtHU2T2ONsdog/fDmb5vQ6Fl8vMMfa9NKKkwSYNgFt4x25tkPWXc24vg5Vk8/NPDzaFjxr08b32RRo1KdumiW1qax30y7NBhqi4miBQtsg7eRvWqOtRG1qIOZ23FjV7POjHU7h9r7NTNNeoF/a6d7u04yN5EtqckEjGz+bWj3K2UzMU7UxNUvH6qudHrqZFKWZSO5ohsrlrmJ0szGOJtTt/WpPZ887ucJeyTAQvY/gPVSw/ZtubJPc7NGj2b9NrTeDu8mUN0fNqclXM++cCs0GagZTO/MuXkbaGOcJ1n8z7o520B6pjc4cpbZDstlRbXh3MyW8arszwqIolTw4KaW4SzWTgg4GslNo7lDDh7YNj6aRbvCV/E2WRnsPzKWxZP10bqtWf/tkOzBRI+D50Y7P9mn06cZ10F9rn24iB9cBM6z9fezYSKeQh6uDRR0VeX8RRmDReAO1cbcrwLfHyXLNYYLL1P7cFrd9mK2XOO9Abl/7kEMXFOyrhzsY2Ldsn6twYbrC6lXiSDXM4PgePPdN4+6eFo523GXOPM7oSd/jTzYD83WsX+OcjzzM2/F+iXL+DJyzobZPXX3U7dPtrzR/cOrju4sj1+8qXbny8yKPJaWLtotE+zex0eZl2tuhGOnv7i0M8JzYpjI8GCDt3dD+laInrwwLqHAJ6HttLO09/C4IYUDbDa4dYnsVQCzbTzBUI0xsN1zp2m/fHgJicDS/fF+P01wnGivMYruOReEbws4zkFF0hgcjP8HXq88NtV9HkwId/iq7X0Pl0OFlyLykk8A/5/NlUyjYBO2uAbYDPOv4Nm1EmPvFNOft4+em39YazdLx+aGxy2myOQ/X/KpmVWfbPLjkLJyhTdGX5l1b0wxrsDC116WYVGs7S3FQ+p5mYHpKUluoDHa7N7UdB7a009L7WpoR0jRWc2ubaX5me7mUz7Ztbn+3M8Y1F7GaJoOFA0HbQqB97XFJ4HFg6iB+sGozc398K7bXsPH8+/csxUootlOlnYua6oYleUbS9qluV/fh42+wqdsnFsPNDiEKm7dKi0a+xE9jIGP5p89YCij6dpr7Zmco5107O9u/bZu1d4xv008HHZwgMF+oVUPfcu8zBx4SKAM8OHCkPOd9LE2uPtZKg8ETU3MFTW0WS7PcdQr2bCfwnW075tuJ3LRQc0curbNqXlzIzYNtzmYzQ0jV0yVZCsUEvt2UIg6BffX2zeGtdw2LWq7vvfNjyeHo7Tu4f5rH8D5BcOi0/6X7mExz7puPp8hceYjKsCFXXe78r59maxZPFs+Hmvunb26acphlpHFoLgOfVj6izu8a7WXW6ZtD2CkgiMIN34RTzeNM8qq8zqWCzYXzD+vWTAc29+r7xg/DiX9up11raQOOpbrB2yvtjK3HEa58gl0Zqj5j81Tgjfv0zaFItnkj5+UObdqFradoxOP2+02nYI2BbVZE2w9gWcGByPYaLEWAvfQ6tefLIS0WHg5YXKAER/tyxMMhgnuXD+Ohc736TViicIDIOTVJ6VzrfR5nm8a7GS7Z6+alHEfzG/IFkT3rtG4bWqnm7LSJtLYdKP72rPSnSfY8F3e7VPvjVF6ps7lCsZlv5chtn7QvNvekKcQrNd1xXKdWEO8uzY1vjph3Z3XNsUgHOXKvFuPLzX+wd71d7dBvHawNRfHu7b8RHx9/LeNnHndIpHjGWnuKoI/PORrJ2JCeQrcUoxqbhKIVfpgAnq5H6z7GEWj9ScnyqUDKk+SDpHf8JCOMlNq4H6Wq2BAjp4NOa7L5aTXoXKOZ5aDQ+EnZGDKJaPeRd0bqZdw3knIYzxvJthj3T+P+adw/jfsmmv9xX8oHpHHfROGpcd807pvGfdO4bxr3TeO+6abI4Pg57kuxzUyRQ5KDcd/MJj0JFEnWOe5wcaiZcxZknCqyWi96h+IimpKNmhZGRw7MH5zsoBcc9qOQHS2TJTmxpEAsWTeWrFRL7oi5KdjE4eFK9vNBgeJMpgLZZ8ayNUwfJiE0JL15rAqFPSmhQU9AF81jbHkMJI/vl3GvMuaSohOFPLkxhDJuXMb4y7hvGfct4740haWS4T1+jvsW2v3jvgelgMd9j3Ff0lk0O8e47zHue4z7HpRtG/c9xn2Pcd/jWlPMddy3UvRl3JeyqdVRVGb8HPensGQd963jvpXSfOO+ddy3jvvSMpP4neO+J8nyuO857nuO+57jvpRuOcdznxTeHvc/x/0pdn6O+57jviT/17jfNe53jftRSPoa9yP5vMb9rnG/a9zvGve7KKJCe3Hc9xr3vcd9yXm6x/3vcf973P+mM4Kyj+P+FIO/x/3vcf973P8e97/H/WmD3RwiZlXAOVLa5orcX0XWkKIspwocYaYXdAKrQucPBfAs544ShfQo6qgoyExyaEngLD2JvfgFWSQ0KY7foWV2JHeO1L8jPe/oIHV0kjra5J6BFbT9PH3Gk2bzdN56ckL5BOdUtZ9nMB2KpNUDHTOBzz0+SCkq6WnRPK1OoFRBYIee4geRzuPo2Clmc5c+Q0GIQNsu0P6KioZB8xxI5BKtciShi7QLIh1WkU6lyBckjRFJ5SQ6AhINPpGpn2jwiXzLTGZHpuBxJrHJ5L9niq1kxWcq3YL0XiLZSLSTE239THs4k/LIdGbnxMcAjYeunFlDk0lX6NAsipQ2xagLnUSFnrSQ2VPoGC0kmWWeDXTIkPQWUouFBLuQgiikAQ7anifpzoN8sIMycicfH+QkHuRlnWRPHGToHWTBnTTCg87TI7HapfMk8wFDOA0Sv4PPKjqUTkp2H5WPHdLzpEkqid9BqvGgpaw0CZW0TVV0jPB5RCqlUmCt0l6ulH+rZHhUOvWr5+QCDYPMtUoLV9n+oS2j+e6R3yGUiuIPs63F1hfpVYJ3aDJ7NHkAmiOXBLTQFMPUHGAkXISmdIum+KTWjG6iYXAYkvEGhv0OGoZhZ5eGQUl5zfAJUt2a9rKmNIim2KEm8dMk/NrwMGg2yGbTJKKakrya9o6mvKmmrKzmtCwtpSbloElDakqEapJDTcutKYWpKd6lOYVIO1dThk+T36Rpy2gKaWjHpjYNg3aTJq2lKeagHQOX6O6cffIMzaG7cy6JlIwmjJ+mo0STiGry5LRnr5dmg5w5Td6cpiNJk4LVtN+1Zwt/JlTpheF0IL2g8ZC/p8nG1px0YC88cDaRxkOn3oyXMxKPs9Xk8Wly+TjZoDkeQ96eJndPc0qDtNbEL0ZGLdHdyRjQdBzryN4NDYMcP02en6ajX5N3o0kfavICdeKcA42HHEHNyW/SLZqOG03OoCZvUNMJq8ly0OQQavIINR2+mnS4zgw/o2GwW0iKWpPrM8FcmXMXdHeyiDQdSZocn5PMsPNik5lsXDIYLsMvyAymLXxRkvSi7XCRrF60ghc96ZXYmtb0gq5DDtBV2cImE51s+4sc3ous7pts2ptOkJvU8k075aZdcDPCj6TlJkm4aQ5vmqi7sMFNfyJX6ibf5yan4WbrXJjfhe1vfo8VsmK9qVirKVY+ilWD4n2veHsqdtfVwdY6S5cqfL3CZ850AS7+xsVH3M0nEYcP5hkyNfNUu1NNTk01t+uUUH3w4cJ+hT7nKz7m5ghuPkt5JkksLe0OR0rVk//iyVIKJNWRVE2iszjRHmeodL7Ztyenn3RFIVOnkP1ZyMEuZH8etE1O9i3puL9oqhiqd5E6ujILPO0Fcokv9gnpuL/psLhJjdw0sJu+dV9soszoDx+wioNHio8rxTpbsbZUlS0VFlxhtEz7g82EeerNQ24eQfPomRp5KiF98CvaS9nTAXsqlVRQJqmqms4+4NcIv2b4tf1BtV/xVTvtTXtoeKfCP4583gKhYgMfKu3bAEJR7eP9n9T+YJp/Cn/Q/T1d2z+2jj9QVNSkfh/4p2nL9gpHVuEPTZ5de6P9Af8a4A+5/aFZADB4Up8Jrm5xlLUNJcJ9Iow8OhpF+6f9yp9rvxYFaDpyiNo173aL9n77x/b72Meg5ufgqY3G9/hB4BZFLXdsH4p9PBnGk3k8OCEhjfHQJTJMzsETn2u/2QH/FBqUgQVqy7AMilOt/coV/+G74a84FpXM3T9ywPgOXib4VQhGxIu271gYiw3LjLQvnq7/FebLzvniJ7ngma+0PK6vy/TjtFwwiosnDUSEHOwhinif9n26RSZhsfe8bVOu8A9c++aDwHp8qraF+B+4kVUors7iCDQIEgioHKlck9NN+cR/cOodCIU56T2X4YoJZRZw6gFniS7Botlsa1yINjLcDH0NYGQWRmHxFYyxjaI0f4Au4dvnk3f0vLgmitdprEkznVFcPMim1/RhMpZ96SIJm6VZo+N5YU+FZuT2AZLUwrz4JBeK9ontj9+fnMWPRhAdv1L+ICEe7y2zwReGtW3/kAToWJe9DOPB95p5SmsCqiF41lIgEB4GFXiCcB6ChX8MvwcfYUTLHAXOAFws9fFk/GeVXJwV/GdKBuyl/s0AghhA0wWYkaZW2j+HLmMYML6QlmGw0tBndanP2MmzeLq+u9srFW1/VVNXtEEfNWocCw3j7LoVcOR9PBF0eWzyQ8OjVzF3kWmvEr5HmIG7arpjxS097tgsBrx2fy+254H3HH3kYAUa7nFUwGSERMMIPCBf59BAhBIOYHxjToa+6METP7juUtnEgSboqF0nj8mQwtVugXoeJr39GEoYhjcGEPlVoFcggXwJeMjk5/O1D/Vf4Q9mrMFVaYWanss0c7SqKYAkjRFEfvDIk0H3bSdI3xwJBTAazcsKj2scT8ZBk9GmZUxGKngdQ2cBjCBlqUFNGwMNo004H0nphBuNP+SxWBFOPXxlVJoCaqzLmi9/8Er0h26/mUxDMwcP9xZrMu5z8L0tDco4ujeMYnxuzE1W4kkyTUTtegdfZRoLvXfQX9v7maWHnD54QF6Uyht3vGoX844ev+yfSwwHaNdz4r7jVWa5zIbfC7yh1CqhsFPpKbPxSdxsvDoVrYmjoZig5o7Hhww1F96pcNn+K4hp5t3RbTuWZPJcY+BNOnZ2rUOJjFddqck/8L5h0Yh0VkBxG+0C0Pc09Z4mQ8+NK8+CNtd89chK4xr3cYb2jjG+TkHO0kwwAJBQ29VhL8Jluw6JqIZZhu1Dd+EATHbyucevMLK205xJYlaKITVK7jXtT1IYBysMR2oCTpQ+GWVol6vfgTIlsRs2JtOUjFdzRFWMaCgMQ+8RaLLdvPLNA93cGXr8kmh1bOQBxU2F5kPT1nSm0L4wYW5SuLelc4c0B2PhrzkbpuA/ydF2UONVk1/HG9fd/Neb4/Um8fFFEkGvMhwjzUMcSiXCWVwq2nhiHIcm6fSern8ofn5WIGTxXGpoUpBsTgFZnvZCqtzwAUO3bH6wJWVGA48MGOGjoq0X/tM3bFedeKqitN7069CfQkZRE/Dqt8fOvH0v2hp6lWDNEjwPtiMsctp/7ce6OfvHM++Z/LFTYAARzoihozQLCJ965kxkcKConFO82oFy8Ml1ZHrVBnD1ach82ub1GKYYHVz4uM2d+Ojs63Kc5lZyBta/HjrUebrSNRPdrPIWqZoEY5iwUO6peKAEj6lWL3cbv4IKjcLYqX0+TeDdMjV5f3Cra+AjtgaSz8ras7pFYfRf4zwMagFtNYQg0V6xhtclsfYMNGQL7j3bXWPmWXPk7djgP5CaB1lubh/FEMfBiQ8aWX/FVX/xH1jDH1otB2Ph1SA1NQYw/+DYAhtaq80UI7vwGa1dZG/82m5Lf6D14j/AKp3ybLVjzxfeoCWv4+E/eDEeTuTiPFRa8GYtD1k0dZGY+RFNxgcFv/iwODXdOJAOm6+SY3MDhzUUCuWRSUBBVafNDj4t71GjM8sMqX0G9Jqkp3+C0sc6o67KZP4hPEzyLhpDImFKzKKq5h9YfI/mItOTnIavHPlE491xsm1xsjUyZsh6R4ngJvtk30by+M7mh4/zpDvy4/FxzRZZoY3S7lvovo7Nv2FkGUCX0jlzslnsgvDWMI4C5sMJuuHsFpsNPC9hnRf+gy58CVzy5jigywYVmQkHUM9hoXXNV/tdcGSm/wO/svc7AnUGCtHS+HZT6T28ofqr/m18kIrjBtoJ1qDoU2KwYt4HRoY6xsYessNBobsYbY/qaR4FOKNomp03+kZw9WZv4pxWeEIHXl4fGfqFODJ8RZdAfwyvbAzYkhFH2E8kCCngK3xvxNqW4RLWrcex2jUCPTQaiVi4Nh66e+9tXuBEuOD0H+MlCEF//iCuj26TxohbNs7R2GDm4UEMvpIz2m+E5lZI8zpoDOB1sgFjJI7P1XEdfEVAPhiS8egSgS+teqAGr4OvIoSF0J3qYzQ9vqkmsgQm0/Lqow0A9kF/Rc8ZX5YdvkYx5l8/2s9d9DQNuEDj4euMSZhA04N/hxkXnwSHIMCKo2tA77m+9rSw223Bfg02OcuCiaNIB42nPzG+ZznS5AysO557+Hd8lfXyXl9Mvh/egCAA6V6kyBxPoaoazsZo223RtMQVjgqKuwndBfcEES08tcVaDdG2A54s0RyglMAlxRLQnscpg6gexhn7lKGNCKeH1rwIqEMd7EDePYQSa59qiteBZaaSu1i0QKAy3Nwd9J6u/F4ROxYtfZx8PNMzynXlya894NsetP1IBVwU/IO7munP0JtKUU6Lhv/ZfBRv+KN3X8XHNGOMkBBvvFjoEGTQbz7BgTy2KW7DCxStd2JuMQhPiSlglhifb7IAxmLNsNoX7y/0OywsueeJQXeAwcdhjhOtV1h/OK4PUunt8brUzc/hSZynAmvnvL/p4xUjqmhttT/QonZnAKw2jLf2MQvjCySIpwQDpxWWuGY4kPsjolVrlZufQ0OU5HwuXaD9ldB4KbBG+Kp/CaSm4MVZfiqHQ/OIyBs88Pp9VRryaOdWzyjLMFUuLTKKI1Csv3DNy4swnLnd4cQTH0eahYz2EdicniPI7jkC3nxmDiPXX3f9FdsdLg9fhxFcPGuUXdulrv+Ku1gqVV1JgOkjmYdxFbrolW2B4xUdDp5bfIU6Yb4HOxaWh5C5BuSXPg43hxQXvhrvJaj5BsNI4StSO3qGyiGena6b/xb7ydLemyKgScVdfGJlPPnUU5uX+jhT2sF43faAb+O5WnnMxzxh/zp5y0cwmEZS3lUGGiMwUcdlayIVgJaLASmp7qFLhfXl4Js364ibled8D2YPRlTrh+5Bkb5ZZG5vIX0AkQcDr+ZKQkLi9vNecEkyZ7tIsz7AdEYX6YvfY0PRXjyj52pwsETfh73SpeHbeDNWeTeoPBSCmwXy5nMp7jPerS9xbvYwV05qFwKhRO9TTB4O+FbqL1uIoiM4d3fd544l9D7himMH3byD7mnb49w5lR5z5xR9HPKYfQfhq3GJNOEs1nUruZ0n48ZNM43Zy8o9tlBWbJcxVLFs08cJ6F/2kNOM9GivxUy052o3CsLckQYqGvr54SGAQsgqbwoBnmNMRfOSYIPAdsgq8tNGeTw6+BubB4rOmKwO/nwZGr6/6u8loOhiZH3FlXCWFsYZOmVsUo+d6uyyIehIsGK+0CU24TcVn9UF+b5TqnPnhkVr8NU6w/fHDBMOiC7hNWncrHeN6xzLmtNwxT7BE3IUprwMlZu1f86wJlnL2tIMaytdUBe0js7Dt3F+2WCH46PPr+MTe84vgYvgevnjgVFs3LflTHlLfOBA92juN1xxPDBLA77Ky3tp1mjw8178+ZOf9+T3DofeKSgJFzfHzcVEz/smT5HGh7mUrmD5vRm3V3EVoFW8MNHdFFvS+oZvw6CMXl1hvnfPVD8drxE0ONtn16ABI5oVLVhPK6MjrthR/TlswDRHq899wscD21Jm/PMaNiBFin5tFBpISxMOU0UIWWi64qJRYCKYsKeGHdvkF49Ei4OgZ5/wQgkPnRFruKWUw7S7Mdba1Bc6XYBFmLEFfKURbZNffXqwJNFZVWxT9iMNjHR8xc/5DLSAouhurXHu/ZN0ALcBo50P4RB49CqMFszOondv+FxOw3lT/VX/XObPSZt4hiI2vYc3hjhCNgFzJV160FIEY0iEJ4Zfe8AZgEdXgSk7+KHgFTyjfA+HNu0eGVowtv52ojVFa1HgIX9ClUgG488jZEACLcMNmIKAZLJKOYr7ubRYHNPHxpiBVejKP43cfC/RFBoGOkwld//3cs1CaZ+pfQipVt9crfZNQBpAMk76+H7mMeA7ptkTEBYf7qLvPuNjjSBenk0y5MJwULPHLhWeH5CcG9dJ5HY6/3UsGSEbwH84ovxGW1Z5mv1OPn4x/IBHoLC/preGjqdHG244npBPWxxPjDKYHm+Av0aBkpo+c+nBAX4vk+NZ+NjBIEKxQsCMZhcPsWk9EDKFAxQZqnDDHobCbDMIkXgUzE68OZ4YNeihBvQlwhIrmEwa6wjM/RyBzc8RyBzXh9/pbwwvwLfxtiydGKJAK71KMQ9aWBighjCt8I+GtU67YV35wZtAaDKsZ3QCX0nD2k7tV9kpYaHCFEJ3TQ3b5hDKoPJB+DoqubhEIvB5T/PctTOKwSUBu53b8Su/29XW13MypLjxHRswXVCHz9/FWsYu5lhWq2cGIfBVd9+zdN8h8HvZt11LlyjsfGSMPAz3PW7G5IyBWCDGQ9uKqgsXd59tyTRDDmxLpos33JVwW6xRc5yjQ12HTfB1S177DFF0Y51jDiIbsstgty/+aKyLYVyXbYfO8O4Ofuoj0QQfabXWKU4h9ysEA4YQ1nmJeiua4FvtE3zwfr2fzl267XOCb/2cYMJ5/ySEp0Pvv30dJ/hk6+Um65V3G0YR6hYPusMfjHWq7uAH3v2/JYxwk/8nQxlMjccPPGPKZK2LOMKlSdFeesYbCLzfXPb2ddu9bLrxRQ883fhprs+wAZUHl2GvDPOlJ9T+YK4nqhW3DqRyBJaVotzUH+31t0gLyDSwU/7RWicWNgq9o6mMaTOg76UAVrerEYkbF3Mdhybs6hmkwbRZYiHtkYeXQw/SfJnqHJOiRNpb2gzt9Z4268b2cMXTSHfRtkcK43kkZLWlzTCZh9cB9AM9ozECy4wG86H6WJvJikjHnjbLLEv4CtNmJk+7eTeK0WBOfJSiiY1pM3N85sKIvak/tEzVfaXNcgc4jrSZE+F7x+kwx7at47SZS9LeHWmzzVPph+p2mA0burnWx0wKdohQT5vZzUUA0xldy5E3m/Y6vsK82WrDr9bCtPp/T5t1izk64CyFLCBVEM1bRlIX9hAZpovTZlFtaTOqigWTmq3ASiky9UyRYRpg2GUUPZ12tfNomrcPFciaecyahZcM2fRRZfTLv+wkSKbBrFOQKqJfANakEV6DVRxsvsikHgb62NaUy9GmvhtzeIc934YmtTdrdsVTbm2m38rDaiGLjE1qP9NQjkxqdvs6Vgj9snnUu/JhUqM17T18nRNs0+RHC+/gnMocAceNxAg4dj5HMB0CItJ5MeorJgDh62jUszcdPI1gJAWpyP6vsdRndFym/UhLx1oNHaXCoL9JwPy92fAiWRZYfaNJjhM8jfPqMJ04jHhpZJ5Lssy9nKRsnAufhY1zJbIIv0ZSE9rv9bKmL/E0zplz4dVi/kPCB9UbUTp8rMoZyYTsGcM4rVBM+Eh0jhWeDqKA+qoIs17Rqii15XvEqkxT/OJVuXhVLgsG/8hZ5O9VKWzzOE5hlpd8T1lshj+vygV36JlFHBVLNbH7/DWF+ZqxoLJNvmgFD4BM9CW/N0x0tZvoxKMt04Gcwjx4/x8OEpHDB7q+U5j3S3TnuF5MdLOZ6H9MYTbjvFnj97DhOPlnJyxmSXCdH374pw+0LUpPcAWZROQEF7sH+Gq4BG6La4rkIH/8ogSXtPTRvh8eARWQs468WUtPS1+4QOXFx9SLUYwwvN+DgegLYIZSSDnl89JMxtHj3mn3gM5NP5D1VZYcn22fI48vq4fHxylGyPsJ2GnP5rETyP6PyPDNbIUyMzv4FC40bCGF6DQ8K2ZnGAriFGcrNnzPurkjlvNGV//m/hBg6uGb/t37YSo9MiXSBj1c3B9r3tyfZ2QBdYlrntSf3R8h4x3n3h0rmSNAL6UjJf3i/SgZrR4P7RiOyKdkTz28uHzooCC0VMbuw8dEgHeRrVeFrUFLE9FemQUxip6BOyf6r2ZGTy7IwoOGK2qCIx6T/cI9pl6nVY/zMK36Xr3wTGT0Wl+88LWG8t7mAcxpd9YRgCdSxI95sDgPiQ36iBZHH25APF6deTI4L7G5C81DZXkgJB7bqjhcu+2TgU/tIXURLTcduLbAVx6jpcmAC0/juxf3vIUAYN+6a7oI1XEV7NM5ADfbHhxq76UofbQG1P0YLZHthPYFDpBXz+Igo+8dCZfIFN99A3Tmp8V9KIoKHCsG6y0qQPQbGHjuF/qKCgSOCkjUnZY5w5siAJb9tI6Uk5YcWuH9OhgBj4uAzjQaVJL3GRymNUYFptmOrzAqMExr4rqaQW2KCsz4OeLlMCpQ3ZurL3Y8GuUYFQi/4m6zvWZUYPG2LOUdRZxcU1RgggN77Bw/Z9x6GKBd/xYVQKSeuysD+yqG0zEqQJj7k7ZHPc0SFZjxdnyFUYHTbFGBF3v6L1GBdla1Iy5CeCNPEImwTU+OCgh7GmF4PSqw2NN5DYoeM/KeRlRAWJ3T83mLVGP4qEOV1BM4O9FxMywwTVHNkK3I1i6n2Q0De829Bnr651aA5IDT8lhYbaOG2XBoqCP7ezLSMwLJaKtO4B2F8KH/mJMRZPTrhwmZHrsNzL/sNJuLEb0WjGiQd9GcIYhoYHQYjEni8gRrjrQ1+qYQ0bDJvZvFeAcd1t2GEY1p2N2VIhrCPj22iAYGkO10owfOYwK6CjtW09jLFE+QtqZ7Nb2wMLF9Hb6NJh7L7n0xFExPZCdDttxjAE6rxwDAhSZjnZJm65rkZvZ181EpxmR1a9PyAObmQcG2QkJnovbavW0UhU2Nlbplp6ZUL0DMh+ue9o8w5dzvsM6+HZdAAH2EW0xtkNis0n8CgTseELgJRINoKUHgMk9y3iBwUHFC2iuzC8DgJFUZAlcnLA5QbkQM1oufJuIMMW7dB7D1BQE3PR9xwMrZC/FvCDhoiHgS18/3qm2zhwbM8hGid/5h1VhMHmnauC3sPwTbuoJ+LKxUK46zwA6alI4jr6PmILvQX0mvllmcQKi6A+o4HIqvOkDQbzndicmbBz2i7roDKvB3WUcGCO45XeefBwKOu3ug+njBB5YXfKBEB73DSaMH0T51T+m6yI8YWPokBO5LZ4Atuvr3CJWQ0seH9H+kM/AjL7j9f9EZbzkMv+AK/xbqZSK3fdUYDWfjiaA3DCuebDacHOw9maTTPpfNceDAUOKUcIQgBtitrccVqTsBm4meAwdeP6O9fqJC0poJmTN9/01puHZT6KGjmKZW7GHWCHYXE70fLcgvQIQCy0yX/aPZPVa2/rCy/3lFhnas5l3ymuKZnmHR+Ar3/3yPZIn4U4238+MUz/TsTHrjIVfS978r3/HM83riyd0znpnd+Z/EM72tZzOs4dswXM8njbfrqfLLwqJvvOx/zKGZ8D9rYTktlkF6SbF7Dvngq76wEseJC0scXcazzveeFLvnVK132VtaWG8/FzZPh3wurI/PhfXhP1rYAK2u/Ol7BNiHOWb3T7o47gtb/NfC/ld0sS//iS725zbRnvPG0FWnkAHHwYv+Kvf3mCv4qYs9b7WTIOf9Vb9I9dFtujixLmbIuU8vujj9qovt8TddDBLb1hm6VFeBxvvF5MLk3pqBiPKULf9kc227mgmVfWL1yVBIfNV3Wd7Vpwyl0IxmVp+cyfdtWwTaZSHsi7+lg7ddFp7pihzyc+1D+s188ocOhy/wbdxlHGfwhcorvCj9/tZRz42Y3s2nf99kHfY8D9k2aJZQhs75HTqXw/kDNtFzrs4ftTJ0ru4Wkef8nT/wigs2MccndC5H81yIyMZPVB/YxKbpovP1jD0x5zk35isZsv5cokBfXuhzKewv4MQflsLue+zDWdGRy6wiO/IxkoqKcSuc87KAkLmuI9dZRa6siclfpKL85VaEb/vrvNnkeCEVdT/T0P5+Qtf8VX9DX+R4+zvHE76Od7v5voRoznFhjfhQPM9ToDwL52akBEVZEGWsRwrmbJacdl7dUCnLgUPWTUaSouVKLJv4Kov35DVYlhPXbKEodOOe34Mh1bFa8GrJ5QbNNVv5eaCEyQ7AqxX0ChBKfzxRUmxWTArwdRxVZMKH9EMJ6M+rRR1hDJyQNHlsaKfMk5c3WQ9GPZ3hxPEULovJqUBIckye2cDsOZUHFlhM3gyxzMmzzyrRYN0v2P2cNSRyb/g2DCpP+ThJ0rn9mTxjMRv2chx/1ogyP34AuAuesYGRhfgKVft8j/ZDNo8zNnhCRQcOPTQPD4ts8IyVgMC+Hbz66YzN+anaJ4HH3A5L7vD1jA3hzKUNpn0bliEwJCx4KhENkxrUhPiviItHRBCkJXOpYT5DJE8hcHwEX/X5jYunQMKB0sJ2X0jkKQS2+6C1+83zez/KHgvXFJeXmuLycnYWcXa+1cS+uwqh2dwupLP0ozNsxtMYbGZ5yhvqPJdv1PlyiaILgc5z2UHngfFNIZ+FT0Ni7NKzSGiiLkp9oi4KW/iFT0PqX4DYQROObBKYbb3mOLDpEwoJlCvqoyb2m7Zpwjrmr4BfxLTaQn9Rnlj5PVfe8RjhqAPhMXEdZD4NOERHR2TIkwpI+MRrzErPWdn6gb8IWGc6MoW4N476xM+3P/ia1JYgAoRFPjQD2wcmIz7qNkdiVm1p0Im1EHhxTwOeNEwdnOJWN2MsQobjDTQwOSRZI49tnxsJuYcdAxR9irt2dTPCqhdotcWpmSDxilbD8Yw3m48UOtiP+bCM5o6dTRzn5nDZCOBD5hR6s4M981F5AtZvNEy9bre+KGJEYfQLdQS2wD+rpZRyK9yl/hILlVJnpJoMQIWKdOfncpyFu9QUfgF1f2bGD67cJdx3TK8y2j7qZxLdqgWI3AHzsxz5EvwX85OJP8kZ6w427jVzz9JdOh7PXizYSZE8JdEF05MnKMF8DyErhBHqTEp6AZ9slFQlflTuOvOG/XIF9GYMZ3UYV+06op0xYxdg5e7EyBPUHPAsPYmubdqg9e74uXJXnCkDbu+fduhEiPeqVa9ksSn1C2nfLGcPVquOHJmhwE7GtBoL+N7Aq1Dz1sRQ8Ii4F9NJstxS1zoA6h0uk4loyTNbA6aj84fNgDfQ4QXyM2s4MWrUAfb3Aj2R6eheG4pSJnmjqOdgz5/0dPTkg+LxCz4oPYKtAllOTUatccHaMV+TuCloLhlda2p7CaXEDIzFyvUxgokdxydHS2abEm6DlztZ0oyonDyCWdg5R3CKUoUJUMRyCBnQwMn72ZBBtijuNfUDjhvXIXxAEKhbzR9w3GsJZwe1aIn+n2gskx44bkRo9dnNVWJWXrL9P8G4uXqhvOYw15nDDSYnFytmPgtkqf0UaaaB7yZINpEpHR9kSsISneCZ634CaohM6Ug/LcrEcd8KSZ36otQHmZKa94JLrovCYSDEcfZFmSROmfHSdam+fFuUO1DFZidTmjBtlviJ3bmO70UxO5mSq78uisRyI27n2qH1d/yyy7dLOCjLHNB6/SgGFbDxDhFHrBGXbzKklAkQJywHAxu9GHQSTXGJEHUKI+h3vS97u7uOWtCJgGEqoDt9mOUC2YMG26qgdoXyylTTETP2hb3JPB5RQHvGI/4pKYNQb2SBHnhvJSmnFpNnjVOpXvmzsqIsrl3yj+oB1wmqBnIlMOokUKRFskVhpMXNcJEWTE2ZoSsT/hJhugbXjsyBovNMmBbJ0ySQK+ph4LsJslVrQezPtS3KWa8qfLt2zldJOEVmU18wVjVpAvQndu/ey9bSwGFyvc894DmMC7IM0X+pqxLEUYIJZI0E74v6Bc8xQCa18A06Rg46rzZnXNs/OePOe80JFB0e+JMJddHaMl8T93LlowZ5gzsAJS81AR2AwuFlHZmwiYQD+CaMa7r56KRQHYDCWyJwsDPU/4vOePokUd6d8ct9OOPTaY6Eztbq6ePrCMI9APxBLYUMsz571tTr+9c4AaxDPiTlKnIsY1OLy00y5/5kABux6EpxjrJvN/s82kCt5eNgAqWoyIx9zDcQPEGYIa+VDO2L4VYcne1us8d6azx5BQ/09LsfZEhqqc/GBEvngc6LUnYPFxYMnTpJlfuFzq+C9p2/meJFk8wYT2TcT+xv9+ptuccyQ9cZQfZKARUYu06VGohdn5zO+Ir6NjJZlGBAjuRvTvajHjy4t+ptQRmd566NBF238XcH/eK27HWpC7kIkj7f6y0U8krWFBZAcdphf2/QdfTfw1056FCp7Bvinu0NC53UCLqe7x4Jo4L2eynv6AXt9yMl08miTP437Do1MthK4CaEBymnOhE0LxfWl5PbLSh9J9344F+qMuMwiKBZBIsit3syJBwroxW+Qk1BRNCDcbkNqhm0naEZ1MIlgtXrOdFb073EsSBkm6GBC1euiGQIUi0tDMUIAESrC7192u8HYcBnnEBM6Bz/JF3C6ABiwGecAKMD3elOj7RO99pVkpRMPRbR+YGVdG+7yzvd+TmC6c6X/FHVXuEOl4Ovd7efDvrIJqtw52kEgkCJR7C78+kXm5WLrsHj7+xMXJMyc6h2L4+sn2yO9RMdLSq5ySdgi6fdoXL9tCCLvnZ09IwGYOICJ3hGAzAG0LE1swZEQySBstLdPJiFJpaTP0q9FHeEhT39zef6I7gGHHyoEZc0RJF4oAQX06Oq3T4Yc+sjKsA8UF+Y9Suw441EUlGsyoPHWVSSF3dRjlUSOz0x6zOpwmJ/1cVj7VXtfAJfxSYmc3sncu5yPyu3M7E5CO8+pnejGLOlf1iVZo0f9br2sABVXdePMMLLqszy8wetMGvVQSGNUQRRv8NlyBxZ4L1eObQjirS56pojEE0l3x0sOC3JScd0MzHFnV6Krln4EL6cnWCd/nzcj6rry90JuZ4W1mmGdeByDdbpl0dMC8PPK+v0SYXdPVByLsxQ/RGnpRpF/SVWt83VUjvkIKSfWKeXSu7KReN1D5RcP2CdJlm0A6+fi8b3QIkki673tWOdmCtaVo27l6pxy06s+cA6ISszEkGPMAKT6ypOYK6tIt552J7z+wOnr8BeIEKdiiK4AAdfdaf0qyhncUAtF0VwQADMt4Mn+LUmZ7rjzzjN9XBKRVHOdEqZ7LkXs6q0APnRKQVW5ubg/1CTQ9b9bPLzl9Y+m1vK5bmUHeUK5b+7pS+JMtgTUVX1Z7/0wRum6J5/90uF/zjyZ8Mk/7tbKoFKfuaJ12p68Eur+/RLhavyXrMOpktsNuy3Xzqpx8BfzDUwN1enzO1MAwU7eVXBuasmvdhK+aUWyi9PidtJ76U6S80LgVAUXXN6Ath9EC7XEWsStf8MMpIUuD1vK4gzd8JlT4TLbWJyfG/T03ZRjZy27RlmTNuqSUmI8OIqOv1A1lbQ+kamOZuIHWQfiKuXCbL0zORizhcJl2P9jXA5zjbKvfbZL74a+sbzvW4YuiV5XbVoOLRlbe1H1hYSwblmzjRHO6OrMZrePYeyts2v6jGUnrXNaxMVt7wnlLnptsq/0C3rWYHZPcqOsFhbufSsIwdliZgA6ZaXVkHCdwgLoQCmkpFueTL+TtulSF7OkQxuQ2hTBKlNwfDlyMSaDF/CXQ5PXoAL9cPBxGER3dWeGXbkBVOl8iFTwci5S17qrchL/epQgXd4rVTeyAR6Hx23EH4tlcrqrVJ5knBhUKB7qez99Eambk0Xp/dK5eZIoZemRxMb0eYncGb42nOwopHPHMBs5DMHoEXuUr2nyd77+FCFKg5guofIRPFeqfzwibt4/FypPMaW2PpLO2mqUn9Lk2V3BU6ThQcLL9v5EOBi58vuTX6wLqrbJnkp6+/OV1ryut35ikuarNSRC+6+l2jyw75X+kqT/Tx5xf/sfNFsgBs38r7ph7zvAwvPl7jVI+/7wXCImeVOxXy4qy4cMfcj7WtEevhgGrLpnVa1O2zq6c0ISi+mq+ZUcPMDj2t32CYvrmVvZsIHKjts/tVhW8ztw/2NrRp8Ncw9/1Qb9xKC2INKk/pCMPMCWQlNnsj+MkHE5Xb/idtQsbZE53FwjPGENteiMMfYDzWP90sbqumjjdlbOCFG+OJvWVil7huJvbp1L/y2H7OwT4k2exZ2hC8WP6e7iiMLaxbnLi/vcRZWiSzsTNt6zsLOrkPWac7C6kcW1j5JEmaCciZt2bmfjuTcDr9nYZHGwLd76sGEUZZM85qFrY94k/DzuCDiKcH/x22CvgJOuvwHbYK0Vvua2Q8F9hbDoGVxmwLrFf49XargisPFnu6n2xSYoB9w3MjKz4/THnTsfszGRKzAZJbWEeRcP0ObIk0cZZOMU4vH/SPP3+xLJAkOXpsAIVrLfaG1RP+nH5oA8QQfs+GQY7SWC1tGBqnqtiZAnWUbJ5hh1kiX0Cc4zkKb7y5AcF9mhzHqZYbvd6LALYmtZawy2C2E8UpG3nPPbd0E1d9vRIE4NwTbjmAbj4Y+T070jYx8a7QhWfeenOP1nLDx3lq4uNFamNL8k+DvAeM+88+dhbkJC7s6E64RFjC5cG/Bko2WoiVEawLfHGjyCe+AxBagyfPatcfSEy8dejrNd2xWBLdYTfUDaI+U6M2jogjKCFSDb5+Be5AcHAwjIJqcmgrPmMQjgiKbN81YQu/ee64A88O9N4ESXW1GE6jzownUFkqYfIQSqJ4p/iDw5WmPSQTuJoVNeKYVuAUlUBX1dHHv0tu7QLHEGjrczAIQ1yvPNbKsraGG3gXqJdSw5B0TByXS70EJl0YXKHYdtcCBdyx5XAIVGJSor5jzncXDfAUlgJXztEyTHnuAwcyeb5A2Huqhad4eEutRiQ1ZjVEJrZcuUFwJITsP/y0sgYlpfZ5OesETXz4aEql+3rJjCncZYYn7tW9cb4+z9s5TKx8iepwYqjjUnoOYLYuROTwAaArjFVqBnycIyjtA5FrCF5sfDLjvfHpOQMfOtLW2dsZXHbV+uDI2bNOFk/NSUaulSaK4e035i0VtIz/E2MQerxCxid5P+BGbmG2i3JM0fD6AFkUW6T028QNnOGPG9UzDE3JsRqvmAGa8ggcw4xW9b/NLbAJR2yHDtxkwPlPSfQB5wQFMCG8WVp1Wj8ZD9QfQ+hZYeO0Q5D87BL3EJv61QxB8bmiNmUh2x7NDEIb73jsEyQbE/94gaI9N/Dx5Jf0xNlE5NlF/jk1c0g92MzZhHg1+1VdsInFsAjPpMzYhuguP2ISAruMVKTaRlGxLtMQm3NKG0G2JY3av2RYEqke9xybS0sK4e9eTtv5k73p2HA1fsYm35iOvyWS1MEB+xyZ+3kCC2Vh2ErIXt4CaVTGJd1B6xCYyxyac9PP75Il4BULUR2zi+Kbteev9NeMVhqN7M16BAMU/xyY6p+R9jdjESw/jcb0ldJDNm+v8NsHESffCMC4c5xlMyBwdUBvLg/uj59xT1U6N8EBYCr6VcCilI/lEuD82LZ3ykaMraTYX5uhKemDc6wtzhjo4ujK7FmfIOBPGfffVBRY+PZgzRDCC/Q4RjGC/Y6a+v5kzRiYavo53uxdKyS6TT+aM7iLKuMOfWk5TfIOpLLTe58+pnyIdWVwEww5j/txOx8BNkdstHFNxTSz9w2+bnIhi/gROneEEGzGB1nlEGzohA+PUe0vlHu144eLS8ZHneqAj+JF/3tWSn1ig2Qmx/8V4JTcFPcvJmP3zwT44ofPA50iY/RnyOGSPRITsP4siJlthD1V0yP7su0zFlyPA0cl22A61jHt0L5RXLqmnYbx6qIjHiHbDY0zQfjdvYGcu/X+hIh2chyB7Hv+KxpjN7ZGs8UrdWXsAL7ZuBxKIT5d4QRrg9opewDAw5nll6mkwwivcSu8NFlHSn5oaCEjf7Iqm00fVAGIompPilmL9YQy6DSUCimRUDZT67IwwsYzn3HFnnl2GMe3zVjeAzQ/QuyQenxFhYdAUtUBwBNBorw4GEtuvgv3Zc010NgtUOJCnpXN+FOz3EEsR5PkLSj7srGod8N/7m214jaUT3gxDhL0TXi+pj1hSb2a7i3PrhBch+teX7EJs/OiEV0XrtFGuP8ELNu8A64540AtKvhcO3L90wivMeV9+57ynX7FcX8TiesxBLa3ZeieHvHRyQOzu+Nze3eGtatVQwXuMjjlUaw+nHDOcIjrhNf07Ymxm7aLsuBOe+y91whtdkGNMI8Sy90NGHAduYdmoDfvBjXL9upfrX89+yB0lnWQ/ZAyYYN2A6Ie8OV8AZ5hdjz1AC69jafaA+7FX4YcF/0WA4g6ViLFe3LwEYR5YoTA76uEr1EoI+RgBFimhpoupbOWww6LdW4mCXBMEQ4DUPGrnlxKFm/KhI8BCpfRrlbpbgPPzAfaubD3AIg8mCG539AUujKisT5y3mv1milvWZBvBRMvPEUy0/FE3B4ANbDXgF53EaiY7HXdYDc8RLN3S2EN+0uL9VqEwDhVuW3D5vQw/1R+g2iBvhgryoUqeyvB3rPajTUT3EB9qY1Z8lyRL87t7XVZy/rKU61MpPAEwFGf3J7i+1+G/dMgaMRaxsI/p6+U9fzUme/3B/XP9AU7fm4M97S+sP7i/EDDY3aLXH/Tey7M/25MgbwIyML/BleITlWG4U8VjOtipFZ0tEE7RK8WthOIzG0Pdmp1hfKTL9Ckax5FTNjkT2akV/dJm3d1f6g8SQTCUbGb8Ahi46hZmWsk7z70vM6IkuKRmojIuzXtod8kmIEM8yc0KQXTJKADGGJN3PeodfiLIE6D5OXmzFGKGqO5fCfKUJgRGd2gn8IQJ8pR6gO87XOlR1v/D9MqgjX+Bi7tH0EaU//9T0ObHNm6iH9UGBHjwJz727IixMI5jAuW5APxBQK7iT8UMjOkEzAYTkKvywNpPWD9FWGRTefWs/+ZeF9PxkL0ujq9iBug9gdiKAe3gAVouALcvxQyPiNELgeL9G3Gre7B860+uUNUDpm/tQ/RO8y1oAqB2n33xCQPQWymWAFfM6dN+AWZ0X5y5Qkd8hSIDXXwmUAJjI6OA/gUa4+vTcXshKJBP/EVQ0OMrNI7jAd34yFI9dwSXkLu4E9WyXw4Ij5AYucHSEuoGjYlPSomJ5kAMx0BuTDQHhVcmNMaZpXdDB248O4wKMMeIrvAl/rUwxDN4RJ6Oir1+9WthyGApQDj+EiUBMWjuB0N7Km7eZ+RhbQpJPTgRmYFt6gCZwSUrF5esfPeEZNRBJZgBx5L7rjVf4ZNEAZnN4VpgBug6Ijogwy6msn/DZf/S2sgbc4s0OTPBDDA2wSEXJiKgYkF9WcIZ9JjFwBlMU945whmUFbcuW5KiZzu9ukI4gxlo+UQP0Loe7lecQR4713S3kRtASmIAu+QREGcwP4rxl/45t8ROkn/tQtxJD9v05cszWULstTCQmRO1ME5yo1smrRPAFAIaLIUvkkJAzca7f8EZjFaT5xUkJqUSJkW0kl9KVQCm0nEGM9YyCATUZn0V27kJDDQslnGS2TSu7r3kZzhmRnsgWpGvyKGP2Gte+gRV2VeuowVifeHjXc8w1GbwGVl8MsIsh3th0JbQi7T19kBXQsBFhgNzESpEtrLjWusRBVngG/le4BsYcMFAA8U3yspbtwAUHFHDYXUHN88sFEPgrTJjH3POJrykIzHyQl/YveHsJM3LjH14Ls4NLwUuE12CYKa84LTFAMJa6PNCqzdRJ4JucCBSuHzDvPS8rtsIsDhmcekfTPcf0Bxor4k8B6Inc2B3JOjdpddfGaKtyVfFMAj1rd/dEQlVsZoSRDOcQ1p09q13S9/6fuLbtYFmWaAq1ALTug5EUdx7crIYdAjIywSHR37oQdjdcXV/dekxTkORX6UGjuGN3uCtj8SPkRabfoi0YPxHzcTdfyXSIhvXP2nU/+uRlpC/Iy2/8aj/KW1n9wYZgjthb1RTdp/+5g4Z96PVuOhw30Ekbm0rSiQHonO9ftpqEl7Cfv/kiLyXnqDdzzwXesMRNXmh0qh1j6H9yqP+FTTxjG3hhz65Lut8VOWHHxxZAf641J15fvODvnB2uK932B1ZQVU45/d4zq9EoHw4slhRgjQHg78wTWgJ8xe696r83rr+/mRu+0NV/qQhcJNU8L4ZGzG58RRjI9Rjq0waAre0E+3QiElNoCG0MVL7O5+Rm20q9Evjyol0ZEJywTs4XKQXTPr6K0Z10mBCGMiIJDADRp1Lo5I3F6O9B1GE84JUqJE104/qakYyw6MwkhmdsbS6ZVY2hdc7krkX1nQYPdbA1Kky8EL6JQiXGKY+ofcTyBwXlo6eVRQJAOFqfboIhdjI2sU0ZxWNevTcjiVNZ2ImoLurZaerRdEtcmLnR7szZdGZWhwxTCqaH3pu6+swk14eg5B4PuY1qquW9wynFT8IyOzfgu7o0E2e9/OqTTEC3L8OL7BL0MgjTnK63hFI73UASE7X3Qm7uRNGMjpuecWevR9FSAjwR4U1WdgRXHXdC9eb4cj6pJcjDCuyzGeQsFH6jq4OKJ9qVx+oo/8wiRg34mlvlZMJa3QBFqz8QqkdxuegbiCPLdtdALMkpO3xRMDnIOum3doythmfhbAf3e2qElCWycpprwrjKQYzm8hMoxqVlF3Zrfhst2UREZpaPc0orcoEwCMMAVdlEqxnzuFN5jh3EuqyGWzto4kAzjNPhWp1IuCxAqcn7DaG9dFs/NgBxeWTAGzoRMcl4AdbLcdutSyOU+FsxezRUZhjZTz5dJwwsNDzpxudW1ph+eSSY3Z7o3ObDy6424+Fzm3tmvY7bBVcpnYxxPl3blZpSVZGO0osPnojaKZPv2QObVaFMtm8RLfnsOSQyUzXP1Jgi+r9DM7NMNPtXgs989WdE36lwJ7BX7zbUSVWfp43orbfrV3IcYImFHYW8k+wPDqq3VPKK2DA7VmV+mnfrCcVY/VPclUEmH26JX9NNo9rCDA7X+PPLpA0iru7I4rveW7LYvNsLtDu7lDc/enurNi07u4c0l74jwF17X5vgLo2iv9pgLoj/Q8F1DU1938NUHer/yGAOg6K4zl3m4WAFoPCr1RVAKi79RoD+4r7gwkR6+S6rXh8Hohz80uTerLMDYHhZkVhR+3lpWNNh/8VbsK0WhJ4Ickq260QvNACiwtq0k9j1J+VCr5Co3zi1TquLSyfE7WHPe7Xqwvz74Z6Jfgf2jA/MQzHU4T9JREtmd9Onm69umbjrA380bDEZtFSdw+K4Tzsm3x7bRaKWLTThVVlCdY331vjzYmqC+WxJs32jtl5g66/W++IM9PnDfFiiDR3ddYstAX9dy2jwAY1w0r3frfSpWElrfRhOrHeObi48HIvYeJjpb1xaGxxWap61BbqaVYzF4AoA2T0H1dAKiI5ojpGDKYi19EwdzSGhGQcF7cesV29MQGD0ZLvyKZKxJLHXshoF9ogAahDrBOi4QhGZIgK2JqP6n5RNyh4YuMSkUXboxcyxqXjjMwTLCs7CUnD7GpD57eoLbR8VgsOf/tBBTx4YuHrvWsMj4VtI0K1yBFMRCCPYJbriRFs8dVXplroDnNF+DrbDdMi6hZEerZY/R3Y16m8a33utosRXQsbrV7YaH8D9h3wy7C1DrXbWpN5Fi9JpV9biW3P1eDscUAVXac+exy87WgwDDdv9NPI8dp5gzrObAZguXDuJQtwP2JouHtumaMy/xZuflYq/gghk8v1zvOJIdxeqIh7fZxvvSLwWCB3C59kx7eNGWfwHL4aIdu0ERkPiqOtuwwTATkRik0csk17yHai3gV0TfOMHy/FdmXDbSFMbo3Rvvl80G3GXvUe9ar3UlAoeD5/2yB+hx5Z0cttPMq9o/buXzfIhG4yHG7HxUwfrCPqxmq90N7SJbR6gPZmaR8Gczsu5oX2duJiGGTWg8IdZBdeQHb+v1ZXOllvf60r/YK97nWlS5Obf+C07Ti79Ghy8++cthKj+COl7ZT1ib37J4zij5S2e2HprPr7KCx9mWEqLHUMO/MvsDP3hJFOsNy/FZY2Cw2a0zg36vr8/1Fh6bMlu+YmtIyYyozXkARJozDSv7Vk19yElsv8MtjWhGFeiI060k30zHkUlgpg3CyMnFmBWRgZfm3Jns7bxaxP+DoD3AbCjusi/9uFpYaTT+ZBoRV/pNA63LyI9px98movzJ1cS0bBNceeftQe8vx5/SzM9awlAcLU97TfCqAhVNqmL/iRf3K8cI5ptNwLjZYLfywsPdy/ZKi92Zo9ZJf/XljqKukoVzcd5Rkz7A1es28KjltnOhi4sDSd17PbFsfDM1Y64Z5g7trsCFrnlbf17OXvnhEdnrtteffUKn4Lfsd4qQ4o+4Xn6plT9JoUSHihufL1AWXY4+dAB77lzSBMle+sArtLanBigHfeYZaZBBCzi0SrEQVuRm0JQKJsEl2fzyXRyZBvzemZRI2EZweoPdMZmbMJCLsJ/Ins2E/gZFoJrxbOJkZl0oS+FwnehaGUnX67B1VmQ7jZ60aj6TcKCgWw0nGZoFvBlrHK3tE/wC6RtOnPsEs8E7GiMK8EDB0kaZbkn9m6Vd0rPM/uxSCvYEqILzZDjlyWKLJ3KsYbUniVhL3tiDYCw2DKFW3ZwZSuboR3o6Iwp38ibXovFZmpv964GknXJggcsn4UV7GceEsV84gZKspvt+ImS294KnGTPaDXex9Rohtc6XjPBswVS2AP9Wys1bOhPdm5lx86Lj90X+WHeIefyw//JXGI6hpOGOruci3Nt3sy8Xg+gEwcUljELWF8jHb1XKJlsOSWS7QrIftWfjhHMBOHcwTeLJxlL+WHWEzac4RoG1clnfM+gplL5BGYaaP79BPM6qp/qT8UlFw9FjaSRjMBGfwLV1gPZMhQ2sSgMVXpDOsdyAk+4IwLy8MpqpYlPJK3jI4LoLcHMmbpk5/FmL+jrGaATzHP1ygRJRE13LjXfDfufcwvIhP2LCRlLe1XkUciW7C9qmEhSdr5T5cAXk9u6qVCtmchJUnSDOAx7+QM4GHYroceJjlYrufGfyryhGHm2tba3l5aqTaw2NOZ7fieP2SbkYjrrbFUDjuFl1tigrtxfK6I7yuBXTGiaeXRrVrQi8MlCby5HwcCvPnkP53BN4zxDfBmkkwFWC3ae0VzCO3kvtV9gs+XKlkWjS8+8D/wyxKP4T8Rgi8kX9wf4Z8IwRcUJkd9XhjBRfDw2RNIxOLIjvxL1dAkBB/gztUgdms7mTfSC6oauuvDct5c6m7Sx72j6clG6mRVN9TrRPJgLAoGr4PZW9kZtV8nKGmjzv2q13IjfIUmqt7opcv6ua1Xzqs9WpAcsnfN6aS3va/JTtQEn9TCGhUdVZncYiLvmEIUXzEoRTFeTUm8WqcQ1T+V9ggOi46oO1Zr/A1lx6U9Sz3UtD7D31C8QFhbBsaOgwsEXG/Wp1tKedaSqGF9vnCGrrg3NEbND41NRl4aMHAX85yblzrHWSrTDX2/N+MxPcknG89mkrHsezOdkTqzsdcMGXevrVM7N4aSSYDy0UQTDKqinJm+oCcOUEHGv3YpRBOxWcYX88tEbk8Sn7UWwmCZRnTlJpqi+w1TgG5cMJRaHgaaMESohaVIVlcmVp4sJPNJZp7YfjXRxFqkgoVObBUPDB8h+8xzBDN3PEcwjW0cgaChfj9MJDVLr2TiaqWZ7iaqqQcrS69HsVublLQxtSDqjpla9uqisvbeccobOky8+W6Q4F/6AU6QXmbOkJm37h2O/xYrFjQwlvKls0pKGKKIlaNsbqaKFYHIexiVqYqC9kn30ivgdubNn3vvSJKU23IfBLv3QRB9XLGMiayAHbY+jR5RizQrVtY+O7hwouPOP/fZOdiqrMxqm/8rRo/sqoodVIcRnSTxSzd6FgN8MXoET0xgoycIwzpwyUXID+LlYeG9WDzXi8UzTW22eNj2wGyjURITOUJczWi9Bp9tp7p8K3+MnQJ14cfPvWXLM7qD5xo0TOb2318mQpgHv6DiTyPbaQSbbDeL5rsihXI9TSVIOxpt1ONJKs4WhspmpYHo0rd29UPgQ7SP4o7SaUG4yIBqo+6XUx6yEKU9v99dA4w23knGImcTedEHAC3kuxP5c4LpizPsrYKIGgQMUaBYZJjGUje6YCzTWBJjWU0ySIQKYvDKApKV2gLva00k19iNSOoa9KLjSIVFRFGPSOwkrgxwncDKcHsFDXUDONkIuKRuC1cvsTeof4UFC/X6GYcmWsPnbkctZcaQd31ttlAQv7lEERMjj5aCjvaN6DCWnJVAS9qe/N2MyGG3+iSjqCjITi2x2l5z6pZYLW22PPssYtAWOFd3UGOvuigua9UUfd47Lq4pehSobGEt4uSQceZ54omcsKg0h64Os1AjzPgXNpvokyP8xkyXmIZhYkLtGVnNKHPngpzMoOOzxxzTljzAcgwbexKCERTd1E1rZDWnJYAHTVJXsg0gUlmrypZqVVWf9DnjJrE+biLq45lVS5ijMst+bWeZedGrPfh7VRyWsEeraFlBrdKd9KucPBhhv2UJ0cXnnhHi4iECmyliOU3jS42WjbIu304TeqzssYKKhxZbo2gUXZREPKh5Z0nE8u1RezawPfOEcJhkTUsaipxguLpzY+5i/7YYRaJvS7LjlfCP8j4zNDAiAA5NINFhBuhtEMKcaB9JZ2mGo5MEdUM6XnV2oMkT1Ikp3SP9SfjuEQjIyWwqsbZLnsMkqAhmFH1/hOrjVduYbXvf2iqB3FnHBTIFJxck49/O++PN0VeddkY9+tZmnFfROVc/R9VbHQmlK06ViCcc4HRkYAD2GGT1RWoMx+ICjUq6nxrlAlL70t2Gvev08xlR3YJe24563ta2PmpDRLYMtDsAE6QHmwldnvHbzCPCJWm51xieSwIx9wTaq3zNSrk04AqrUuk1Za8MFujwO8wrzmSDmiGCpPYnlqwiWlBs9b0wdgpvVcAW646F7/V0tUMqMpMi+aflhptB0PkMYllpEWJ1qnaLUZyUdRh1w8lxGFSS3YhoeU71wu/UZTatmeT3ZCcbIXABSEtLS/LuPa1kvSeacLh++34UPaMZr7DINu49/1J5AHvvmntP9HPCfebsarS456jm3hOjKkJENdhE9ywsxd3lMQBnljPP9/2Ynl6GybjZPEZpy0fUDu/gdfoUUTWjU+mxmlu62hvagOJJLAazzGiyKnYLLJbLK32PoWlZIl+zn7coFdWI8Pj7ZsOt481CU9OBB32zrRvQU9MpwqEcy/pNz1H4DmEaVe0WGKTrz/xSlY9S1twqFpOKwusqORdNDcke5WwVVyqK7biHa0FAgF2XEfEqYq6+Q1skahSW0jsnF7ULQl9UtbxnOy5h2LcSeNqVCtW3qB5Mk4uEjcq9mWIgsto9fWjvnbUaTT/JWt2DHZc4HrIgWUHWJG+XuKflhNXWZBy9TPsgSEFZ8m5a7RSYwmvMcp2edRbvPZS5UtsRNN9bgpBKqaV4e8NVgMuvZ8+wDMMLy05B6IXHACyHmZ8B0w78uJcW4lgmY4/N2nu0HNv1BKKdfH3ThdqIzTYafy2x3N4gbPZLstwgbI0Dc5vBF48bUA9FWw7wdgKqTtyVF2ZuKaG6B0vrxDXYvFQT9Xk0sh57RhZ63FZKaCfDRoapAsHPKKwPKaEctXqLvnbkw5DaiapwHAdxxyu33MtpCMHfoh1JCtQQdUlx90bbpUzyTpRenUvzqL4aK58VCoo3W/HRSBhp/yEoCObYBGVHTPhEt5zv4YB6qde5FCklK4uP6KLBf0RmIIBZ9AwOx17AMjvJ2bw1JOuqDHmkhqBg+RN+buUZz9STvQuFKIS61SYoPXxcMcw7+7fLCJz3S1U1vjLre00moL67C8oETPhbAiYwK7dUKr0JCtQHFXQtUFCIDlz7t4ijSUFU6YmA8cUk/dcioY4YLkQndi4g1F8FhBjPFsHEkxnxRayYmw6eaxUVisqpX9RwmwkvHSYMBL+JCtSEF2y5OtUw1DqTGGAAGMXgKra4K83YbpvBk/qyZV9kEdUiBhdH6a4Ty4lEtbXUF71gaTwIwBL6ml9rtU/HYNxLmyxUGOJzhyDcwgjibJl2Fea5ntUZ6vnexfJVGIcwK+4zlQTL9m1gT2APiAffFnEsofpmTOWtSFGJcjA+XZdysMmxfXOPiEk1hdAG1FQS5KDiR0MEKX7Y2uzrSBOu9RhGWOi/UfzE0Ljn5cROIGIC21fc7u2UhwKj0k53wkTEXsFk6rOqSU24qr2Q6mmUSmWS0HupqssyxYs3EDxqq4QidhUlFEuOSELNfqJ1nu+6cI+Jah4kye5COzuM3ZUEdHZEv4sI9NQXFm480U4WFD7RZqHSTWZCipP2R7JAEeZV9jXXQ06I15vKQjQBcpdG5XJk2Ij9TU5Ee2cV+JZhqUAybh2a58/5zQrttUsvegp7hRV9M2tVRK4qFBS3N7DEhmB4orlmbRMdbu8KZrPsD4Z5sOwlS5/oD9YJuYWgZE44ZHU6u8BrUFC46mgSZZPpI9/DOiEUlFlF1Dm6bxm0Xymw3wQFnMJiCBVzqi4obxutnWdpmj6TFbv3+sLVkF2/JB57a+TVBcV/CQqbPqJSBw+0yaLdXyW7vseSIsbGbQpB4fo4t2Iv8XkTFEyOmcmhTTmhTkKt1EpMTUD9SYSNRT+YxWyvrihAkVGwU6uFnRoGJbi4HZMfOIw8zEto0Wz8HiioWW3T+4Yt7AeM+Hexni8NyIeqNsR5fAJJEPVWnnU1+ArZD+gSoNT3QhpY7FlIg9U7uNhLHQ91GTOeTTTPwCivf+U8TlmJmjZRhdNfoVSI9xxJhWPSu0F+INhdWCrcR64SS2OK8Z7ChbgubIUihAVyvt4umcJebmS2FtqzuiZdJF0e58l6R1QX2d02Qhii3fSC79yzmoYCjOdqQAKHgGfbEWtpfHomY7DwJuXMmJeTMcyo87wHn5jMN3L3wLUfA/B2nEj9VX/PCIt81XmeAhLtQPUckPB+Oxwzc0L5kH0m/ea5EsmT5SXfSzyUvHPl4KAhCGDIYj/BE8GDMLNP0l9l8R4Z9XwCnyebz1zS5E86Cv35jyaT/yEKYNJuMml2WTKOCGWZxwbjHjIfWAt4avmVyclZZRndGNPmjjKyPlEUwDPTVX9PvXp8nj2+JiqBPb6LDSn6XEovRpNnLlift+BVDkQ+nUP0mcmn1ebxeeYfwFdmf883bTzkhxEs7Yp0iUORujl+DpTncMBUkcV9hvKzx9cjVf2EDHONTl6jc9mwSnFDep6Sgzw+f3x4fL4sHl9z6eiAjCwCkcVivhdYfILUG3GivZftiNH1N1UYwQsx1dct8OZPyv76M0fWIHjQLlJRK39OM14i8jrF5NvP6LH4jxle/Ul6xTP+2Z8UMXg/2DyQs6aDCDA9ZNi7/HCuHV/JqoN+sDFZgL9pjTwD1vxFVWX+qs+DDXdevN7RMDmWrhLfxOdIayFbmGJxE9WlHBqfuexD+Dt98uLBjECUrc3ImUipnImlh9NV7RVZG462Y3KQZeiyEhR53kEteUIvuifmJCga2tfJiRlPHTQJS2h/ncKSNmGR1+C+v4mLcVN02Q1ZCZwPDxxydDOWqVP5ualhgPAPEBF1aQGt06UFXy0MaqpYgQ8PHOsPhpYk8KEf0JkQxUaJFUM6SVGn80NcUt7EhYK77A3gq35P8Z4a4iLGZlcnWEv3Njj13nIxoLFQc2ZjAWP61CxjVRmYl0JxaTaWo5M+OFItYWa/pg7TCL7BM5wxMzk/5MWzvHgwXZhbly5C4f2cWZFkioXI91LwpFxCeILxcqbwfn/1k7yAyZ+YtYvPp9eDHYERJC9c5x8oV2bCPgzKPGTOPOR8kbjkL+1C1AT9XA+JoraBLfn+nlrfi6Rd8BWRqE1g2L3typDch7jAiZ9OX/SqkTMmM1A0SgjZcQzPbadOYREqFO8JnPUJRRfKVGVOP7QrkgAx7qd9WzjDbyd7adqg2EAne2H54QB+f5VlwzM41zmynkulNSrcwKiw+JRjh84Oz7d82ByhfIfSqJYWggv9nsXO56eovxzbxWNjdWOI1MR+BHMLZLRKMwXoeIwQaOgSlK7nZin27D6Twlepv1dnxjzdH8+6QlGoMjTdC9015o8TM+l4xmu7mV4y9vh4FmjchrztHfzrJnNEHDnzJiPjIlnwaOdmcLc/mZ/42m18axVWnN9Q/Zkd5Nyk3AzwWHHkNvVXslVYEUQTVA5V2J0t4Lrmfq/A77k8oavgs8M8ZT5/oLtWT9lns8CbcMrzzHnEWeVXf0AE5GK+ZvzIpri8uj44ndmEj+nsGeK6FVnSs1z7fHJdSLbaBJ7PynNBbXjaKw4zPCeUXd+Cyb4+oTe/d2Ym3x0PkzlclR0hIPKku5nTOU84luDFBXvMZv4ws4tvtssFpByOYKNI9n35rSvegrd8n05JpO1ZbvAVzpUXqwN+n8ne/cRTbHzmi0S4Qp+rHLbqjOLjvBlccyEqzivfBc5V5tDa3O2ZQ2sZQmveLFxoqMybRovtXIdv4w7n/QWRgr7Xp5uuF5L017n63OxhbU29dwNYNg4CGPLOpbOAcm1dKb1z3PWQv75aFuYpDHRQ6lG2UZa2Pbhx+Kxvnom/aONw9UyhSAHi0VERBffcN0xoXZoJMfZNMPweqdN2wmcwKVERcdIrJ1ZE+UURbUmvDu76URHFL0UU4l7++B/sHE7f7Z98tpxBA2VZ6STyPCazAZMLeZtZYMn6Sof0Q0eUzIGKZriEg9d5pxzLHAQBOyttHVFKWOtq+zqfj3XOZq6p5ACSRkmuJtz5gK/jMtcZKk60zMeiIN/Y9v6wysHubHtG1BIv/Xb/ssqyLkLmMf9lmWlRatrWMOqvXsv5VbpwEePeYFTPRax4yb5ZIy9KNLvVEMNzs0bPn3e0WSNjn0LJlQFxJnaAWOa4SD4dreKlnpv1rD9bDX9QpbRZY/NmTIz/TVUq73vtn3x2RnuqUoqg03HDF0sPsdmfk2InQNK8HjjwrPW5/+LxsnSFMwsfjla+SzzzbWJnf8lsJeeLtt9/tCodrbCFsf+HrIqJX02UkFJDUnX8sC6FaTaLwiv23cXRr/4qL++RXTSrr0ty/HlLu4thrCX1Yiw0i8rKYidW1hT9NCGLfpqQRabF9jry/FVgV1Iq+mo7vXPYFQ6btcHToth92n/XyLQLGCMj9O2/quS9De5/opLJJoUFKp9k03lnhpQqWTTrArOVcb8lFbhiN1sLu0/4Co/x+Z6wSLvZWjgVCMGfrkcK+y/FXIlY+UqqG4yhQIyw262iQwGrkayeamQplXvoKewk/qZHiiuA3QJPHfRIcQ/x+smn+MUp/raM/qBFnuqrV4n9ixqR3DngOQezkeusV3vVIuOkBn3AyOH+Ki/vkY4orn6xNiAFo2FnNfviWUn4jS+pZD9vVpxoY4RKIrinkpDuFwkho/QBe/8G7CjNEj2alQ7fxpsVvi3FSbIRR9lfrfOXs/JSSzbwf4Z1vozwRyXxJoNSwPz2FL1tzCJgrzIoBWzKBgcyZE/iLmDhRwErHDAu+SyRBSw+BOycN4NrrgKWXk6h5J4Cxo5lifVdwJqKaRsVvw03K7yJiiIlJ/so/1nAot0FbOt1+t8QsOci/rOASd5MtCglTaB1fxGwtuagaMY5xN5zyXwO5d0VKY8eHqEUPofY+yz5KsTWXsrO1l7eiBfmOVRezFkZ9iZztix9D1+PoaOUsxztZz+GmNO/FDJny7Hlm/9wDOm6mzdHmPX5/5E1K2NpsjD5H6zZ5YR8Uv7r7vT+cFAlScqNSuLYLdXyRbLW+ZH4OWm3oVTUXUUcZHy0GxTmWCvs65cqe9KBOjhfVMQ5P15JALkEudRw0HweAb6Pt2NT9XCkJI74tIRm5zl9MSnHTzpCq/RhCF3miGt84R+Cq1MCJVvyX5TEmwTuPFG/6Ig3CVw6NT/6Gyy68EsCpXiVXbyuDzsbmb4AH/QiXtfWay1zjRts/4v128Wb/0qbeN1PeF1hQES5FYkX551cNcdB4nWXngzKho/I4yTxqupFvO6HeP2rwiGK/qM9/c+tWR765rl4xAzyB4Wj6v6RsDZoN7OWzLi9DPRL5TwyAYd+RocO9UzjHeq5cjuZz8ZcCPx0pfpDGyD77Vk85jcrFUtXs5Rze77kTmGaDyw1n7yH6CSe4yPzSSZ4S3AbdHKevHAg4Nwi9dBCxIMVtvj27B+A83Y9qsFfJIRZFLnuPCz8QZ1deFZ+o2V/vXAKdc2FaNAHf3l73APgW8yi7Ih6SKe3cjnuTbyfJno9+m/R+Y9rbOkD3PB1ZgHxbp3e6HiW/hoOTwCGx2jXq3cz2VDA8gFfhNIEwBBKGgQikmP4ZKcchLM7Ck38VpAO+vfAfmFjdpKXrQLtSoeu1qLrExGGC+vBuOtrcWrA51HUgiQI5VlW6pnJ/iA5EBOTb/u1z6BTsg67V5QXt4bOX4lsR3++XjScqQCYe9zmQOgBwQNzQemEPkN4NOTLoSyVw0uFrAboiahlFUXf98N6FGW2eYFx9j2v3WRZmToZOb6JdBy3+4ygXSu/nGOi7k7WL+qlkYVRsKU4JUm+RSZho+yaEX18tdF44Z4b/cu+u/xNioZaZF/ymlSvfAONCFBQIw3aXygaiEEKKz5E807zWRhQj42iQXDzJCcpU2aBwu8cDXOjSy2SHYPIf+dowMF4pGKdw8pLIO43iobZ/Pto+oAbjzK2TZAYfFE0sEYBWJKLeytww7QNeeFImbQNU1tM2oa8sm+pF2rTR2YCD9BHemWyXnXekkwNq2c1rssL/9UchZXNz1apnkR0S0uT51bsxeuzfpqJf0Jdm8/Grgq7UB8LR5EgeRKmrhutN6ZEDaH+BnlOct8qeEfm0YZasQt1XPhVOiPWTHQJJqLryUQk5DyhTL+3Eujyq9VjW6FMz1Hh8m+jkmR5rzINO+ewlbdXNZiu9w9qN7E3zMJaARttynT4LnGYZA+dTCR3y203pUWXDI4ViN7ZzIL0B6HuDBPQAFeYb/N0zuZJiSKGcb4MY+MkAkPRy/48zzZjgz15EnJskDbNNIHhafdOgw1l2x9ENcn4ccm1Fe5no2W7kmRPIhWmDmzDZ0GseDZgrwzagE2sK4kcUmEjORcyYb8eSpnTB1lNtDZmvuJbz2Qj+UZXqRracypyU+GKXdLSAzSZ6otUxadUzQ04MyaWIKSCdqejE172jCAf5IbJsh9UXmzAOQSh1XkIU8rwsJ9Ng+xQloJzvNs/tht9JFCWuHYmtSGpL31G/WIuQCHnqZlRrjs5Gvt6DhY54aZIcwSFLJoXNmsHlzSDqqrraaNYBZrR+1hQc3q83UrUvfVWknK+CjE2UoqrXv8gcg/MGK9rN6FXj7OPY/oscxzxhThrZWMnjyctRE3+fA5D9FAaB6DqurdziWaiiORzNWPbcrO2ClZ1P9vQXFyY+7bD1tFhi/2oxMrKplS9Y3o4LW/43Jk8jFKVDtu2MCd5kCth1Tz21KMnnWhKBevqz7RFe7CI563C5fCCEkMclGD8RWw6MCcU1vFc1zGk56i4s+5uiQ4PDq58PKnEYlmWomuyPEe1O7GbJCJHVHwx2+GoLKcXja32w3BtGdUPzbSoLUwMDwT1trB56CkUercQovuhxRa6u8kJuR+Gq5oyYY8A4Z45V18nkHSCtQb0qShGdaEF7cNwX8MYARk/SZu7s4lbA16thFWrqvzwUk68YnUJlAsz6SFxXzxfrS8d7xnymDtxidxE9vJ3XUl877r+Uqysh+f2oiqXcdwv46jbCfLUlYxoMdIuz+nlPG4Lhuf8i64kc3QlnoSKMknixxr0TVdSqgxjnzK5hXYTutYLqeKLrqTpwJZ5ghfUdp8FdjdebiMiXXSl7Gzl2PG95Imd4wuDjVCWafoIZxaO73a8nJuFvihLqp5hH6GuLIru4R8/leVi4F9p4QqFsUDVohzVi7KU6+rvl0MUDLAjzCPqqSufjEBG7X342Ed4V5Wipx6nwbo1N/0GFP9uzb2qysWwzumvPoJUlaOEeaXU2y26+2nRSVXJ/XqWSihBedxltc6I1uDxm6pS5vywPFHEluxOfmXY6Xiy80bUeVicuHGBmvU94hntLGkvIV7PDRL9Lw0SE1qYxxb6+ihlPaI46AUjPXOW6fQgnu/dclaS+c599aVnN3+p6krcV2LTVb5lXQJQSD7E9YN4WUFNiZWyU5HdH+xXYC2U85zHo7D4HPPguoVGEnl5Fjp2xa3Z37qYrBnNZL+GckgwXVXcAWyjokQJES5Z+6CdPv6yKj3CVWWsC1oAcXcIkze8gCBj5Kv3rkSyIXCqgzOT2pnMmBjOF4G0Q9A70T58B4qJf+hjBOGjhYZ/kE0ubNU5hdUAMGFsgsTRK5cmDX+Kb1nfHqGdpcvAYu0wx/tSWZo60dDa5hW+fqb0bHmFY14SKiSIUL7abxJXIwt3/tzF8CrotLSlmlKXuCdiEkCRYETUwzD73kKeurdv7fIkOE56zwIp9PhtOCe5UoUmDe1OtcaYDNUlwSu2GtodNPLT+E2+RqcpYVC7Ub29ciejHkxFhJ02ilIMKs0kETzAafwi5obZ1ehYal+CjebMSu57ODjL+sqacyaf0D4HDiojodG9lc6ezcEu0QurrnBPN5u4d4utAdsfWME0j8HYmteOVoY2QE5LsFo0qtw7IGfceHWmruAjdTZ9pe12LISkGLzBO83GVJajJIJn1QrGvNljS3L9Y9omoBN/1SaVl2sfsWpwoTZ3uGoY/6rAyD+Rba7ibGlVZx6L5jqLNl0vjWm0drOjFSo1UfNJkL1Uph35p8Y05zVjNKPLQLp3xgFs4f5bY5pprSMd0TIZf2xM83rG/mNjGjLB7x6aEibxHxrTtCEy91Z/0OuZoepKcnhKMT3qyYXNENJCErJaWcluSk709LtWJds2uhce173HRzsFqsGoe51KFq3AqWR1XTyuZSwM2cjaTHK4zMwseQebYxB8WHevWuqQcYY+ZPNGlIQ6oVzMlpyYMfCNzHnBmovIu2O25CUv3qklzb/yJHWC7fd6+MvsPElrWqtbd2JogYcW1lbHN9roAjsmWvUGbFQWnq2QhJoG5RysYPe43/Lev/ZCwvaD3Pt7aIFrUVB9NG+NmUTnGPbop72DZr8MIPZNpfuu59hut9EwcW4JMXXZ7hqjWdSVLXzgFCFEjdyOuxuC49qbCmDjx6VNBjxycC99OYC6HbZwftDoB7emfLnnkGwJxSpe1bWe1C05Bj2oRt4cmCwcGMaj4D4HKpK9ecc+qpgeo1rUOQTsjuw45lfREMqrIYSnZxbmzW6czwTdF1UJhhfzo3V3dqsdaF8y0W5pd98z1klY57943yIzJvPWW3Gaf45jz0W7lQw/z0AlCSkegpVPzxG4MT5n0bWjI22WxpZiICs6o6eSrfs5DdE3D9Bu0NKuIb6etBWQHQ4T+cXrFyQBItu4JkLcayp5SCrh1hbxCIlSySE9E9xhyUDOUT3rfHELAf5zetkX5ZKFzzK4FgW9o9gNSeaSzZdqvDs1oyxnyE/QWF4b306Iy+Zlu7RHiz+TyQNNhhIiUpVb7k8Ep9JLUjs+04+jMHCZ0xDSHiriNnUyqz0D+U+fGsYYsFuQWpKIfRlP9exVN/spIdePEF1KolDo1epuVKW1Gzpq+igaC0irCyUsxPSBNyxu4g2nTx17tN/IAH0kjuXF6sqyGdDmU4+l3gIqaMj1li0pbWbtkt8RS+3NYmHNfSFcW8e5prwOI772UXFOvXVjGi3vUMG/hFjd0mZvbs9JGMDDkKKBdwy4uUUNJMSS1pyOGy1nel/nLGriZXcyv3YnY/ZX8d5oMabk0bRZ8xTOD1dZJS4OzxT3AjD8Ks6DCstdPHxIzzVY4bFuUgbPcL/OrxpT0DRKHYaNw9KDmgjbgM1RiXD/HJXIjYq88tKVRq04PFQO+njmQUdjc2a4leHEYhZFh0nlt26QsBnKxZrYOXkCdKmeii6wmpCYDBCmurUxAo0e8ou5BrAJM3I1wg8JSMQ1RnEuDcLKal4ImOBLGzVzzEhc2Rt69l0mLIChUXUPvWAf8R2fgxKDAr36vekBc8tFD3TFhHlHkOizyzYbHU1YHZG3avQqVhRo75lH+m/LTaH+QKPjH7APr7mpgRT7yE3t0AcREo/P3BSi6j6MjkMgUrbcFGIy19zUNqqetJdJ4bfc1FG33BTaHFse35F4Tf2I4h7KI1WFNG9rqgrT+IUbbclwNBqa5c+ZKhrFsfTjA0q3/7+zq0uXG9WBe5kVYMA2LGYeMN3e/xKukdAf4E7mvuRLOue4wYCQVKWSqcgw7SsHpEpGMQBV5a+BKgXTH0da8LvbDXBVx/r6bWOAaB0DVSZMSfiTKo9V6ew6w0jLhfB7m6+GnV92cxqenRhJMkolrXpDb1te0gccxwFX8s/7dpZTfWRnCC1dDG8asE8yYAIWypot8DfjZf6Hw4elgbMQ8vuIgf9nOYFNbU9l+TR9LC0LOyqChPk5NBibn4Si49jOgWXUZPpMTUpm3q/lJ4FNsMjheP3CgO9ld01o7kFMWwkw4HIGWW7hW2yLUWEoZEdFFLTcIb1W/0Wg4YlhT3BT2NPqctQlrrnV2TlrRmE6lnkEsH+IM52Y7+EmMGiCEB66WCyhJRgWrvr40Ae6rGwvlL2kHYMExTLKWBcDWZlijFB2pkJGrgQf3GJ/5W1x67TtfEFtpo9EsaGtlbOzrlc76gUiOVUylSmfb+/XgoGkWxQfFeQVuDchRmb/ADxo77UyAJMqDO8QXzzs7jvHMEfuRmlTam/sAoGHYqE37VOjG6hhTx/sey24w7Z+Ru1ey7LDslSmXB9NpDnRPMO+KLO/3lbca6D+kBdt2kEmKY3r3v9WXzZ6W8UStVMd3LreEQ779bHiuMMXD/x9qJ6yXIEWxuXePVW1w5TejvrFwenG6qnTpjeYtDhEjglcLgWAMv1Kl1Uu+7BBTWcH2JfsexidYt8jw80gqboH6OSpQE5fk2oQPF72KD2owC4bQiNORRxvLIaOY4WJigYpNyb9RnuBneYik4QdpPX6oqhOk1jOtqivg1T59Y2c4AOUIV2VGwxo/ALr64ruRok7ROGY+K17ngQhn7fxbMqQe2P1qtPjsENUDVupJgU3fhqc7TkZTcd0mBPU1xma5Nup8KlCURo2KQ+6zWTGmjiDbjc50UD1dSLoAF7rMWYbwmZHIcCkrLsIPMgpFKXbwu+46AM7VxJTN8kD4FBkmku/PUcvmQJ6QBrCS8E4WD+juYIFfPtCmIl6OkKfR+gcCedvYxGmjYWZtlGYCZtxQfkF+3DQTRJWT/WV9DV+ieASv+acXE0sqRdzSYPFJiaLqye9H+VK3+1ROyx629+Fd/ZOLMZUg9N93JPClNYHyJCVQ6K3olk2taGpQFg2RbBcKaB4xWprS44hGy3JbgCGqCq3keEJtnnMVDAExd4JrRoyypHD7MlCjuH6JpU8aULd0I5Xc6K6c79PYClxS5nFchDiBnk3H6UjMB21jcs/CLe9CAmzRG2DooH3pHsBIxY3tKgNzvYHHimy/lqk3HcMxh5v/luhz3q/8Js9zljPE7bjmg35YajYI6Nkj70/uF/0HR0M6BPi3woBUy2AT2rErQxxVIq6CmBBL1Pw08iXsSCWu2kPLvinNNtFXEFVARdqD66uhyyjIhfw+MUSg0k2Akq5P2zOT0/dqJTSnzK8JVC22fTcZblzKTL2p+4O1dZUVN8/lNVUpJRjQUqRcGlALVZTiXsTNoRfr4aVUqiGncnH8WOcXrwEDt1reE5l9yvlesxqxOqkjeXtwPTviIjVeZKjIcbCR59+S4Mu5/gdkUeIr3Y/E6x3t5ijZi14aLBIUWNbiAw3ezfxu8M7nNM5eFXgSiqKkGRRIR7L1aTfAZRZ5Uuld9ho6nu4sgi/pjxM4nJpunAE7ofIcawhSqs0DGdJODqD7w/M7gIXCiKCAA3fxkWiIjv0tdvx0LhU4sT4x+kUPrCtlheTSVXd1WZ+CrjFHVjAUqaNorgp5Ooi52Pqp0DHb5v6KXtUVvA/5qqG3M+wSQv0WVmnfvI+p36yABk/UtHworLu0Nu+vXWDdFTCSszm91y02TKnLa/AoIvj2LdUNHgAcIOw59EyT2fAK99xuuava8o6Su3mdM22zkVXF1+LyuBK2G7TrPQtF62GtdepqMwJteZHMnouKotW+4C8jufvX2h5PCWj1zVllwIiT8V7/1E3oT2XAqxoXWJGF9z3d+XEUGSWT6OGMA7kz0VmTYffZg8EAhh8kh9FZjiMWNdtktupu6BdrLbvkB0jh9bpinbVr1SGBVmzwb5DpnCw75gpnKhsG1Zm/kfzrl381v8NreZk3jHXaM07JguJ9z49XmKtPAD1ZX4tC+sjyY7oLBQ7WMbWU0CRcxRGCvFIcrZCmLFHXX4y60ORGgqU06XW6cDEKJViGUkp9fhGcnlFK7syRH23rRL56J9gpXLASwyvGFbRgALtnEw51shZ3EhZZ1AtGjO9cuxhGeHuVcyv1ofnsEwXz/2QFoDvr/RvNvklir2yJayzIfbBBm3RSp0okU+nijVhY+XFxroiqiBl4oKaqEd7CrKblHZfOdKqerA1lViq5Plj1PHp6V4gkUi6t+8YDcYulIdmWesD05JyuZMaUW2omOI8qYjXXiHAwFZow5Ym+9XW/HI7b7LTYUOHpImRtN28rkPPb+hxqvRyemWQRMu5rAwYMqnjpHMDXTws2OrBOOLBMOjh29q312bhf9HisGQUGYXfDd8yG69aJYwMeFiqDqaJBswhK44iuIUiSDCZPGcFG1I/MGBZT7sd6qp1YY9wLgNngIEyUg6Ruj6Pdf0S8JRRFxTpUrpECpxjd8YBclPeTpdCqLMRPmcFaZV6py2IFbOULU5cXRz88TEEAjBtOO2guGNIgDrFYMoW1ByA53/rJi5WJU4M+DOgiqL9GXhkvobaNlvJmJNVJm+OqzZ4lZImas8f/CLKYELx08uIT+UaFwpTvbRIEQyIOt++bUb8C2iqCOIv3GXlYBV2JJXuGZamZg1oFNT2OK15K4r2rmMz8AG+JjbrMVxaaUuSyzLs7cH6nFyzaCx537X5lhjUYGVd9azvWkWsjbZeNRpwqMsA1K2qutkT5QQEK9M1UgYrw9JaVIe0gJobeO6QuPYLiakkOpBDycu5Lnlp6pZcefgmxXa5rFWrhkslLtDtMBbCcAHQadpOhEHzSrWy/ZI8ZAozspTsBi1WEWu7B4R8rPhZpXjaab9c4TtT4xA9z9tSa1rwkSAeP3B3ccfmsdmgIk+meXXXSWMtjQ752OzJ2ClVyOs3Csc2dJH0bknQ6itbAUDGCkA8Qgr+6DZwaA3SDJmxDi9xaZ+/Sb9UOfLz9qpK8ECY7Du9XqmNoW4sVpxRDavOw1LqkC0KJJ0q/+ck7eO5QcEfFtqbihijoQ1rerjXNYW10DEAXD1qf9WtTRvvEIX69TtElfTwZR7Ombbw4VLOHHV2F72YROOHVHFrkIVJYxu1LbYI1RzClyvILtBtQZAdwm1eNxnN71AhS+/eS7iN3SVILxPcJk7uRliwfKaTgV3trGp0LiPrUiWPWz66w226PXq8nmfGu+WZc0fZ+lgumnM0Smk9u21EaHf0ICEF2KgZnXLsWBULIzX5D+jR6QwhWX3SmitlIr68PXw7qjyclCe+f/F9TY13+fTfkwnu/r8mU2P882RCj/31ZLbwN5OJ6ddkph/fnavzY7EiytGI+j/5Ec+7/puh7PNE6bI/8O7aXEWWd4Wwtv1xoXDP+7Oprqz9vYKb6ChT0n/x3jISk+U5ruJzUOlIlaa1LEpoTrRTY73UojQklP75PKZtspa42FiXpLr+R59Tu9Ov7TOOIOhjcMJjmTTFdSBE18dUsgyomgE59a3MJXE0wRYU0ljavCuPgIhjQmCqJ0sX9tFt9fbb8ss9ria9jRT0IJnyXoHbg9/xLNjt/Z+nk9XbaAYCH3HW/PaLfSiPzy77KFXFQvOnP94WIONnLTXV49wWDsCP7JFzgbWo7+0ERw+MpIQ63nAmnk2e+f36it7pySDm6wg++HDglcJnZ6iQyDhcPwhyJcikacDP7K7lY2VOIfiipE1ufm/n4/Hij9d68SNOfgT9b64Xu4HNGsGPlX4aMz5uu0EQE9gtjcRy+ZvckAbeXh6tLxOs+yLefL2euNjo/zxDph+5cAMg0CSE4BA4+d8aUFwhvm6rLUdzbCtLFLQcOb4hgD5ru2ufD56nKZsWHC93cFeV5abLvjkZ8Ef9po5NhobM1m/ccEL1q4ZWsyyAytWAe3ny/K0V+nh+T/BzG/8c5c8g3VZvZfBJPQt+h0KvWu+o92EQWcuPcy+/nOSXqzax//z7Px03vIOEwgEA", + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658", + "function_idx": 0 + }, + { + "selector": "0x3c118a68e16e12e97ed25cb4901c12f4d3162818669cc44c391d8049924c14", + "function_idx": 3 + }, + { + "selector": "0x5562b3e932b4d139366854d5a2e578382e6a3b6572ac9943d55e7efbe43d00", + "function_idx": 9 + }, + { + "selector": "0x5df99ae77df976b4f0e5cf28c7dcfe09bd6e81aab787b19ac0c08e03d928cf", + "function_idx": 1 + }, + { + "selector": "0xb17d8a2731ba7ca1816631e6be14f0fc1b8390422d649fa27f0fbb0c91eea8", + "function_idx": 10 + }, + { + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b", + "function_idx": 12 + }, + { + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "function_idx": 11 + }, + { + "selector": "0x27a4a7332e590dd789019a6d125ff2aacd358e453090978cbf81f0d85e4c045", + "function_idx": 2 + }, + { + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "function_idx": 7 + }, + { + "selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "function_idx": 4 + }, + { + "selector": "0x2d7cf5d5a324a320f9f37804b1615a533fde487400b41af80f13f7ac5581325", + "function_idx": 5 + }, + { + "selector": "0x31aafc75f498fdfa7528880ad27246b4c15af4954f96228c9a132b328de1c92", + "function_idx": 6 + }, + { + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50", + "function_idx": 8 + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 13 + } + ] + }, + "abi": "[{\"type\": \"constructor\", \"name\": \"constructor\", \"inputs\": []}, {\"type\": \"function\", \"name\": \"test\", \"inputs\": [{\"name\": \"arg\", \"type\": \"core::felt252\"}, {\"name\": \"arg1\", \"type\": \"core::felt252\"}, {\"name\": \"arg2\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_read\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_write\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}, {\"name\": \"value\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_get_execution_info\", \"inputs\": [{\"name\": \"block_number\", \"type\": \"core::felt252\"}, {\"name\": \"block_timestamp\", \"type\": \"core::felt252\"}, {\"name\": \"sequencer_address\", \"type\": \"core::felt252\"}, {\"name\": \"version\", \"type\": \"core::felt252\"}, {\"name\": \"account_address\", \"type\": \"core::felt252\"}, {\"name\": \"max_fee\", \"type\": \"core::felt252\"}, {\"name\": \"chain_id\", \"type\": \"core::felt252\"}, {\"name\": \"nonce\", \"type\": \"core::felt252\"}, {\"name\": \"caller_address\", \"type\": \"core::felt252\"}, {\"name\": \"contract_address\", \"type\": \"core::felt252\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_event\", \"inputs\": [{\"name\": \"keys\", \"type\": \"core::array::Array::\"}, {\"name\": \"data\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_send_message_to_l1\", \"inputs\": [{\"name\": \"to_address\", \"type\": \"core::felt252\"}, {\"name\": \"payload\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_simple_event\", \"inputs\": [{\"name\": \"argument\", \"type\": \"core::felt252\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\"}, {\"name\": \"another_argument\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_call_contract\", \"inputs\": [{\"name\": \"contract_address\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_library_call\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"assert_eq\", \"inputs\": [{\"name\": \"x\", \"type\": \"core::felt252\"}, {\"name\": \"y\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_segment_arena\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"enum\", \"name\": \"core::bool\", \"variants\": [{\"name\": \"False\", \"type\": \"()\"}, {\"name\": \"True\", \"type\": \"()\"}]}, {\"type\": \"function\", \"name\": \"test_deploy\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"contract_address_salt\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}, {\"name\": \"deploy_from_zero\", \"type\": \"core::bool\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_replace_class\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"struct\", \"members\": [{\"name\": \"argument\", \"type\": \"core::felt252\", \"kind\": \"data\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::Event\", \"kind\": \"enum\", \"variants\": [{\"name\": \"simple_event\", \"type\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"nested\"}]}]" + }, + "compiled_class_hash": "0x2ed2ccb5433d1d50d84d3e9dd8000d4cc618492c95169e30da0f9f93bcf1d01", + "sender_address": "0x43eef75848203b37363edd1e44e4121b49c8d4adff592c21b59566f5b76562f", + "type": "DECLARE" +} diff --git a/crates/starknet_client/resources/writer/declare_v3.json b/crates/starknet_client/resources/writer/declare_v3.json new file mode 100644 index 00000000000..7fbdea94175 --- /dev/null +++ b/crates/starknet_client/resources/writer/declare_v3.json @@ -0,0 +1,94 @@ +{ + "compiled_class_hash": "0x610e7b31000d4c7ced1196680fe0082f005e244356eb24567ee0c03d384c1ca", + "contract_class": { + "contract_class_version": "0.1.0", + "sierra_program": "H4sIABeSnWQC/8y9WZLsuq4lOJWy/K4P9s1Y6ouipDHk8IsACRCkpIjYN2+avXPMdnh4uEsUCYJoFhb+v/+l/rf+X//v/9N+mP5Dvf02flg3Pnvc/ad346cJOlwhBu9sSMEHG47lmy4GHa0z0YccanTt36v/JYT28faONdbbcVeno4ntkjH339cRettupaOKcKs7jiFY+mN0EW5j6Q/6KNdRorlivvJ5GJ9ivZ27r/b6tlGpw6joi7/SZXPxoX3ApWCqO6K+A41ojOC69GUOfaR8p+qyv41SV/sZTEzFnS7a9t5lgrlNPLy5fJuMmr1xVaU6huh8uNoAzzE8XcOZVIqXUsEZ166czWmS0eUM13GGNivl1MUe4dQmWXuWcIaklc3a6zEzof+I3lqaQ2tSOn12Ry7On9of7WnrEbOytwr1PFQ4TLzVUVLSKVzV1buUnKyK9ciRHntZsLa2d4T5HQ9iUjyOdLVRKFPUmeoZzuuwztX2DFcNOZ3uvnON2jhTdD5LdTDPTmdzKJKp3C6q7vv2td0tXLfxR1CpSVC89B21uq0q5bruJlvtEdq8wBhzrq4tsR0PbmMbRAq1Km0vk0IubVmrD6Wc9bI+Jn+k+7jzbepRbn27tobGWt1kT52uDKHuPyoLUoaHDbxStGDuvFyo2bZxHMm701h9eqeszdeVyqXDcejU/ljaqO4raR9NaTIJi+HvsWB6PH321l8lKJuya7Pv9VmO4zyOfCmjnfbhbnPWlkbltjptV9iz6mRMu8/RhLRf4yZBGgMfv+bDHk0y/XG2lW0Pc9zVF5dd1k3k3HWfZ8xNoO7Utu3tTpWybwtztIs3eYvjImOl7W2aEF+16GquI8Y7xRza0oRUvfE1tvc0iM2Vj8uo9plkj+syWrlqjRnPqsfILDzedWXlm7i3D9/+0vFu8nLnEN2lmwTqerdNetlDpfbIbbzJ5WqtagMci6XHCH3bTCCbIaOM6tDELpa2aLT749GEu1qdXUjWH+rMZzbVtKcvuWrXHqzcysa2Srpc0RXdZiAlk9oPN3aBHvds2/pIru2k67xdW4YmYqaJ+9keodywlQ57gxI4U7vK0bbw2WbMwy4otikIUkdja7XN1PSAAz0Hysrp4AL85pvUjWnXQ0fa00bQBuU+rPG6qYfzzL6Y3OYtHLd2yafzMu2xYmmr62xuY2/CfvmqPa1lu2EFJdzUcIKfIY2nIpHUsSk8c9orntVepy/3Fa9yOeXPu6mepsGb8Kj2TD7Wq5QmoKUmmIImabS2TTf7Jk9Na8GzgR6HV4EU+Bnbh4v3Od53E2R1t8k8lVVniaFN7VVvfblb26ZRnC2qaG9Ax+Zaqz5oy5BqanqDHiGf8WyjUq5pM5VjuuLRni839a2bflLxbuKoo0+pjeloc1XbswbjXJtVdUVa3fHz9qYdBU2O9KXb3WtpUpmTOUKu6mxKKjWhaSrUXm2tQ1JNvq+cD5/bJJRsSDWOn23aQlu61B4ql+rPYlw54KGOto3aBk1tA7Y7qtA0XdCnqU39NmVoS2qCOK5R5tHWnhnkBQ5ag4vo3+SmnQPp9Tsvn20rqoyy1cF540L7xTUZN75toqteoHHbo7UR17aeRp2nb8vm7Wmu87rOStpMn7UdSDlb13Rwuttp0KS7CVO5yumuJv+plqYRmv5oJ33T69WkJsShnY9t7oZ6tcWE0mTQFGt9WxpXmjaITWsW1/RtcUrVtqqlaYzaToAjmwsOl6tN3z2e1mp+/mDJLmhna41Kl3YItjsrVQ6tj1CVuXM7X1CrNTmHZzP6aKZIVldVTWH72vQaqSzSg45voJvBMm5La30F70s7iZogNEmztbQN2N7LJYPwtXPiuNvJZNoWrmeT+hxrO9XTmUI7pMOQwnmikRpvB6Gz+jib0rlUvkpuyvPM5bzs2UyGu4loUwYRDIi2NmCZuKaij3bmtwNwSI6lx6B5GlNuWbHV3La3Oo5iNWyeNiEnKNR2eJUbN1/KV2h/jO4+mgI4vW/GXLMcQiyVRk6K7QLF5psOboJGZ5Nqn9PH5bOvyVzZxLOdxqEZYUebo6ybatZtmZsmM5cFqyI3cTyONns5t+Nh3OAihVVtSq6ZTaF96D6aLKSjKchyt8mtupi2Budd24iP6kAbHTDQJoLKNWkmk7LJY2xSHVxt5zfYq+k8XTu9XIhRhWYdNtV9N3m5tAPd0pRHEx11mXo1ASRLjk62oK9LwTnUniY4bw/ftnxbrRNu096ytmnoNgHFlnhFezdDoclkO3nbFjvJRF4MYQenGRwLvh8SZAo7+9OnedM3ees6Hk7Cnz4Llllb3GYPhQQf1vZsJ4pLl7FtHU2T2ONsdog/fDmb5vQ6Fl8vMMfa9NKKkwSYNgFt4x25tkPWXc24vg5Vk8/NPDzaFjxr08b32RRo1KdumiW1qax30y7NBhqi4miBQtsg7eRvWqOtRG1qIOZ23FjV7POjHU7h9r7NTNNeoF/a6d7u04yN5EtqckEjGz+bWj3K2UzMU7UxNUvH6qudHrqZFKWZSO5ohsrlrmJ0szGOJtTt/WpPZ887ucJeyTAQvY/gPVSw/ZtubJPc7NGj2b9NrTeDu8mUN0fNqclXM++cCs0GagZTO/MuXkbaGOcJ1n8z7o520B6pjc4cpbZDstlRbXh3MyW8arszwqIolTw4KaW4SzWTgg4GslNo7lDDh7YNj6aRbvCV/E2WRnsPzKWxZP10bqtWf/tkOzBRI+D50Y7P9mn06cZ10F9rn24iB9cBM6z9fezYSKeQh6uDRR0VeX8RRmDReAO1cbcrwLfHyXLNYYLL1P7cFrd9mK2XOO9Abl/7kEMXFOyrhzsY2Ldsn6twYbrC6lXiSDXM4PgePPdN4+6eFo523GXOPM7oSd/jTzYD83WsX+OcjzzM2/F+iXL+DJyzobZPXX3U7dPtrzR/cOrju4sj1+8qXbny8yKPJaWLtotE+zex0eZl2tuhGOnv7i0M8JzYpjI8GCDt3dD+laInrwwLqHAJ6HttLO09/C4IYUDbDa4dYnsVQCzbTzBUI0xsN1zp2m/fHgJicDS/fF+P01wnGivMYruOReEbws4zkFF0hgcjP8HXq88NtV9HkwId/iq7X0Pl0OFlyLykk8A/5/NlUyjYBO2uAbYDPOv4Nm1EmPvFNOft4+em39YazdLx+aGxy2myOQ/X/KpmVWfbPLjkLJyhTdGX5l1b0wxrsDC116WYVGs7S3FQ+p5mYHpKUluoDHa7N7UdB7a009L7WpoR0jRWc2ubaX5me7mUz7Ztbn+3M8Y1F7GaJoOFA0HbQqB97XFJ4HFg6iB+sGozc398K7bXsPH8+/csxUootlOlnYua6oYleUbS9qluV/fh42+wqdsnFsPNDiEKm7dKi0a+xE9jIGP5p89YCij6dpr7Zmco5107O9u/bZu1d4xv008HHZwgMF+oVUPfcu8zBx4SKAM8OHCkPOd9LE2uPtZKg8ETU3MFTW0WS7PcdQr2bCfwnW075tuJ3LRQc0curbNqXlzIzYNtzmYzQ0jV0yVZCsUEvt2UIg6BffX2zeGtdw2LWq7vvfNjyeHo7Tu4f5rH8D5BcOi0/6X7mExz7puPp8hceYjKsCFXXe78r59maxZPFs+Hmvunb26acphlpHFoLgOfVj6izu8a7WXW6ZtD2CkgiMIN34RTzeNM8qq8zqWCzYXzD+vWTAc29+r7xg/DiX9up11raQOOpbrB2yvtjK3HEa58gl0Zqj5j81Tgjfv0zaFItnkj5+UObdqFradoxOP2+02nYI2BbVZE2w9gWcGByPYaLEWAvfQ6tefLIS0WHg5YXKAER/tyxMMhgnuXD+Ohc736TViicIDIOTVJ6VzrfR5nm8a7GS7Z6+alHEfzG/IFkT3rtG4bWqnm7LSJtLYdKP72rPSnSfY8F3e7VPvjVF6ps7lCsZlv5chtn7QvNvekKcQrNd1xXKdWEO8uzY1vjph3Z3XNsUgHOXKvFuPLzX+wd71d7dBvHawNRfHu7b8RHx9/LeNnHndIpHjGWnuKoI/PORrJ2JCeQrcUoxqbhKIVfpgAnq5H6z7GEWj9ScnyqUDKk+SDpHf8JCOMlNq4H6Wq2BAjp4NOa7L5aTXoXKOZ5aDQ+EnZGDKJaPeRd0bqZdw3knIYzxvJthj3T+P+adw/jfsmmv9xX8oHpHHfROGpcd807pvGfdO4bxr3TeO+6abI4Pg57kuxzUyRQ5KDcd/MJj0JFEnWOe5wcaiZcxZknCqyWi96h+IimpKNmhZGRw7MH5zsoBcc9qOQHS2TJTmxpEAsWTeWrFRL7oi5KdjE4eFK9vNBgeJMpgLZZ8ayNUwfJiE0JL15rAqFPSmhQU9AF81jbHkMJI/vl3GvMuaSohOFPLkxhDJuXMb4y7hvGfct4740haWS4T1+jvsW2v3jvgelgMd9j3Ff0lk0O8e47zHue4z7HpRtG/c9xn2Pcd/jWlPMddy3UvRl3JeyqdVRVGb8HPensGQd963jvpXSfOO+ddy3jvvSMpP4neO+J8nyuO857nuO+57jvpRuOcdznxTeHvc/x/0pdn6O+57jviT/17jfNe53jftRSPoa9yP5vMb9rnG/a9zvGve7KKJCe3Hc9xr3vcd9yXm6x/3vcf973P+mM4Kyj+P+FIO/x/3vcf973P8e97/H/WmD3RwiZlXAOVLa5orcX0XWkKIspwocYaYXdAKrQucPBfAs544ShfQo6qgoyExyaEngLD2JvfgFWSQ0KY7foWV2JHeO1L8jPe/oIHV0kjra5J6BFbT9PH3Gk2bzdN56ckL5BOdUtZ9nMB2KpNUDHTOBzz0+SCkq6WnRPK1OoFRBYIee4geRzuPo2Clmc5c+Q0GIQNsu0P6KioZB8xxI5BKtciShi7QLIh1WkU6lyBckjRFJ5SQ6AhINPpGpn2jwiXzLTGZHpuBxJrHJ5L9niq1kxWcq3YL0XiLZSLSTE239THs4k/LIdGbnxMcAjYeunFlDk0lX6NAsipQ2xagLnUSFnrSQ2VPoGC0kmWWeDXTIkPQWUouFBLuQgiikAQ7anifpzoN8sIMycicfH+QkHuRlnWRPHGToHWTBnTTCg87TI7HapfMk8wFDOA0Sv4PPKjqUTkp2H5WPHdLzpEkqid9BqvGgpaw0CZW0TVV0jPB5RCqlUmCt0l6ulH+rZHhUOvWr5+QCDYPMtUoLV9n+oS2j+e6R3yGUiuIPs63F1hfpVYJ3aDJ7NHkAmiOXBLTQFMPUHGAkXISmdIum+KTWjG6iYXAYkvEGhv0OGoZhZ5eGQUl5zfAJUt2a9rKmNIim2KEm8dMk/NrwMGg2yGbTJKKakrya9o6mvKmmrKzmtCwtpSbloElDakqEapJDTcutKYWpKd6lOYVIO1dThk+T36Rpy2gKaWjHpjYNg3aTJq2lKeagHQOX6O6cffIMzaG7cy6JlIwmjJ+mo0STiGry5LRnr5dmg5w5Td6cpiNJk4LVtN+1Zwt/JlTpheF0IL2g8ZC/p8nG1px0YC88cDaRxkOn3oyXMxKPs9Xk8Wly+TjZoDkeQ96eJndPc0qDtNbEL0ZGLdHdyRjQdBzryN4NDYMcP02en6ajX5N3o0kfavICdeKcA42HHEHNyW/SLZqOG03OoCZvUNMJq8ly0OQQavIINR2+mnS4zgw/o2GwW0iKWpPrM8FcmXMXdHeyiDQdSZocn5PMsPNik5lsXDIYLsMvyAymLXxRkvSi7XCRrF60ghc96ZXYmtb0gq5DDtBV2cImE51s+4sc3ous7pts2ptOkJvU8k075aZdcDPCj6TlJkm4aQ5vmqi7sMFNfyJX6ibf5yan4WbrXJjfhe1vfo8VsmK9qVirKVY+ilWD4n2veHsqdtfVwdY6S5cqfL3CZ850AS7+xsVH3M0nEYcP5hkyNfNUu1NNTk01t+uUUH3w4cJ+hT7nKz7m5ghuPkt5JkksLe0OR0rVk//iyVIKJNWRVE2iszjRHmeodL7Ztyenn3RFIVOnkP1ZyMEuZH8etE1O9i3puL9oqhiqd5E6ujILPO0Fcokv9gnpuL/psLhJjdw0sJu+dV9soszoDx+wioNHio8rxTpbsbZUlS0VFlxhtEz7g82EeerNQ24eQfPomRp5KiF98CvaS9nTAXsqlVRQJqmqms4+4NcIv2b4tf1BtV/xVTvtTXtoeKfCP4583gKhYgMfKu3bAEJR7eP9n9T+YJp/Cn/Q/T1d2z+2jj9QVNSkfh/4p2nL9gpHVuEPTZ5de6P9Af8a4A+5/aFZADB4Up8Jrm5xlLUNJcJ9Iow8OhpF+6f9yp9rvxYFaDpyiNo173aL9n77x/b72Meg5ufgqY3G9/hB4BZFLXdsH4p9PBnGk3k8OCEhjfHQJTJMzsETn2u/2QH/FBqUgQVqy7AMilOt/coV/+G74a84FpXM3T9ywPgOXib4VQhGxIu271gYiw3LjLQvnq7/FebLzvniJ7ngma+0PK6vy/TjtFwwiosnDUSEHOwhinif9n26RSZhsfe8bVOu8A9c++aDwHp8qraF+B+4kVUors7iCDQIEgioHKlck9NN+cR/cOodCIU56T2X4YoJZRZw6gFniS7Botlsa1yINjLcDH0NYGQWRmHxFYyxjaI0f4Au4dvnk3f0vLgmitdprEkznVFcPMim1/RhMpZ96SIJm6VZo+N5YU+FZuT2AZLUwrz4JBeK9ontj9+fnMWPRhAdv1L+ICEe7y2zwReGtW3/kAToWJe9DOPB95p5SmsCqiF41lIgEB4GFXiCcB6ChX8MvwcfYUTLHAXOAFws9fFk/GeVXJwV/GdKBuyl/s0AghhA0wWYkaZW2j+HLmMYML6QlmGw0tBndanP2MmzeLq+u9srFW1/VVNXtEEfNWocCw3j7LoVcOR9PBF0eWzyQ8OjVzF3kWmvEr5HmIG7arpjxS097tgsBrx2fy+254H3HH3kYAUa7nFUwGSERMMIPCBf59BAhBIOYHxjToa+6METP7juUtnEgSboqF0nj8mQwtVugXoeJr39GEoYhjcGEPlVoFcggXwJeMjk5/O1D/Vf4Q9mrMFVaYWanss0c7SqKYAkjRFEfvDIk0H3bSdI3xwJBTAazcsKj2scT8ZBk9GmZUxGKngdQ2cBjCBlqUFNGwMNo004H0nphBuNP+SxWBFOPXxlVJoCaqzLmi9/8Er0h26/mUxDMwcP9xZrMu5z8L0tDco4ujeMYnxuzE1W4kkyTUTtegdfZRoLvXfQX9v7maWHnD54QF6Uyht3vGoX844ev+yfSwwHaNdz4r7jVWa5zIbfC7yh1CqhsFPpKbPxSdxsvDoVrYmjoZig5o7Hhww1F96pcNn+K4hp5t3RbTuWZPJcY+BNOnZ2rUOJjFddqck/8L5h0Yh0VkBxG+0C0Pc09Z4mQ8+NK8+CNtd89chK4xr3cYb2jjG+TkHO0kwwAJBQ29VhL8Jluw6JqIZZhu1Dd+EATHbyucevMLK205xJYlaKITVK7jXtT1IYBysMR2oCTpQ+GWVol6vfgTIlsRs2JtOUjFdzRFWMaCgMQ+8RaLLdvPLNA93cGXr8kmh1bOQBxU2F5kPT1nSm0L4wYW5SuLelc4c0B2PhrzkbpuA/ydF2UONVk1/HG9fd/Neb4/Um8fFFEkGvMhwjzUMcSiXCWVwq2nhiHIcm6fSern8ofn5WIGTxXGpoUpBsTgFZnvZCqtzwAUO3bH6wJWVGA48MGOGjoq0X/tM3bFedeKqitN7069CfQkZRE/Dqt8fOvH0v2hp6lWDNEjwPtiMsctp/7ce6OfvHM++Z/LFTYAARzoihozQLCJ965kxkcKConFO82oFy8Ml1ZHrVBnD1ach82ub1GKYYHVz4uM2d+Ojs63Kc5lZyBta/HjrUebrSNRPdrPIWqZoEY5iwUO6peKAEj6lWL3cbv4IKjcLYqX0+TeDdMjV5f3Cra+AjtgaSz8ras7pFYfRf4zwMagFtNYQg0V6xhtclsfYMNGQL7j3bXWPmWXPk7djgP5CaB1lubh/FEMfBiQ8aWX/FVX/xH1jDH1otB2Ph1SA1NQYw/+DYAhtaq80UI7vwGa1dZG/82m5Lf6D14j/AKp3ybLVjzxfeoCWv4+E/eDEeTuTiPFRa8GYtD1k0dZGY+RFNxgcFv/iwODXdOJAOm6+SY3MDhzUUCuWRSUBBVafNDj4t71GjM8sMqX0G9Jqkp3+C0sc6o67KZP4hPEzyLhpDImFKzKKq5h9YfI/mItOTnIavHPlE491xsm1xsjUyZsh6R4ngJvtk30by+M7mh4/zpDvy4/FxzRZZoY3S7lvovo7Nv2FkGUCX0jlzslnsgvDWMI4C5sMJuuHsFpsNPC9hnRf+gy58CVzy5jigywYVmQkHUM9hoXXNV/tdcGSm/wO/svc7AnUGCtHS+HZT6T28ofqr/m18kIrjBtoJ1qDoU2KwYt4HRoY6xsYessNBobsYbY/qaR4FOKNomp03+kZw9WZv4pxWeEIHXl4fGfqFODJ8RZdAfwyvbAzYkhFH2E8kCCngK3xvxNqW4RLWrcex2jUCPTQaiVi4Nh66e+9tXuBEuOD0H+MlCEF//iCuj26TxohbNs7R2GDm4UEMvpIz2m+E5lZI8zpoDOB1sgFjJI7P1XEdfEVAPhiS8egSgS+teqAGr4OvIoSF0J3qYzQ9vqkmsgQm0/Lqow0A9kF/Rc8ZX5YdvkYx5l8/2s9d9DQNuEDj4euMSZhA04N/hxkXnwSHIMCKo2tA77m+9rSw223Bfg02OcuCiaNIB42nPzG+ZznS5AysO557+Hd8lfXyXl9Mvh/egCAA6V6kyBxPoaoazsZo223RtMQVjgqKuwndBfcEES08tcVaDdG2A54s0RyglMAlxRLQnscpg6gexhn7lKGNCKeH1rwIqEMd7EDePYQSa59qiteBZaaSu1i0QKAy3Nwd9J6u/F4ROxYtfZx8PNMzynXlya894NsetP1IBVwU/IO7munP0JtKUU6Lhv/ZfBRv+KN3X8XHNGOMkBBvvFjoEGTQbz7BgTy2KW7DCxStd2JuMQhPiSlglhifb7IAxmLNsNoX7y/0OywsueeJQXeAwcdhjhOtV1h/OK4PUunt8brUzc/hSZynAmvnvL/p4xUjqmhttT/QonZnAKw2jLf2MQvjCySIpwQDpxWWuGY4kPsjolVrlZufQ0OU5HwuXaD9ldB4KbBG+Kp/CaSm4MVZfiqHQ/OIyBs88Pp9VRryaOdWzyjLMFUuLTKKI1Csv3DNy4swnLnd4cQTH0eahYz2EdicniPI7jkC3nxmDiPXX3f9FdsdLg9fhxFcPGuUXdulrv+Ku1gqVV1JgOkjmYdxFbrolW2B4xUdDp5bfIU6Yb4HOxaWh5C5BuSXPg43hxQXvhrvJaj5BsNI4StSO3qGyiGena6b/xb7ydLemyKgScVdfGJlPPnUU5uX+jhT2sF43faAb+O5WnnMxzxh/zp5y0cwmEZS3lUGGiMwUcdlayIVgJaLASmp7qFLhfXl4Js364ibled8D2YPRlTrh+5Bkb5ZZG5vIX0AkQcDr+ZKQkLi9vNecEkyZ7tIsz7AdEYX6YvfY0PRXjyj52pwsETfh73SpeHbeDNWeTeoPBSCmwXy5nMp7jPerS9xbvYwV05qFwKhRO9TTB4O+FbqL1uIoiM4d3fd544l9D7himMH3byD7mnb49w5lR5z5xR9HPKYfQfhq3GJNOEs1nUruZ0n48ZNM43Zy8o9tlBWbJcxVLFs08cJ6F/2kNOM9GivxUy052o3CsLckQYqGvr54SGAQsgqbwoBnmNMRfOSYIPAdsgq8tNGeTw6+BubB4rOmKwO/nwZGr6/6u8loOhiZH3FlXCWFsYZOmVsUo+d6uyyIehIsGK+0CU24TcVn9UF+b5TqnPnhkVr8NU6w/fHDBMOiC7hNWncrHeN6xzLmtNwxT7BE3IUprwMlZu1f86wJlnL2tIMaytdUBe0js7Dt3F+2WCH46PPr+MTe84vgYvgevnjgVFs3LflTHlLfOBA92juN1xxPDBLA77Ky3tp1mjw8178+ZOf9+T3DofeKSgJFzfHzcVEz/smT5HGh7mUrmD5vRm3V3EVoFW8MNHdFFvS+oZvw6CMXl1hvnfPVD8drxE0ONtn16ABI5oVLVhPK6MjrthR/TlswDRHq899wscD21Jm/PMaNiBFin5tFBpISxMOU0UIWWi64qJRYCKYsKeGHdvkF49Ei4OgZ5/wQgkPnRFruKWUw7S7Mdba1Bc6XYBFmLEFfKURbZNffXqwJNFZVWxT9iMNjHR8xc/5DLSAouhurXHu/ZN0ALcBo50P4RB49CqMFszOondv+FxOw3lT/VX/XObPSZt4hiI2vYc3hjhCNgFzJV160FIEY0iEJ4Zfe8AZgEdXgSk7+KHgFTyjfA+HNu0eGVowtv52ojVFa1HgIX9ClUgG488jZEACLcMNmIKAZLJKOYr7ubRYHNPHxpiBVejKP43cfC/RFBoGOkwld//3cs1CaZ+pfQipVt9crfZNQBpAMk76+H7mMeA7ptkTEBYf7qLvPuNjjSBenk0y5MJwULPHLhWeH5CcG9dJ5HY6/3UsGSEbwH84ovxGW1Z5mv1OPn4x/IBHoLC/preGjqdHG244npBPWxxPjDKYHm+Av0aBkpo+c+nBAX4vk+NZ+NjBIEKxQsCMZhcPsWk9EDKFAxQZqnDDHobCbDMIkXgUzE68OZ4YNeihBvQlwhIrmEwa6wjM/RyBzc8RyBzXh9/pbwwvwLfxtiydGKJAK71KMQ9aWBighjCt8I+GtU67YV35wZtAaDKsZ3QCX0nD2k7tV9kpYaHCFEJ3TQ3b5hDKoPJB+DoqubhEIvB5T/PctTOKwSUBu53b8Su/29XW13MypLjxHRswXVCHz9/FWsYu5lhWq2cGIfBVd9+zdN8h8HvZt11LlyjsfGSMPAz3PW7G5IyBWCDGQ9uKqgsXd59tyTRDDmxLpos33JVwW6xRc5yjQ12HTfB1S177DFF0Y51jDiIbsstgty/+aKyLYVyXbYfO8O4Ofuoj0QQfabXWKU4h9ysEA4YQ1nmJeiua4FvtE3zwfr2fzl267XOCb/2cYMJ5/ySEp0Pvv30dJ/hk6+Um65V3G0YR6hYPusMfjHWq7uAH3v2/JYxwk/8nQxlMjccPPGPKZK2LOMKlSdFeesYbCLzfXPb2ddu9bLrxRQ883fhprs+wAZUHl2GvDPOlJ9T+YK4nqhW3DqRyBJaVotzUH+31t0gLyDSwU/7RWicWNgq9o6mMaTOg76UAVrerEYkbF3Mdhybs6hmkwbRZYiHtkYeXQw/SfJnqHJOiRNpb2gzt9Z4268b2cMXTSHfRtkcK43kkZLWlzTCZh9cB9AM9ozECy4wG86H6WJvJikjHnjbLLEv4CtNmJk+7eTeK0WBOfJSiiY1pM3N85sKIvak/tEzVfaXNcgc4jrSZE+F7x+kwx7at47SZS9LeHWmzzVPph+p2mA0burnWx0wKdohQT5vZzUUA0xldy5E3m/Y6vsK82WrDr9bCtPp/T5t1izk64CyFLCBVEM1bRlIX9hAZpovTZlFtaTOqigWTmq3ASiky9UyRYRpg2GUUPZ12tfNomrcPFciaecyahZcM2fRRZfTLv+wkSKbBrFOQKqJfANakEV6DVRxsvsikHgb62NaUy9GmvhtzeIc934YmtTdrdsVTbm2m38rDaiGLjE1qP9NQjkxqdvs6Vgj9snnUu/JhUqM17T18nRNs0+RHC+/gnMocAceNxAg4dj5HMB0CItJ5MeorJgDh62jUszcdPI1gJAWpyP6vsdRndFym/UhLx1oNHaXCoL9JwPy92fAiWRZYfaNJjhM8jfPqMJ04jHhpZJ5Lssy9nKRsnAufhY1zJbIIv0ZSE9rv9bKmL/E0zplz4dVi/kPCB9UbUTp8rMoZyYTsGcM4rVBM+Eh0jhWeDqKA+qoIs17Rqii15XvEqkxT/OJVuXhVLgsG/8hZ5O9VKWzzOE5hlpd8T1lshj+vygV36JlFHBVLNbH7/DWF+ZqxoLJNvmgFD4BM9CW/N0x0tZvoxKMt04Gcwjx4/x8OEpHDB7q+U5j3S3TnuF5MdLOZ6H9MYTbjvFnj97DhOPlnJyxmSXCdH374pw+0LUpPcAWZROQEF7sH+Gq4BG6La4rkIH/8ogSXtPTRvh8eARWQs468WUtPS1+4QOXFx9SLUYwwvN+DgegLYIZSSDnl89JMxtHj3mn3gM5NP5D1VZYcn22fI48vq4fHxylGyPsJ2GnP5rETyP6PyPDNbIUyMzv4FC40bCGF6DQ8K2ZnGAriFGcrNnzPurkjlvNGV//m/hBg6uGb/t37YSo9MiXSBj1c3B9r3tyfZ2QBdYlrntSf3R8h4x3n3h0rmSNAL6UjJf3i/SgZrR4P7RiOyKdkTz28uHzooCC0VMbuw8dEgHeRrVeFrUFLE9FemQUxip6BOyf6r2ZGTy7IwoOGK2qCIx6T/cI9pl6nVY/zMK36Xr3wTGT0Wl+88LWG8t7mAcxpd9YRgCdSxI95sDgPiQ36iBZHH25APF6deTI4L7G5C81DZXkgJB7bqjhcu+2TgU/tIXURLTcduLbAVx6jpcmAC0/juxf3vIUAYN+6a7oI1XEV7NM5ADfbHhxq76UofbQG1P0YLZHthPYFDpBXz+Igo+8dCZfIFN99A3Tmp8V9KIoKHCsG6y0qQPQbGHjuF/qKCgSOCkjUnZY5w5siAJb9tI6Uk5YcWuH9OhgBj4uAzjQaVJL3GRymNUYFptmOrzAqMExr4rqaQW2KCsz4OeLlMCpQ3ZurL3Y8GuUYFQi/4m6zvWZUYPG2LOUdRZxcU1RgggN77Bw/Z9x6GKBd/xYVQKSeuysD+yqG0zEqQJj7k7ZHPc0SFZjxdnyFUYHTbFGBF3v6L1GBdla1Iy5CeCNPEImwTU+OCgh7GmF4PSqw2NN5DYoeM/KeRlRAWJ3T83mLVGP4qEOV1BM4O9FxMywwTVHNkK3I1i6n2Q0De829Bnr651aA5IDT8lhYbaOG2XBoqCP7ezLSMwLJaKtO4B2F8KH/mJMRZPTrhwmZHrsNzL/sNJuLEb0WjGiQd9GcIYhoYHQYjEni8gRrjrQ1+qYQ0bDJvZvFeAcd1t2GEY1p2N2VIhrCPj22iAYGkO10owfOYwK6CjtW09jLFE+QtqZ7Nb2wMLF9Hb6NJh7L7n0xFExPZCdDttxjAE6rxwDAhSZjnZJm65rkZvZ181EpxmR1a9PyAObmQcG2QkJnovbavW0UhU2Nlbplp6ZUL0DMh+ue9o8w5dzvsM6+HZdAAH2EW0xtkNis0n8CgTseELgJRINoKUHgMk9y3iBwUHFC2iuzC8DgJFUZAlcnLA5QbkQM1oufJuIMMW7dB7D1BQE3PR9xwMrZC/FvCDhoiHgS18/3qm2zhwbM8hGid/5h1VhMHmnauC3sPwTbuoJ+LKxUK46zwA6alI4jr6PmILvQX0mvllmcQKi6A+o4HIqvOkDQbzndicmbBz2i7roDKvB3WUcGCO45XeefBwKOu3ug+njBB5YXfKBEB73DSaMH0T51T+m6yI8YWPokBO5LZ4Atuvr3CJWQ0seH9H+kM/AjL7j9f9EZbzkMv+AK/xbqZSK3fdUYDWfjiaA3DCuebDacHOw9maTTPpfNceDAUOKUcIQgBtitrccVqTsBm4meAwdeP6O9fqJC0poJmTN9/01puHZT6KGjmKZW7GHWCHYXE70fLcgvQIQCy0yX/aPZPVa2/rCy/3lFhnas5l3ymuKZnmHR+Ar3/3yPZIn4U4238+MUz/TsTHrjIVfS978r3/HM83riyd0znpnd+Z/EM72tZzOs4dswXM8njbfrqfLLwqJvvOx/zKGZ8D9rYTktlkF6SbF7Dvngq76wEseJC0scXcazzveeFLvnVK132VtaWG8/FzZPh3wurI/PhfXhP1rYAK2u/Ol7BNiHOWb3T7o47gtb/NfC/ld0sS//iS725zbRnvPG0FWnkAHHwYv+Kvf3mCv4qYs9b7WTIOf9Vb9I9dFtujixLmbIuU8vujj9qovt8TddDBLb1hm6VFeBxvvF5MLk3pqBiPKULf9kc227mgmVfWL1yVBIfNV3Wd7Vpwyl0IxmVp+cyfdtWwTaZSHsi7+lg7ddFp7pihzyc+1D+s188ocOhy/wbdxlHGfwhcorvCj9/tZRz42Y3s2nf99kHfY8D9k2aJZQhs75HTqXw/kDNtFzrs4ftTJ0ru4Wkef8nT/wigs2MccndC5H81yIyMZPVB/YxKbpovP1jD0x5zk35isZsv5cokBfXuhzKewv4MQflsLue+zDWdGRy6wiO/IxkoqKcSuc87KAkLmuI9dZRa6siclfpKL85VaEb/vrvNnkeCEVdT/T0P5+Qtf8VX9DX+R4+zvHE76Od7v5voRoznFhjfhQPM9ToDwL52akBEVZEGWsRwrmbJacdl7dUCnLgUPWTUaSouVKLJv4Kov35DVYlhPXbKEodOOe34Mh1bFa8GrJ5QbNNVv5eaCEyQ7AqxX0ChBKfzxRUmxWTArwdRxVZMKH9EMJ6M+rRR1hDJyQNHlsaKfMk5c3WQ9GPZ3hxPEULovJqUBIckye2cDsOZUHFlhM3gyxzMmzzyrRYN0v2P2cNSRyb/g2DCpP+ThJ0rn9mTxjMRv2chx/1ogyP34AuAuesYGRhfgKVft8j/ZDNo8zNnhCRQcOPTQPD4ts8IyVgMC+Hbz66YzN+anaJ4HH3A5L7vD1jA3hzKUNpn0bliEwJCx4KhENkxrUhPiviItHRBCkJXOpYT5DJE8hcHwEX/X5jYunQMKB0sJ2X0jkKQS2+6C1+83zez/KHgvXFJeXmuLycnYWcXa+1cS+uwqh2dwupLP0ozNsxtMYbGZ5yhvqPJdv1PlyiaILgc5z2UHngfFNIZ+FT0Ni7NKzSGiiLkp9oi4KW/iFT0PqX4DYQROObBKYbb3mOLDpEwoJlCvqoyb2m7Zpwjrmr4BfxLTaQn9Rnlj5PVfe8RjhqAPhMXEdZD4NOERHR2TIkwpI+MRrzErPWdn6gb8IWGc6MoW4N476xM+3P/ia1JYgAoRFPjQD2wcmIz7qNkdiVm1p0Im1EHhxTwOeNEwdnOJWN2MsQobjDTQwOSRZI49tnxsJuYcdAxR9irt2dTPCqhdotcWpmSDxilbD8Yw3m48UOtiP+bCM5o6dTRzn5nDZCOBD5hR6s4M981F5AtZvNEy9bre+KGJEYfQLdQS2wD+rpZRyK9yl/hILlVJnpJoMQIWKdOfncpyFu9QUfgF1f2bGD67cJdx3TK8y2j7qZxLdqgWI3AHzsxz5EvwX85OJP8kZ6w427jVzz9JdOh7PXizYSZE8JdEF05MnKMF8DyErhBHqTEp6AZ9slFQlflTuOvOG/XIF9GYMZ3UYV+06op0xYxdg5e7EyBPUHPAsPYmubdqg9e74uXJXnCkDbu+fduhEiPeqVa9ksSn1C2nfLGcPVquOHJmhwE7GtBoL+N7Aq1Dz1sRQ8Ii4F9NJstxS1zoA6h0uk4loyTNbA6aj84fNgDfQ4QXyM2s4MWrUAfb3Aj2R6eheG4pSJnmjqOdgz5/0dPTkg+LxCz4oPYKtAllOTUatccHaMV+TuCloLhlda2p7CaXEDIzFyvUxgokdxydHS2abEm6DlztZ0oyonDyCWdg5R3CKUoUJUMRyCBnQwMn72ZBBtijuNfUDjhvXIXxAEKhbzR9w3GsJZwe1aIn+n2gskx44bkRo9dnNVWJWXrL9P8G4uXqhvOYw15nDDSYnFytmPgtkqf0UaaaB7yZINpEpHR9kSsISneCZ634CaohM6Ug/LcrEcd8KSZ36otQHmZKa94JLrovCYSDEcfZFmSROmfHSdam+fFuUO1DFZidTmjBtlviJ3bmO70UxO5mSq78uisRyI27n2qH1d/yyy7dLOCjLHNB6/SgGFbDxDhFHrBGXbzKklAkQJywHAxu9GHQSTXGJEHUKI+h3vS97u7uOWtCJgGEqoDt9mOUC2YMG26qgdoXyylTTETP2hb3JPB5RQHvGI/4pKYNQb2SBHnhvJSmnFpNnjVOpXvmzsqIsrl3yj+oB1wmqBnIlMOokUKRFskVhpMXNcJEWTE2ZoSsT/hJhugbXjsyBovNMmBbJ0ySQK+ph4LsJslVrQezPtS3KWa8qfLt2zldJOEVmU18wVjVpAvQndu/ey9bSwGFyvc894DmMC7IM0X+pqxLEUYIJZI0E74v6Bc8xQCa18A06Rg46rzZnXNs/OePOe80JFB0e+JMJddHaMl8T93LlowZ5gzsAJS81AR2AwuFlHZmwiYQD+CaMa7r56KRQHYDCWyJwsDPU/4vOePokUd6d8ct9OOPTaY6Eztbq6ePrCMI9APxBLYUMsz571tTr+9c4AaxDPiTlKnIsY1OLy00y5/5kABux6EpxjrJvN/s82kCt5eNgAqWoyIx9zDcQPEGYIa+VDO2L4VYcne1us8d6azx5BQ/09LsfZEhqqc/GBEvngc6LUnYPFxYMnTpJlfuFzq+C9p2/meJFk8wYT2TcT+xv9+ptuccyQ9cZQfZKARUYu06VGohdn5zO+Ir6NjJZlGBAjuRvTvajHjy4t+ptQRmd566NBF238XcH/eK27HWpC7kIkj7f6y0U8krWFBZAcdphf2/QdfTfw1056FCp7Bvinu0NC53UCLqe7x4Jo4L2eynv6AXt9yMl08miTP437Do1MthK4CaEBymnOhE0LxfWl5PbLSh9J9344F+qMuMwiKBZBIsit3syJBwroxW+Qk1BRNCDcbkNqhm0naEZ1MIlgtXrOdFb073EsSBkm6GBC1euiGQIUi0tDMUIAESrC7192u8HYcBnnEBM6Bz/JF3C6ABiwGecAKMD3elOj7RO99pVkpRMPRbR+YGVdG+7yzvd+TmC6c6X/FHVXuEOl4Ovd7efDvrIJqtw52kEgkCJR7C78+kXm5WLrsHj7+xMXJMyc6h2L4+sn2yO9RMdLSq5ySdgi6fdoXL9tCCLvnZ09IwGYOICJ3hGAzAG0LE1swZEQySBstLdPJiFJpaTP0q9FHeEhT39zef6I7gGHHyoEZc0RJF4oAQX06Oq3T4Yc+sjKsA8UF+Y9Suw441EUlGsyoPHWVSSF3dRjlUSOz0x6zOpwmJ/1cVj7VXtfAJfxSYmc3sncu5yPyu3M7E5CO8+pnejGLOlf1iVZo0f9br2sABVXdePMMLLqszy8wetMGvVQSGNUQRRv8NlyBxZ4L1eObQjirS56pojEE0l3x0sOC3JScd0MzHFnV6Krln4EL6cnWCd/nzcj6rry90JuZ4W1mmGdeByDdbpl0dMC8PPK+v0SYXdPVByLsxQ/RGnpRpF/SVWt83VUjvkIKSfWKeXSu7KReN1D5RcP2CdJlm0A6+fi8b3QIkki673tWOdmCtaVo27l6pxy06s+cA6ISszEkGPMAKT6ypOYK6tIt552J7z+wOnr8BeIEKdiiK4AAdfdaf0qyhncUAtF0VwQADMt4Mn+LUmZ7rjzzjN9XBKRVHOdEqZ7LkXs6q0APnRKQVW5ubg/1CTQ9b9bPLzl9Y+m1vK5bmUHeUK5b+7pS+JMtgTUVX1Z7/0wRum6J5/90uF/zjyZ8Mk/7tbKoFKfuaJ12p68Eur+/RLhavyXrMOpktsNuy3Xzqpx8BfzDUwN1enzO1MAwU7eVXBuasmvdhK+aUWyi9PidtJ76U6S80LgVAUXXN6Ath9EC7XEWsStf8MMpIUuD1vK4gzd8JlT4TLbWJyfG/T03ZRjZy27RlmTNuqSUmI8OIqOv1A1lbQ+kamOZuIHWQfiKuXCbL0zORizhcJl2P9jXA5zjbKvfbZL74a+sbzvW4YuiV5XbVoOLRlbe1H1hYSwblmzjRHO6OrMZrePYeyts2v6jGUnrXNaxMVt7wnlLnptsq/0C3rWYHZPcqOsFhbufSsIwdliZgA6ZaXVkHCdwgLoQCmkpFueTL+TtulSF7OkQxuQ2hTBKlNwfDlyMSaDF/CXQ5PXoAL9cPBxGER3dWeGXbkBVOl8iFTwci5S17qrchL/epQgXd4rVTeyAR6Hx23EH4tlcrqrVJ5knBhUKB7qez99Eambk0Xp/dK5eZIoZemRxMb0eYncGb42nOwopHPHMBs5DMHoEXuUr2nyd77+FCFKg5guofIRPFeqfzwibt4/FypPMaW2PpLO2mqUn9Lk2V3BU6ThQcLL9v5EOBi58vuTX6wLqrbJnkp6+/OV1ryut35ikuarNSRC+6+l2jyw75X+kqT/Tx5xf/sfNFsgBs38r7ph7zvAwvPl7jVI+/7wXCImeVOxXy4qy4cMfcj7WtEevhgGrLpnVa1O2zq6c0ISi+mq+ZUcPMDj2t32CYvrmVvZsIHKjts/tVhW8ztw/2NrRp8Ncw9/1Qb9xKC2INKk/pCMPMCWQlNnsj+MkHE5Xb/idtQsbZE53FwjPGENteiMMfYDzWP90sbqumjjdlbOCFG+OJvWVil7huJvbp1L/y2H7OwT4k2exZ2hC8WP6e7iiMLaxbnLi/vcRZWiSzsTNt6zsLOrkPWac7C6kcW1j5JEmaCciZt2bmfjuTcDr9nYZHGwLd76sGEUZZM85qFrY94k/DzuCDiKcH/x22CvgJOuvwHbYK0Vvua2Q8F9hbDoGVxmwLrFf49XargisPFnu6n2xSYoB9w3MjKz4/THnTsfszGRKzAZJbWEeRcP0ObIk0cZZOMU4vH/SPP3+xLJAkOXpsAIVrLfaG1RP+nH5oA8QQfs+GQY7SWC1tGBqnqtiZAnWUbJ5hh1kiX0Cc4zkKb7y5AcF9mhzHqZYbvd6LALYmtZawy2C2E8UpG3nPPbd0E1d9vRIE4NwTbjmAbj4Y+T070jYx8a7QhWfeenOP1nLDx3lq4uNFamNL8k+DvAeM+88+dhbkJC7s6E64RFjC5cG/Bko2WoiVEawLfHGjyCe+AxBagyfPatcfSEy8dejrNd2xWBLdYTfUDaI+U6M2jogjKCFSDb5+Be5AcHAwjIJqcmgrPmMQjgiKbN81YQu/ee64A88O9N4ESXW1GE6jzownUFkqYfIQSqJ4p/iDw5WmPSQTuJoVNeKYVuAUlUBX1dHHv0tu7QLHEGjrczAIQ1yvPNbKsraGG3gXqJdSw5B0TByXS70EJl0YXKHYdtcCBdyx5XAIVGJSor5jzncXDfAUlgJXztEyTHnuAwcyeb5A2Huqhad4eEutRiQ1ZjVEJrZcuUFwJITsP/y0sgYlpfZ5OesETXz4aEql+3rJjCncZYYn7tW9cb4+z9s5TKx8iepwYqjjUnoOYLYuROTwAaArjFVqBnycIyjtA5FrCF5sfDLjvfHpOQMfOtLW2dsZXHbV+uDI2bNOFk/NSUaulSaK4e035i0VtIz/E2MQerxCxid5P+BGbmG2i3JM0fD6AFkUW6T028QNnOGPG9UzDE3JsRqvmAGa8ggcw4xW9b/NLbAJR2yHDtxkwPlPSfQB5wQFMCG8WVp1Wj8ZD9QfQ+hZYeO0Q5D87BL3EJv61QxB8bmiNmUh2x7NDEIb73jsEyQbE/94gaI9N/Dx5Jf0xNlE5NlF/jk1c0g92MzZhHg1+1VdsInFsAjPpMzYhuguP2ISAruMVKTaRlGxLtMQm3NKG0G2JY3av2RYEqke9xybS0sK4e9eTtv5k73p2HA1fsYm35iOvyWS1MEB+xyZ+3kCC2Vh2ErIXt4CaVTGJd1B6xCYyxyac9PP75Il4BULUR2zi+Kbteev9NeMVhqN7M16BAMU/xyY6p+R9jdjESw/jcb0ldJDNm+v8NsHESffCMC4c5xlMyBwdUBvLg/uj59xT1U6N8EBYCr6VcCilI/lEuD82LZ3ykaMraTYX5uhKemDc6wtzhjo4ujK7FmfIOBPGfffVBRY+PZgzRDCC/Q4RjGC/Y6a+v5kzRiYavo53uxdKyS6TT+aM7iLKuMOfWk5TfIOpLLTe58+pnyIdWVwEww5j/txOx8BNkdstHFNxTSz9w2+bnIhi/gROneEEGzGB1nlEGzohA+PUe0vlHu144eLS8ZHneqAj+JF/3tWSn1ig2Qmx/8V4JTcFPcvJmP3zwT44ofPA50iY/RnyOGSPRITsP4siJlthD1V0yP7su0zFlyPA0cl22A61jHt0L5RXLqmnYbx6qIjHiHbDY0zQfjdvYGcu/X+hIh2chyB7Hv+KxpjN7ZGs8UrdWXsAL7ZuBxKIT5d4QRrg9opewDAw5nll6mkwwivcSu8NFlHSn5oaCEjf7Iqm00fVAGIompPilmL9YQy6DSUCimRUDZT67IwwsYzn3HFnnl2GMe3zVjeAzQ/QuyQenxFhYdAUtUBwBNBorw4GEtuvgv3Zc010NgtUOJCnpXN+FOz3EEsR5PkLSj7srGod8N/7m214jaUT3gxDhL0TXi+pj1hSb2a7i3PrhBch+teX7EJs/OiEV0XrtFGuP8ELNu8A64540AtKvhcO3L90wivMeV9+57ynX7FcX8TiesxBLa3ZeieHvHRyQOzu+Nze3eGtatVQwXuMjjlUaw+nHDOcIjrhNf07Ymxm7aLsuBOe+y91whtdkGNMI8Sy90NGHAduYdmoDfvBjXL9upfrX89+yB0lnWQ/ZAyYYN2A6Ie8OV8AZ5hdjz1AC69jafaA+7FX4YcF/0WA4g6ViLFe3LwEYR5YoTA76uEr1EoI+RgBFimhpoupbOWww6LdW4mCXBMEQ4DUPGrnlxKFm/KhI8BCpfRrlbpbgPPzAfaubD3AIg8mCG539AUujKisT5y3mv1milvWZBvBRMvPEUy0/FE3B4ANbDXgF53EaiY7HXdYDc8RLN3S2EN+0uL9VqEwDhVuW3D5vQw/1R+g2iBvhgryoUqeyvB3rPajTUT3EB9qY1Z8lyRL87t7XVZy/rKU61MpPAEwFGf3J7i+1+G/dMgaMRaxsI/p6+U9fzUme/3B/XP9AU7fm4M97S+sP7i/EDDY3aLXH/Tey7M/25MgbwIyML/BleITlWG4U8VjOtipFZ0tEE7RK8WthOIzG0Pdmp1hfKTL9Ckax5FTNjkT2akV/dJm3d1f6g8SQTCUbGb8Ahi46hZmWsk7z70vM6IkuKRmojIuzXtod8kmIEM8yc0KQXTJKADGGJN3PeodfiLIE6D5OXmzFGKGqO5fCfKUJgRGd2gn8IQJ8pR6gO87XOlR1v/D9MqgjX+Bi7tH0EaU//9T0ObHNm6iH9UGBHjwJz727IixMI5jAuW5APxBQK7iT8UMjOkEzAYTkKvywNpPWD9FWGRTefWs/+ZeF9PxkL0ujq9iBug9gdiKAe3gAVouALcvxQyPiNELgeL9G3Gre7B860+uUNUDpm/tQ/RO8y1oAqB2n33xCQPQWymWAFfM6dN+AWZ0X5y5Qkd8hSIDXXwmUAJjI6OA/gUa4+vTcXshKJBP/EVQ0OMrNI7jAd34yFI9dwSXkLu4E9WyXw4Ij5AYucHSEuoGjYlPSomJ5kAMx0BuTDQHhVcmNMaZpXdDB248O4wKMMeIrvAl/rUwxDN4RJ6Oir1+9WthyGApQDj+EiUBMWjuB0N7Km7eZ+RhbQpJPTgRmYFt6gCZwSUrF5esfPeEZNRBJZgBx5L7rjVf4ZNEAZnN4VpgBug6Ijogwy6msn/DZf/S2sgbc4s0OTPBDDA2wSEXJiKgYkF9WcIZ9JjFwBlMU945whmUFbcuW5KiZzu9ukI4gxlo+UQP0Loe7lecQR4713S3kRtASmIAu+QREGcwP4rxl/45t8ROkn/tQtxJD9v05cszWULstTCQmRO1ME5yo1smrRPAFAIaLIUvkkJAzca7f8EZjFaT5xUkJqUSJkW0kl9KVQCm0nEGM9YyCATUZn0V27kJDDQslnGS2TSu7r3kZzhmRnsgWpGvyKGP2Gte+gRV2VeuowVifeHjXc8w1GbwGVl8MsIsh3th0JbQi7T19kBXQsBFhgNzESpEtrLjWusRBVngG/le4BsYcMFAA8U3yspbtwAUHFHDYXUHN88sFEPgrTJjH3POJrykIzHyQl/YveHsJM3LjH14Ls4NLwUuE12CYKa84LTFAMJa6PNCqzdRJ4JucCBSuHzDvPS8rtsIsDhmcekfTPcf0Bxor4k8B6Inc2B3JOjdpddfGaKtyVfFMAj1rd/dEQlVsZoSRDOcQ1p09q13S9/6fuLbtYFmWaAq1ALTug5EUdx7crIYdAjIywSHR37oQdjdcXV/dekxTkORX6UGjuGN3uCtj8SPkRabfoi0YPxHzcTdfyXSIhvXP2nU/+uRlpC/Iy2/8aj/KW1n9wYZgjthb1RTdp/+5g4Z96PVuOhw30Ekbm0rSiQHonO9ftpqEl7Cfv/kiLyXnqDdzzwXesMRNXmh0qh1j6H9yqP+FTTxjG3hhz65Lut8VOWHHxxZAf641J15fvODvnB2uK932B1ZQVU45/d4zq9EoHw4slhRgjQHg78wTWgJ8xe696r83rr+/mRu+0NV/qQhcJNU8L4ZGzG58RRjI9Rjq0waAre0E+3QiElNoCG0MVL7O5+Rm20q9Evjyol0ZEJywTs4XKQXTPr6K0Z10mBCGMiIJDADRp1Lo5I3F6O9B1GE84JUqJE104/qakYyw6MwkhmdsbS6ZVY2hdc7krkX1nQYPdbA1Kky8EL6JQiXGKY+ofcTyBwXlo6eVRQJAOFqfboIhdjI2sU0ZxWNevTcjiVNZ2ImoLurZaerRdEtcmLnR7szZdGZWhwxTCqaH3pu6+swk14eg5B4PuY1qquW9wynFT8IyOzfgu7o0E2e9/OqTTEC3L8OL7BL0MgjTnK63hFI73UASE7X3Qm7uRNGMjpuecWevR9FSAjwR4U1WdgRXHXdC9eb4cj6pJcjDCuyzGeQsFH6jq4OKJ9qVx+oo/8wiRg34mlvlZMJa3QBFqz8QqkdxuegbiCPLdtdALMkpO3xRMDnIOum3doythmfhbAf3e2qElCWycpprwrjKQYzm8hMoxqVlF3Zrfhst2UREZpaPc0orcoEwCMMAVdlEqxnzuFN5jh3EuqyGWzto4kAzjNPhWp1IuCxAqcn7DaG9dFs/NgBxeWTAGzoRMcl4AdbLcdutSyOU+FsxezRUZhjZTz5dJwwsNDzpxudW1ph+eSSY3Z7o3ObDy6424+Fzm3tmvY7bBVcpnYxxPl3blZpSVZGO0osPnojaKZPv2QObVaFMtm8RLfnsOSQyUzXP1Jgi+r9DM7NMNPtXgs989WdE36lwJ7BX7zbUSVWfp43orbfrV3IcYImFHYW8k+wPDqq3VPKK2DA7VmV+mnfrCcVY/VPclUEmH26JX9NNo9rCDA7X+PPLpA0iru7I4rveW7LYvNsLtDu7lDc/enurNi07u4c0l74jwF17X5vgLo2iv9pgLoj/Q8F1DU1938NUHer/yGAOg6K4zl3m4WAFoPCr1RVAKi79RoD+4r7gwkR6+S6rXh8Hohz80uTerLMDYHhZkVhR+3lpWNNh/8VbsK0WhJ4Ickq260QvNACiwtq0k9j1J+VCr5Co3zi1TquLSyfE7WHPe7Xqwvz74Z6Jfgf2jA/MQzHU4T9JREtmd9Onm69umbjrA380bDEZtFSdw+K4Tzsm3x7bRaKWLTThVVlCdY331vjzYmqC+WxJs32jtl5g66/W++IM9PnDfFiiDR3ddYstAX9dy2jwAY1w0r3frfSpWElrfRhOrHeObi48HIvYeJjpb1xaGxxWap61BbqaVYzF4AoA2T0H1dAKiI5ojpGDKYi19EwdzSGhGQcF7cesV29MQGD0ZLvyKZKxJLHXshoF9ogAahDrBOi4QhGZIgK2JqP6n5RNyh4YuMSkUXboxcyxqXjjMwTLCs7CUnD7GpD57eoLbR8VgsOf/tBBTx4YuHrvWsMj4VtI0K1yBFMRCCPYJbriRFs8dVXplroDnNF+DrbDdMi6hZEerZY/R3Y16m8a33utosRXQsbrV7YaH8D9h3wy7C1DrXbWpN5Fi9JpV9biW3P1eDscUAVXac+exy87WgwDDdv9NPI8dp5gzrObAZguXDuJQtwP2JouHtumaMy/xZuflYq/gghk8v1zvOJIdxeqIh7fZxvvSLwWCB3C59kx7eNGWfwHL4aIdu0ERkPiqOtuwwTATkRik0csk17yHai3gV0TfOMHy/FdmXDbSFMbo3Rvvl80G3GXvUe9ar3UlAoeD5/2yB+hx5Z0cttPMq9o/buXzfIhG4yHG7HxUwfrCPqxmq90N7SJbR6gPZmaR8Gczsu5oX2duJiGGTWg8IdZBdeQHb+v1ZXOllvf60r/YK97nWlS5Obf+C07Ti79Ghy8++cthKj+COl7ZT1ib37J4zij5S2e2HprPr7KCx9mWEqLHUMO/MvsDP3hJFOsNy/FZY2Cw2a0zg36vr8/1Fh6bMlu+YmtIyYyozXkARJozDSv7Vk19yElsv8MtjWhGFeiI060k30zHkUlgpg3CyMnFmBWRgZfm3Jns7bxaxP+DoD3AbCjusi/9uFpYaTT+ZBoRV/pNA63LyI9px98movzJ1cS0bBNceeftQe8vx5/SzM9awlAcLU97TfCqAhVNqmL/iRf3K8cI5ptNwLjZYLfywsPdy/ZKi92Zo9ZJf/XljqKukoVzcd5Rkz7A1es28KjltnOhi4sDSd17PbFsfDM1Y64Z5g7trsCFrnlbf17OXvnhEdnrtteffUKn4Lfsd4qQ4o+4Xn6plT9JoUSHihufL1AWXY4+dAB77lzSBMle+sArtLanBigHfeYZaZBBCzi0SrEQVuRm0JQKJsEl2fzyXRyZBvzemZRI2EZweoPdMZmbMJCLsJ/Ins2E/gZFoJrxbOJkZl0oS+FwnehaGUnX67B1VmQ7jZ60aj6TcKCgWw0nGZoFvBlrHK3tE/wC6RtOnPsEs8E7GiMK8EDB0kaZbkn9m6Vd0rPM/uxSCvYEqILzZDjlyWKLJ3KsYbUniVhL3tiDYCw2DKFW3ZwZSuboR3o6Iwp38ibXovFZmpv964GknXJggcsn4UV7GceEsV84gZKspvt+ImS294KnGTPaDXex9Rohtc6XjPBswVS2AP9Wys1bOhPdm5lx86Lj90X+WHeIefyw//JXGI6hpOGOruci3Nt3sy8Xg+gEwcUljELWF8jHb1XKJlsOSWS7QrIftWfjhHMBOHcwTeLJxlL+WHWEzac4RoG1clnfM+gplL5BGYaaP79BPM6qp/qT8UlFw9FjaSRjMBGfwLV1gPZMhQ2sSgMVXpDOsdyAk+4IwLy8MpqpYlPJK3jI4LoLcHMmbpk5/FmL+jrGaATzHP1ygRJRE13LjXfDfufcwvIhP2LCRlLe1XkUciW7C9qmEhSdr5T5cAXk9u6qVCtmchJUnSDOAx7+QM4GHYroceJjlYrufGfyryhGHm2tba3l5aqTaw2NOZ7fieP2SbkYjrrbFUDjuFl1tigrtxfK6I7yuBXTGiaeXRrVrQi8MlCby5HwcCvPnkP53BN4zxDfBmkkwFWC3ae0VzCO3kvtV9gs+XKlkWjS8+8D/wyxKP4T8Rgi8kX9wf4Z8IwRcUJkd9XhjBRfDw2RNIxOLIjvxL1dAkBB/gztUgdms7mTfSC6oauuvDct5c6m7Sx72j6clG6mRVN9TrRPJgLAoGr4PZW9kZtV8nKGmjzv2q13IjfIUmqt7opcv6ua1Xzqs9WpAcsnfN6aS3va/JTtQEn9TCGhUdVZncYiLvmEIUXzEoRTFeTUm8WqcQ1T+V9ggOi46oO1Zr/A1lx6U9Sz3UtD7D31C8QFhbBsaOgwsEXG/Wp1tKedaSqGF9vnCGrrg3NEbND41NRl4aMHAX85yblzrHWSrTDX2/N+MxPcknG89mkrHsezOdkTqzsdcMGXevrVM7N4aSSYDy0UQTDKqinJm+oCcOUEHGv3YpRBOxWcYX88tEbk8Sn7UWwmCZRnTlJpqi+w1TgG5cMJRaHgaaMESohaVIVlcmVp4sJPNJZp7YfjXRxFqkgoVObBUPDB8h+8xzBDN3PEcwjW0cgaChfj9MJDVLr2TiaqWZ7iaqqQcrS69HsVublLQxtSDqjpla9uqisvbeccobOky8+W6Q4F/6AU6QXmbOkJm37h2O/xYrFjQwlvKls0pKGKKIlaNsbqaKFYHIexiVqYqC9kn30ivgdubNn3vvSJKU23IfBLv3QRB9XLGMiayAHbY+jR5RizQrVtY+O7hwouPOP/fZOdiqrMxqm/8rRo/sqoodVIcRnSTxSzd6FgN8MXoET0xgoycIwzpwyUXID+LlYeG9WDzXi8UzTW22eNj2wGyjURITOUJczWi9Bp9tp7p8K3+MnQJ14cfPvWXLM7qD5xo0TOb2318mQpgHv6DiTyPbaQSbbDeL5rsihXI9TSVIOxpt1ONJKs4WhspmpYHo0rd29UPgQ7SP4o7SaUG4yIBqo+6XUx6yEKU9v99dA4w23knGImcTedEHAC3kuxP5c4LpizPsrYKIGgQMUaBYZJjGUje6YCzTWBJjWU0ySIQKYvDKApKV2gLva00k19iNSOoa9KLjSIVFRFGPSOwkrgxwncDKcHsFDXUDONkIuKRuC1cvsTeof4UFC/X6GYcmWsPnbkctZcaQd31ttlAQv7lEERMjj5aCjvaN6DCWnJVAS9qe/N2MyGG3+iSjqCjITi2x2l5z6pZYLW22PPssYtAWOFd3UGOvuigua9UUfd47Lq4pehSobGEt4uSQceZ54omcsKg0h64Os1AjzPgXNpvokyP8xkyXmIZhYkLtGVnNKHPngpzMoOOzxxzTljzAcgwbexKCERTd1E1rZDWnJYAHTVJXsg0gUlmrypZqVVWf9DnjJrE+biLq45lVS5ijMst+bWeZedGrPfh7VRyWsEeraFlBrdKd9KucPBhhv2UJ0cXnnhHi4iECmyliOU3jS42WjbIu304TeqzssYKKhxZbo2gUXZREPKh5Z0nE8u1RezawPfOEcJhkTUsaipxguLpzY+5i/7YYRaJvS7LjlfCP8j4zNDAiAA5NINFhBuhtEMKcaB9JZ2mGo5MEdUM6XnV2oMkT1Ikp3SP9SfjuEQjIyWwqsbZLnsMkqAhmFH1/hOrjVduYbXvf2iqB3FnHBTIFJxck49/O++PN0VeddkY9+tZmnFfROVc/R9VbHQmlK06ViCcc4HRkYAD2GGT1RWoMx+ICjUq6nxrlAlL70t2Gvev08xlR3YJe24563ta2PmpDRLYMtDsAE6QHmwldnvHbzCPCJWm51xieSwIx9wTaq3zNSrk04AqrUuk1Za8MFujwO8wrzmSDmiGCpPYnlqwiWlBs9b0wdgpvVcAW646F7/V0tUMqMpMi+aflhptB0PkMYllpEWJ1qnaLUZyUdRh1w8lxGFSS3YhoeU71wu/UZTatmeT3ZCcbIXABSEtLS/LuPa1kvSeacLh++34UPaMZr7DINu49/1J5AHvvmntP9HPCfebsarS456jm3hOjKkJENdhE9ywsxd3lMQBnljPP9/2Ynl6GybjZPEZpy0fUDu/gdfoUUTWjU+mxmlu62hvagOJJLAazzGiyKnYLLJbLK32PoWlZIl+zn7coFdWI8Pj7ZsOt481CU9OBB32zrRvQU9MpwqEcy/pNz1H4DmEaVe0WGKTrz/xSlY9S1twqFpOKwusqORdNDcke5WwVVyqK7biHa0FAgF2XEfEqYq6+Q1skahSW0jsnF7ULQl9UtbxnOy5h2LcSeNqVCtW3qB5Mk4uEjcq9mWIgsto9fWjvnbUaTT/JWt2DHZc4HrIgWUHWJG+XuKflhNXWZBy9TPsgSEFZ8m5a7RSYwmvMcp2edRbvPZS5UtsRNN9bgpBKqaV4e8NVgMuvZ8+wDMMLy05B6IXHACyHmZ8B0w78uJcW4lgmY4/N2nu0HNv1BKKdfH3ThdqIzTYafy2x3N4gbPZLstwgbI0Dc5vBF48bUA9FWw7wdgKqTtyVF2ZuKaG6B0vrxDXYvFQT9Xk0sh57RhZ63FZKaCfDRoapAsHPKKwPKaEctXqLvnbkw5DaiapwHAdxxyu33MtpCMHfoh1JCtQQdUlx90bbpUzyTpRenUvzqL4aK58VCoo3W/HRSBhp/yEoCObYBGVHTPhEt5zv4YB6qde5FCklK4uP6KLBf0RmIIBZ9AwOx17AMjvJ2bw1JOuqDHmkhqBg+RN+buUZz9STvQuFKIS61SYoPXxcMcw7+7fLCJz3S1U1vjLre00moL67C8oETPhbAiYwK7dUKr0JCtQHFXQtUFCIDlz7t4ijSUFU6YmA8cUk/dcioY4YLkQndi4g1F8FhBjPFsHEkxnxRayYmw6eaxUVisqpX9RwmwkvHSYMBL+JCtSEF2y5OtUw1DqTGGAAGMXgKra4K83YbpvBk/qyZV9kEdUiBhdH6a4Ty4lEtbXUF71gaTwIwBL6ml9rtU/HYNxLmyxUGOJzhyDcwgjibJl2Fea5ntUZ6vnexfJVGIcwK+4zlQTL9m1gT2APiAffFnEsofpmTOWtSFGJcjA+XZdysMmxfXOPiEk1hdAG1FQS5KDiR0MEKX7Y2uzrSBOu9RhGWOi/UfzE0Ljn5cROIGIC21fc7u2UhwKj0k53wkTEXsFk6rOqSU24qr2Q6mmUSmWS0HupqssyxYs3EDxqq4QidhUlFEuOSELNfqJ1nu+6cI+Jah4kye5COzuM3ZUEdHZEv4sI9NQXFm480U4WFD7RZqHSTWZCipP2R7JAEeZV9jXXQ06I15vKQjQBcpdG5XJk2Ij9TU5Ee2cV+JZhqUAybh2a58/5zQrttUsvegp7hRV9M2tVRK4qFBS3N7DEhmB4orlmbRMdbu8KZrPsD4Z5sOwlS5/oD9YJuYWgZE44ZHU6u8BrUFC46mgSZZPpI9/DOiEUlFlF1Dm6bxm0Xymw3wQFnMJiCBVzqi4obxutnWdpmj6TFbv3+sLVkF2/JB57a+TVBcV/CQqbPqJSBw+0yaLdXyW7vseSIsbGbQpB4fo4t2Iv8XkTFEyOmcmhTTmhTkKt1EpMTUD9SYSNRT+YxWyvrihAkVGwU6uFnRoGJbi4HZMfOIw8zEto0Wz8HiioWW3T+4Yt7AeM+Hexni8NyIeqNsR5fAJJEPVWnnU1+ArZD+gSoNT3QhpY7FlIg9U7uNhLHQ91GTOeTTTPwCivf+U8TlmJmjZRhdNfoVSI9xxJhWPSu0F+INhdWCrcR64SS2OK8Z7ChbgubIUihAVyvt4umcJebmS2FtqzuiZdJF0e58l6R1QX2d02Qhii3fSC79yzmoYCjOdqQAKHgGfbEWtpfHomY7DwJuXMmJeTMcyo87wHn5jMN3L3wLUfA/B2nEj9VX/PCIt81XmeAhLtQPUckPB+Oxwzc0L5kH0m/ea5EsmT5SXfSzyUvHPl4KAhCGDIYj/BE8GDMLNP0l9l8R4Z9XwCnyebz1zS5E86Cv35jyaT/yEKYNJuMml2WTKOCGWZxwbjHjIfWAt4avmVyclZZRndGNPmjjKyPlEUwDPTVX9PvXp8nj2+JiqBPb6LDSn6XEovRpNnLlift+BVDkQ+nUP0mcmn1ebxeeYfwFdmf883bTzkhxEs7Yp0iUORujl+DpTncMBUkcV9hvKzx9cjVf2EDHONTl6jc9mwSnFDep6Sgzw+f3x4fL4sHl9z6eiAjCwCkcVivhdYfILUG3GivZftiNH1N1UYwQsx1dct8OZPyv76M0fWIHjQLlJRK39OM14i8jrF5NvP6LH4jxle/Ul6xTP+2Z8UMXg/2DyQs6aDCDA9ZNi7/HCuHV/JqoN+sDFZgL9pjTwD1vxFVWX+qs+DDXdevN7RMDmWrhLfxOdIayFbmGJxE9WlHBqfuexD+Dt98uLBjECUrc3ImUipnImlh9NV7RVZG462Y3KQZeiyEhR53kEteUIvuifmJCga2tfJiRlPHTQJS2h/ncKSNmGR1+C+v4mLcVN02Q1ZCZwPDxxydDOWqVP5ualhgPAPEBF1aQGt06UFXy0MaqpYgQ8PHOsPhpYk8KEf0JkQxUaJFUM6SVGn80NcUt7EhYK77A3gq35P8Z4a4iLGZlcnWEv3Njj13nIxoLFQc2ZjAWP61CxjVRmYl0JxaTaWo5M+OFItYWa/pg7TCL7BM5wxMzk/5MWzvHgwXZhbly5C4f2cWZFkioXI91LwpFxCeILxcqbwfn/1k7yAyZ+YtYvPp9eDHYERJC9c5x8oV2bCPgzKPGTOPOR8kbjkL+1C1AT9XA+JoraBLfn+nlrfi6Rd8BWRqE1g2L3typDch7jAiZ9OX/SqkTMmM1A0SgjZcQzPbadOYREqFO8JnPUJRRfKVGVOP7QrkgAx7qd9WzjDbyd7adqg2EAne2H54QB+f5VlwzM41zmynkulNSrcwKiw+JRjh84Oz7d82ByhfIfSqJYWggv9nsXO56eovxzbxWNjdWOI1MR+BHMLZLRKMwXoeIwQaOgSlK7nZin27D6Twlepv1dnxjzdH8+6QlGoMjTdC9015o8TM+l4xmu7mV4y9vh4FmjchrztHfzrJnNEHDnzJiPjIlnwaOdmcLc/mZ/42m18axVWnN9Q/Zkd5Nyk3AzwWHHkNvVXslVYEUQTVA5V2J0t4Lrmfq/A77k8oavgs8M8ZT5/oLtWT9lns8CbcMrzzHnEWeVXf0AE5GK+ZvzIpri8uj44ndmEj+nsGeK6FVnSs1z7fHJdSLbaBJ7PynNBbXjaKw4zPCeUXd+Cyb4+oTe/d2Ym3x0PkzlclR0hIPKku5nTOU84luDFBXvMZv4ws4tvtssFpByOYKNI9n35rSvegrd8n05JpO1ZbvAVzpUXqwN+n8ne/cRTbHzmi0S4Qp+rHLbqjOLjvBlccyEqzivfBc5V5tDa3O2ZQ2sZQmveLFxoqMybRovtXIdv4w7n/QWRgr7Xp5uuF5L017n63OxhbU29dwNYNg4CGPLOpbOAcm1dKb1z3PWQv75aFuYpDHRQ6lG2UZa2Pbhx+Kxvnom/aONw9UyhSAHi0VERBffcN0xoXZoJMfZNMPweqdN2wmcwKVERcdIrJ1ZE+UURbUmvDu76URHFL0UU4l7++B/sHE7f7Z98tpxBA2VZ6STyPCazAZMLeZtZYMn6Sof0Q0eUzIGKZriEg9d5pxzLHAQBOyttHVFKWOtq+zqfj3XOZq6p5ACSRkmuJtz5gK/jMtcZKk60zMeiIN/Y9v6wysHubHtG1BIv/Xb/ssqyLkLmMf9lmWlRatrWMOqvXsv5VbpwEePeYFTPRax4yb5ZIy9KNLvVEMNzs0bPn3e0WSNjn0LJlQFxJnaAWOa4SD4dreKlnpv1rD9bDX9QpbRZY/NmTIz/TVUq73vtn3x2RnuqUoqg03HDF0sPsdmfk2InQNK8HjjwrPW5/+LxsnSFMwsfjla+SzzzbWJnf8lsJeeLtt9/tCodrbCFsf+HrIqJX02UkFJDUnX8sC6FaTaLwiv23cXRr/4qL++RXTSrr0ty/HlLu4thrCX1Yiw0i8rKYidW1hT9NCGLfpqQRabF9jry/FVgV1Iq+mo7vXPYFQ6btcHToth92n/XyLQLGCMj9O2/quS9De5/opLJJoUFKp9k03lnhpQqWTTrArOVcb8lFbhiN1sLu0/4Co/x+Z6wSLvZWjgVCMGfrkcK+y/FXIlY+UqqG4yhQIyw262iQwGrkayeamQplXvoKewk/qZHiiuA3QJPHfRIcQ/x+smn+MUp/raM/qBFnuqrV4n9ixqR3DngOQezkeusV3vVIuOkBn3AyOH+Ki/vkY4orn6xNiAFo2FnNfviWUn4jS+pZD9vVpxoY4RKIrinkpDuFwkho/QBe/8G7CjNEj2alQ7fxpsVvi3FSbIRR9lfrfOXs/JSSzbwf4Z1vozwRyXxJoNSwPz2FL1tzCJgrzIoBWzKBgcyZE/iLmDhRwErHDAu+SyRBSw+BOycN4NrrgKWXk6h5J4Cxo5lifVdwJqKaRsVvw03K7yJiiIlJ/so/1nAot0FbOt1+t8QsOci/rOASd5MtCglTaB1fxGwtuagaMY5xN5zyXwO5d0VKY8eHqEUPofY+yz5KsTWXsrO1l7eiBfmOVRezFkZ9iZztix9D1+PoaOUsxztZz+GmNO/FDJny7Hlm/9wDOm6mzdHmPX5/5E1K2NpsjD5H6zZ5YR8Uv7r7vT+cFAlScqNSuLYLdXyRbLW+ZH4OWm3oVTUXUUcZHy0GxTmWCvs65cqe9KBOjhfVMQ5P15JALkEudRw0HweAb6Pt2NT9XCkJI74tIRm5zl9MSnHTzpCq/RhCF3miGt84R+Cq1MCJVvyX5TEmwTuPFG/6Ig3CVw6NT/6Gyy68EsCpXiVXbyuDzsbmb4AH/QiXtfWay1zjRts/4v128Wb/0qbeN1PeF1hQES5FYkX551cNcdB4nWXngzKho/I4yTxqupFvO6HeP2rwiGK/qM9/c+tWR765rl4xAzyB4Wj6v6RsDZoN7OWzLi9DPRL5TwyAYd+RocO9UzjHeq5cjuZz8ZcCPx0pfpDGyD77Vk85jcrFUtXs5Rze77kTmGaDyw1n7yH6CSe4yPzSSZ4S3AbdHKevHAg4Nwi9dBCxIMVtvj27B+A83Y9qsFfJIRZFLnuPCz8QZ1deFZ+o2V/vXAKdc2FaNAHf3l73APgW8yi7Ih6SKe3cjnuTbyfJno9+m/R+Y9rbOkD3PB1ZgHxbp3e6HiW/hoOTwCGx2jXq3cz2VDA8gFfhNIEwBBKGgQikmP4ZKcchLM7Ck38VpAO+vfAfmFjdpKXrQLtSoeu1qLrExGGC+vBuOtrcWrA51HUgiQI5VlW6pnJ/iA5EBOTb/u1z6BTsg67V5QXt4bOX4lsR3++XjScqQCYe9zmQOgBwQNzQemEPkN4NOTLoSyVw0uFrAboiahlFUXf98N6FGW2eYFx9j2v3WRZmToZOb6JdBy3+4ygXSu/nGOi7k7WL+qlkYVRsKU4JUm+RSZho+yaEX18tdF44Z4b/cu+u/xNioZaZF/ymlSvfAONCFBQIw3aXygaiEEKKz5E807zWRhQj42iQXDzJCcpU2aBwu8cDXOjSy2SHYPIf+dowMF4pGKdw8pLIO43iobZ/Pto+oAbjzK2TZAYfFE0sEYBWJKLeytww7QNeeFImbQNU1tM2oa8sm+pF2rTR2YCD9BHemWyXnXekkwNq2c1rssL/9UchZXNz1apnkR0S0uT51bsxeuzfpqJf0Jdm8/Grgq7UB8LR5EgeRKmrhutN6ZEDaH+BnlOct8qeEfm0YZasQt1XPhVOiPWTHQJJqLryUQk5DyhTL+3Eujyq9VjW6FMz1Hh8m+jkmR5rzINO+ewlbdXNZiu9w9qN7E3zMJaARttynT4LnGYZA+dTCR3y203pUWXDI4ViN7ZzIL0B6HuDBPQAFeYb/N0zuZJiSKGcb4MY+MkAkPRy/48zzZjgz15EnJskDbNNIHhafdOgw1l2x9ENcn4ccm1Fe5no2W7kmRPIhWmDmzDZ0GseDZgrwzagE2sK4kcUmEjORcyYb8eSpnTB1lNtDZmvuJbz2Qj+UZXqRracypyU+GKXdLSAzSZ6otUxadUzQ04MyaWIKSCdqejE172jCAf5IbJsh9UXmzAOQSh1XkIU8rwsJ9Ng+xQloJzvNs/tht9JFCWuHYmtSGpL31G/WIuQCHnqZlRrjs5Gvt6DhY54aZIcwSFLJoXNmsHlzSDqqrraaNYBZrR+1hQc3q83UrUvfVWknK+CjE2UoqrXv8gcg/MGK9rN6FXj7OPY/oscxzxhThrZWMnjyctRE3+fA5D9FAaB6DqurdziWaiiORzNWPbcrO2ClZ1P9vQXFyY+7bD1tFhi/2oxMrKplS9Y3o4LW/43Jk8jFKVDtu2MCd5kCth1Tz21KMnnWhKBevqz7RFe7CI563C5fCCEkMclGD8RWw6MCcU1vFc1zGk56i4s+5uiQ4PDq58PKnEYlmWomuyPEe1O7GbJCJHVHwx2+GoLKcXja32w3BtGdUPzbSoLUwMDwT1trB56CkUercQovuhxRa6u8kJuR+Gq5oyYY8A4Z45V18nkHSCtQb0qShGdaEF7cNwX8MYARk/SZu7s4lbA16thFWrqvzwUk68YnUJlAsz6SFxXzxfrS8d7xnymDtxidxE9vJ3XUl877r+Uqysh+f2oiqXcdwv46jbCfLUlYxoMdIuz+nlPG4Lhuf8i64kc3QlnoSKMknixxr0TVdSqgxjnzK5hXYTutYLqeKLrqTpwJZ5ghfUdp8FdjdebiMiXXSl7Gzl2PG95Imd4wuDjVCWafoIZxaO73a8nJuFvihLqp5hH6GuLIru4R8/leVi4F9p4QqFsUDVohzVi7KU6+rvl0MUDLAjzCPqqSufjEBG7X342Ed4V5Wipx6nwbo1N/0GFP9uzb2qysWwzumvPoJUlaOEeaXU2y26+2nRSVXJ/XqWSihBedxltc6I1uDxm6pS5vywPFHEluxOfmXY6Xiy80bUeVicuHGBmvU94hntLGkvIV7PDRL9Lw0SE1qYxxb6+ihlPaI46AUjPXOW6fQgnu/dclaS+c599aVnN3+p6krcV2LTVb5lXQJQSD7E9YN4WUFNiZWyU5HdH+xXYC2U85zHo7D4HPPguoVGEnl5Fjp2xa3Z37qYrBnNZL+GckgwXVXcAWyjokQJES5Z+6CdPv6yKj3CVWWsC1oAcXcIkze8gCBj5Kv3rkSyIXCqgzOT2pnMmBjOF4G0Q9A70T58B4qJf+hjBOGjhYZ/kE0ubNU5hdUAMGFsgsTRK5cmDX+Kb1nfHqGdpcvAYu0wx/tSWZo60dDa5hW+fqb0bHmFY14SKiSIUL7abxJXIwt3/tzF8CrotLSlmlKXuCdiEkCRYETUwzD73kKeurdv7fIkOE56zwIp9PhtOCe5UoUmDe1OtcaYDNUlwSu2GtodNPLT+E2+RqcpYVC7Ub29ciejHkxFhJ02ilIMKs0kETzAafwi5obZ1ehYal+CjebMSu57ODjL+sqacyaf0D4HDiojodG9lc6ezcEu0QurrnBPN5u4d4utAdsfWME0j8HYmteOVoY2QE5LsFo0qtw7IGfceHWmruAjdTZ9pe12LISkGLzBO83GVJajJIJn1QrGvNljS3L9Y9omoBN/1SaVl2sfsWpwoTZ3uGoY/6rAyD+Rba7ibGlVZx6L5jqLNl0vjWm0drOjFSo1UfNJkL1Uph35p8Y05zVjNKPLQLp3xgFs4f5bY5pprSMd0TIZf2xM83rG/mNjGjLB7x6aEibxHxrTtCEy91Z/0OuZoepKcnhKMT3qyYXNENJCErJaWcluSk709LtWJds2uhce173HRzsFqsGoe51KFq3AqWR1XTyuZSwM2cjaTHK4zMwseQebYxB8WHevWuqQcYY+ZPNGlIQ6oVzMlpyYMfCNzHnBmovIu2O25CUv3qklzb/yJHWC7fd6+MvsPElrWqtbd2JogYcW1lbHN9roAjsmWvUGbFQWnq2QhJoG5RysYPe43/Lev/ZCwvaD3Pt7aIFrUVB9NG+NmUTnGPbop72DZr8MIPZNpfuu59hut9EwcW4JMXXZ7hqjWdSVLXzgFCFEjdyOuxuC49qbCmDjx6VNBjxycC99OYC6HbZwftDoB7emfLnnkGwJxSpe1bWe1C05Bj2oRt4cmCwcGMaj4D4HKpK9ecc+qpgeo1rUOQTsjuw45lfREMqrIYSnZxbmzW6czwTdF1UJhhfzo3V3dqsdaF8y0W5pd98z1klY57943yIzJvPWW3Gaf45jz0W7lQw/z0AlCSkegpVPzxG4MT5n0bWjI22WxpZiICs6o6eSrfs5DdE3D9Bu0NKuIb6etBWQHQ4T+cXrFyQBItu4JkLcayp5SCrh1hbxCIlSySE9E9xhyUDOUT3rfHELAf5zetkX5ZKFzzK4FgW9o9gNSeaSzZdqvDs1oyxnyE/QWF4b306Iy+Zlu7RHiz+TyQNNhhIiUpVb7k8Ep9JLUjs+04+jMHCZ0xDSHiriNnUyqz0D+U+fGsYYsFuQWpKIfRlP9exVN/spIdePEF1KolDo1epuVKW1Gzpq+igaC0irCyUsxPSBNyxu4g2nTx17tN/IAH0kjuXF6sqyGdDmU4+l3gIqaMj1li0pbWbtkt8RS+3NYmHNfSFcW8e5prwOI772UXFOvXVjGi3vUMG/hFjd0mZvbs9JGMDDkKKBdwy4uUUNJMSS1pyOGy1nel/nLGriZXcyv3YnY/ZX8d5oMabk0bRZ8xTOD1dZJS4OzxT3AjD8Ks6DCstdPHxIzzVY4bFuUgbPcL/OrxpT0DRKHYaNw9KDmgjbgM1RiXD/HJXIjYq88tKVRq04PFQO+njmQUdjc2a4leHEYhZFh0nlt26QsBnKxZrYOXkCdKmeii6wmpCYDBCmurUxAo0e8ou5BrAJM3I1wg8JSMQ1RnEuDcLKal4ImOBLGzVzzEhc2Rt69l0mLIChUXUPvWAf8R2fgxKDAr36vekBc8tFD3TFhHlHkOizyzYbHU1YHZG3avQqVhRo75lH+m/LTaH+QKPjH7APr7mpgRT7yE3t0AcREo/P3BSi6j6MjkMgUrbcFGIy19zUNqqetJdJ4bfc1FG33BTaHFse35F4Tf2I4h7KI1WFNG9rqgrT+IUbbclwNBqa5c+ZKhrFsfTjA0q3/7+zq0uXG9WBe5kVYMA2LGYeMN3e/xKukdAf4E7mvuRLOue4wYCQVKWSqcgw7SsHpEpGMQBV5a+BKgXTH0da8LvbDXBVx/r6bWOAaB0DVSZMSfiTKo9V6ew6w0jLhfB7m6+GnV92cxqenRhJMkolrXpDb1te0gccxwFX8s/7dpZTfWRnCC1dDG8asE8yYAIWypot8DfjZf6Hw4elgbMQ8vuIgf9nOYFNbU9l+TR9LC0LOyqChPk5NBibn4Si49jOgWXUZPpMTUpm3q/lJ4FNsMjheP3CgO9ld01o7kFMWwkw4HIGWW7hW2yLUWEoZEdFFLTcIb1W/0Wg4YlhT3BT2NPqctQlrrnV2TlrRmE6lnkEsH+IM52Y7+EmMGiCEB66WCyhJRgWrvr40Ae6rGwvlL2kHYMExTLKWBcDWZlijFB2pkJGrgQf3GJ/5W1x67TtfEFtpo9EsaGtlbOzrlc76gUiOVUylSmfb+/XgoGkWxQfFeQVuDchRmb/ADxo77UyAJMqDO8QXzzs7jvHMEfuRmlTam/sAoGHYqE37VOjG6hhTx/sey24w7Z+Ru1ey7LDslSmXB9NpDnRPMO+KLO/3lbca6D+kBdt2kEmKY3r3v9WXzZ6W8UStVMd3LreEQ779bHiuMMXD/x9qJ6yXIEWxuXePVW1w5TejvrFwenG6qnTpjeYtDhEjglcLgWAMv1Kl1Uu+7BBTWcH2JfsexidYt8jw80gqboH6OSpQE5fk2oQPF72KD2owC4bQiNORRxvLIaOY4WJigYpNyb9RnuBneYik4QdpPX6oqhOk1jOtqivg1T59Y2c4AOUIV2VGwxo/ALr64ruRok7ROGY+K17ngQhn7fxbMqQe2P1qtPjsENUDVupJgU3fhqc7TkZTcd0mBPU1xma5Nup8KlCURo2KQ+6zWTGmjiDbjc50UD1dSLoAF7rMWYbwmZHIcCkrLsIPMgpFKXbwu+46AM7VxJTN8kD4FBkmku/PUcvmQJ6QBrCS8E4WD+juYIFfPtCmIl6OkKfR+gcCedvYxGmjYWZtlGYCZtxQfkF+3DQTRJWT/WV9DV+ieASv+acXE0sqRdzSYPFJiaLqye9H+VK3+1ROyx629+Fd/ZOLMZUg9N93JPClNYHyJCVQ6K3olk2taGpQFg2RbBcKaB4xWprS44hGy3JbgCGqCq3keEJtnnMVDAExd4JrRoyypHD7MlCjuH6JpU8aULd0I5Xc6K6c79PYClxS5nFchDiBnk3H6UjMB21jcs/CLe9CAmzRG2DooH3pHsBIxY3tKgNzvYHHimy/lqk3HcMxh5v/luhz3q/8Js9zljPE7bjmg35YajYI6Nkj70/uF/0HR0M6BPi3woBUy2AT2rErQxxVIq6CmBBL1Pw08iXsSCWu2kPLvinNNtFXEFVARdqD66uhyyjIhfw+MUSg0k2Akq5P2zOT0/dqJTSnzK8JVC22fTcZblzKTL2p+4O1dZUVN8/lNVUpJRjQUqRcGlALVZTiXsTNoRfr4aVUqiGncnH8WOcXrwEDt1reE5l9yvlesxqxOqkjeXtwPTviIjVeZKjIcbCR59+S4Mu5/gdkUeIr3Y/E6x3t5ijZi14aLBIUWNbiAw3ezfxu8M7nNM5eFXgSiqKkGRRIR7L1aTfAZRZ5Uuld9ho6nu4sgi/pjxM4nJpunAE7ofIcawhSqs0DGdJODqD7w/M7gIXCiKCAA3fxkWiIjv0tdvx0LhU4sT4x+kUPrCtlheTSVXd1WZ+CrjFHVjAUqaNorgp5Ooi52Pqp0DHb5v6KXtUVvA/5qqG3M+wSQv0WVmnfvI+p36yABk/UtHworLu0Nu+vXWDdFTCSszm91y02TKnLa/AoIvj2LdUNHgAcIOw59EyT2fAK99xuuava8o6Su3mdM22zkVXF1+LyuBK2G7TrPQtF62GtdepqMwJteZHMnouKotW+4C8jufvX2h5PCWj1zVllwIiT8V7/1E3oT2XAqxoXWJGF9z3d+XEUGSWT6OGMA7kz0VmTYffZg8EAhh8kh9FZjiMWNdtktupu6BdrLbvkB0jh9bpinbVr1SGBVmzwb5DpnCw75gpnKhsG1Zm/kfzrl381v8NreZk3jHXaM07JguJ9z49XmKtPAD1ZX4tC+sjyY7oLBQ7WMbWU0CRcxRGCvFIcrZCmLFHXX4y60ORGgqU06XW6cDEKJViGUkp9fhGcnlFK7syRH23rRL56J9gpXLASwyvGFbRgALtnEw51shZ3EhZZ1AtGjO9cuxhGeHuVcyv1ofnsEwXz/2QFoDvr/RvNvklir2yJayzIfbBBm3RSp0okU+nijVhY+XFxroiqiBl4oKaqEd7CrKblHZfOdKqerA1lViq5Plj1PHp6V4gkUi6t+8YDcYulIdmWesD05JyuZMaUW2omOI8qYjXXiHAwFZow5Ym+9XW/HI7b7LTYUOHpImRtN28rkPPb+hxqvRyemWQRMu5rAwYMqnjpHMDXTws2OrBOOLBMOjh29q312bhf9HisGQUGYXfDd8yG69aJYwMeFiqDqaJBswhK44iuIUiSDCZPGcFG1I/MGBZT7sd6qp1YY9wLgNngIEyUg6Ruj6Pdf0S8JRRFxTpUrpECpxjd8YBclPeTpdCqLMRPmcFaZV6py2IFbOULU5cXRz88TEEAjBtOO2guGNIgDrFYMoW1ByA53/rJi5WJU4M+DOgiqL9GXhkvobaNlvJmJNVJm+OqzZ4lZImas8f/CLKYELx08uIT+UaFwpTvbRIEQyIOt++bUb8C2iqCOIv3GXlYBV2JJXuGZamZg1oFNT2OK15K4r2rmMz8AG+JjbrMVxaaUuSyzLs7cH6nFyzaCx537X5lhjUYGVd9azvWkWsjbZeNRpwqMsA1K2qutkT5QQEK9M1UgYrw9JaVIe0gJobeO6QuPYLiakkOpBDycu5Lnlp6pZcefgmxXa5rFWrhkslLtDtMBbCcAHQadpOhEHzSrWy/ZI8ZAozspTsBi1WEWu7B4R8rPhZpXjaab9c4TtT4xA9z9tSa1rwkSAeP3B3ccfmsdmgIk+meXXXSWMtjQ752OzJ2ClVyOs3Csc2dJH0bknQ6itbAUDGCkA8Qgr+6DZwaA3SDJmxDi9xaZ+/Sb9UOfLz9qpK8ECY7Du9XqmNoW4sVpxRDavOw1LqkC0KJJ0q/+ck7eO5QcEfFtqbihijoQ1rerjXNYW10DEAXD1qf9WtTRvvEIX69TtElfTwZR7Ombbw4VLOHHV2F72YROOHVHFrkIVJYxu1LbYI1RzClyvILtBtQZAdwm1eNxnN71AhS+/eS7iN3SVILxPcJk7uRliwfKaTgV3trGp0LiPrUiWPWz66w226PXq8nmfGu+WZc0fZ+lgumnM0Smk9u21EaHf0ICEF2KgZnXLsWBULIzX5D+jR6QwhWX3SmitlIr68PXw7qjyclCe+f/F9TY13+fTfkwnu/r8mU2P882RCj/31ZLbwN5OJ6ddkph/fnavzY7EiytGI+j/5Ec+7/puh7PNE6bI/8O7aXEWWd4Wwtv1xoXDP+7Oprqz9vYKb6ChT0n/x3jISk+U5ruJzUOlIlaa1LEpoTrRTY73UojQklP75PKZtspa42FiXpLr+R59Tu9Ov7TOOIOhjcMJjmTTFdSBE18dUsgyomgE59a3MJXE0wRYU0ljavCuPgIhjQmCqJ0sX9tFt9fbb8ss9ria9jRT0IJnyXoHbg9/xLNjt/Z+nk9XbaAYCH3HW/PaLfSiPzy77KFXFQvOnP94WIONnLTXV49wWDsCP7JFzgbWo7+0ERw+MpIQ63nAmnk2e+f36it7pySDm6wg++HDglcJnZ6iQyDhcPwhyJcikacDP7K7lY2VOIfiipE1ufm/n4/Hij9d68SNOfgT9b64Xu4HNGsGPlX4aMz5uu0EQE9gtjcRy+ZvckAbeXh6tLxOs+yLefL2euNjo/zxDph+5cAMg0CSE4BA4+d8aUFwhvm6rLUdzbCtLFLQcOb4hgD5ru2ufD56nKZsWHC93cFeV5abLvjkZ8Ef9po5NhobM1m/ccEL1q4ZWsyyAytWAe3ny/K0V+nh+T/BzG/8c5c8g3VZvZfBJPQt+h0KvWu+o92EQWcuPcy+/nOSXqzax//z7Px03vIOEwgEA", + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658", + "function_idx": 0 + }, + { + "selector": "0x3c118a68e16e12e97ed25cb4901c12f4d3162818669cc44c391d8049924c14", + "function_idx": 3 + }, + { + "selector": "0x5562b3e932b4d139366854d5a2e578382e6a3b6572ac9943d55e7efbe43d00", + "function_idx": 9 + }, + { + "selector": "0x5df99ae77df976b4f0e5cf28c7dcfe09bd6e81aab787b19ac0c08e03d928cf", + "function_idx": 1 + }, + { + "selector": "0xb17d8a2731ba7ca1816631e6be14f0fc1b8390422d649fa27f0fbb0c91eea8", + "function_idx": 10 + }, + { + "selector": "0xe7510edcf6e9f1b70f7bd1f488767b50f0363422f3c563160ab77adf62467b", + "function_idx": 12 + }, + { + "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f", + "function_idx": 11 + }, + { + "selector": "0x27a4a7332e590dd789019a6d125ff2aacd358e453090978cbf81f0d85e4c045", + "function_idx": 2 + }, + { + "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "function_idx": 7 + }, + { + "selector": "0x2913ee03e5e3308c41e308bd391ea4faac9b9cb5062c76a6b3ab4f65397e106", + "function_idx": 4 + }, + { + "selector": "0x2d7cf5d5a324a320f9f37804b1615a533fde487400b41af80f13f7ac5581325", + "function_idx": 5 + }, + { + "selector": "0x31aafc75f498fdfa7528880ad27246b4c15af4954f96228c9a132b328de1c92", + "function_idx": 6 + }, + { + "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50", + "function_idx": 8 + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 13 + } + ] + }, + "abi": "[{\"type\": \"constructor\", \"name\": \"constructor\", \"inputs\": []}, {\"type\": \"function\", \"name\": \"test\", \"inputs\": [{\"name\": \"arg\", \"type\": \"core::felt252\"}, {\"name\": \"arg1\", \"type\": \"core::felt252\"}, {\"name\": \"arg2\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_read\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_storage_write\", \"inputs\": [{\"name\": \"address\", \"type\": \"core::felt252\"}, {\"name\": \"value\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_get_execution_info\", \"inputs\": [{\"name\": \"block_number\", \"type\": \"core::felt252\"}, {\"name\": \"block_timestamp\", \"type\": \"core::felt252\"}, {\"name\": \"sequencer_address\", \"type\": \"core::felt252\"}, {\"name\": \"version\", \"type\": \"core::felt252\"}, {\"name\": \"account_address\", \"type\": \"core::felt252\"}, {\"name\": \"max_fee\", \"type\": \"core::felt252\"}, {\"name\": \"chain_id\", \"type\": \"core::felt252\"}, {\"name\": \"nonce\", \"type\": \"core::felt252\"}, {\"name\": \"caller_address\", \"type\": \"core::felt252\"}, {\"name\": \"contract_address\", \"type\": \"core::felt252\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_event\", \"inputs\": [{\"name\": \"keys\", \"type\": \"core::array::Array::\"}, {\"name\": \"data\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_send_message_to_l1\", \"inputs\": [{\"name\": \"to_address\", \"type\": \"core::felt252\"}, {\"name\": \"payload\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_emit_simple_event\", \"inputs\": [{\"name\": \"argument\", \"type\": \"core::felt252\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\"}, {\"name\": \"another_argument\", \"type\": \"core::felt252\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_call_contract\", \"inputs\": [{\"name\": \"contract_address\", \"type\": \"core::starknet::contract_address::ContractAddress\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_library_call\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"entry_point_selector\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"assert_eq\", \"inputs\": [{\"name\": \"x\", \"type\": \"core::felt252\"}, {\"name\": \"y\", \"type\": \"core::felt252\"}], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_segment_arena\", \"inputs\": [], \"outputs\": [{\"type\": \"core::felt252\"}], \"state_mutability\": \"external\"}, {\"type\": \"enum\", \"name\": \"core::bool\", \"variants\": [{\"name\": \"False\", \"type\": \"()\"}, {\"name\": \"True\", \"type\": \"()\"}]}, {\"type\": \"function\", \"name\": \"test_deploy\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}, {\"name\": \"contract_address_salt\", \"type\": \"core::felt252\"}, {\"name\": \"calldata\", \"type\": \"core::array::Array::\"}, {\"name\": \"deploy_from_zero\", \"type\": \"core::bool\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"function\", \"name\": \"test_replace_class\", \"inputs\": [{\"name\": \"class_hash\", \"type\": \"core::starknet::class_hash::ClassHash\"}], \"outputs\": [], \"state_mutability\": \"external\"}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"struct\", \"members\": [{\"name\": \"argument\", \"type\": \"core::felt252\", \"kind\": \"data\"}, {\"name\": \"my_array\", \"type\": \"core::array::Array::\", \"kind\": \"data\"}]}, {\"type\": \"event\", \"name\": \"test_contract::test_contract_cairo1::TestContract::Event\", \"kind\": \"enum\", \"variants\": [{\"name\": \"simple_event\", \"type\": \"test_contract::test_contract_cairo1::TestContract::simple_event\", \"kind\": \"nested\"}]}]" + }, + "nonce": "0x0", + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x5", + "max_price_per_unit": "0x6" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x1b34d819720bd84c89bdfb476bc2c4d0de9a41b766efabd20fa292280e4c6d9", + "signature": [ + "0x1132577", + "0x17df53c" + ], + "type": "DECLARE", + "version": "0x3", + "tip": "0x0", + "account_deployment_data": [], + "fee_data_availability_mode": 0, + "nonce_data_availability_mode": 0, + "paymaster_data": [] +} diff --git a/crates/starknet_client/resources/writer/deploy_account_response.json b/crates/starknet_client/resources/writer/deploy_account_response.json new file mode 100644 index 00000000000..2301cc9702f --- /dev/null +++ b/crates/starknet_client/resources/writer/deploy_account_response.json @@ -0,0 +1,5 @@ +{ + "code": "TRANSACTION_RECEIVED", + "transaction_hash": "0x6d0ea68e3e8e257ff7c6633277fc3ea6a42a57d0d15ada480cbaeec9c6be5d0", + "address": "0x219937256cd88844f9fdc9c33a2d6d492e253ae13814c2dc0ecab7f26919d46" +} diff --git a/crates/starknet_client/resources/writer/deploy_account_v1.json b/crates/starknet_client/resources/writer/deploy_account_v1.json new file mode 100644 index 00000000000..cce3d7c9b93 --- /dev/null +++ b/crates/starknet_client/resources/writer/deploy_account_v1.json @@ -0,0 +1,15 @@ +{ + "version": "0x1", + "max_fee": "0xde0b6b3a7640000", + "signature": [ + "0x146e9a5aa075be1c025b9dcd4e728203b37b7b285fe61ba2fdd4e97eb8d731e", + "0x1bc2c4e3492e7d25ce33c60fa96127db534e45039d2840c6c2a38f88bd9d841" + ], + "nonce": "0x0", + "class_hash": "0x4189defe07cb5c3ae9fd57d88a339bd99785d44690dc83484998b0fd769d3c4", + "contract_address_salt": "0x229dbd8708a6d894da30582ef2b46675ebcfee684fde9446548a1d4219d8b14", + "constructor_calldata": [ + "0x406a640b3b70dad390d661c088df1fbaeb5162a07d57cf29ba794e2b0e3c804" + ], + "type": "DEPLOY_ACCOUNT" +} diff --git a/crates/starknet_client/resources/writer/deploy_account_v3.json b/crates/starknet_client/resources/writer/deploy_account_v3.json new file mode 100644 index 00000000000..ced06cad516 --- /dev/null +++ b/crates/starknet_client/resources/writer/deploy_account_v3.json @@ -0,0 +1,37 @@ +{ + "class_hash": "0x1fcd2dcd811e049eaa730b87038a68f39220a04986b43fe287d690da0df01b8", + "constructor_calldata": [ + "0x0", + "0x1", + "0x2", + "0x3", + "0x4", + "0x5", + "0x6", + "0x7", + "0x8", + "0x9" + ], + "contract_address_salt": "0x2", + "nonce": "0x0", + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x5", + "max_price_per_unit": "0x6" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "signature": [ + "0x1132577", + "0x17df53c" + ], + "type": "DEPLOY_ACCOUNT", + "version": "0x3", + "tip": "0x0", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "paymaster_data": [] +} diff --git a/crates/starknet_client/resources/writer/invoke_response.json b/crates/starknet_client/resources/writer/invoke_response.json new file mode 100644 index 00000000000..de03726e1f0 --- /dev/null +++ b/crates/starknet_client/resources/writer/invoke_response.json @@ -0,0 +1,4 @@ +{ + "code": "TRANSACTION_RECEIVED", + "transaction_hash": "0xd5c953f3345bb4135b7d879dd7fbb41cdb8024ba41ef8a9f8b834ac8f4483" +} diff --git a/crates/starknet_client/resources/writer/invoke_v1.json b/crates/starknet_client/resources/writer/invoke_v1.json new file mode 100644 index 00000000000..d4d943f443a --- /dev/null +++ b/crates/starknet_client/resources/writer/invoke_v1.json @@ -0,0 +1,26 @@ +{ + "version": "0x1", + "max_fee": "0xde0b6b3a7640000", + "signature": [ + "0xfdb1626b6acc48f92185e6018b577a51d540982883d53036977df9a08fb564", + "0x37dabc3ef10428306a7ac9003d721bafdcda2b933f053c92ab6288d8408b1d9" + ], + "nonce": "0x9", + "sender_address": "0x219937256cd88844f9fdc9c33a2d6d492e253ae13814c2dc0ecab7f26919d46", + "calldata": [ + "0x1", + "0x12c3a0b15ef9bf39e03af3653ad1cff528cd32bd75167cdeb7615d8da93fd17", + "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c", + "0x0", + "0x7", + "0x7", + "0x12c3a0b15ef9bf39e03af3653ad1cff528cd32bd75167cdeb7615d8da93fd17", + "0x2d7cf5d5a324a320f9f37804b1615a533fde487400b41af80f13f7ac5581325", + "0x4", + "0xe88ed417dee71cd1ebad48637002ebaa09b2fa00", + "0x2", + "0x1e8d90c08bb80f786f13eb48376bbb462d0bc09b9ccc69e9cda78192263dc4a", + "0x1c190b4c7ce26ff28464062dd13641fb42cf9a075229d87e25674c6f2b57693" + ], + "type": "INVOKE_FUNCTION" +} diff --git a/crates/starknet_client/resources/writer/invoke_v3.json b/crates/starknet_client/resources/writer/invoke_v3.json new file mode 100644 index 00000000000..197167dcb2e --- /dev/null +++ b/crates/starknet_client/resources/writer/invoke_v3.json @@ -0,0 +1,37 @@ +{ + "calldata": [ + "0x0", + "0x1", + "0x2", + "0x3", + "0x4", + "0x5", + "0x6", + "0x7", + "0x8", + "0x9" + ], + "nonce": "0x0", + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x5", + "max_price_per_unit": "0x6" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "sender_address": "0x1b34d819720bd84c89bdfb476bc2c4d0de9a41b766efabd20fa292280e4c6d9", + "signature": [ + "0x1132577", + "0x17df53c" + ], + "type": "INVOKE_FUNCTION", + "version": "0x3", + "tip": "0x0", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "paymaster_data": [], + "account_deployment_data": [] +} diff --git a/crates/starknet_client/src/lib.rs b/crates/starknet_client/src/lib.rs new file mode 100644 index 00000000000..1479ccb9678 --- /dev/null +++ b/crates/starknet_client/src/lib.rs @@ -0,0 +1,212 @@ +// config compiler to support coverage_attribute feature when running coverage in nightly mode +// within this crate +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] + +//! This crate contains clients that can communicate with [`Starknet`] through the various +//! endpoints [`Starknet`] has. +//! +//! +//! [`Starknet`]: https://starknet.io/ + +pub mod reader; +pub mod retry; +#[cfg(test)] +mod starknet_client_test; +pub mod starknet_error; +#[cfg(test)] +mod test_utils; +pub mod writer; + +use std::collections::HashMap; + +use reqwest::header::HeaderMap; +use reqwest::{Client, RequestBuilder, StatusCode}; +use tracing::warn; + +use self::retry::Retry; +pub use self::retry::RetryConfig; +pub use self::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +/// A [`Result`] in which the error is a [`ClientError`]. +type ClientResult = Result; + +/// A starknet client. +struct StarknetClient { + http_headers: HeaderMap, + pub internal_client: Client, + retry_config: RetryConfig, +} + +/// Errors that might be encountered while creating the client. +#[derive(thiserror::Error, Debug)] +pub enum ClientCreationError { + #[error(transparent)] + BadUrl(#[from] url::ParseError), + #[error(transparent)] + BuildError(#[from] reqwest::Error), + #[error(transparent)] + HttpHeaderError(#[from] http::Error), +} + +/// Errors that might be solved by retrying mechanism. +#[derive(Debug, Eq, PartialEq)] +pub enum RetryErrorCode { + Redirect, + Timeout, + TooManyRequests, + ServiceUnavailable, + Disconnect, +} + +/// Errors that may be returned by a reader or writer client. +#[derive(thiserror::Error, Debug)] +pub enum ClientError { + /// A client error representing bad status http responses. + #[error("Bad response status code: {:?} message: {:?}.", code, message)] + BadResponseStatus { code: StatusCode, message: String }, + /// A client error representing http request errors. + #[error(transparent)] + RequestError(#[from] reqwest::Error), + /// A client error representing errors that might be solved by retrying mechanism. + #[error("Retry error code: {:?}, message: {:?}.", code, message)] + RetryError { code: RetryErrorCode, message: String }, + /// A client error representing deserialization errors. + #[error(transparent)] + SerdeError(#[from] serde_json::Error), + /// A client error representing errors returned by the starknet client. + #[error(transparent)] + StarknetError(#[from] StarknetError), +} + +// A wrapper error for request_with_retry to handle the case that clone failed. +#[derive(thiserror::Error, Debug)] +enum RequestWithRetryError { + #[error("Request is unclonable.")] + CloneError, + #[error(transparent)] + ClientError(#[from] ClientError), +} + +impl StarknetClient { + /// Creates a new client for a starknet gateway at `url_str` with retry_config [`RetryConfig`]. + pub fn new( + http_headers: Option>, + node_version: &'static str, + retry_config: RetryConfig, + ) -> Result { + let header_map = match http_headers { + Some(inner) => (&inner).try_into()?, + None => HeaderMap::new(), + }; + let info = os_info::get(); + let system_information = + format!("{}; {}; {}", info.os_type(), info.version(), info.bitness()); + let app_user_agent = format!( + "{product_name}/{product_version} ({system_information})", + product_name = "papyrus", + product_version = node_version, + system_information = system_information + ); + Ok(StarknetClient { + http_headers: header_map, + internal_client: Client::builder().user_agent(app_user_agent).build()?, + retry_config, + }) + } + + fn get_retry_error_code(err: &ClientError) -> Option { + match err { + ClientError::BadResponseStatus { code, message: _ } => match *code { + StatusCode::TEMPORARY_REDIRECT => Some(RetryErrorCode::Redirect), + StatusCode::REQUEST_TIMEOUT | StatusCode::GATEWAY_TIMEOUT => { + Some(RetryErrorCode::Timeout) + } + StatusCode::TOO_MANY_REQUESTS => Some(RetryErrorCode::TooManyRequests), + StatusCode::SERVICE_UNAVAILABLE => Some(RetryErrorCode::ServiceUnavailable), + _ => None, + }, + + ClientError::RequestError(internal_err) => { + if internal_err.is_timeout() { + Some(RetryErrorCode::Timeout) + } else if internal_err.is_request() { + None + } else if internal_err.is_connect() { + Some(RetryErrorCode::Disconnect) + } else if internal_err.is_redirect() { + Some(RetryErrorCode::Redirect) + } else { + None + } + } + + ClientError::StarknetError(StarknetError { + code: + StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::TransactionLimitExceeded), + message: _, + }) => Some(RetryErrorCode::TooManyRequests), + _ => None, + } + } + + fn should_retry(err: &RequestWithRetryError) -> bool { + match err { + RequestWithRetryError::ClientError(err) => Self::get_retry_error_code(err).is_some(), + RequestWithRetryError::CloneError => false, + } + } + + // If the request_builder is unclonable, the function will not retry the request upon failure. + pub async fn request_with_retry( + &self, + request_builder: RequestBuilder, + ) -> ClientResult { + let res = Retry::new(&self.retry_config) + .start_with_condition( + || async { + match request_builder.try_clone() { + Some(request_builder) => self + .request(request_builder) + .await + .map_err(RequestWithRetryError::ClientError), + None => Err(RequestWithRetryError::CloneError), + } + }, + Self::should_retry, + ) + .await; + + match res { + Ok(string) => Ok(string), + Err(RequestWithRetryError::ClientError(err)) => Err(Self::get_retry_error_code(&err) + .map(|code| ClientError::RetryError { code, message: err.to_string() }) + .unwrap_or(err)), + Err(RequestWithRetryError::CloneError) => { + warn!("Starknet client got an unclonable request. Can't retry upon failure."); + self.request(request_builder).await + } + } + } + + async fn request(&self, request_builder: RequestBuilder) -> ClientResult { + let res = request_builder.headers(self.http_headers.clone()).send().await; + let (code, message) = match res { + Ok(response) => (response.status(), response.text().await?), + Err(err) => { + let msg = err.to_string(); + (err.status().ok_or(err)?, msg) + } + }; + match code { + StatusCode::OK => Ok(message), + // TODO(Omri): The error code returned from SN changed from error 500 to error 400. For + // now, keeping both options. In the future, remove the '500' (INTERNAL_SERVER_ERROR) + // option. + StatusCode::INTERNAL_SERVER_ERROR | StatusCode::BAD_REQUEST => { + let starknet_error: StarknetError = serde_json::from_str(&message)?; + Err(ClientError::StarknetError(starknet_error)) + } + _ => Err(ClientError::BadResponseStatus { code, message }), + } + } +} diff --git a/crates/starknet_client/src/reader/mod.rs b/crates/starknet_client/src/reader/mod.rs new file mode 100644 index 00000000000..8120205f69b --- /dev/null +++ b/crates/starknet_client/src/reader/mod.rs @@ -0,0 +1,410 @@ +//! This module contains client that can read data from [`Starknet`]. +//! +//! [`Starknet`]: https://starknet.io/ + +pub mod objects; +#[cfg(test)] +mod starknet_feeder_gateway_client_test; + +use std::collections::HashMap; + +use async_trait::async_trait; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +#[cfg(any(feature = "testing", test))] +use mockall::automock; +use papyrus_common::pending_classes::ApiContractClass; +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ClassHash, SequencerPublicKey}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::transaction::TransactionHash; +use starknet_api::StarknetApiError; +use starknet_types_core::felt::Felt; +use tracing::{debug, error, instrument}; +use url::Url; + +pub use crate::reader::objects::block::{ + Block, + BlockSignatureData, + BlockSignatureMessage, + TransactionReceiptsError, +}; +pub use crate::reader::objects::pending_data::PendingData; +pub use crate::reader::objects::state::{ + ContractClass, + DeclaredClassHashEntry, + DeployedContract, + ReplacedClass, + StateDiff, + StateUpdate, + StorageEntry, +}; +#[cfg(doc)] +pub use crate::reader::objects::transaction::TransactionReceipt; +use crate::retry::RetryConfig; +use crate::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; +use crate::{ClientCreationError, ClientError, StarknetClient}; + +/// Errors that may be returned from a reader client. +#[derive(thiserror::Error, Debug)] +pub enum ReaderClientError { + /// A client error representing errors from the base StarknetClient. + #[error(transparent)] + ClientError(#[from] ClientError), + /// A client error representing deserialization errors. + /// Note: [`ClientError`] contains SerdeError as well. The difference is that this variant is + /// responsible for serde errors coming from [`StarknetReader`] and ClientError::SerdeError + /// is responsible for serde errors coming from StarknetClient. + #[error(transparent)] + SerdeError(#[from] serde_json::Error), + /// A client error representing errors from [`starknet_api`]. + #[error(transparent)] + StarknetApiError(#[from] StarknetApiError), + /// A client error representing transaction receipts errors. + #[error(transparent)] + TransactionReceiptsError(#[from] TransactionReceiptsError), + #[error("Invalid transaction: {:?}, error: {:?}.", tx_hash, msg)] + BadTransaction { tx_hash: TransactionHash, msg: String }, +} + +pub type ReaderClientResult = Result; + +/// A trait describing an object that can communicate with [`Starknet`] and read data from it. +/// +/// [`Starknet`]: https://starknet.io/ +#[cfg_attr(any(test, feature = "testing"), automock)] +#[async_trait] +pub trait StarknetReader { + /// Returns the last block in the system, returning [`None`] in case there are no blocks in the + /// system. + async fn latest_block(&self) -> ReaderClientResult>; + /// Returns a [`Block`] corresponding to `block_number`, returning [`None`] in case + /// no such block exists in the system. + async fn block(&self, block_number: BlockNumber) -> ReaderClientResult>; + /// Returns a [`GenericContractClass`] corresponding to `class_hash`. + async fn class_by_hash( + &self, + class_hash: ClassHash, + ) -> ReaderClientResult>; + /// Returns a [`CasmContractClass`] corresponding to `class_hash`. + async fn compiled_class_by_hash( + &self, + class_hash: ClassHash, + ) -> ReaderClientResult>; + /// Returns a [`starknet_client`][`StateUpdate`] corresponding to `block_number`. + async fn state_update( + &self, + block_number: BlockNumber, + ) -> ReaderClientResult>; + + // TODO(dvir): delete this when stop supporting pending data. + /// Returns pending [`starknet_client`][`PendingData`]. + async fn pending_data(&self) -> ReaderClientResult>; + + // Returns true if the reader is alive. + async fn is_alive(&self) -> bool; + + async fn block_signature( + &self, + block_number: BlockNumber, + ) -> ReaderClientResult>; + + async fn sequencer_pub_key(&self) -> ReaderClientResult; +} + +/// A client for the [`Starknet`] feeder gateway. +/// +/// [`Starknet`]: https://starknet.io/ +pub struct StarknetFeederGatewayClient { + urls: StarknetUrls, + client: StarknetClient, +} + +#[derive(Clone, Debug)] +struct StarknetUrls { + get_block: Url, + get_contract_by_hash: Url, + get_compiled_class_by_class_hash: Url, + get_state_update: Url, + get_pending_data: Url, + feeder_gateway_is_alive: Url, + get_block_signature: Url, + get_sequencer_pub_key: Url, +} + +const GET_BLOCK_URL: &str = "feeder_gateway/get_block"; +const GET_CONTRACT_BY_HASH_URL: &str = "feeder_gateway/get_class_by_hash"; +const GET_COMPILED_CLASS_BY_CLASS_HASH_URL: &str = + "feeder_gateway/get_compiled_class_by_class_hash"; +const GET_STATE_UPDATE_URL: &str = "feeder_gateway/get_state_update"; +const BLOCK_NUMBER_QUERY: &str = "blockNumber"; +const LATEST_BLOCK_NUMBER: &str = "latest"; +const CLASS_HASH_QUERY: &str = "classHash"; +const PENDING_BLOCK_ID: &str = "pending"; +const INCLUDE_BLOCK: &str = "includeBlock"; +const FEEDER_GATEWAY_IS_ALIVE: &str = "feeder_gateway/is_alive"; +const FEEDER_GATEWAY_ALIVE_RESPONSE: &str = "FeederGateway is alive!"; +const GET_BLOCK_SIGNATURE_URL: &str = "feeder_gateway/get_signature"; +const GET_SEQUENCER_PUB_KEY_URL: &str = "feeder_gateway/get_public_key"; + +impl StarknetUrls { + fn new(url_str: &str) -> Result { + let base_url = Url::parse(url_str)?; + Ok(StarknetUrls { + get_block: base_url.join(GET_BLOCK_URL)?, + // Query the pending block since the feeder-gateway uses the `latest` block by default. + get_contract_by_hash: base_url + .join(GET_CONTRACT_BY_HASH_URL)? + .query_pairs_mut() + .append_pair(BLOCK_NUMBER_QUERY, PENDING_BLOCK_ID) + .finish() + .clone(), + // Query the pending block since the feeder-gateway uses the `latest` block by default. + get_compiled_class_by_class_hash: base_url + .join(GET_COMPILED_CLASS_BY_CLASS_HASH_URL)? + .query_pairs_mut() + .append_pair(BLOCK_NUMBER_QUERY, PENDING_BLOCK_ID) + .finish() + .clone(), + get_state_update: base_url.join(GET_STATE_UPDATE_URL)?, + get_pending_data: base_url + .join(GET_STATE_UPDATE_URL)? + .query_pairs_mut() + .append_pair(BLOCK_NUMBER_QUERY, PENDING_BLOCK_ID) + .append_pair(INCLUDE_BLOCK, "true") + .finish() + .clone(), + feeder_gateway_is_alive: base_url.join(FEEDER_GATEWAY_IS_ALIVE)?, + get_block_signature: base_url.join(GET_BLOCK_SIGNATURE_URL)?, + get_sequencer_pub_key: base_url.join(GET_SEQUENCER_PUB_KEY_URL)?, + }) + } +} + +impl StarknetFeederGatewayClient { + pub fn new( + url_str: &str, + http_headers: Option>, + node_version: &'static str, + retry_config: RetryConfig, + ) -> Result { + Ok(StarknetFeederGatewayClient { + urls: StarknetUrls::new(url_str)?, + client: StarknetClient::new(http_headers, node_version, retry_config)?, + }) + } + + async fn request_with_retry_url(&self, url: Url) -> ReaderClientResult { + self.client + .request_with_retry(self.client.internal_client.get(url)) + .await + .map_err(Into::::into) + } + + async fn request_block( + &self, + block_number: Option, + ) -> ReaderClientResult> { + let mut url = self.urls.get_block.clone(); + let block_number = + block_number.map(|bn| bn.to_string()).unwrap_or(String::from(LATEST_BLOCK_NUMBER)); + url.query_pairs_mut().append_pair(BLOCK_NUMBER_QUERY, block_number.as_str()); + + let response = self.request_with_retry_url(url).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::BlockNotFound), + format!("Failed to get block number {block_number:?} from starknet server."), + ) + } +} + +#[async_trait] +impl StarknetReader for StarknetFeederGatewayClient { + #[instrument(skip(self), level = "debug")] + async fn latest_block(&self) -> ReaderClientResult> { + Ok(self.request_block(None).await?) + } + + #[instrument(skip(self), level = "debug")] + async fn block(&self, block_number: BlockNumber) -> ReaderClientResult> { + self.request_block(Some(block_number)).await + } + + #[instrument(skip(self), level = "debug")] + async fn class_by_hash( + &self, + class_hash: ClassHash, + ) -> ReaderClientResult> { + let mut url = self.urls.get_contract_by_hash.clone(); + let class_hash_result = serde_json::to_string(&class_hash); + if class_hash_result.is_err() { + error!("Failed to serialize {class_hash:?}"); + } + let class_hash = class_hash_result?; + url.query_pairs_mut() + .append_pair(CLASS_HASH_QUERY, &class_hash.as_str()[1..class_hash.len() - 1]); + let response = self.request_with_retry_url(url).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::UndeclaredClass), + format!("Failed to get class with hash {class_hash:?} from starknet server."), + ) + } + + #[instrument(skip(self), level = "debug")] + async fn state_update( + &self, + block_number: BlockNumber, + ) -> ReaderClientResult> { + let mut url = self.urls.get_state_update.clone(); + url.query_pairs_mut().append_pair(BLOCK_NUMBER_QUERY, &block_number.to_string()); + let response = self.request_with_retry_url(url).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::BlockNotFound), + format!( + "Failed to get state update for block number {block_number} from starknet server." + ), + ) + } + + #[instrument(skip(self), level = "debug")] + async fn compiled_class_by_hash( + &self, + class_hash: ClassHash, + ) -> ReaderClientResult> { + debug!("Got compiled_class_by_hash {} from starknet server.", class_hash); + // FIXME: Remove the following default CasmContractClass once integration environment gets + // regenesissed. + // Use default value for CasmConractClass that are malformed in the integration environment. + // TODO: Make this array a const. + if [ + ClassHash(Felt::from_hex_unchecked( + "0x4e70b19333ae94bd958625f7b61ce9eec631653597e68645e13780061b2136c", + )), + ClassHash(Felt::from_hex_unchecked( + "0x6208b3f9f94e6220f3d6a3562fe06a35a66181a202d946c3522fd28eda9ea1b", + )), + ClassHash(Felt::from_hex_unchecked( + "0xd6916ff38c93f834e7223a95b41d4542152d8288ff388b5d3dcdf8126a784a", + )), + ClassHash(Felt::from_hex_unchecked( + "0x161354521d46ca89a5b64aa41fa4e77ffeadc0f9796272d9b94227dbbb3840e", + )), + ClassHash(Felt::from_hex_unchecked( + "0x6a9eb910b3f83989900c8d65f9d67d67016f2528cc1b834019cf489f4f7d716", + )), + ] + .contains(&class_hash) + { + debug!("Using default compiled class for class hash {}.", class_hash); + return Ok(Some(CasmContractClass::default())); + } + + let mut url = self.urls.get_compiled_class_by_class_hash.clone(); + let class_hash_result = serde_json::to_string(&class_hash); + if class_hash_result.is_err() { + error!("Failed to serialize {class_hash:?}"); + } + let class_hash = class_hash_result?; + url.query_pairs_mut() + .append_pair(CLASS_HASH_QUERY, &class_hash.as_str()[1..class_hash.len() - 1]); + let response = self.request_with_retry_url(url).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::UndeclaredClass), + format!("Failed to get compiled class with hash {class_hash:?} from starknet server."), + ) + } + + #[instrument(skip(self), level = "debug")] + async fn pending_data(&self) -> ReaderClientResult> { + let response = self.request_with_retry_url(self.urls.get_pending_data.clone()).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::BlockNotFound), + "Failed to get pending data from starknet server.".to_string(), + ) + } + + async fn is_alive(&self) -> bool { + let url = self.urls.feeder_gateway_is_alive.clone(); + let response = self.request_with_retry_url(url).await; + let expected_response = FEEDER_GATEWAY_ALIVE_RESPONSE.to_string(); + response.is_ok_and(|response| response == expected_response) + } + + #[instrument(skip(self), level = "debug")] + async fn block_signature( + &self, + block_number: BlockNumber, + ) -> ReaderClientResult> { + let mut url = self.urls.get_block_signature.clone(); + url.query_pairs_mut().append_pair(BLOCK_NUMBER_QUERY, &block_number.to_string()); + let response = self.request_with_retry_url(url).await; + load_object_from_response( + response, + Some(KnownStarknetErrorCode::BlockNotFound), + format!("Failed to get signature for block {block_number:?} from starknet server."), + ) + } + + #[instrument(skip(self), level = "debug")] + async fn sequencer_pub_key(&self) -> ReaderClientResult { + let response = self.request_with_retry_url(self.urls.get_sequencer_pub_key.clone()).await; + load_object_from_response( + response, + None, + "Failed to get sequencer public key from starknet server.".to_string(), + ) + .map(|option| option.expect("Sequencer public key should not be None.")) + } +} + +/// Load an object from a json string response. If there was a StarknetError with +/// `none_error_code`, return None. If there was a different error, log `error_message`. +fn load_object_from_response Deserialize<'a>>( + response: ReaderClientResult, + none_error_code: Option, + error_message: String, +) -> ReaderClientResult> { + match (response, none_error_code) { + (Ok(raw_object), _) => { + let result = serde_json::from_str(&raw_object); + if let Err(err) = &result { + error!("Failed to deserialize {raw_object:?}. Error: {err}"); + } + Ok(Some(result?)) + } + ( + Err(ReaderClientError::ClientError(ClientError::StarknetError(StarknetError { + code: StarknetErrorCode::KnownErrorCode(error_code), + message: _, + }))), + Some(none_error_code), + ) if error_code == none_error_code => Ok(None), + (Err(err), _) => { + debug!(error_message); + Err(err) + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GenericContractClass { + Cairo0ContractClass(DeprecatedContractClass), + Cairo1ContractClass(ContractClass), +} + +impl From for ApiContractClass { + fn from(value: GenericContractClass) -> Self { + match value { + GenericContractClass::Cairo0ContractClass(class) => { + Self::DeprecatedContractClass(class) + } + GenericContractClass::Cairo1ContractClass(class) => Self::ContractClass(class.into()), + } + } +} diff --git a/crates/starknet_client/src/reader/objects/block.rs b/crates/starknet_client/src/reader/objects/block.rs new file mode 100644 index 00000000000..fdda5eceaa6 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/block.rs @@ -0,0 +1,441 @@ +#[cfg(test)] +#[path = "block_test.rs"] +mod block_test; + +use std::ops::Index; + +use serde::{Deserialize, Serialize}; +use starknet_api::block::{ + Block as starknet_api_block, + BlockHash, + BlockNumber, + BlockTimestamp, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + EventCommitment, + GlobalRoot, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; +#[cfg(doc)] +use starknet_api::transaction::TransactionOutput as starknet_api_transaction_output; +use starknet_api::transaction::{TransactionHash, TransactionOffsetInBlock}; +use starknet_types_core::felt::Felt; + +use crate::reader::objects::transaction::{ + L1ToL2Message, + Transaction, + TransactionReceipt, + TransactionType, +}; +use crate::reader::{ReaderClientError, ReaderClientResult}; + +/// A block as returned by the starknet gateway since V0.13.1. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct BlockPostV0_13_1 { + pub block_hash: BlockHash, + pub block_number: BlockNumber, + pub parent_block_hash: BlockHash, + #[serde(default)] + pub sequencer_address: SequencerContractAddress, + pub state_root: GlobalRoot, + pub status: BlockStatus, + #[serde(default)] + pub timestamp: BlockTimestamp, + pub transactions: Vec, + pub transaction_receipts: Vec, + // Default since old blocks don't include this field. + #[serde(default)] + pub starknet_version: String, + // Additions to the block structure in V0.13.1. + pub l1_da_mode: L1DataAvailabilityMode, + // Replacing the eth_l1_gas_price & strk_l1_gas_price fields with a single field. + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub transaction_commitment: TransactionCommitment, + pub event_commitment: EventCommitment, + // Additions to the block structure in V0.13.2. These additions do not appear in older blocks + // even if the Feeder Gateway is of this version. + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub state_diff_commitment: Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub receipt_commitment: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub state_diff_length: Option, +} + +impl BlockPostV0_13_1 { + pub fn to_starknet_api_block_and_version(self) -> ReaderClientResult { + let block_or_deprecated = Block::PostV0_13_1(self); + block_or_deprecated.to_starknet_api_block_and_version() + } +} + +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(untagged)] +pub enum Block { + PostV0_13_1(BlockPostV0_13_1), +} + +// TODO(yair): add tests for the new block. +impl Default for Block { + fn default() -> Self { + Block::PostV0_13_1(BlockPostV0_13_1::default()) + } +} + +/// Errors that might be encountered while converting the client representation of a [`Block`] to a +/// starknet_api [Block](`starknet_api_block`), specifically when converting a list of +/// [`TransactionReceipt`] to a list of starknet_api +/// [TransactionOutput](`starknet_api_transaction_output`). +#[derive(thiserror::Error, Debug)] +pub enum TransactionReceiptsError { + #[error( + "In block number {} there are {} transactions and {} transaction receipts.", + block_number, + num_of_txs, + num_of_receipts + )] + WrongNumberOfReceipts { block_number: BlockNumber, num_of_txs: usize, num_of_receipts: usize }, + #[error( + "In block number {}, transaction in index {:?} with hash {:?} and type {:?} has a receipt \ + with mismatched fields.", + block_number, + tx_index, + tx_hash, + tx_type + )] + MismatchFields { + block_number: BlockNumber, + tx_index: TransactionOffsetInBlock, + tx_hash: TransactionHash, + tx_type: TransactionType, + }, + #[error( + "In block number {}, transaction in index {:?} with hash {:?} has a receipt with \ + transaction hash {:?}.", + block_number, + tx_index, + tx_hash, + receipt_tx_hash + )] + MismatchTransactionHash { + block_number: BlockNumber, + tx_index: TransactionOffsetInBlock, + tx_hash: TransactionHash, + receipt_tx_hash: TransactionHash, + }, + #[error( + "In block number {}, transaction in index {:?} with hash {:?} has a receipt with \ + transaction index {:?}.", + block_number, + tx_index, + tx_hash, + receipt_tx_index + )] + MismatchTransactionIndex { + block_number: BlockNumber, + tx_index: TransactionOffsetInBlock, + tx_hash: TransactionHash, + receipt_tx_index: TransactionOffsetInBlock, + }, +} + +/// Converts the client representation of [`Block`] to a tuple of a starknet_api +/// [Block](`starknet_api_block`) and String representing the Starknet version corresponding to +/// that block. +impl Block { + pub fn transactions(&self) -> &[Transaction] { + match self { + Block::PostV0_13_1(block) => &block.transactions, + } + } + + pub fn transaction_receipts(&self) -> &[TransactionReceipt] { + match self { + Block::PostV0_13_1(block) => &block.transaction_receipts, + } + } + + pub fn block_number(&self) -> BlockNumber { + match self { + Block::PostV0_13_1(block) => block.block_number, + } + } + + pub fn block_hash(&self) -> BlockHash { + match self { + Block::PostV0_13_1(block) => block.block_hash, + } + } + + pub fn parent_block_hash(&self) -> BlockHash { + match self { + Block::PostV0_13_1(block) => block.parent_block_hash, + } + } + + pub fn l1_gas_price(&self) -> GasPricePerToken { + match self { + Block::PostV0_13_1(block) => block.l1_gas_price, + } + } + + pub fn l1_data_gas_price(&self) -> GasPricePerToken { + match self { + Block::PostV0_13_1(block) => block.l1_data_gas_price, + } + } + + pub fn state_root(&self) -> GlobalRoot { + match self { + Block::PostV0_13_1(block) => block.state_root, + } + } + + pub fn sequencer_address(&self) -> SequencerContractAddress { + match self { + Block::PostV0_13_1(block) => block.sequencer_address, + } + } + + pub fn timestamp(&self) -> BlockTimestamp { + match self { + Block::PostV0_13_1(block) => block.timestamp, + } + } + + pub fn starknet_version(&self) -> String { + match self { + Block::PostV0_13_1(block) => block.starknet_version.clone(), + } + } + + pub fn l1_da_mode(&self) -> L1DataAvailabilityMode { + match self { + Block::PostV0_13_1(block) => block.l1_da_mode, + } + } + + pub fn transaction_commitment(&self) -> TransactionCommitment { + match self { + Block::PostV0_13_1(block) => block.transaction_commitment, + } + } + + pub fn event_commitment(&self) -> EventCommitment { + match self { + Block::PostV0_13_1(block) => block.event_commitment, + } + } + + pub fn state_diff_commitment(&self) -> Option { + match self { + // TODO(shahak): in SN API, make StateDiffCommitment implement Copy and remove this + // clone. + Block::PostV0_13_1(block) => block.state_diff_commitment.clone(), + } + } + + pub fn receipt_commitment(&self) -> Option { + match self { + Block::PostV0_13_1(block) => block.receipt_commitment, + } + } + + pub fn state_diff_length(&self) -> Option { + match self { + Block::PostV0_13_1(block) => block.state_diff_length, + } + } + + // TODO(shahak): Rename to to_starknet_api_block. + pub fn to_starknet_api_block_and_version(self) -> ReaderClientResult { + // Check that the number of receipts is the same as the number of transactions. + let num_of_txs = self.transactions().len(); + let num_of_receipts = self.transaction_receipts().len(); + if num_of_txs != num_of_receipts { + return Err(ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::WrongNumberOfReceipts { + block_number: self.block_number(), + num_of_txs, + num_of_receipts, + }, + )); + } + + // TODO(shahak): Consider deducing this from the starknet_version field instead. + let is_post_v0_13_2 = self.receipt_commitment().is_some(); + let (transaction_commitment, event_commitment) = if is_post_v0_13_2 { + (Some(self.transaction_commitment()), Some(self.event_commitment())) + } else { + // In some older starknet versions, the transaction and event commitment are + // calculated with a deprecated formula. We prefer not storing those hashes rather than + // storing incorrect hashes. + (None, None) + }; + + let n_transactions = self.transactions().len(); + let n_events = + self.transaction_receipts().iter().fold(0, |acc, receipt| acc + receipt.events.len()); + + // Get the header. + let header = starknet_api::block::BlockHeader { + block_hash: self.block_hash(), + parent_hash: self.parent_block_hash(), + block_number: self.block_number(), + l1_gas_price: self.l1_gas_price(), + state_root: self.state_root(), + sequencer: self.sequencer_address(), + timestamp: self.timestamp(), + l1_data_gas_price: self.l1_data_gas_price(), + l1_da_mode: self.l1_da_mode(), + state_diff_commitment: self.state_diff_commitment(), + transaction_commitment, + event_commitment, + receipt_commitment: self.receipt_commitment(), + state_diff_length: self.state_diff_length(), + n_transactions, + n_events, + starknet_version: StarknetVersion(self.starknet_version()), + }; + + let (transactions, transaction_receipts) = self.get_body(); + + // Get the transaction outputs and execution statuses. + let mut transaction_outputs = vec![]; + let mut transaction_hashes = vec![]; + for (i, receipt) in transaction_receipts.into_iter().enumerate() { + let transaction = transactions.index(i); + + // Check that the transaction index that appears in the receipt is the same as the + // index of the transaction. + if i != receipt.transaction_index.0 { + return Err(ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchTransactionIndex { + block_number: header.block_number, + tx_index: TransactionOffsetInBlock(i), + tx_hash: transaction.transaction_hash(), + receipt_tx_index: receipt.transaction_index, + }, + )); + } + + // Check that the transaction hash that appears in the receipt is the same as in the + // transaction. + if transaction.transaction_hash() != receipt.transaction_hash { + return Err(ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchTransactionHash { + block_number: header.block_number, + tx_index: TransactionOffsetInBlock(i), + tx_hash: transaction.transaction_hash(), + receipt_tx_hash: receipt.transaction_hash, + }, + )); + } + + // Check that the receipt has the correct fields according to the transaction type. + if transaction.transaction_type() != TransactionType::L1Handler + && receipt.l1_to_l2_consumed_message != L1ToL2Message::default() + { + return Err(ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchFields { + block_number: header.block_number, + tx_index: TransactionOffsetInBlock(i), + tx_hash: transaction.transaction_hash(), + tx_type: transaction.transaction_type(), + }, + )); + } + + transaction_hashes.push(receipt.transaction_hash); + let tx_output = receipt.into_starknet_api_transaction_output(transaction); + transaction_outputs.push(tx_output); + } + + // Get the transactions. + // Note: This cannot happen before getting the transaction outputs since we need to borrow + // the block transactions inside the for loop for the transaction type (TransactionType is + // defined in starknet_client therefore starknet_api::Transaction cannot return it). + let transactions: Vec<_> = transactions + .into_iter() + .map(starknet_api::transaction::Transaction::try_from) + .collect::>()?; + + let body = starknet_api::block::BlockBody { + transactions, + transaction_outputs, + transaction_hashes, + }; + + Ok(starknet_api_block { header, body }) + } + + fn get_body(self) -> (Vec, Vec) { + match self { + Block::PostV0_13_1(block) => (block.transactions, block.transaction_receipts), + } + } +} + +#[derive( + Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default, +)] +pub enum BlockStatus { + #[serde(rename(deserialize = "ABORTED", serialize = "ABORTED"))] + Aborted, + #[serde(rename(deserialize = "ACCEPTED_ON_L1", serialize = "ACCEPTED_ON_L1"))] + AcceptedOnL1, + #[serde(rename(deserialize = "ACCEPTED_ON_L2", serialize = "ACCEPTED_ON_L2"))] + #[default] + AcceptedOnL2, + #[serde(rename(deserialize = "PENDING", serialize = "PENDING"))] + Pending, + #[serde(rename(deserialize = "REVERTED", serialize = "REVERTED"))] + Reverted, +} + +impl From for starknet_api::block::BlockStatus { + fn from(status: BlockStatus) -> Self { + match status { + BlockStatus::Aborted => starknet_api::block::BlockStatus::Rejected, + BlockStatus::AcceptedOnL1 => starknet_api::block::BlockStatus::AcceptedOnL1, + BlockStatus::AcceptedOnL2 => starknet_api::block::BlockStatus::AcceptedOnL2, + BlockStatus::Pending => starknet_api::block::BlockStatus::Pending, + BlockStatus::Reverted => starknet_api::block::BlockStatus::Rejected, + } + } +} + +/// A block signature and the input data used to create it. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(untagged)] +pub enum BlockSignatureData { + Deprecated { + block_number: BlockNumber, + signature: [Felt; 2], + signature_input: BlockSignatureMessage, + }, + V0_13_2 { + block_hash: BlockHash, + signature: [Felt; 2], + }, +} + +/// The input data used to create a block signature (Poseidon hash of this data). +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, +)] +pub struct BlockSignatureMessage { + pub block_hash: BlockHash, + // TODO(yair): Change to StateDiffHash. + pub state_diff_commitment: GlobalRoot, +} diff --git a/crates/starknet_client/src/reader/objects/block_test.rs b/crates/starknet_client/src/reader/objects/block_test.rs new file mode 100644 index 00000000000..9d4b58aa5af --- /dev/null +++ b/crates/starknet_client/src/reader/objects/block_test.rs @@ -0,0 +1,180 @@ +use assert_matches::assert_matches; +use indexmap::IndexMap; +use pretty_assertions::assert_eq; +use starknet_api::block::BlockHash; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkHash; +use starknet_api::state::StorageKey; +use starknet_api::transaction::{TransactionHash, TransactionOffsetInBlock}; +use starknet_api::{felt, patricia_key}; + +use super::{Block, GlobalRoot, TransactionReceiptsError}; +use crate::reader::objects::block::BlockPostV0_13_1; +use crate::reader::objects::state::{ + DeclaredClassHashEntry, + DeployedContract, + ReplacedClass, + StateDiff, + StateUpdate, + StorageEntry, +}; +use crate::reader::objects::transaction::TransactionReceipt; +use crate::reader::ReaderClientError; +use crate::test_utils::read_resource::read_resource_file; + +#[test] +fn load_block_succeeds() { + for block_path in [ + // TODO: add 0_13_2 block. + "reader/block_post_0_13_1.json", + "reader/old_block_post_0_13_1_no_sn_version.json", + "reader/old_block_post_0_13_1_no_sequencer.json", + ] { + serde_json::from_str::(&read_resource_file(block_path)).unwrap_or_else(|err| { + panic!("Failed loading block in path {block_path}. Error: {err}") + }); + } +} + +#[test] +fn load_block_state_update_succeeds() { + let expected_state_update = StateUpdate { + block_hash: BlockHash(felt!( + "0x3f65ef25e87a83d92f32f5e4869a33580f9db47ec980c1ff27bdb5151914de5" + )), + new_root: GlobalRoot(StarkHash::from_hex_unchecked( + "02ade8eea6eb6523d22a408a1f035bd351a9a5dce28926ca92d7abb490c0e74a", + )), + old_root: GlobalRoot(StarkHash::from_hex_unchecked( + "0465b219d93bcb2776aa3abb009423be3e2d04dba6453d7e027830740cd699a4", + )), + state_diff: StateDiff { + storage_diffs: IndexMap::from([( + ContractAddress(patricia_key!( + "0x13386f165f065115c1da38d755be261023c32f0134a03a8e66b6bb1e0016014" + )), + vec![ + StorageEntry { + key: StorageKey(patricia_key!( + "0x3b3a699bb6ef37ff4b9c4e14319c7d8e9c9bdd10ff402d1ebde18c62ae58381" + )), + value: felt!("0x61454dd6e5c83621e41b74c"), + }, + StorageEntry { + key: StorageKey(patricia_key!( + "0x1557182e4359a1f0c6301278e8f5b35a776ab58d39892581e357578fb287836" + )), + value: felt!("0x79dd8085e3e5a96ea43e7d"), + }, + ], + )]), + deployed_contracts: vec![DeployedContract { + address: ContractAddress(patricia_key!( + "0x3e10411edafd29dfe6d427d03e35cb261b7a5efeee61bf73909ada048c029b9" + )), + class_hash: ClassHash(felt!( + "0x071c3c99f5cf76fc19945d4b8b7d34c7c5528f22730d56192b50c6bbfd338a64" + )), + }], + declared_classes: vec![DeclaredClassHashEntry { + class_hash: ClassHash(felt!("0x10")), + compiled_class_hash: CompiledClassHash(felt!("0x1000")), + }], + old_declared_contracts: vec![ClassHash(felt!("0x100"))], + nonces: IndexMap::from([( + ContractAddress(patricia_key!( + "0x51c62af8919b31499b36bd1f1f702c8ef5a6309554427186c7bd456b862c115" + )), + Nonce(felt!("0x12")), + )]), + replaced_classes: vec![ReplacedClass { + address: ContractAddress(patricia_key!( + "0x56b0efe9d91fcda0f341af928404056c5220ee0ccc66be15d20611a172dbd52" + )), + class_hash: ClassHash(felt!( + "0x2248aff260e5837317641ff4f861495dd71e78b9dae98a31113e569b336bd26" + )), + }], + }, + }; + assert_eq!( + expected_state_update, + serde_json::from_str::(&read_resource_file("reader/block_state_update.json")) + .unwrap() + ) +} + +#[tokio::test] +async fn to_starknet_api_block_and_version() { + // TODO(yair): Add block.json for a 0.13.1 block. + let raw_block = read_resource_file("reader/block_post_0_13_1.json"); + let block: Block = serde_json::from_str(&raw_block).unwrap(); + let expected_num_of_tx_outputs = block.transactions().len(); + let starknet_api_block = block.to_starknet_api_block_and_version().unwrap(); + assert_eq!(expected_num_of_tx_outputs, starknet_api_block.body.transaction_outputs.len()); + // Check that for pre 0.13.2 blocks, we erase their hash since it's a deprecated formula. + assert!(starknet_api_block.header.event_commitment.is_none()); + assert!(starknet_api_block.header.transaction_commitment.is_none()); + + let mut err_block: BlockPostV0_13_1 = serde_json::from_str(&raw_block).unwrap(); + err_block.transaction_receipts.pop(); + let err = err_block.to_starknet_api_block_and_version().unwrap_err(); + assert_matches!( + err, + ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::WrongNumberOfReceipts { + block_number: _, + num_of_txs: _, + num_of_receipts: _, + } + ) + ); + + let mut err_block: BlockPostV0_13_1 = serde_json::from_str(&raw_block).unwrap(); + err_block.transaction_receipts[0].transaction_index = TransactionOffsetInBlock(1); + let err = err_block.to_starknet_api_block_and_version().unwrap_err(); + assert_matches!( + err, + ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchTransactionIndex { + block_number: _, + tx_index: _, + tx_hash: _, + receipt_tx_index: _, + } + ) + ); + + let mut err_block: BlockPostV0_13_1 = serde_json::from_str(&raw_block).unwrap(); + err_block.transaction_receipts[0].transaction_hash = TransactionHash(felt!("0x4")); + let err = err_block.to_starknet_api_block_and_version().unwrap_err(); + assert_matches!( + err, + ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchTransactionHash { + block_number: _, + tx_index: _, + tx_hash: _, + receipt_tx_hash: _, + } + ) + ); + + let mut err_block: BlockPostV0_13_1 = serde_json::from_str(&raw_block).unwrap(); + err_block.transaction_receipts[0] = TransactionReceipt { + transaction_hash: err_block.transactions[1].transaction_hash(), + ..err_block.transaction_receipts[0].clone() + }; + let err = err_block.to_starknet_api_block_and_version().unwrap_err(); + assert_matches!( + err, + ReaderClientError::TransactionReceiptsError( + TransactionReceiptsError::MismatchTransactionHash { + block_number: _, + tx_index: _, + tx_hash: _, + receipt_tx_hash: _, + } + ) + ); +} diff --git a/crates/starknet_client/src/reader/objects/mod.rs b/crates/starknet_client/src/reader/objects/mod.rs new file mode 100644 index 00000000000..1531036e80c --- /dev/null +++ b/crates/starknet_client/src/reader/objects/mod.rs @@ -0,0 +1,6 @@ +pub mod block; +pub mod pending_data; +pub mod state; +#[cfg(any(feature = "testing", test))] +pub mod test_utils; +pub mod transaction; diff --git a/crates/starknet_client/src/reader/objects/pending_data.rs b/crates/starknet_client/src/reader/objects/pending_data.rs new file mode 100644 index 00000000000..f611da26615 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/pending_data.rs @@ -0,0 +1,230 @@ +use serde::{Deserialize, Serialize}; +use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp, GasPrice, GasPricePerToken}; +use starknet_api::core::{ + EventCommitment, + GlobalRoot, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::data_availability::L1DataAvailabilityMode; + +use super::block::BlockStatus; +use super::transaction::{Transaction, TransactionReceipt}; +use crate::reader::StateDiff; + +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +pub struct PendingData { + pub block: PendingBlockOrDeprecated, + pub state_update: PendingStateUpdate, +} + +#[derive(Debug, Deserialize, Clone, Eq, PartialEq)] +#[serde(untagged)] +pub enum PendingBlockOrDeprecated { + Deprecated(DeprecatedPendingBlock), + Current(PendingBlock), +} + +impl Default for PendingBlockOrDeprecated { + fn default() -> Self { + PendingBlockOrDeprecated::Deprecated(DeprecatedPendingBlock::default()) + } +} + +impl PendingBlockOrDeprecated { + pub fn block_hash(&self) -> Option { + match self { + PendingBlockOrDeprecated::Deprecated(block) => { + block.accepted_on_l2_extra_data.as_ref().map(|data| data.block_hash) + } + PendingBlockOrDeprecated::Current(block) => { + block.accepted_on_l2_extra_data.as_ref().map(|data| data.block_hash) + } + } + } + pub fn parent_block_hash(&self) -> BlockHash { + match self { + PendingBlockOrDeprecated::Deprecated(block) => block.parent_block_hash, + PendingBlockOrDeprecated::Current(block) => block.parent_block_hash, + } + } + #[cfg(any(feature = "testing", test))] + pub fn parent_block_hash_mutable(&mut self) -> &mut BlockHash { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.parent_block_hash, + PendingBlockOrDeprecated::Current(block) => &mut block.parent_block_hash, + } + } + + pub fn sequencer_address(&self) -> SequencerContractAddress { + match self { + PendingBlockOrDeprecated::Deprecated(block) => block.sequencer_address, + PendingBlockOrDeprecated::Current(block) => block.sequencer_address, + } + } + #[cfg(any(feature = "testing", test))] + pub fn sequencer_address_mutable(&mut self) -> &mut SequencerContractAddress { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.sequencer_address, + PendingBlockOrDeprecated::Current(block) => &mut block.sequencer_address, + } + } + pub fn timestamp(&self) -> BlockTimestamp { + match self { + PendingBlockOrDeprecated::Deprecated(block) => block.timestamp, + PendingBlockOrDeprecated::Current(block) => block.timestamp, + } + } + #[cfg(any(feature = "testing", test))] + pub fn timestamp_mutable(&mut self) -> &mut BlockTimestamp { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.timestamp, + PendingBlockOrDeprecated::Current(block) => &mut block.timestamp, + } + } + pub fn transactions(&self) -> &[Transaction] { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &block.transactions, + PendingBlockOrDeprecated::Current(block) => &block.transactions, + } + } + pub fn transactions_mutable(&mut self) -> &mut Vec { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.transactions, + PendingBlockOrDeprecated::Current(block) => &mut block.transactions, + } + } + pub fn transaction_receipts(&self) -> &[TransactionReceipt] { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &block.transaction_receipts, + PendingBlockOrDeprecated::Current(block) => &block.transaction_receipts, + } + } + pub fn transaction_receipts_mutable(&mut self) -> &mut Vec { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.transaction_receipts, + PendingBlockOrDeprecated::Current(block) => &mut block.transaction_receipts, + } + } + pub fn transactions_and_receipts_mutable( + &mut self, + ) -> (&mut Vec, &mut Vec) { + match self { + PendingBlockOrDeprecated::Deprecated(block) => { + (&mut block.transactions, &mut block.transaction_receipts) + } + PendingBlockOrDeprecated::Current(block) => { + (&mut block.transactions, &mut block.transaction_receipts) + } + } + } + pub fn starknet_version(&self) -> String { + match self { + PendingBlockOrDeprecated::Deprecated(block) => block.starknet_version.clone(), + PendingBlockOrDeprecated::Current(block) => block.starknet_version.clone(), + } + } + #[cfg(any(feature = "testing", test))] + pub fn starknet_version_mutable(&mut self) -> &mut String { + match self { + PendingBlockOrDeprecated::Deprecated(block) => &mut block.starknet_version, + PendingBlockOrDeprecated::Current(block) => &mut block.starknet_version, + } + } + pub fn l1_gas_price(&self) -> GasPricePerToken { + match self { + PendingBlockOrDeprecated::Deprecated(block) => GasPricePerToken { + price_in_wei: block.eth_l1_gas_price, + price_in_fri: block.strk_l1_gas_price, + }, + PendingBlockOrDeprecated::Current(block) => block.l1_gas_price, + } + } + #[cfg(any(feature = "testing", test))] + pub fn set_l1_gas_price(&mut self, val: &GasPricePerToken) { + match self { + PendingBlockOrDeprecated::Deprecated(block) => { + block.eth_l1_gas_price = val.price_in_wei; + block.strk_l1_gas_price = val.price_in_fri; + } + PendingBlockOrDeprecated::Current(block) => block.l1_gas_price = *val, + } + } + pub fn l1_data_gas_price(&self) -> GasPricePerToken { + match self { + // In older versions, data gas price was 0. + PendingBlockOrDeprecated::Deprecated(_) => GasPricePerToken::default(), + PendingBlockOrDeprecated::Current(block) => block.l1_data_gas_price, + } + } + pub fn l1_da_mode(&self) -> L1DataAvailabilityMode { + match self { + // In older versions, all blocks were using calldata. + PendingBlockOrDeprecated::Deprecated(_) => L1DataAvailabilityMode::Calldata, + PendingBlockOrDeprecated::Current(block) => block.l1_da_mode, + } + } +} + +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeprecatedPendingBlock { + #[serde(flatten)] + pub accepted_on_l2_extra_data: Option, + pub parent_block_hash: BlockHash, + pub status: BlockStatus, + // In older versions, eth_l1_gas_price was named gas_price and there was no strk_l1_gas_price. + #[serde(alias = "gas_price")] + pub eth_l1_gas_price: GasPrice, + #[serde(default)] + pub strk_l1_gas_price: GasPrice, + pub transactions: Vec, + pub timestamp: BlockTimestamp, + pub sequencer_address: SequencerContractAddress, + pub transaction_receipts: Vec, + pub starknet_version: String, +} + +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct PendingBlock { + #[serde(flatten)] + pub accepted_on_l2_extra_data: Option, + pub parent_block_hash: BlockHash, + pub status: BlockStatus, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub transactions: Vec, + pub timestamp: BlockTimestamp, + pub sequencer_address: SequencerContractAddress, + pub transaction_receipts: Vec, + pub starknet_version: String, + pub l1_da_mode: L1DataAvailabilityMode, + + // We do not care about commitments in pending blocks. + #[serde(default)] + pub transaction_commitment: Option, + #[serde(default)] + pub event_commitment: Option, + #[serde(default)] + pub receipt_commitment: Option, + #[serde(default)] + pub state_diff_commitment: Option, + #[serde(default)] + pub state_diff_length: Option, +} + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct PendingStateUpdate { + pub old_root: GlobalRoot, + pub state_diff: StateDiff, +} + +#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize)] +pub struct AcceptedOnL2ExtraData { + pub block_hash: BlockHash, + pub block_number: BlockNumber, + pub state_root: GlobalRoot, +} diff --git a/crates/starknet_client/src/reader/objects/state.rs b/crates/starknet_client/src/reader/objects/state.rs new file mode 100644 index 00000000000..c20656d83c4 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/state.rs @@ -0,0 +1,73 @@ +use std::collections::HashMap; + +use indexmap::IndexMap; +pub use papyrus_common::state::{ + DeclaredClassHashEntry, + DeployedContract, + ReplacedClass, + StorageEntry, +}; +use serde::{Deserialize, Serialize}; +use starknet_api::block::BlockHash; +use starknet_api::core::{ClassHash, ContractAddress, GlobalRoot, Nonce}; +use starknet_api::state::{EntryPoint, EntryPointType}; +use starknet_types_core::felt::Felt; + +/// A state update derived from a single block as returned by the starknet gateway. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct StateUpdate { + pub block_hash: BlockHash, + pub new_root: GlobalRoot, + pub old_root: GlobalRoot, + pub state_diff: StateDiff, +} + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct StateDiff { + // IndexMap is serialized as a mapping in json, keeps ordering and is efficiently iterable. + pub storage_diffs: IndexMap>, + pub deployed_contracts: Vec, + pub declared_classes: Vec, + pub old_declared_contracts: Vec, + pub nonces: IndexMap, + pub replaced_classes: Vec, +} + +impl StateDiff { + // Returns the declared class hashes in the following order: + // [declared classes, deprecated declared class, class hashes of deployed contracts]. + pub fn class_hashes(&self) -> Vec { + let mut declared_class_hashes: Vec = self + .declared_classes + .iter() + .map(|DeclaredClassHashEntry { class_hash, compiled_class_hash: _ }| *class_hash) + .collect(); + declared_class_hashes.append(&mut self.old_declared_contracts.clone()); + let mut deployed_class_hashes = self + .deployed_contracts + .iter() + .map(|contract| contract.class_hash) + .filter(|hash| !declared_class_hashes.contains(hash)) + .collect(); + declared_class_hashes.append(&mut deployed_class_hashes); + declared_class_hashes + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + pub sierra_program: Vec, + pub entry_points_by_type: HashMap>, + pub contract_class_version: String, + pub abi: String, +} + +impl From for starknet_api::state::ContractClass { + fn from(class: ContractClass) -> Self { + Self { + sierra_program: class.sierra_program, + entry_points_by_type: class.entry_points_by_type, + abi: class.abi, + } + } +} diff --git a/crates/starknet_client/src/reader/objects/test_utils.rs b/crates/starknet_client/src/reader/objects/test_utils.rs new file mode 100644 index 00000000000..facf3e50328 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/test_utils.rs @@ -0,0 +1,178 @@ +use std::collections::HashMap; + +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, +}; +use starknet_api::hash::StarkHash; +use starknet_api::state::{EntryPoint, EntryPointType}; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + Event, + Fee, + GasVector, + L1ToL2Payload, + L2ToL1Payload, + PaymasterData, + ResourceBoundsMapping, + Tip, + TransactionHash, + TransactionOffsetInBlock, + TransactionSignature, + TransactionVersion, +}; +use starknet_types_core::felt::Felt; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, GetTestInstance}; + +use crate::reader::objects::state::ContractClass; +use crate::reader::objects::transaction::{ + Builtin, + DeployTransaction, + ExecutionResources, + IntermediateDeclareTransaction, + IntermediateDeployAccountTransaction, + IntermediateInvokeTransaction, + L1HandlerTransaction, + L1ToL2Message, + L1ToL2Nonce, + L2ToL1Message, + ReservedDataAvailabilityMode, + Transaction, + TransactionExecutionStatus, + TransactionReceipt, +}; + +auto_impl_get_test_instance! { + pub enum Transaction { + Declare(IntermediateDeclareTransaction) = 0, + DeployAccount(IntermediateDeployAccountTransaction) = 1, + Deploy(DeployTransaction) = 2, + Invoke(IntermediateInvokeTransaction) = 3, + L1Handler(L1HandlerTransaction) = 4, + } + pub enum ReservedDataAvailabilityMode { + Reserved = 0, + } + pub struct IntermediateDeclareTransaction { + pub resource_bounds: Option, + pub tip: Option, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: Option, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: Option, + pub fee_data_availability_mode: Option, + pub paymaster_data: Option, + pub account_deployment_data: Option, + pub max_fee: Option, + pub version: TransactionVersion, + pub transaction_hash: TransactionHash, + } + pub struct IntermediateDeployAccountTransaction { + pub resource_bounds: Option, + pub tip: Option, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub nonce_data_availability_mode: Option, + pub fee_data_availability_mode: Option, + pub paymaster_data: Option, + pub sender_address: ContractAddress, + pub max_fee: Option, + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, + } + pub struct DeployTransaction { + pub contract_address: ContractAddress, + pub contract_address_salt: ContractAddressSalt, + pub class_hash: ClassHash, + pub constructor_calldata: Calldata, + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, + } + pub struct IntermediateInvokeTransaction { + pub resource_bounds: Option, + pub tip: Option, + pub calldata: Calldata, + pub sender_address: ContractAddress, + pub entry_point_selector: Option, + pub nonce: Option, + pub max_fee: Option, + pub signature: TransactionSignature, + pub nonce_data_availability_mode: Option, + pub fee_data_availability_mode: Option, + pub paymaster_data: Option, + pub account_deployment_data: Option, + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, + } + pub struct L1HandlerTransaction { + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, + pub nonce: Nonce, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub struct ContractClass { + pub sierra_program: Vec, + pub entry_points_by_type: HashMap>, + pub contract_class_version: String, + pub abi: String, + } + pub enum TransactionExecutionStatus { + Succeeded = 0, + Reverted = 1, + } + pub struct TransactionReceipt { + pub transaction_index: TransactionOffsetInBlock, + pub transaction_hash: TransactionHash, + pub l1_to_l2_consumed_message: L1ToL2Message, + pub l2_to_l1_messages: Vec, + pub events: Vec, + pub execution_resources: ExecutionResources, + pub actual_fee: Fee, + pub execution_status: TransactionExecutionStatus, + pub revert_error: Option, + } + pub struct L1ToL2Message { + pub from_address: EthAddress, + pub to_address: ContractAddress, + pub selector: EntryPointSelector, + pub payload: L1ToL2Payload, + pub nonce: L1ToL2Nonce, + } + pub struct L1ToL2Nonce(pub StarkHash); + pub struct L2ToL1Message { + pub from_address: ContractAddress, + pub to_address: EthAddress, + pub payload: L2ToL1Payload, + } + pub struct ExecutionResources { + pub n_steps: u64, + pub builtin_instance_counter: HashMap, + pub n_memory_holes: u64, + pub data_availability: Option, + pub total_gas_consumed: Option, + } + pub enum Builtin { + RangeCheck = 0, + Pedersen = 1, + Poseidon = 2, + EcOp = 3, + Ecdsa = 4, + Bitwise = 5, + Keccak = 6, + Output = 7, + SegmentArena = 8, + } +} diff --git a/crates/starknet_client/src/reader/objects/transaction.rs b/crates/starknet_client/src/reader/objects/transaction.rs new file mode 100644 index 00000000000..e1cf6ee17c0 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/transaction.rs @@ -0,0 +1,888 @@ +#[cfg(test)] +#[path = "transaction_test.rs"] +mod transaction_test; + +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + Nonce, +}; +use starknet_api::hash::StarkHash; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + DeclareTransactionOutput, + DeployAccountTransactionOutput, + DeployTransactionOutput, + Event, + Fee, + GasVector, + InvokeTransactionOutput, + L1HandlerTransactionOutput, + L1ToL2Payload, + L2ToL1Payload, + MessageToL1, + PaymasterData, + ResourceBoundsMapping, + RevertedTransactionExecutionStatus as SnApiRevertedTransactionExecutionStatus, + Tip, + TransactionExecutionStatus as SnApiTransactionExecutionStatus, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput, + TransactionSignature, + TransactionVersion, +}; +use strum_macros::EnumIter; +use tracing::error; + +use crate::reader::ReaderClientError; + +// TODO(dan): consider extracting common fields out (version, hash, type). +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum Transaction { + #[serde(rename = "DECLARE")] + Declare(IntermediateDeclareTransaction), + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount(IntermediateDeployAccountTransaction), + #[serde(rename = "DEPLOY")] + Deploy(DeployTransaction), + #[serde(rename = "INVOKE_FUNCTION")] + Invoke(IntermediateInvokeTransaction), + #[serde(rename = "L1_HANDLER")] + L1Handler(L1HandlerTransaction), +} + +impl TryFrom for starknet_api::transaction::Transaction { + type Error = ReaderClientError; + fn try_from(tx: Transaction) -> Result { + match tx { + Transaction::Declare(declare_tx) => { + Ok(starknet_api::transaction::Transaction::Declare(declare_tx.try_into()?)) + } + Transaction::Deploy(deploy_tx) => { + Ok(starknet_api::transaction::Transaction::Deploy(deploy_tx.into())) + } + Transaction::DeployAccount(deploy_acc_tx) => { + Ok(starknet_api::transaction::Transaction::DeployAccount(deploy_acc_tx.try_into()?)) + } + Transaction::Invoke(invoke_tx) => { + Ok(starknet_api::transaction::Transaction::Invoke(invoke_tx.try_into()?)) + } + Transaction::L1Handler(l1_handler_tx) => { + Ok(starknet_api::transaction::Transaction::L1Handler(l1_handler_tx.into())) + } + } + } +} + +impl Transaction { + pub fn transaction_hash(&self) -> TransactionHash { + match self { + Transaction::Declare(tx) => tx.transaction_hash, + Transaction::Deploy(tx) => tx.transaction_hash, + Transaction::DeployAccount(tx) => tx.transaction_hash, + Transaction::Invoke(tx) => tx.transaction_hash, + Transaction::L1Handler(tx) => tx.transaction_hash, + } + } + + pub fn transaction_hash_mut(&mut self) -> &mut TransactionHash { + match self { + Transaction::Declare(tx) => &mut tx.transaction_hash, + Transaction::Deploy(tx) => &mut tx.transaction_hash, + Transaction::DeployAccount(tx) => &mut tx.transaction_hash, + Transaction::Invoke(tx) => &mut tx.transaction_hash, + Transaction::L1Handler(tx) => &mut tx.transaction_hash, + } + } + + pub fn transaction_type(&self) -> TransactionType { + match self { + Transaction::Declare(_) => TransactionType::Declare, + Transaction::Deploy(_) => TransactionType::Deploy, + Transaction::DeployAccount(_) => TransactionType::DeployAccount, + Transaction::Invoke(_) => TransactionType::InvokeFunction, + Transaction::L1Handler(_) => TransactionType::L1Handler, + } + } + + pub fn contract_address(&self) -> Option { + match self { + Transaction::Deploy(tx) => Some(tx.contract_address), + Transaction::DeployAccount(tx) => Some(tx.sender_address), + _ => None, + } + } + + pub fn transaction_version(&self) -> TransactionVersion { + match self { + Transaction::Declare(tx) => tx.version, + Transaction::Deploy(tx) => tx.version, + Transaction::DeployAccount(tx) => tx.version, + Transaction::Invoke(tx) => tx.version, + Transaction::L1Handler(tx) => tx.version, + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +#[serde(deny_unknown_fields)] +pub struct L1HandlerTransaction { + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, + #[serde(default)] + pub nonce: Nonce, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, +} + +impl From for starknet_api::transaction::L1HandlerTransaction { + fn from(l1_handler_tx: L1HandlerTransaction) -> Self { + starknet_api::transaction::L1HandlerTransaction { + version: l1_handler_tx.version, + nonce: l1_handler_tx.nonce, + contract_address: l1_handler_tx.contract_address, + entry_point_selector: l1_handler_tx.entry_point_selector, + calldata: l1_handler_tx.calldata, + } + } +} + +// This enum is required since the FGW sends this field with value 0 as a reserved value. Once the +// feature will be activated this enum should be removed from here and taken from starknet-api. +#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, Eq, PartialEq)] +#[repr(u8)] +pub enum ReservedDataAvailabilityMode { + Reserved = 0, +} + +impl From for starknet_api::data_availability::DataAvailabilityMode { + fn from(_: ReservedDataAvailabilityMode) -> Self { + starknet_api::data_availability::DataAvailabilityMode::L1 + } +} + +// TODO(shahak, 01/11/2023): Add serde tests for v3 transactions. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct IntermediateDeclareTransaction { + #[serde(skip_serializing_if = "Option::is_none")] + pub resource_bounds: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tip: Option, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + #[serde(skip_serializing_if = "Option::is_none")] + pub compiled_class_hash: Option, + pub sender_address: ContractAddress, + #[serde(skip_serializing_if = "Option::is_none")] + pub nonce_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub paymaster_data: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub account_deployment_data: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub max_fee: Option, + pub version: TransactionVersion, + pub transaction_hash: TransactionHash, +} + +// TODO(shahak, 01/11/2023): Add conversion tests. +impl TryFrom for starknet_api::transaction::DeclareTransaction { + type Error = ReaderClientError; + + // TODO: Consider using match instead. + fn try_from(declare_tx: IntermediateDeclareTransaction) -> Result { + if declare_tx.version == TransactionVersion::ZERO { + return Ok(Self::V0(declare_tx.try_into()?)); + } + if declare_tx.version == TransactionVersion::ONE { + return Ok(Self::V1(declare_tx.try_into()?)); + } + if declare_tx.version == TransactionVersion::TWO { + return Ok(Self::V2(declare_tx.try_into()?)); + } + if declare_tx.version == TransactionVersion::THREE { + return Ok(Self::V3(declare_tx.try_into()?)); + } + Err(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: format!("Declare version {:?} is not supported.", declare_tx.version), + }) + } +} + +impl TryFrom for starknet_api::transaction::DeclareTransactionV0V1 { + type Error = ReaderClientError; + + fn try_from(declare_tx: IntermediateDeclareTransaction) -> Result { + Ok(Self { + max_fee: declare_tx.max_fee.ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V1 must contain max_fee field.".to_string(), + })?, + signature: declare_tx.signature, + nonce: declare_tx.nonce, + class_hash: declare_tx.class_hash, + sender_address: declare_tx.sender_address, + }) + } +} + +impl TryFrom for starknet_api::transaction::DeclareTransactionV2 { + type Error = ReaderClientError; + + fn try_from(declare_tx: IntermediateDeclareTransaction) -> Result { + Ok(Self { + max_fee: declare_tx.max_fee.ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V2 must contain max_fee field.".to_string(), + })?, + signature: declare_tx.signature, + nonce: declare_tx.nonce, + class_hash: declare_tx.class_hash, + compiled_class_hash: declare_tx.compiled_class_hash.ok_or( + ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V2 must contain compiled_class_hash field.".to_string(), + }, + )?, + sender_address: declare_tx.sender_address, + }) + } +} + +impl TryFrom for starknet_api::transaction::DeclareTransactionV3 { + type Error = ReaderClientError; + + fn try_from(declare_tx: IntermediateDeclareTransaction) -> Result { + Ok(Self { + resource_bounds: declare_tx.resource_bounds.ok_or( + ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain resource_bounds field.".to_string(), + }, + )?, + tip: declare_tx.tip.ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain tip field.".to_string(), + })?, + signature: declare_tx.signature, + nonce: declare_tx.nonce, + class_hash: declare_tx.class_hash, + compiled_class_hash: declare_tx.compiled_class_hash.ok_or( + ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain compiled_class_hash field.".to_string(), + }, + )?, + sender_address: declare_tx.sender_address, + nonce_data_availability_mode: declare_tx + .nonce_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain nonce_data_availability_mode field.".to_string(), + })? + .into(), + fee_data_availability_mode: declare_tx + .fee_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain fee_data_availability_mode field.".to_string(), + })? + .into(), + paymaster_data: declare_tx.paymaster_data.ok_or(ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain paymaster_data field.".to_string(), + })?, + account_deployment_data: declare_tx.account_deployment_data.ok_or( + ReaderClientError::BadTransaction { + tx_hash: declare_tx.transaction_hash, + msg: "Declare V3 must contain account_deployment_data field.".to_string(), + }, + )?, + }) + } +} + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeployTransaction { + pub contract_address: ContractAddress, + pub contract_address_salt: ContractAddressSalt, + pub class_hash: ClassHash, + pub constructor_calldata: Calldata, + pub transaction_hash: TransactionHash, + #[serde(default)] + pub version: TransactionVersion, +} + +impl From for starknet_api::transaction::DeployTransaction { + fn from(deploy_tx: DeployTransaction) -> Self { + starknet_api::transaction::DeployTransaction { + version: deploy_tx.version, + constructor_calldata: deploy_tx.constructor_calldata, + class_hash: deploy_tx.class_hash, + contract_address_salt: deploy_tx.contract_address_salt, + } + } +} + +// TODO(shahak, 01/11/2023): Add serde tests for v3 transactions. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct IntermediateDeployAccountTransaction { + #[serde(skip_serializing_if = "Option::is_none")] + pub resource_bounds: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tip: Option, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + #[serde(skip_serializing_if = "Option::is_none")] + pub nonce_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub paymaster_data: Option, + // In early versions of starknet, the `sender_address` field was originally named + // `contract_address`. + #[serde(alias = "contract_address")] + pub sender_address: ContractAddress, + #[serde(skip_serializing_if = "Option::is_none")] + pub max_fee: Option, + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, +} + +// TODO(shahak, 01/11/2023): Add conversion tests. +impl TryFrom + for starknet_api::transaction::DeployAccountTransaction +{ + type Error = ReaderClientError; + + fn try_from( + deploy_account_tx: IntermediateDeployAccountTransaction, + ) -> Result { + if deploy_account_tx.version == TransactionVersion::ONE { + return Ok(Self::V1(deploy_account_tx.try_into()?)); + } + if deploy_account_tx.version == TransactionVersion::THREE { + return Ok(Self::V3(deploy_account_tx.try_into()?)); + } + Err(ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: format!("DeployAccount version {:?} is not supported.", deploy_account_tx.version), + }) + } +} + +impl TryFrom + for starknet_api::transaction::DeployAccountTransactionV1 +{ + type Error = ReaderClientError; + + fn try_from( + deploy_account_tx: IntermediateDeployAccountTransaction, + ) -> Result { + Ok(Self { + constructor_calldata: deploy_account_tx.constructor_calldata, + class_hash: deploy_account_tx.class_hash, + contract_address_salt: deploy_account_tx.contract_address_salt, + max_fee: deploy_account_tx.max_fee.ok_or(ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V1 must contain max_fee field.".to_string(), + })?, + signature: deploy_account_tx.signature, + nonce: deploy_account_tx.nonce, + }) + } +} + +impl TryFrom + for starknet_api::transaction::DeployAccountTransactionV3 +{ + type Error = ReaderClientError; + + fn try_from( + deploy_account_tx: IntermediateDeployAccountTransaction, + ) -> Result { + Ok(Self { + resource_bounds: deploy_account_tx.resource_bounds.ok_or( + ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V3 must contain resource_bounds field.".to_string(), + }, + )?, + tip: deploy_account_tx.tip.ok_or(ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V3 must contain tip field.".to_string(), + })?, + signature: deploy_account_tx.signature, + nonce: deploy_account_tx.nonce, + class_hash: deploy_account_tx.class_hash, + contract_address_salt: deploy_account_tx.contract_address_salt, + constructor_calldata: deploy_account_tx.constructor_calldata, + nonce_data_availability_mode: deploy_account_tx + .nonce_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V3 must contain nonce_data_availability_mode field." + .to_string(), + })? + .into(), + fee_data_availability_mode: deploy_account_tx + .fee_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V3 must contain fee_data_availability_mode field." + .to_string(), + })? + .into(), + paymaster_data: deploy_account_tx.paymaster_data.ok_or( + ReaderClientError::BadTransaction { + tx_hash: deploy_account_tx.transaction_hash, + msg: "DeployAccount V3 must contain paymaster_data field.".to_string(), + }, + )?, + }) + } +} + +// TODO(shahak, 01/11/2023): Add serde tests for v3 transactions. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct IntermediateInvokeTransaction { + #[serde(skip_serializing_if = "Option::is_none")] + pub resource_bounds: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tip: Option, + pub calldata: Calldata, + // In early versions of starknet, the `sender_address` field was originally named + // `contract_address`. + #[serde(alias = "contract_address")] + pub sender_address: ContractAddress, + #[serde(skip_serializing_if = "Option::is_none")] + pub entry_point_selector: Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub nonce: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub max_fee: Option, + pub signature: TransactionSignature, + #[serde(skip_serializing_if = "Option::is_none")] + pub nonce_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub fee_data_availability_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub paymaster_data: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub account_deployment_data: Option, + pub transaction_hash: TransactionHash, + pub version: TransactionVersion, +} + +// TODO(shahak, 01/11/2023): Add conversion tests. +impl TryFrom for starknet_api::transaction::InvokeTransaction { + type Error = ReaderClientError; + + fn try_from(invoke_tx: IntermediateInvokeTransaction) -> Result { + if invoke_tx.version == TransactionVersion::ZERO { + return Ok(Self::V0(invoke_tx.try_into()?)); + } + if invoke_tx.version == TransactionVersion::ONE { + return Ok(Self::V1(invoke_tx.try_into()?)); + } + if invoke_tx.version == TransactionVersion::THREE { + return Ok(Self::V3(invoke_tx.try_into()?)); + } + Err(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: format!("Invoke version {:?} is not supported.", invoke_tx.version), + }) + } +} + +impl TryFrom for starknet_api::transaction::InvokeTransactionV0 { + type Error = ReaderClientError; + + fn try_from(invoke_tx: IntermediateInvokeTransaction) -> Result { + Ok(Self { + max_fee: invoke_tx.max_fee.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V0 must contain max_fee field.".to_string(), + })?, + signature: invoke_tx.signature, + contract_address: invoke_tx.sender_address, + entry_point_selector: invoke_tx.entry_point_selector.ok_or( + ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V0 must contain entry_point_selector field.".to_string(), + }, + )?, + calldata: invoke_tx.calldata, + }) + } +} + +impl TryFrom for starknet_api::transaction::InvokeTransactionV1 { + type Error = ReaderClientError; + + fn try_from(invoke_tx: IntermediateInvokeTransaction) -> Result { + // TODO(yair): Consider asserting that entry_point_selector is None. + Ok(Self { + max_fee: invoke_tx.max_fee.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V1 must contain max_fee field.".to_string(), + })?, + signature: invoke_tx.signature, + nonce: invoke_tx.nonce.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V1 must contain nonce field.".to_string(), + })?, + sender_address: invoke_tx.sender_address, + calldata: invoke_tx.calldata, + }) + } +} + +impl TryFrom for starknet_api::transaction::InvokeTransactionV3 { + type Error = ReaderClientError; + + fn try_from(invoke_tx: IntermediateInvokeTransaction) -> Result { + // TODO(yair): Consider asserting that entry_point_selector is None. + Ok(Self { + resource_bounds: invoke_tx.resource_bounds.ok_or( + ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain resource_bounds field.".to_string(), + }, + )?, + tip: invoke_tx.tip.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain tip field.".to_string(), + })?, + signature: invoke_tx.signature, + nonce: invoke_tx.nonce.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain nonce field.".to_string(), + })?, + sender_address: invoke_tx.sender_address, + calldata: invoke_tx.calldata, + nonce_data_availability_mode: invoke_tx + .nonce_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain nonce_data_availability_mode field.".to_string(), + })? + .into(), + fee_data_availability_mode: invoke_tx + .fee_data_availability_mode + .ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain fee_data_availability_mode field.".to_string(), + })? + .into(), + paymaster_data: invoke_tx.paymaster_data.ok_or(ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain paymaster_data field.".to_string(), + })?, + account_deployment_data: invoke_tx.account_deployment_data.ok_or( + ReaderClientError::BadTransaction { + tx_hash: invoke_tx.transaction_hash, + msg: "Invoke V3 must contain account_deployment_data field.".to_string(), + }, + )?, + }) + } +} + +/// The execution resources used by a transaction. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct ExecutionResources { + // Note: in starknet_api this field is named `steps` + pub n_steps: u64, + pub builtin_instance_counter: HashMap, + // Note: in starknet_api this field is named `memory_holes` + pub n_memory_holes: u64, + // This field is missing in blocks created before v0.13.1, even if the feeder gateway is of + // that version + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub data_availability: Option, + // This field is missing in blocks created before v0.13.2, even if the feeder gateway is of + // that version + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub total_gas_consumed: Option, +} + +// Note: the serialization is different from the one in starknet_api. +#[derive(Hash, Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub enum Builtin { + #[serde(rename = "range_check_builtin")] + RangeCheck, + #[serde(rename = "pedersen_builtin")] + Pedersen, + #[serde(rename = "poseidon_builtin")] + Poseidon, + #[serde(rename = "ec_op_builtin")] + EcOp, + #[serde(rename = "ecdsa_builtin")] + Ecdsa, + #[serde(rename = "bitwise_builtin")] + Bitwise, + #[serde(rename = "keccak_builtin")] + Keccak, + // Note: in starknet_api this variant doesn't exist. + #[serde(rename = "output_builtin")] + Output, + #[serde(rename = "segment_arena_builtin")] + SegmentArena, + #[serde(rename = "add_mod_builtin")] + AddMod, + #[serde(rename = "mul_mod_builtin")] + MulMod, + #[serde(rename = "range_check96_builtin")] + RangeCheck96, +} + +impl From for starknet_api::transaction::ExecutionResources { + fn from(execution_resources: ExecutionResources) -> Self { + let da_gas_consumed = execution_resources.data_availability.unwrap_or_default(); + Self { + steps: execution_resources.n_steps, + builtin_instance_counter: execution_resources + .builtin_instance_counter + .into_iter() + .filter_map(|(builtin, count)| match builtin { + Builtin::RangeCheck => { + Some((starknet_api::transaction::Builtin::RangeCheck, count)) + } + Builtin::Pedersen => { + Some((starknet_api::transaction::Builtin::Pedersen, count)) + } + Builtin::Poseidon => { + Some((starknet_api::transaction::Builtin::Poseidon, count)) + } + Builtin::EcOp => Some((starknet_api::transaction::Builtin::EcOp, count)), + Builtin::Ecdsa => Some((starknet_api::transaction::Builtin::Ecdsa, count)), + Builtin::Bitwise => Some((starknet_api::transaction::Builtin::Bitwise, count)), + Builtin::Keccak => Some((starknet_api::transaction::Builtin::Keccak, count)), + // output builtin should be ignored. + Builtin::Output => None, + Builtin::SegmentArena => { + Some((starknet_api::transaction::Builtin::SegmentArena, count)) + } + Builtin::AddMod => Some((starknet_api::transaction::Builtin::AddMod, count)), + Builtin::MulMod => Some((starknet_api::transaction::Builtin::MulMod, count)), + Builtin::RangeCheck96 => { + Some((starknet_api::transaction::Builtin::RangeCheck96, count)) + } + }) + .collect(), + memory_holes: execution_resources.n_memory_holes, + gas_consumed: match execution_resources.total_gas_consumed { + Some(total_gas_consumed) => total_gas_consumed, + None => GasVector { + // It's hardcoded that this field is 0 for pre-v0.13.2 blocks (this field is + // only used in calculating the receipt hash) + l1_gas: 0, + l1_data_gas: da_gas_consumed.l1_data_gas, + }, + }, + da_gas_consumed, + } + } +} + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct TransactionReceipt { + pub transaction_index: TransactionOffsetInBlock, + pub transaction_hash: TransactionHash, + #[serde(default)] + pub l1_to_l2_consumed_message: L1ToL2Message, + pub l2_to_l1_messages: Vec, + pub events: Vec, + #[serde(default)] + pub execution_resources: ExecutionResources, + pub actual_fee: Fee, + // TODO: Check if we can remove the serde(default). + #[serde(default)] + pub execution_status: TransactionExecutionStatus, + // Note that in starknet_api this field is named `revert_reason`. + // Assumption: if the transaction execution status is Succeeded, then revert_error is None, and + // if the transaction execution status is Reverted, then revert_error is Some. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub revert_error: Option, +} + +/// Transaction execution status. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, Default)] +pub enum TransactionExecutionStatus { + #[serde(rename = "SUCCEEDED")] + #[default] + Succeeded, + #[serde(rename = "REVERTED")] + Reverted, +} + +impl TransactionReceipt { + pub fn into_starknet_api_transaction_output( + self, + transaction: &Transaction, + ) -> TransactionOutput { + let contract_address = transaction.contract_address(); + let execution_status = match &self.execution_status { + TransactionExecutionStatus::Succeeded => { + if self.revert_error.is_some() { + error!( + "Transaction execution status is Succeeded, but revert_error is not None: \ + {:?}", + self + ); + } + SnApiTransactionExecutionStatus::Succeeded + } + TransactionExecutionStatus::Reverted => { + SnApiTransactionExecutionStatus::Reverted(SnApiRevertedTransactionExecutionStatus { + revert_reason: self.revert_error.clone().unwrap_or_else(|| { + error!("Reverted transaction without a revert reason: {:?}", self); + "Reverted without a reason".to_owned() + }), + }) + } + }; + let messages_sent = self.l2_to_l1_messages.into_iter().map(MessageToL1::from).collect(); + match transaction.transaction_type() { + TransactionType::Declare => TransactionOutput::Declare(DeclareTransactionOutput { + actual_fee: self.actual_fee, + messages_sent, + events: self.events, + execution_status, + execution_resources: self.execution_resources.into(), + }), + TransactionType::Deploy => TransactionOutput::Deploy(DeployTransactionOutput { + actual_fee: self.actual_fee, + messages_sent, + events: self.events, + contract_address: contract_address + .expect("Deploy transaction must have a contract address."), + execution_status, + execution_resources: self.execution_resources.into(), + }), + TransactionType::DeployAccount => { + TransactionOutput::DeployAccount(DeployAccountTransactionOutput { + actual_fee: self.actual_fee, + messages_sent, + events: self.events, + contract_address: contract_address + .expect("Deploy account transaction must have a contract address."), + execution_status, + execution_resources: self.execution_resources.into(), + }) + } + TransactionType::InvokeFunction => TransactionOutput::Invoke(InvokeTransactionOutput { + actual_fee: self.actual_fee, + messages_sent, + events: self.events, + execution_status, + execution_resources: self.execution_resources.into(), + }), + TransactionType::L1Handler => { + TransactionOutput::L1Handler(L1HandlerTransactionOutput { + actual_fee: self.actual_fee, + messages_sent, + events: self.events, + execution_status, + execution_resources: self.execution_resources.into(), + }) + } + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub struct L1ToL2Nonce(pub StarkHash); + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct L1ToL2Message { + pub from_address: EthAddress, + pub to_address: ContractAddress, + pub selector: EntryPointSelector, + pub payload: L1ToL2Payload, + #[serde(default)] + pub nonce: L1ToL2Nonce, +} + +impl From for starknet_api::transaction::MessageToL2 { + fn from(message: L1ToL2Message) -> Self { + starknet_api::transaction::MessageToL2 { + from_address: message.from_address, + payload: message.payload, + } + } +} + +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub struct L2ToL1Message { + pub from_address: ContractAddress, + pub to_address: EthAddress, + pub payload: L2ToL1Payload, +} + +impl From for starknet_api::transaction::MessageToL1 { + fn from(message: L2ToL1Message) -> Self { + starknet_api::transaction::MessageToL1 { + to_address: message.to_address, + payload: message.payload, + from_address: message.from_address, + } + } +} + +#[derive( + Debug, + Copy, + Clone, + Eq, + PartialEq, + Hash, + Deserialize, + Serialize, + PartialOrd, + Ord, + Default, + EnumIter, +)] +pub enum TransactionType { + #[serde(rename(deserialize = "DECLARE", serialize = "DECLARE"))] + Declare, + #[serde(rename(deserialize = "DEPLOY", serialize = "DEPLOY"))] + Deploy, + #[serde(rename(deserialize = "DEPLOY_ACCOUNT", serialize = "DEPLOY_ACCOUNT"))] + DeployAccount, + #[serde(rename(deserialize = "INVOKE_FUNCTION", serialize = "INVOKE_FUNCTION"))] + #[default] + InvokeFunction, + #[serde(rename(deserialize = "L1_HANDLER", serialize = "L1_HANDLER"))] + L1Handler, +} diff --git a/crates/starknet_client/src/reader/objects/transaction_test.rs b/crates/starknet_client/src/reader/objects/transaction_test.rs new file mode 100644 index 00000000000..074aa10d5b3 --- /dev/null +++ b/crates/starknet_client/src/reader/objects/transaction_test.rs @@ -0,0 +1,118 @@ +use assert_matches::assert_matches; + +use super::{Transaction, TransactionReceipt}; +use crate::test_utils::read_resource::read_resource_file; + +#[test] +fn load_deploy_transaction_succeeds() { + assert_matches!( + serde_json::from_str::(&read_resource_file("reader/deploy_v0.json")), + Ok(Transaction::Deploy(_)) + ); +} + +#[test] +fn load_invoke_transaction_succeeds() { + assert_matches!( + serde_json::from_str::(&read_resource_file("reader/invoke_v0.json")), + Ok(Transaction::Invoke(_)) + ); +} + +#[test] +fn load_invoke_with_contract_address_transaction_succeeds() { + let mut json_val: serde_json::Value = + serde_json::from_str(&read_resource_file("reader/invoke_v0.json")).unwrap(); + let object = json_val.as_object_mut().unwrap(); + let sender_address_value = object.remove("sender_address").unwrap(); + object.insert("contract_address".to_string(), sender_address_value); + assert_matches!(serde_json::from_value::(json_val), Ok(Transaction::Invoke(_))); +} + +#[test] +fn load_l1_handler_transaction_succeeds() { + assert_matches!( + serde_json::from_str::(&read_resource_file("reader/l1_handler_v0.json")), + Ok(Transaction::L1Handler(_)) + ); +} + +#[test] +fn load_declare_transaction_succeeds() { + assert_matches!( + serde_json::from_str::(&read_resource_file("reader/declare_v0.json")), + Ok(Transaction::Declare(_)) + ); +} + +#[test] +fn load_transaction_succeeds() { + for file_name in [ + "reader/deploy_v0.json", + "reader/invoke_v0.json", + "reader/invoke_v3.json", + "reader/declare_v0.json", + "reader/declare_v3.json", + "reader/deploy_account_v3.json", + ] { + let res = serde_json::from_str::(&read_resource_file(file_name)); + assert!(res.is_ok(), "filename: {}, error: {:?}", file_name, res); + } +} + +#[test] +fn load_transaction_unknown_field_fails() { + for file_name in [ + "reader/deploy_v0.json", + "reader/invoke_v0.json", + "reader/declare_v0.json", + "reader/deploy_account_v3.json", + ] { + let mut json_value: serde_json::Value = + serde_json::from_str(&read_resource_file(file_name)).unwrap(); + json_value + .as_object_mut() + .unwrap() + .insert("unknown_field".to_string(), serde_json::Value::Null); + let json_str = serde_json::to_string(&json_value).unwrap(); + assert!(serde_json::from_str::(&json_str).is_err(), "filename: {}", file_name); + } +} + +#[test] +fn load_transaction_wrong_type_fails() { + for (file_name, new_wrong_type) in [ + // The transaction has a type that doesn't match the type it is paired with. + ("reader/deploy_v0.json", "INVOKE_FUNCTION"), + ("reader/invoke_v0.json", "DECLARE"), + ("reader/declare_v0.json", "DEPLOY"), + ("reader/deploy_account_v3.json", "INVOKE_FUNCTION"), + ] { + let mut json_value: serde_json::Value = + serde_json::from_str(&read_resource_file(file_name)).unwrap(); + json_value + .as_object_mut() + .unwrap() + .insert("type".to_string(), serde_json::Value::String(new_wrong_type.to_string())); + let json_str = serde_json::to_string(&json_value).unwrap(); + assert!(serde_json::from_str::(&json_str).is_err(), "filename: {}", file_name); + } +} + +#[test] +fn load_transaction_receipt_succeeds() { + for file_name in [ + "reader/transaction_receipt.json", + "reader/transaction_receipt_without_l1_to_l2.json", + "reader/transaction_receipt_without_l1_to_l2_nonce.json", + ] { + serde_json::from_str::(&read_resource_file(file_name)).unwrap_or_else( + |err| { + panic!( + "Failed to deserialize transaction receipt. Filename: {}. Error: {}", + file_name, err + ) + }, + ); + } +} diff --git a/crates/starknet_client/src/reader/starknet_feeder_gateway_client_test.rs b/crates/starknet_client/src/reader/starknet_feeder_gateway_client_test.rs new file mode 100644 index 00000000000..2767a4bb572 --- /dev/null +++ b/crates/starknet_client/src/reader/starknet_feeder_gateway_client_test.rs @@ -0,0 +1,624 @@ +use std::collections::HashMap; +use std::fmt::Debug; +use std::future::Future; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::indexmap; +use mockito::mock; +use pretty_assertions::assert_eq; +use starknet_api::block::{BlockHash, BlockNumber}; +use starknet_api::core::{ + ClassHash, + ContractAddress, + EntryPointSelector, + GlobalRoot, + Nonce, + PatriciaKey, + SequencerPublicKey, +}; +use starknet_api::crypto::utils::PublicKey; +use starknet_api::deprecated_contract_class::{ + ConstructorType, + ContractClass as DeprecatedContractClass, + ContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointOffset, + EntryPointType as DeprecatedEntryPointType, + FunctionAbiEntry, + Program, + TypedParameter, +}; +use starknet_api::state::{EntryPoint, EntryPointType, FunctionIndex}; +use starknet_api::transaction::{Fee, TransactionHash, TransactionSignature, TransactionVersion}; +use starknet_api::{felt, patricia_key}; + +use super::objects::state::StateUpdate; +use super::objects::transaction::IntermediateDeclareTransaction; +use super::{ + ContractClass, + GenericContractClass, + PendingData, + ReaderClientError, + ReaderClientResult, + StarknetFeederGatewayClient, + StarknetReader, + BLOCK_NUMBER_QUERY, + CLASS_HASH_QUERY, + GET_BLOCK_URL, + GET_STATE_UPDATE_URL, +}; +use crate::reader::objects::block::{BlockSignatureData, BlockSignatureMessage}; +use crate::reader::Block; +use crate::test_utils::read_resource::read_resource_file; +use crate::test_utils::retry::get_test_config; + +const NODE_VERSION: &str = "NODE VERSION"; +const FEEDER_GATEWAY_ALIVE_RESPONSE: &str = "FeederGateway is alive!"; + +#[test] +fn new_urls() { + let url_base_str = "https://url"; + let starknet_client = + StarknetFeederGatewayClient::new(url_base_str, None, NODE_VERSION, get_test_config()) + .unwrap(); + assert_eq!( + starknet_client.urls.get_block.as_str(), + url_base_str.to_string() + "/" + GET_BLOCK_URL + ); + assert_eq!( + starknet_client.urls.get_state_update.as_str(), + url_base_str.to_string() + "/" + GET_STATE_UPDATE_URL + ); +} + +#[tokio::test] +async fn get_block_number() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + // There are blocks in Starknet. + let mock_block = mock("GET", "/feeder_gateway/get_block?blockNumber=latest") + .with_status(200) + .with_body(read_resource_file("reader/block_post_0_13_1.json")) + .create(); + let latest_block = starknet_client.latest_block().await.unwrap(); + mock_block.assert(); + assert_eq!(latest_block.unwrap().block_number(), BlockNumber(329525)); + + // There are no blocks in Starknet. + let body = r#"{"code": "StarknetErrorCode.BLOCK_NOT_FOUND", "message": "Block number -1 was not found."}"#; + let mock_no_block = mock("GET", "/feeder_gateway/get_block?blockNumber=latest") + .with_status(400) + .with_body(body) + .create(); + let latest_block = starknet_client.latest_block().await.unwrap(); + mock_no_block.assert(); + assert!(latest_block.is_none()); +} + +#[tokio::test] +async fn declare_tx_serde() { + let declare_tx = IntermediateDeclareTransaction { + class_hash: ClassHash(felt!( + "0x7319e2f01b0947afd86c0bb0e95029551b32f6dc192c47b2e8b08415eebbc25" + )), + compiled_class_hash: None, + sender_address: ContractAddress(patricia_key!("0x1")), + nonce: Nonce(felt!("0x0")), + max_fee: Some(Fee(0)), + version: TransactionVersion::ONE, + resource_bounds: None, + tip: None, + nonce_data_availability_mode: None, + fee_data_availability_mode: None, + paymaster_data: None, + account_deployment_data: None, + transaction_hash: TransactionHash(felt!( + "0x2f2ef64daffdc72bf33b34ad024891691b8eb1d0ab70cc7f8fb71f6fd5e1f22" + )), + signature: TransactionSignature(vec![]), + }; + let raw_declare_tx = serde_json::to_string(&declare_tx).unwrap(); + assert_eq!(declare_tx, serde_json::from_str(&raw_declare_tx).unwrap()); +} + +#[tokio::test] +async fn state_update() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let raw_state_update = read_resource_file("reader/block_state_update.json"); + let mock_state_update = + mock("GET", &format!("/feeder_gateway/get_state_update?{BLOCK_NUMBER_QUERY}=123456")[..]) + .with_status(200) + .with_body(&raw_state_update) + .create(); + let state_update = starknet_client.state_update(BlockNumber(123456)).await.unwrap(); + mock_state_update.assert(); + let expected_state_update: StateUpdate = serde_json::from_str(&raw_state_update).unwrap(); + assert_eq!(state_update.unwrap(), expected_state_update); + + let body = r#"{"code": "StarknetErrorCode.BLOCK_NOT_FOUND", "message": "Block number -1 was not found."}"#; + let mock_no_block = + mock("GET", &format!("/feeder_gateway/get_state_update?{BLOCK_NUMBER_QUERY}=999999")[..]) + .with_status(400) + .with_body(body) + .create(); + let state_update = starknet_client.state_update(BlockNumber(999999)).await.unwrap(); + assert!(state_update.is_none()); + mock_no_block.assert(); +} + +#[tokio::test] +async fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} + +#[tokio::test] +async fn contract_class() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let expected_contract_class = ContractClass { + sierra_program: vec![ + felt!("0x302e312e30"), + felt!("0x1c"), + felt!("0x52616e6765436865636b"), + ], + entry_points_by_type: HashMap::from([( + EntryPointType::External, + vec! [EntryPoint { + function_idx: FunctionIndex(0), + selector: EntryPointSelector(felt!( + "0x22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658" + )), + }], + ), + (EntryPointType::Constructor, vec![]), + (EntryPointType::L1Handler, vec![]), + ]), + contract_class_version: String::from("0.1.0"), + abi: String::from("[\n {\n \"type\": \"function\",\n \"name\": \"test\",\n \"inputs\": [\n {\n \"name\": \"arg\",\n \"ty\": \"core::felt\"\n },\n {\n \"name\": \"arg1\",\n \"ty\": \"core::felt\"\n },\n {\n \"name\": \"arg2\",\n \"ty\": \"core::felt\"\n }\n ],\n \"output_ty\": \"core::felt\",\n \"state_mutability\": \"external\"\n },\n {\n \"type\": \"function\",\n \"name\": \"empty\",\n \"inputs\": [],\n \"output_ty\": \"()\",\n \"state_mutability\": \"external\"\n },\n {\n \"type\": \"function\",\n \"name\": \"call_foo\",\n \"inputs\": [\n {\n \"name\": \"a\",\n \"ty\": \"core::integer::u128\"\n }\n ],\n \"output_ty\": \"core::integer::u128\",\n \"state_mutability\": \"external\"\n }\n]"), + }; + + let mock_by_hash = + mock( + "GET", + &format!("/feeder_gateway/get_class_by_hash?blockNumber=pending&\ + {CLASS_HASH_QUERY}=0x4e70b19333ae94bd958625f7b61ce9eec631653597e68645e13780061b2136c")[..], + ) + .with_status(200) + .with_body(read_resource_file("reader/contract_class.json")) + .create(); + let contract_class = starknet_client + .class_by_hash(ClassHash(felt!( + "0x4e70b19333ae94bd958625f7b61ce9eec631653597e68645e13780061b2136c" + ))) + .await + .unwrap() + .unwrap(); + + let contract_class = match contract_class { + GenericContractClass::Cairo1ContractClass(class) => class, + _ => unreachable!("Expecting Cairo0ContractClass."), + }; + mock_by_hash.assert(); + assert_eq!(contract_class, expected_contract_class); +} + +#[tokio::test] +async fn deprecated_contract_class() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let expected_contract_class = DeprecatedContractClass { + abi: Some(vec![ContractClassAbiEntry::Constructor(FunctionAbiEntry:: { + name: "constructor".to_string(), + inputs: vec![TypedParameter { + name: "implementation".to_string(), + r#type: "felt".to_string(), + }], + outputs: vec![], + state_mutability: None, + r#type: ConstructorType::Constructor, + })]), + program: Program { + attributes: serde_json::Value::Array(vec![serde_json::json!(1234)]), + builtins: serde_json::Value::Array(Vec::new()), + compiler_version: serde_json::Value::Null, + data: serde_json::Value::Array(vec![ + serde_json::Value::String("0x20780017fff7ffd".to_string()), + serde_json::Value::String("0x4".to_string()), + serde_json::Value::String("0x400780017fff7ffd".to_string()), + ]), + debug_info: serde_json::Value::Null, + hints: serde_json::Value::Object(serde_json::Map::new()), + identifiers: serde_json::Value::Object(serde_json::Map::new()), + main_scope: serde_json::Value::String("__main__".to_string()), + prime: serde_json::Value::String( + "0x800000000000011000000000000000000000000000000000000000000000001".to_string(), + ), + reference_manager: serde_json::Value::Object(serde_json::Map::new()), + }, + entry_points_by_type: HashMap::from([ + (DeprecatedEntryPointType::L1Handler, vec![]), + ( + DeprecatedEntryPointType::Constructor, + vec![DeprecatedEntryPoint { + selector: EntryPointSelector(felt!( + "0x028ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194" + )), + offset: EntryPointOffset(62), + }], + ), + ( + DeprecatedEntryPointType::External, + vec![DeprecatedEntryPoint { + selector: EntryPointSelector(felt!( + "0x0000000000000000000000000000000000000000000000000000000000000000" + )), + offset: EntryPointOffset(86), + }], + ), + ]), + }; + let mock_by_hash = + mock( + "GET", + &format!("/feeder_gateway/get_class_by_hash?blockNumber=pending&\ + {CLASS_HASH_QUERY}=0x7af612493193c771c1b12f511a8b4d3b0c6d0648242af4680c7cd0d06186f17")[..], + ) + .with_status(200) + .with_body(read_resource_file("reader/deprecated_contract_class.json")) + .create(); + let contract_class = starknet_client + .class_by_hash(ClassHash(felt!( + "0x7af612493193c771c1b12f511a8b4d3b0c6d0648242af4680c7cd0d06186f17" + ))) + .await + .unwrap() + .unwrap(); + let contract_class = match contract_class { + GenericContractClass::Cairo0ContractClass(class) => class, + _ => unreachable!("Expecting deprecated contract class."), + }; + mock_by_hash.assert(); + assert_eq!(contract_class, expected_contract_class); + + // Undeclared class. + let body = r#"{"code": "StarknetErrorCode.UNDECLARED_CLASS", "message": "Class with hash 0x7 is not declared."}"#; + let mock_by_hash = + mock( + "GET", + &format!( + "/feeder_gateway/get_class_by_hash?blockNumber=pending&{CLASS_HASH_QUERY}=0x7" + )[..], + ) + .with_status(400) + .with_body(body) + .create(); + let class = starknet_client.class_by_hash(ClassHash(felt!("0x7"))).await.unwrap(); + mock_by_hash.assert(); + assert!(class.is_none()); +} + +// TODO: Add test for pending_data. + +#[tokio::test] +async fn deprecated_pending_data() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + + // Pending + let raw_pending_data = read_resource_file("reader/deprecated_pending_data.json"); + let mock_pending = + mock("GET", "/feeder_gateway/get_state_update?blockNumber=pending&includeBlock=true") + .with_status(200) + .with_body(&raw_pending_data) + .create(); + let pending_data = starknet_client.pending_data().await; + mock_pending.assert(); + let expected_pending_data: PendingData = serde_json::from_str(&raw_pending_data).unwrap(); + assert_eq!(pending_data.unwrap().unwrap(), expected_pending_data); + + // Accepted on L2. + let raw_pending_data = read_resource_file("reader/accepted_on_l2_deprecated_data.json"); + let mock_accepted = + mock("GET", "/feeder_gateway/get_state_update?blockNumber=pending&includeBlock=true") + .with_status(200) + .with_body(&raw_pending_data) + .create(); + let pending_data = starknet_client.pending_data().await; + mock_accepted.assert(); + let expected_pending_data: PendingData = serde_json::from_str(&raw_pending_data).unwrap(); + assert_eq!(pending_data.unwrap().unwrap(), expected_pending_data); +} + +#[tokio::test] +async fn get_block() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let raw_block = read_resource_file("reader/block_post_0_13_1.json"); + let mock_block = mock("GET", &format!("/feeder_gateway/get_block?{BLOCK_NUMBER_QUERY}=20")[..]) + .with_status(200) + .with_body(&raw_block) + .create(); + let block = starknet_client.block(BlockNumber(20)).await.unwrap().unwrap(); + mock_block.assert(); + let expected_block: Block = serde_json::from_str(&raw_block).unwrap(); + assert_eq!(block, expected_block); + + // Non-existing block. + let body = r#"{"code": "StarknetErrorCode.BLOCK_NOT_FOUND", "message": "Block 9999999999 was not found."}"#; + let mock_no_block = + mock("GET", &format!("/feeder_gateway/get_block?{BLOCK_NUMBER_QUERY}=9999999999")[..]) + .with_status(400) + .with_body(body) + .create(); + let block = starknet_client.block(BlockNumber(9999999999)).await.unwrap(); + mock_no_block.assert(); + assert!(block.is_none()); +} + +#[tokio::test] +async fn compiled_class_by_hash() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let raw_casm_contract_class = read_resource_file("reader/casm_contract_class.json"); + let mock_casm_contract_class = mock( + "GET", + &format!( + "/feeder_gateway/get_compiled_class_by_class_hash?blockNumber=pending&\ + {CLASS_HASH_QUERY}=0x7" + )[..], + ) + .with_status(200) + .with_body(&raw_casm_contract_class) + .create(); + let casm_contract_class = + starknet_client.compiled_class_by_hash(ClassHash(felt!("0x7"))).await.unwrap().unwrap(); + mock_casm_contract_class.assert(); + let expected_casm_contract_class: CasmContractClass = + serde_json::from_str(&raw_casm_contract_class).unwrap(); + assert_eq!(casm_contract_class, expected_casm_contract_class); + + let body = r#"{"code": "StarknetErrorCode.UNDECLARED_CLASS", "message": "Class with hash 0x7 is not declared."}"#; + let mock_undeclared = mock( + "GET", + &format!( + "/feeder_gateway/get_compiled_class_by_class_hash?blockNumber=pending&\ + {CLASS_HASH_QUERY}=0x0" + )[..], + ) + .with_status(400) + .with_body(body) + .create(); + let class = starknet_client.compiled_class_by_hash(ClassHash(felt!("0x0"))).await.unwrap(); + mock_undeclared.assert(); + assert!(class.is_none()); +} + +#[tokio::test] +async fn is_alive() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let mock_is_alive = mock("GET", "/feeder_gateway/is_alive") + .with_status(200) + .with_body(FEEDER_GATEWAY_ALIVE_RESPONSE) + .create(); + let response = starknet_client.is_alive().await; + mock_is_alive.assert(); + assert!(response); +} + +// Empty storage diffs were filtered out in the past, but should not anymore (part of the inputs to +// the state diff commitment). +#[tokio::test] +async fn state_update_with_empty_storage_diff() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let mut state_update = StateUpdate::default(); + let empty_storage_diff = indexmap!(ContractAddress::default() => vec![]); + state_update.state_diff.storage_diffs.clone_from(&empty_storage_diff); + + let mock = + mock("GET", &format!("/feeder_gateway/get_state_update?{BLOCK_NUMBER_QUERY}=123456")[..]) + .with_status(200) + .with_body(serde_json::to_string(&state_update).unwrap()) + .create(); + let state_update = starknet_client.state_update(BlockNumber(123456)).await.unwrap().unwrap(); + mock.assert(); + assert_eq!(state_update.state_diff.storage_diffs, empty_storage_diff); +} + +async fn test_unserializable< + Output: Send + Debug, + Fut: Future>, + F: FnOnce(StarknetFeederGatewayClient) -> Fut, +>( + url_suffix: &str, + call_method: F, +) { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + let body = "body"; + let mock = mock("GET", url_suffix).with_status(200).with_body(body).create(); + let error = call_method(starknet_client).await.unwrap_err(); + mock.assert(); + assert_matches!(error, ReaderClientError::SerdeError(_)); +} + +#[tokio::test] +async fn latest_block_unserializable() { + test_unserializable( + "/feeder_gateway/get_block?blockNumber=latest", + |starknet_client| async move { starknet_client.latest_block().await }, + ) + .await +} + +#[tokio::test] +async fn block_unserializable() { + test_unserializable("/feeder_gateway/get_block?blockNumber=20", |starknet_client| async move { + starknet_client.block(BlockNumber(20)).await + }) + .await +} + +#[tokio::test] +async fn class_by_hash_unserializable() { + test_unserializable( + &format!("/feeder_gateway/get_class_by_hash?blockNumber=pending&{CLASS_HASH_QUERY}=0x1")[..], + |starknet_client| async move { + starknet_client.class_by_hash(ClassHash(felt!("0x1"))).await + }, + ) + .await +} + +#[tokio::test] +async fn state_update_unserializable() { + test_unserializable( + &format!("/feeder_gateway/get_state_update?{BLOCK_NUMBER_QUERY}=123456")[..], + |starknet_client| async move { starknet_client.state_update(BlockNumber(123456)).await }, + ) + .await +} + +#[tokio::test] +async fn compiled_class_by_hash_unserializable() { + test_unserializable( + &format!( + "/feeder_gateway/get_compiled_class_by_class_hash?blockNumber=pending&\ + {CLASS_HASH_QUERY}=0x7" + )[..], + |starknet_client| async move { + starknet_client.compiled_class_by_hash(ClassHash(felt!("0x7"))).await + }, + ) + .await +} + +#[tokio::test] +async fn get_block_signature() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + + let expected_block_signature = BlockSignatureData::Deprecated { + block_number: BlockNumber(20), + signature: [felt!("0x1"), felt!("0x2")], + signature_input: BlockSignatureMessage { + block_hash: BlockHash(felt!("0x20")), + state_diff_commitment: GlobalRoot(felt!("0x1234")), + }, + }; + + let mock_block_signature = + mock("GET", &format!("/feeder_gateway/get_signature?{BLOCK_NUMBER_QUERY}=20")[..]) + .with_status(200) + .with_body(serde_json::to_string(&expected_block_signature).unwrap()) + .create(); + + let block_signature = starknet_client.block_signature(BlockNumber(20)).await.unwrap().unwrap(); + mock_block_signature.assert(); + assert_eq!(block_signature, expected_block_signature); +} + +#[tokio::test] +async fn get_block_signature_unknown_block() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + + let body = r#"{"code": "StarknetErrorCode.BLOCK_NOT_FOUND", "message": "Block number 999999 was not found."}"#; + let mock_no_block = + mock("GET", &format!("/feeder_gateway/get_signature?{BLOCK_NUMBER_QUERY}=999999")[..]) + .with_status(400) + .with_body(body) + .create(); + let block_signature = starknet_client.block_signature(BlockNumber(999999)).await.unwrap(); + mock_no_block.assert(); + assert!(block_signature.is_none()); +} + +#[tokio::test] +async fn get_sequencer_public_key() { + let starknet_client = StarknetFeederGatewayClient::new( + &mockito::server_url(), + None, + NODE_VERSION, + get_test_config(), + ) + .unwrap(); + + let expected_sequencer_pub_key = SequencerPublicKey(PublicKey(felt!("0x1"))); + + let mock_key = mock("GET", "/feeder_gateway/get_public_key") + .with_status(200) + .with_body(serde_json::to_string(&expected_sequencer_pub_key).unwrap()) + .create(); + + let pub_key = starknet_client.sequencer_pub_key().await.unwrap(); + mock_key.assert(); + assert_eq!(pub_key, expected_sequencer_pub_key); +} diff --git a/crates/starknet_client/src/retry.rs b/crates/starknet_client/src/retry.rs new file mode 100644 index 00000000000..bbebc9bd393 --- /dev/null +++ b/crates/starknet_client/src/retry.rs @@ -0,0 +1,105 @@ +#[cfg(test)] +#[path = "retry_test.rs"] +mod retry_test; + +use std::collections::BTreeMap; +use std::fmt::Debug; +use std::iter::Take; +use std::time::Duration; + +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use tokio_retry::strategy::ExponentialBackoff; +use tokio_retry::{Action, Condition, RetryIf}; +use tracing::debug; + +/// A configuration for the retry mechanism. +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +pub struct RetryConfig { + /// The initial waiting time in milliseconds. + pub retry_base_millis: u64, + /// The maximum waiting time in milliseconds. + pub retry_max_delay_millis: u64, + /// The maximum number of retries. + pub max_retries: usize, +} + +impl SerializeConfig for RetryConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param( + "retry_base_millis", + &self.retry_base_millis, + "Base waiting time after a failed request. After that, the time increases \ + exponentially.", + ParamPrivacyInput::Public, + ), + ser_param( + "retry_max_delay_millis", + &self.retry_max_delay_millis, + "Max waiting time after a failed request.", + ParamPrivacyInput::Public, + ), + ser_param( + "max_retries", + &self.max_retries, + "Maximum number of retries before the node stops retrying.", + ParamPrivacyInput::Public, + ), + ]) + } +} + +/// A utility for retrying actions with a configurable backoff and error filter. Uses an +/// [`ExponentialBackoff`] strategy. +pub struct Retry { + strategy: Take, +} + +impl Retry { + pub fn new(config: &RetryConfig) -> Self { + Retry { + strategy: ExponentialBackoff::from_millis(config.retry_base_millis) + .max_delay(Duration::from_millis(config.retry_max_delay_millis)) + .take(config.max_retries), + } + } + + fn log_condition(err: &E, condition: &mut C) -> bool + where + E: Debug, + C: Condition, + { + if condition.should_retry(err) { + debug!("Received error {:?}, retrying.", err); + true + } else { + debug!("Received error {:?}, not retrying.", err); + false + } + } + + pub async fn start(&self, action: A) -> Result + where + E: Debug, + A: Action, + { + self.start_with_condition(action, |_: &_| true).await + } + + pub async fn start_with_condition( + &self, + action: A, + mut condition: C, + ) -> Result + where + E: Debug, + A: Action, + C: Condition + Send, + { + let condition: Box bool> = + Box::new(|err| Self::log_condition(err, &mut condition)); + RetryIf::spawn(self.strategy.clone(), action, condition).await + } +} diff --git a/crates/starknet_client/src/retry_test.rs b/crates/starknet_client/src/retry_test.rs new file mode 100644 index 00000000000..7686bd32f68 --- /dev/null +++ b/crates/starknet_client/src/retry_test.rs @@ -0,0 +1,49 @@ +use std::sync::{Arc, Mutex}; + +use pretty_assertions::assert_eq; + +use super::Retry; +use crate::test_utils::retry::get_test_config; + +struct Worker { + // Number of times the worker was called. Updated in every call to work. + number_of_calls: Arc>, + // Number of times the worker returns errors before it returns ok. + number_of_errors: Arc, +} + +impl Worker { + fn new(number_of_errors: usize) -> Self { + Worker { + number_of_calls: Arc::new(Mutex::new(0)), + number_of_errors: Arc::new(number_of_errors), + } + } + + fn get_last_attempt(&self) -> usize { + *self.number_of_calls.lock().unwrap() + } + + async fn work(&self) -> Result<(), &str> { + let mut number_of_calls = self.number_of_calls.lock().unwrap(); + *number_of_calls += 1; + + if *number_of_calls <= *self.number_of_errors { Err("Some error.") } else { Ok(()) } + } +} + +#[tokio::test] +async fn fail_on_all_attempts() { + let config = get_test_config(); + let worker = Worker::new(10); + Retry::new(&config).start(|| worker.work()).await.unwrap_err(); + assert_eq!(worker.get_last_attempt(), 5); +} + +#[tokio::test] +async fn success_on_third_attempt() { + let config = get_test_config(); + let worker = Worker::new(2); + Retry::new(&config).start(|| worker.work()).await.unwrap(); + assert_eq!(worker.get_last_attempt(), 3); +} diff --git a/crates/starknet_client/src/starknet_client_test.rs b/crates/starknet_client/src/starknet_client_test.rs new file mode 100644 index 00000000000..1c7fad3d90b --- /dev/null +++ b/crates/starknet_client/src/starknet_client_test.rs @@ -0,0 +1,186 @@ +use assert_matches::assert_matches; +use mockito::mock; +use reqwest::StatusCode; + +use crate::starknet_error::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; +use crate::test_utils::retry::{get_test_config, MAX_RETRIES}; +use crate::{ClientError, RetryErrorCode, StarknetClient}; + +const NODE_VERSION: &str = "NODE VERSION"; +const URL_SUFFIX: &str = "/query"; + +#[tokio::test] +async fn request_with_retry_positive_flow() { + const BODY: &str = "body"; + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let mock = mock("GET", URL_SUFFIX).with_status(200).with_body(BODY).create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_eq!(result.unwrap(), BODY); + mock.assert(); +} + +#[tokio::test] +async fn request_with_retry_bad_response_status() { + let error_code = StatusCode::NOT_FOUND; + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let mock = mock("GET", URL_SUFFIX).with_status(error_code.as_u16().into()).create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_matches!( + result, + Err(ClientError::BadResponseStatus { code, message: _ }) if code == error_code + ); + mock.assert(); +} + +#[tokio::test] +async fn request_with_retry_starknet_error_no_retry() { + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let expected_starknet_error = StarknetError { + code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::UndeclaredClass), + message: "message".to_string(), + }; + let mock = mock("GET", URL_SUFFIX) + .with_status(StatusCode::BAD_REQUEST.as_u16().into()) + .with_body(serde_json::to_string(&expected_starknet_error).unwrap()) + .create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + let Err(ClientError::StarknetError(starknet_error)) = result else { + panic!("Did not get a StarknetError."); + }; + assert_eq!(starknet_error, expected_starknet_error); + mock.assert(); +} + +#[tokio::test] +async fn request_with_retry_serde_error_in_starknet_error() { + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let mock = mock("GET", URL_SUFFIX) + .with_status(StatusCode::BAD_REQUEST.as_u16().into()) + .with_body("body") + .create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_matches!(result, Err(ClientError::SerdeError(_))); + mock.assert(); +} + +#[tokio::test] +async fn request_with_retry_max_retries_reached() { + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + for (status_code, error_code) in [ + (StatusCode::TEMPORARY_REDIRECT, RetryErrorCode::Redirect), + (StatusCode::REQUEST_TIMEOUT, RetryErrorCode::Timeout), + (StatusCode::TOO_MANY_REQUESTS, RetryErrorCode::TooManyRequests), + (StatusCode::SERVICE_UNAVAILABLE, RetryErrorCode::ServiceUnavailable), + (StatusCode::GATEWAY_TIMEOUT, RetryErrorCode::Timeout), + ] { + let mock = mock("GET", URL_SUFFIX) + .with_status(status_code.as_u16().into()) + .expect(MAX_RETRIES + 1) + .create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_matches!( + result, Err(ClientError::RetryError { code, message: _ }) if code == error_code + ); + mock.assert(); + } +} + +#[tokio::test] +async fn request_with_retry_success_on_retry() { + const BODY: &str = "body"; + assert_ne!(0, MAX_RETRIES); + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + for status_code in [ + StatusCode::TEMPORARY_REDIRECT, + StatusCode::REQUEST_TIMEOUT, + StatusCode::TOO_MANY_REQUESTS, + StatusCode::SERVICE_UNAVAILABLE, + StatusCode::GATEWAY_TIMEOUT, + ] { + let mock_failure = mock("GET", URL_SUFFIX) + .with_status(status_code.as_u16().into()) + .expect(MAX_RETRIES) + .create(); + let mock_success = mock("GET", URL_SUFFIX).with_status(200).with_body(BODY).create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_eq!(result.unwrap(), BODY); + mock_failure.assert(); + mock_success.assert(); + } +} + +#[tokio::test] +async fn request_with_retry_starknet_error_max_retries_reached() { + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let starknet_error = StarknetError { + code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::TransactionLimitExceeded), + message: "message".to_string(), + }; + let starknet_error_str = serde_json::to_string(&starknet_error).unwrap(); + let mock = mock("GET", URL_SUFFIX) + .with_status(StatusCode::BAD_REQUEST.as_u16().into()) + .with_body(starknet_error_str) + .expect(MAX_RETRIES + 1) + .create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_matches!( + result, + Err(ClientError::RetryError { code, message: _ }) if code == RetryErrorCode::TooManyRequests + ); + mock.assert(); +} + +#[tokio::test] +async fn request_with_retry_starknet_error_success_on_retry() { + const BODY: &str = "body"; + assert_ne!(0, MAX_RETRIES); + let starknet_client = StarknetClient::new(None, NODE_VERSION, get_test_config()).unwrap(); + let starknet_error = StarknetError { + code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::TransactionLimitExceeded), + message: "message".to_string(), + }; + let starknet_error_str = serde_json::to_string(&starknet_error).unwrap(); + let mock_failure = mock("GET", URL_SUFFIX) + .with_status(StatusCode::BAD_REQUEST.as_u16().into()) + .with_body(starknet_error_str) + .expect(MAX_RETRIES) + .create(); + let mock_success = mock("GET", URL_SUFFIX).with_status(200).with_body(BODY).create(); + let mut url = mockito::server_url(); + url.push_str(URL_SUFFIX); + let result = + starknet_client.request_with_retry(starknet_client.internal_client.get(&url)).await; + assert_eq!(result.unwrap(), BODY); + mock_failure.assert(); + mock_success.assert(); +} + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/starknet_client/src/starknet_error.rs b/crates/starknet_client/src/starknet_error.rs new file mode 100644 index 00000000000..5a59d7b9e83 --- /dev/null +++ b/crates/starknet_client/src/starknet_error.rs @@ -0,0 +1,96 @@ +#[cfg(test)] +#[path = "starknet_error_test.rs"] +mod starknet_error_test; + +use std::fmt::{self, Display, Formatter}; + +#[cfg(any(feature = "testing", test))] +use enum_iterator::Sequence; +use serde::de::Error; +use serde::{Deserialize, Deserializer, Serialize}; + +/// Error codes returned by the starknet gateway. +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[serde(untagged)] +pub enum StarknetErrorCode { + #[serde(deserialize_with = "deserialize_unknown_error_code")] + UnknownErrorCode(String), + KnownErrorCode(KnownStarknetErrorCode), +} + +// This struct is needed because #[serde(other)] supports only unit variants and because +// #[serde(field_identifier)] doesn't work with serializable types. +// The issue requesting that #[serde(other)] will deserialize the variant with the unknown tag's +// content is: https://github.com/serde-rs/serde/issues/1701 +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "testing"), derive(Sequence))] +pub enum KnownStarknetErrorCode { + #[serde(rename = "StarknetErrorCode.UNDECLARED_CLASS")] + UndeclaredClass, + #[serde(rename = "StarknetErrorCode.BLOCK_NOT_FOUND")] + BlockNotFound, + #[serde(rename = "StarkErrorCode.MALFORMED_REQUEST")] + MalformedRequest, + #[serde(rename = "StarknetErrorCode.OUT_OF_RANGE_CLASS_HASH")] + OutOfRangeClassHash, + #[serde(rename = "StarknetErrorCode.CLASS_ALREADY_DECLARED")] + ClassAlreadyDeclared, + #[serde(rename = "StarknetErrorCode.COMPILATION_FAILED")] + CompilationFailed, + #[serde(rename = "StarknetErrorCode.CONTRACT_BYTECODE_SIZE_TOO_LARGE")] + ContractBytecodeSizeTooLarge, + #[serde(rename = "StarknetErrorCode.CONTRACT_CLASS_OBJECT_SIZE_TOO_LARGE")] + ContractClassObjectSizeTooLarge, + #[serde(rename = "StarknetErrorCode.DUPLICATED_TRANSACTION")] + DuplicatedTransaction, + #[serde(rename = "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT")] + EntryPointNotFoundInContract, + #[serde(rename = "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE")] + InsufficientAccountBalance, + #[serde(rename = "StarknetErrorCode.INSUFFICIENT_MAX_FEE")] + InsufficientMaxFee, + #[serde(rename = "StarknetErrorCode.INVALID_COMPILED_CLASS_HASH")] + InvalidCompiledClassHash, + #[serde(rename = "StarknetErrorCode.INVALID_CONTRACT_CLASS_VERSION")] + InvalidContractClassVersion, + #[serde(rename = "StarknetErrorCode.INVALID_TRANSACTION_NONCE")] + InvalidTransactionNonce, + #[serde(rename = "StarknetErrorCode.INVALID_TRANSACTION_VERSION")] + InvalidTransactionVersion, + #[serde(rename = "StarknetErrorCode.VALIDATE_FAILURE")] + ValidateFailure, + #[serde(rename = "StarknetErrorCode.TRANSACTION_LIMIT_EXCEEDED")] + TransactionLimitExceeded, +} + +/// A client error wrapping error codes returned by the starknet gateway. +#[derive(thiserror::Error, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +pub struct StarknetError { + pub code: StarknetErrorCode, + pub message: String, +} + +impl Display for StarknetError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{self:?}") + } +} + +pub fn deserialize_unknown_error_code<'de, D>(de: D) -> Result +where + D: Deserializer<'de>, +{ + let string: String = Deserialize::deserialize(de)?; + let string_as_json = format!("\"{string}\""); + match serde_json::from_str::(&string_as_json) { + Ok(_) => Err(D::Error::custom( + "Trying to serialize a known Starknet error code into UnknownErrorCode", + )), + Err(json_err) => { + if json_err.is_data() { + return Ok(string); + } + Err(D::Error::custom(json_err)) + } + } +} diff --git a/crates/starknet_client/src/starknet_error_test.rs b/crates/starknet_client/src/starknet_error_test.rs new file mode 100644 index 00000000000..afc428ec37f --- /dev/null +++ b/crates/starknet_client/src/starknet_error_test.rs @@ -0,0 +1,90 @@ +use serde_json::{Map, Value as JsonValue}; + +use super::{KnownStarknetErrorCode, StarknetError, StarknetErrorCode}; + +fn deserialize_starknet_error(code: &str, message: &str) -> StarknetError { + serde_json::from_value::(JsonValue::Object(Map::from_iter([ + ("code".to_string(), JsonValue::String(code.to_string())), + ("message".to_string(), JsonValue::String(message.to_string())), + ]))) + .unwrap() +} + +#[test] +fn known_error_code_deserialization() { + const MESSAGE: &str = "message"; + for (code_str, known_code) in [ + ("StarknetErrorCode.UNDECLARED_CLASS", KnownStarknetErrorCode::UndeclaredClass), + ("StarknetErrorCode.BLOCK_NOT_FOUND", KnownStarknetErrorCode::BlockNotFound), + ("StarkErrorCode.MALFORMED_REQUEST", KnownStarknetErrorCode::MalformedRequest), + ("StarknetErrorCode.OUT_OF_RANGE_CLASS_HASH", KnownStarknetErrorCode::OutOfRangeClassHash), + ("StarknetErrorCode.CLASS_ALREADY_DECLARED", KnownStarknetErrorCode::ClassAlreadyDeclared), + ("StarknetErrorCode.COMPILATION_FAILED", KnownStarknetErrorCode::CompilationFailed), + ( + "StarknetErrorCode.CONTRACT_BYTECODE_SIZE_TOO_LARGE", + KnownStarknetErrorCode::ContractBytecodeSizeTooLarge, + ), + ( + "StarknetErrorCode.CONTRACT_CLASS_OBJECT_SIZE_TOO_LARGE", + KnownStarknetErrorCode::ContractClassObjectSizeTooLarge, + ), + ("StarknetErrorCode.DUPLICATED_TRANSACTION", KnownStarknetErrorCode::DuplicatedTransaction), + ( + "StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT", + KnownStarknetErrorCode::EntryPointNotFoundInContract, + ), + ( + "StarknetErrorCode.INSUFFICIENT_ACCOUNT_BALANCE", + KnownStarknetErrorCode::InsufficientAccountBalance, + ), + ("StarknetErrorCode.INSUFFICIENT_MAX_FEE", KnownStarknetErrorCode::InsufficientMaxFee), + ( + "StarknetErrorCode.INVALID_COMPILED_CLASS_HASH", + KnownStarknetErrorCode::InvalidCompiledClassHash, + ), + ( + "StarknetErrorCode.INVALID_CONTRACT_CLASS_VERSION", + KnownStarknetErrorCode::InvalidContractClassVersion, + ), + ( + "StarknetErrorCode.INVALID_TRANSACTION_NONCE", + KnownStarknetErrorCode::InvalidTransactionNonce, + ), + ( + "StarknetErrorCode.INVALID_TRANSACTION_VERSION", + KnownStarknetErrorCode::InvalidTransactionVersion, + ), + ("StarknetErrorCode.VALIDATE_FAILURE", KnownStarknetErrorCode::ValidateFailure), + ( + "StarknetErrorCode.TRANSACTION_LIMIT_EXCEEDED", + KnownStarknetErrorCode::TransactionLimitExceeded, + ), + ] { + let starknet_error = deserialize_starknet_error(code_str, MESSAGE); + let expected_starknet_error = StarknetError { + code: StarknetErrorCode::KnownErrorCode(known_code), + message: MESSAGE.to_string(), + }; + assert_eq!(expected_starknet_error, starknet_error); + } +} + +#[test] +fn unknown_error_code_deserialization() { + const MESSAGE: &str = "message"; + const CODE_STR: &str = "StarknetErrorCode.MADE_UP_CODE_FOR_TEST"; + let starknet_error = deserialize_starknet_error(CODE_STR, MESSAGE); + let expected_starknet_error = StarknetError { + code: StarknetErrorCode::UnknownErrorCode(CODE_STR.to_string()), + message: MESSAGE.to_string(), + }; + assert_eq!(expected_starknet_error, starknet_error); +} + +// This test is needed because bugs can happen in the custom deserialization of UnknownErrorCode +#[test] +fn starknet_error_code_invalid_json_format_fails() { + assert!( + serde_json::from_str::("A string not surrounded with quotes").is_err() + ); +} diff --git a/crates/starknet_client/src/test_utils/mod.rs b/crates/starknet_client/src/test_utils/mod.rs new file mode 100644 index 00000000000..06211610d4d --- /dev/null +++ b/crates/starknet_client/src/test_utils/mod.rs @@ -0,0 +1,4 @@ +#[cfg(test)] +pub mod read_resource; +#[cfg(test)] +pub mod retry; diff --git a/crates/starknet_client/src/test_utils/read_resource.rs b/crates/starknet_client/src/test_utils/read_resource.rs new file mode 100644 index 00000000000..6627703e29e --- /dev/null +++ b/crates/starknet_client/src/test_utils/read_resource.rs @@ -0,0 +1,11 @@ +use std::env; +use std::fs::read_to_string; +use std::path::Path; +use std::string::String; + +pub fn read_resource_file(path_in_resource_dir: &str) -> String { + let path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("resources") + .join(path_in_resource_dir); + return read_to_string(path.to_str().unwrap()).unwrap(); +} diff --git a/crates/starknet_client/src/test_utils/retry.rs b/crates/starknet_client/src/test_utils/retry.rs new file mode 100644 index 00000000000..1fa18976e69 --- /dev/null +++ b/crates/starknet_client/src/test_utils/retry.rs @@ -0,0 +1,9 @@ +use crate::retry::RetryConfig; + +pub const MAX_RETRIES: usize = 4; + +pub fn get_test_config() -> RetryConfig { + // Taking the fastest config possible (except for MAX_RETRIES which we want to be a bit bigger + // to test the functionality). + RetryConfig { retry_base_millis: 0, retry_max_delay_millis: 0, max_retries: MAX_RETRIES } +} diff --git a/crates/starknet_client/src/writer/mod.rs b/crates/starknet_client/src/writer/mod.rs new file mode 100644 index 00000000000..344f5b089b8 --- /dev/null +++ b/crates/starknet_client/src/writer/mod.rs @@ -0,0 +1,150 @@ +//! This module contains client that can request changes to [`Starknet`]. +//! +//! [`Starknet`]: https://starknet.io/ + +pub mod objects; + +#[cfg(test)] +mod starknet_gateway_client_test; + +use async_trait::async_trait; +#[cfg(any(feature = "testing", test))] +use mockall::automock; +use serde::{Deserialize, Serialize}; +use tracing::instrument; +use url::Url; + +use crate::writer::objects::response::{DeclareResponse, DeployAccountResponse, InvokeResponse}; +use crate::writer::objects::transaction::{ + DeclareTransaction, + DeployAccountTransaction, + InvokeTransaction, +}; +use crate::{ClientCreationError, ClientError, RetryConfig, StarknetClient}; + +/// Errors that may be returned from a writer client. +#[derive(thiserror::Error, Debug)] +pub enum WriterClientError { + /// A client error representing errors from the base StarknetClient. + #[error(transparent)] + ClientError(#[from] ClientError), + /// A client error representing deserialization errors. + /// Note: [`ClientError`] contains SerdeError as well. The difference is that this variant is + /// responsible for serde errors coming from [`StarknetWriter`] and ClientError::SerdeError + /// is responsible for serde errors coming from StarknetClient. + #[error(transparent)] + SerdeError(#[from] serde_json::Error), +} + +pub type WriterClientResult = Result; + +/// A trait describing an object that can communicate with [`Starknet`] and make changes to it. +/// +/// [`Starknet`]: https://starknet.io/ +#[cfg_attr(any(test, feature = "testing"), automock)] +#[async_trait] +pub trait StarknetWriter: Sync + Send + 'static { + /// Add an invoke transaction to [`Starknet`]. + /// + /// [`Starknet`]: https://starknet.io/ + async fn add_invoke_transaction( + &self, + tx: &InvokeTransaction, + ) -> WriterClientResult; + + /// Add a declare transaction to [`Starknet`]. + /// + /// [`Starknet`]: https://starknet.io/ + async fn add_declare_transaction( + &self, + tx: &DeclareTransaction, + ) -> WriterClientResult; + + /// Add a deploy account transaction to [`Starknet`]. + /// + /// [`Starknet`]: https://starknet.io/ + async fn add_deploy_account_transaction( + &self, + tx: &DeployAccountTransaction, + ) -> WriterClientResult; + + // Returns true if the writer is alive. + async fn is_alive(&self) -> bool; +} + +const ADD_TRANSACTION_URL_SUFFIX: &str = "gateway/add_transaction"; +const GATEWAY_IS_ALIVE: &str = "gateway/is_alive"; +const GATEWAY_ALIVE_RESPONSE: &str = "Gateway is alive!"; + +/// A client for the [`Starknet`] gateway. +/// +/// [`Starknet`]: https://starknet.io/ +pub struct StarknetGatewayClient { + add_transaction_url: Url, + is_alive_url: Url, + client: StarknetClient, +} + +#[async_trait] +impl StarknetWriter for StarknetGatewayClient { + #[instrument(skip(self), level = "debug")] + async fn add_invoke_transaction( + &self, + tx: &InvokeTransaction, + ) -> WriterClientResult { + self.add_transaction(&tx).await + } + + #[instrument(skip(self), level = "debug")] + async fn add_deploy_account_transaction( + &self, + tx: &DeployAccountTransaction, + ) -> WriterClientResult { + self.add_transaction(&tx).await + } + + #[instrument(skip(self), level = "debug")] + async fn add_declare_transaction( + &self, + tx: &DeclareTransaction, + ) -> WriterClientResult { + self.add_transaction(&tx).await + } + + async fn is_alive(&self) -> bool { + let url = self.is_alive_url.clone(); + let response = self.client.request_with_retry(self.client.internal_client.get(url)).await; + let expected_response = GATEWAY_ALIVE_RESPONSE.to_string(); + response.is_ok_and(|response| response == expected_response) + } +} + +impl StarknetGatewayClient { + pub fn new( + starknet_url: &str, + node_version: &'static str, + retry_config: RetryConfig, + ) -> Result { + Ok(StarknetGatewayClient { + add_transaction_url: Url::parse(starknet_url)?.join(ADD_TRANSACTION_URL_SUFFIX)?, + is_alive_url: Url::parse(starknet_url)?.join(GATEWAY_IS_ALIVE)?, + client: StarknetClient::new(None, node_version, retry_config)?, + }) + } + + async fn add_transaction Deserialize<'a>>( + &self, + tx: &Transaction, + ) -> WriterClientResult { + let response: String = self + .client + .request_with_retry( + self.client + .internal_client + .post(self.add_transaction_url.clone()) + .body(serde_json::to_string(&tx)?), + ) + .await?; + Ok(serde_json::from_str::(&response)?) + } +} diff --git a/crates/starknet_client/src/writer/objects/mod.rs b/crates/starknet_client/src/writer/objects/mod.rs new file mode 100644 index 00000000000..62fc7eae98e --- /dev/null +++ b/crates/starknet_client/src/writer/objects/mod.rs @@ -0,0 +1,4 @@ +pub mod response; +#[cfg(any(feature = "testing", test))] +pub mod test_utils; +pub mod transaction; diff --git a/crates/starknet_client/src/writer/objects/response.rs b/crates/starknet_client/src/writer/objects/response.rs new file mode 100644 index 00000000000..73f13f8bc1e --- /dev/null +++ b/crates/starknet_client/src/writer/objects/response.rs @@ -0,0 +1,45 @@ +//! This module contains the response returned by the [`Starknet`] gateway on the successful flow. +//! +//! [`Starknet`]: https://starknet.io/ + +#[cfg(test)] +#[path = "response_test.rs"] +mod response_test; + +use serde::{Deserialize, Serialize}; +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::transaction::TransactionHash; + +/// A Starknet error code that reports success. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +pub enum SuccessfulStarknetErrorCode { + #[serde(rename = "TRANSACTION_RECEIVED")] + #[default] + TransactionReceived, +} + +/// The response of adding a declare transaction through the Starknet gateway successfully. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeclareResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, +} + +/// The response of adding a deploy account transaction through the Starknet gateway successfully. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeployAccountResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, + pub address: ContractAddress, +} + +/// The response of adding an invoke transaction through the Starknet gateway successfully. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct InvokeResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, +} diff --git a/crates/starknet_client/src/writer/objects/response_test.rs b/crates/starknet_client/src/writer/objects/response_test.rs new file mode 100644 index 00000000000..15d2231f2c8 --- /dev/null +++ b/crates/starknet_client/src/writer/objects/response_test.rs @@ -0,0 +1,18 @@ +use test_utils::validate_load_and_dump; + +use super::{DeclareResponse, DeployAccountResponse, InvokeResponse}; + +#[test] +fn load_and_dump_deploy_account_same_string() { + validate_load_and_dump::("writer/deploy_account_response.json"); +} + +#[test] +fn load_and_dump_invoke_same_string() { + validate_load_and_dump::("writer/invoke_response.json"); +} + +#[test] +fn load_and_dump_declare_same_string() { + validate_load_and_dump::("writer/declare_response.json"); +} diff --git a/crates/starknet_client/src/writer/objects/test_utils.rs b/crates/starknet_client/src/writer/objects/test_utils.rs new file mode 100644 index 00000000000..ddc3dd85896 --- /dev/null +++ b/crates/starknet_client/src/writer/objects/test_utils.rs @@ -0,0 +1,43 @@ +use std::collections::HashMap; + +use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::deprecated_contract_class::{ + ContractClassAbiEntry as DeprecatedContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointType as DeprecatedEntryPointType, +}; +use starknet_api::transaction::TransactionHash; +use test_utils::{auto_impl_get_test_instance, get_number_of_variants, GetTestInstance}; + +use crate::writer::objects::response::{ + DeclareResponse, + DeployAccountResponse, + InvokeResponse, + SuccessfulStarknetErrorCode, +}; +use crate::writer::objects::transaction::DeprecatedContractClass; + +auto_impl_get_test_instance! { + pub struct DeprecatedContractClass { + pub abi: Option>, + pub compressed_program: String, + pub entry_points_by_type: HashMap>, + } + pub struct InvokeResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, + } + pub struct DeployAccountResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, + pub address: ContractAddress, + } + pub struct DeclareResponse { + pub code: SuccessfulStarknetErrorCode, + pub transaction_hash: TransactionHash, + pub class_hash: ClassHash, + } + pub enum SuccessfulStarknetErrorCode { + TransactionReceived = 0, + } +} diff --git a/crates/starknet_client/src/writer/objects/transaction.rs b/crates/starknet_client/src/writer/objects/transaction.rs new file mode 100644 index 00000000000..94b47ab2741 --- /dev/null +++ b/crates/starknet_client/src/writer/objects/transaction.rs @@ -0,0 +1,284 @@ +//! This module contains all the different transactions that can be added to [`Starknet`] via the +//! gateway. +//! +//! Each transaction can be serialized into a JSON object that the gateway can receive through the +//! `add_transaction` HTTP method. +//! +//! [`Starknet`]: https://starknet.io/ + +#[cfg(test)] +#[path = "transaction_test.rs"] +mod transaction_test; + +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + Nonce, +}; +use starknet_api::deprecated_contract_class::{ + ContractClassAbiEntry as DeprecatedContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointType as DeprecatedEntryPointType, +}; +use starknet_api::state::{EntryPoint, EntryPointType}; +use starknet_api::transaction::{ + AccountDeploymentData, + Calldata, + ContractAddressSalt, + Fee, + PaymasterData, + ResourceBoundsMapping, + Tip, + TransactionSignature, + TransactionVersion, +}; + +// Each transaction type has a field called `type`. This field needs to be of a type that +// serializes to/deserializes from a constant string. +// +// The reason we don't solve this by having an enum of a generic transaction and let serde generate +// the `type` field through #[serde(tag)] is because we want to serialize/deserialize from the +// structs of the specific transaction types. + +/// The type field of a deploy account transaction. This enum serializes/deserializes into a +/// constant string. +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] +pub enum DeployAccountType { + #[serde(rename = "DEPLOY_ACCOUNT")] + #[default] + DeployAccount, +} + +/// The type field of an invoke transaction. This enum serializes/deserializes into a constant +/// string. +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] +pub enum InvokeType { + #[serde(rename = "INVOKE_FUNCTION")] + #[default] + Invoke, +} + +/// The type field of a declare transaction. This enum serializes/deserializes into a constant +/// string. +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] +pub enum DeclareType { + #[serde(rename = "DECLARE")] + #[default] + Declare, +} + +// This enum is required since the GW receives this field with value 0 as a reserved value. Once the +// feature will be activated this enum should be removed from here and taken from starknet-api. +#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, Eq, PartialEq)] +#[repr(u8)] +pub enum ReservedDataAvailabilityMode { + Reserved = 0, +} + +/// A deploy account transaction that can be added to Starknet through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeployAccountV1Transaction { + pub contract_address_salt: ContractAddressSalt, + pub class_hash: ClassHash, + pub constructor_calldata: Calldata, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + pub version: TransactionVersion, + pub r#type: DeployAccountType, +} + +/// A deploy account transaction that can be added to Starknet through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +// TODO(Shahak): Add tests for deploy account v3. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeployAccountV3Transaction { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub contract_address_salt: ContractAddressSalt, + pub class_hash: ClassHash, + pub constructor_calldata: Calldata, + pub nonce: Nonce, + pub signature: TransactionSignature, + pub nonce_data_availability_mode: ReservedDataAvailabilityMode, + pub fee_data_availability_mode: ReservedDataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub version: TransactionVersion, + pub r#type: DeployAccountType, +} + +/// A deploy account transaction that can be added to Starknet through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(untagged)] +pub enum DeployAccountTransaction { + DeployAccountV1(DeployAccountV1Transaction), + DeployAccountV3(DeployAccountV3Transaction), +} + +/// An invoke account transaction that can be added to Starknet through the Starknet gateway. +/// The invoke is a V0 transaction. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +// TODO(Shahak): Add tests for invoke v0. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct InvokeV0Transaction { + pub calldata: Calldata, + pub contract_address: ContractAddress, + pub max_fee: Fee, + pub signature: TransactionSignature, + pub version: TransactionVersion, + pub r#type: InvokeType, + pub entry_point_selector: EntryPointSelector, +} + +/// An invoke account transaction that can be added to Starknet through the Starknet gateway. +/// The invoke is a V1 transaction. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct InvokeV1Transaction { + pub calldata: Calldata, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub signature: TransactionSignature, + pub version: TransactionVersion, + pub r#type: InvokeType, +} + +/// An invoke account transaction that can be added to Starknet through the Starknet gateway. +/// The invoke is a V3 transaction. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +// TODO(Shahak): Add tests for invoke v3. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct InvokeV3Transaction { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub calldata: Calldata, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub signature: TransactionSignature, + pub nonce_data_availability_mode: ReservedDataAvailabilityMode, + pub fee_data_availability_mode: ReservedDataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub version: TransactionVersion, + pub r#type: InvokeType, +} + +/// An invoke transaction that can be added to Starknet through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(untagged)] +pub enum InvokeTransaction { + InvokeV0(InvokeV0Transaction), + InvokeV1(InvokeV1Transaction), + InvokeV3(InvokeV3Transaction), +} +/// A declare transaction of a Cairo-v0 (deprecated) contract class that can be added to Starknet +/// through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeclareV1Transaction { + pub contract_class: DeprecatedContractClass, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion, + pub signature: TransactionSignature, + pub r#type: DeclareType, +} + +/// A declare transaction of a Cairo-v1 contract class that can be added to Starknet through the +/// Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeclareV2Transaction { + pub contract_class: ContractClass, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce: Nonce, + pub max_fee: Fee, + pub version: TransactionVersion, + pub signature: TransactionSignature, + pub r#type: DeclareType, +} + +/// A declare transaction of a Cairo-v1 contract class that can be added to Starknet through the +/// Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +// TODO(shahak): Add tests for declare v3. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct DeclareV3Transaction { + pub contract_class: ContractClass, + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: ReservedDataAvailabilityMode, + pub fee_data_availability_mode: ReservedDataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub version: TransactionVersion, + pub r#type: DeclareType, +} + +/// A declare transaction that can be added to Starknet through the Starknet gateway. +/// It has a serialization format that the Starknet gateway accepts in the `add_transaction` +/// HTTP method. +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(untagged)] +pub enum DeclareTransaction { + DeclareV1(DeclareV1Transaction), + DeclareV2(DeclareV2Transaction), + DeclareV3(DeclareV3Transaction), +} + +// The structs that are implemented here are the structs that have deviations from starknet_api. + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct DeprecatedContractClass { + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub abi: Option>, + #[serde(rename = "program")] + // TODO(shahak): Create a struct for a compressed base64 value. + pub compressed_program: String, + pub entry_points_by_type: HashMap>, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct ContractClass { + // TODO(shahak): Create a struct for a compressed base64 value. + #[serde(rename = "sierra_program")] + pub compressed_sierra_program: String, + pub contract_class_version: String, + pub entry_points_by_type: HashMap>, + pub abi: String, +} diff --git a/crates/starknet_client/src/writer/objects/transaction_test.rs b/crates/starknet_client/src/writer/objects/transaction_test.rs new file mode 100644 index 00000000000..af12e7d0ca9 --- /dev/null +++ b/crates/starknet_client/src/writer/objects/transaction_test.rs @@ -0,0 +1,46 @@ +use test_utils::validate_load_and_dump; + +use super::{ + DeclareV1Transaction, + DeclareV2Transaction, + DeclareV3Transaction, + DeployAccountV1Transaction, + DeployAccountV3Transaction, + InvokeV1Transaction, + InvokeV3Transaction, +}; + +#[test] +fn load_and_dump_deploy_account_v1_same_string() { + validate_load_and_dump::("writer/deploy_account_v1.json"); +} + +#[test] +fn load_and_dump_deploy_account_v3_same_string() { + validate_load_and_dump::("writer/deploy_account_v3.json"); +} + +#[test] +fn load_and_dump_invoke_v1_same_string() { + validate_load_and_dump::("writer/invoke_v1.json"); +} + +#[test] +fn load_and_dump_invoke_v3_same_string() { + validate_load_and_dump::("writer/invoke_v3.json"); +} + +#[test] +fn load_and_dump_declare_v1_same_string() { + validate_load_and_dump::("writer/declare_v1.json"); +} + +#[test] +fn load_and_dump_declare_v2_same_string() { + validate_load_and_dump::("writer/declare_v2.json"); +} + +#[test] +fn load_and_dump_declare_v3_same_string() { + validate_load_and_dump::("writer/declare_v3.json"); +} diff --git a/crates/starknet_client/src/writer/starknet_gateway_client_test.rs b/crates/starknet_client/src/writer/starknet_gateway_client_test.rs new file mode 100644 index 00000000000..37f3e4e7b40 --- /dev/null +++ b/crates/starknet_client/src/writer/starknet_gateway_client_test.rs @@ -0,0 +1,218 @@ +use std::fmt::Debug; +use std::future::Future; + +use mockito::{mock, Matcher}; +use serde::{Deserialize, Serialize}; +use test_utils::read_json_file; + +use crate::test_utils::retry::get_test_config; +use crate::writer::{StarknetGatewayClient, StarknetWriter, WriterClientError, WriterClientResult}; + +const NODE_VERSION: &str = "NODE VERSION"; +const GATEWAY_ALIVE_RESPONSE: &str = "Gateway is alive!"; + +async fn run_add_transaction< + Transaction: Serialize + for<'a> Deserialize<'a>, + Response: for<'a> Deserialize<'a> + Debug + Eq, + F: FnOnce(StarknetGatewayClient, Transaction) -> Fut, + Fut: Future>, +>( + resource_file_transaction_path: &str, + resource_file_response_path: &str, + add_transaction_function: F, +) -> WriterClientResult { + let client = + StarknetGatewayClient::new(&mockito::server_url(), NODE_VERSION, get_test_config()) + .unwrap(); + let tx_json_value = read_json_file(resource_file_transaction_path); + let tx = serde_json::from_value::(tx_json_value.clone()).unwrap(); + let response_json_value = read_json_file(resource_file_response_path); + let mock_add_transaction = mock("POST", "/gateway/add_transaction") + .match_body(Matcher::Json(tx_json_value)) + .with_status(200) + .with_body(serde_json::to_string(&response_json_value).unwrap()) + .create(); + let result = add_transaction_function(client, tx).await; + mock_add_transaction.assert(); + result +} + +async fn test_add_transaction_succeeds< + Transaction: Serialize + for<'a> Deserialize<'a>, + Response: for<'a> Deserialize<'a> + Debug + Eq, + F: FnOnce(StarknetGatewayClient, Transaction) -> Fut, + Fut: Future>, +>( + resource_file_transaction_path: &str, + resource_file_response_path: &str, + add_transaction_function: F, +) { + let response_json_value = read_json_file(resource_file_response_path); + let expected_response = serde_json::from_value::(response_json_value).unwrap(); + assert_eq!( + expected_response, + run_add_transaction( + resource_file_transaction_path, + resource_file_response_path, + add_transaction_function + ) + .await + .unwrap() + ); +} + +async fn test_add_transaction_fails_serde< + Transaction: Serialize + for<'a> Deserialize<'a>, + Response: for<'a> Deserialize<'a> + Debug + Eq, + F: FnOnce(StarknetGatewayClient, Transaction) -> Fut, + Fut: Future>, +>( + resource_file_transaction_path: &str, + resource_file_response_path: &str, + add_transaction_function: F, +) { + let Err(WriterClientError::SerdeError(_)) = run_add_transaction( + resource_file_transaction_path, + resource_file_response_path, + add_transaction_function, + ) + .await + else { + panic!("Adding a transaction with bad response did not cause a SerdeError"); + }; +} + +#[tokio::test] +async fn is_alive() { + let starknet_client = + StarknetGatewayClient::new(&mockito::server_url(), NODE_VERSION, get_test_config()) + .unwrap(); + let mock_is_alive = mock("GET", "/gateway/is_alive") + .with_status(200) + .with_body(GATEWAY_ALIVE_RESPONSE) + .create(); + let response = starknet_client.is_alive().await; + mock_is_alive.assert(); + assert!(response); +} + +#[tokio::test] +async fn add_invoke_v1_transaction() { + test_add_transaction_succeeds( + "writer/invoke_v1.json", + "writer/invoke_response.json", + |client, tx| async move { client.add_invoke_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_invoke_v3_transaction() { + test_add_transaction_succeeds( + "writer/invoke_v3.json", + "writer/invoke_response.json", + |client, tx| async move { client.add_invoke_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_declare_v1_transaction() { + test_add_transaction_succeeds( + "writer/declare_v1.json", + "writer/declare_response.json", + |client, tx| async move { client.add_declare_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_declare_v2_transaction() { + test_add_transaction_succeeds( + "writer/declare_v2.json", + "writer/declare_response.json", + |client, tx| async move { client.add_declare_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_declare_v3_transaction() { + test_add_transaction_succeeds( + "writer/declare_v3.json", + "writer/declare_response.json", + |client, tx| async move { client.add_declare_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_deploy_account_v1_transaction() { + test_add_transaction_succeeds( + "writer/deploy_account_v1.json", + "writer/deploy_account_response.json", + |client, tx| async move { client.add_deploy_account_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_deploy_account_v3_transaction() { + test_add_transaction_succeeds( + "writer/deploy_account_v3.json", + "writer/deploy_account_response.json", + |client, tx| async move { client.add_deploy_account_transaction(&tx).await }, + ) + .await; +} + +#[tokio::test] +async fn add_invoke_v1_transaction_wrong_type_response() { + for bad_response_path in ["writer/declare_response.json", "writer/deploy_account_response.json"] + { + test_add_transaction_fails_serde( + "writer/invoke_v1.json", + bad_response_path, + |client, tx| async move { client.add_invoke_transaction(&tx).await }, + ) + .await; + } +} + +#[tokio::test] +async fn add_declare_v1_transaction_wrong_type_response() { + for bad_response_path in ["writer/invoke_response.json", "writer/deploy_account_response.json"] + { + test_add_transaction_fails_serde( + "writer/declare_v1.json", + bad_response_path, + |client, tx| async move { client.add_declare_transaction(&tx).await }, + ) + .await; + } +} + +#[tokio::test] +async fn add_declare_v2_transaction_wrong_type_response() { + for bad_response_path in ["writer/invoke_response.json", "writer/deploy_account_response.json"] + { + test_add_transaction_fails_serde( + "writer/declare_v2.json", + bad_response_path, + |client, tx| async move { client.add_declare_transaction(&tx).await }, + ) + .await; + } +} + +#[tokio::test] +async fn add_deploy_account_transaction_wrong_type_response() { + for bad_response_path in ["writer/invoke_response.json", "writer/declare_response.json"] { + test_add_transaction_fails_serde( + "writer/deploy_account_v1.json", + bad_response_path, + |client, tx| async move { client.add_deploy_account_transaction(&tx).await }, + ) + .await; + } +} diff --git a/crates/starknet_client/tests/feeder_gateway_integration_test.rs b/crates/starknet_client/tests/feeder_gateway_integration_test.rs new file mode 100644 index 00000000000..1266ecb917a --- /dev/null +++ b/crates/starknet_client/tests/feeder_gateway_integration_test.rs @@ -0,0 +1,187 @@ +// TODO(shahak): Uncomment or erase this. + +// #![allow(clippy::unwrap_used)] +// use serde::Serialize; +// use starknet_api::block::BlockNumber; +// use starknet_api::core::ClassHash; +// use starknet_api::hash::StarkHash; +// use starknet_client::reader::{StarknetFeederGatewayClient, StarknetReader}; +// use starknet_client::retry::RetryConfig; +// use tokio::join; + +// const NODE_VERSION: &str = "PAPYRUS-INTEGRATION-TEST-STARKNET-FEEDER-GATEWAY-CLIENT"; + +// #[derive(Serialize)] +// // Blocks with API changes to be tested with the get_block function. +// struct BlocksForGetBlock { +// // First block, the original definitions. +// first_block: u32, +// // A block with declare transaction. (added in v0.9.0). +// declare_tx: u32, +// // A block with starknet version. (added in v0.9.1). +// starknet_version: u32, +// // A block with declare transaction version 1. (added in v0.10.0). +// // A block with nonce field in transaction. (added in v0.10.0). +// declare_version_1: u32, +// // A block with invoke_function transaction version 1 (added in v0.10.0). +// invoke_version_1: u32, +// // A block with deploy_account transaction. (added in v0.10.1). +// deploy_account: u32, +// // A block with declare transaction version 2. (added in v0.11.0). +// declare_version_2: u32, +// } + +// #[derive(Serialize)] +// // Blocks with API changes to be tested with the get_state_update function. +// struct BlocksForGetStateUpdate { +// // First block, the original definitions. +// first_block: u32, +// // A state update with 'old_declared_contracts'. (added in v0.9.1). +// old_declared_contracts: u32, +// // A state update with 'nonces'. (added in v0.10.0). +// nonces: u32, +// // A state update with 'declared_classes'. (added in v0.11.0). +// declared_classes: u32, +// // A state update with 'replaced_classes'. (added in v0.11.0). +// replaced_classes: u32, +// } + +// #[derive(Serialize)] +// // Class hashes of different versions. +// struct ClassHashes { +// // A class definition of Cairo 0 contract. +// cairo_0_class_hash: String, +// // A class definition of Cairo 1 contract. (added in v0.11.0). +// cairo_1_class_hash: String, +// } + +// // Test data for a specific testnet. +// struct TestEnvData { +// url: String, +// get_blocks: BlocksForGetBlock, +// get_state_updates: BlocksForGetStateUpdate, +// class_hashes: ClassHashes, +// } + +// fn into_block_number_vec(obj: T) -> Vec { +// serde_json::to_value(obj) +// .unwrap() +// .as_object() +// .unwrap() +// .values() +// .map(|block_number_json_val| BlockNumber(block_number_json_val.as_u64().unwrap())) +// .collect() +// } + +// #[tokio::test] +// #[ignore] +// async fn test_integration_testnet() { +// let _ = simple_logger::init_with_env(); +// let integration_testnet_data = TestEnvData { +// url: "https://external.integration.starknet.io".to_owned(), +// get_blocks: BlocksForGetBlock { +// first_block: 0, +// declare_tx: 171486, +// starknet_version: 192397, +// declare_version_1: 228224, +// invoke_version_1: 228208, +// deploy_account: 238699, +// declare_version_2: 285182, +// }, +// get_state_updates: BlocksForGetStateUpdate { +// first_block: 0, +// old_declared_contracts: 209679, +// nonces: 228155, +// declared_classes: 285182, +// replaced_classes: 0, // No block with this API change yet. +// }, +// class_hashes: ClassHashes { +// cairo_0_class_hash: +// "0x2753ce06a79a9a9c608787a608b424f79c56f465954f1f3a7f6785d575366fb" .to_owned(), +// cairo_1_class_hash: +// "0x2f80a64102b148f7142f1ec14a786ef130e2d4320f2214f4aafebb961e3ab45" .to_owned(), +// }, +// }; +// run(integration_testnet_data).await; +// } + +// #[tokio::test] +// #[ignore] +// async fn test_alpha_testnet() { +// let _ = simple_logger::init_with_env(); +// let alpha_testnet_data = TestEnvData { +// url: "https://alpha4.starknet.io/".to_owned(), +// get_blocks: BlocksForGetBlock { +// first_block: 0, +// declare_tx: 248971, +// starknet_version: 280000, +// declare_version_1: 330039, +// invoke_version_1: 330291, +// deploy_account: 385429, +// declare_version_2: 789048, +// }, +// get_state_updates: BlocksForGetStateUpdate { +// first_block: 0, +// old_declared_contracts: 248971, +// nonces: 330039, +// declared_classes: 789048, +// replaced_classes: 788504, +// }, +// class_hashes: ClassHashes { +// cairo_0_class_hash: +// "0x7af612493193c771c1b12f511a8b4d3b0c6d0648242af4680c7cd0d06186f17" .to_owned(), +// cairo_1_class_hash: +// "0x702a9e80c74a214caf0e77326180e72ba3bd3f53dbd5519ede339eb3ae9eed4" .to_owned(), +// }, +// }; +// run(alpha_testnet_data).await; +// } + +// async fn run(test_env_data: TestEnvData) { +// let starknet_client = StarknetFeederGatewayClient::new( +// &test_env_data.url, +// None, +// NODE_VERSION, +// RetryConfig { retry_base_millis: 30, retry_max_delay_millis: 30000, max_retries: 10 }, +// ) +// .expect("Create new client"); + +// join!( +// test_get_block(&starknet_client, test_env_data.get_blocks), +// test_get_state_update(&starknet_client, test_env_data.get_state_updates), +// test_class_hash(&starknet_client, test_env_data.class_hashes), +// async { starknet_client.pending_data().await.unwrap().unwrap() }, +// ); +// } + +// // Call get_block on the given list of block_numbers. +// async fn test_get_block( +// starknet_client: &StarknetFeederGatewayClient, +// block_numbers: BlocksForGetBlock, +// ) { for block_number in into_block_number_vec(block_numbers) { +// starknet_client.block(block_number).await.unwrap().unwrap(); } + +// // Get the last block. +// starknet_client.latest_block().await.unwrap().unwrap(); +// // Not existing block. +// assert!(starknet_client.block(BlockNumber(u64::MAX)).await.unwrap().is_none()); +// } + +// // Call get_state_update on the given list of block_numbers. +// async fn test_get_state_update( +// starknet_client: &StarknetFeederGatewayClient, +// block_numbers: BlocksForGetStateUpdate, +// ) { for block_number in into_block_number_vec(block_numbers) { +// starknet_client.state_update(block_number).await.unwrap().unwrap(); } +// } + +// // Call class_by_hash for the given list of class_hashes. +// async fn test_class_hash(starknet_client: &StarknetFeederGatewayClient, class_hashes: +// ClassHashes) { let data = serde_json::to_value(class_hashes).unwrap(); + +// for class_hash_json_val in data.as_object().unwrap().values() { +// let class_hash_val = class_hash_json_val.as_str().unwrap(); +// let class_hash = ClassHash(StarkHash::try_from(class_hash_val).unwrap()); +// starknet_client.class_by_hash(class_hash).await.unwrap().unwrap(); +// } +// } diff --git a/crates/starknet_sierra_compile/Cargo.toml b/crates/starknet_sierra_compile/Cargo.toml new file mode 100644 index 00000000000..51f253868b2 --- /dev/null +++ b/crates/starknet_sierra_compile/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "starknet_sierra_compile" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +cairo-lang-sierra.workspace = true +cairo-lang-starknet-classes.workspace = true +cairo-lang-utils.workspace = true +serde_json.workspace = true +serde.workspace = true +starknet_api.workspace = true +starknet-types-core.workspace = true +thiserror.workspace = true + +[dev-dependencies] +assert_matches.workspace = true +mempool_test_utils = {path = "../mempool_test_utils"} diff --git a/crates/starknet_sierra_compile/src/compile.rs b/crates/starknet_sierra_compile/src/compile.rs new file mode 100644 index 00000000000..23ac70ce395 --- /dev/null +++ b/crates/starknet_sierra_compile/src/compile.rs @@ -0,0 +1,33 @@ +use cairo_lang_starknet_classes::allowed_libfuncs::ListSelector; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use cairo_lang_starknet_classes::contract_class::ContractClass; + +use crate::errors::CompilationUtilError; + +#[cfg(test)] +#[path = "compile_test.rs"] +pub mod compile_test; +pub struct SierraToCasmCompilationArgs { + list_selector: ListSelector, + add_pythonic_hints: bool, + max_bytecode_size: usize, +} + +/// This function may panic. +pub fn compile_sierra_to_casm( + contract_class: ContractClass, +) -> Result { + let compilation_args = SierraToCasmCompilationArgs { + list_selector: ListSelector::DefaultList, + add_pythonic_hints: true, + max_bytecode_size: 1000000, + }; + + contract_class.validate_version_compatible(compilation_args.list_selector)?; + + Ok(CasmContractClass::from_contract_class( + contract_class, + compilation_args.add_pythonic_hints, + compilation_args.max_bytecode_size, + )?) +} diff --git a/crates/starknet_sierra_compile/src/compile_test.rs b/crates/starknet_sierra_compile/src/compile_test.rs new file mode 100644 index 00000000000..14e0b3d130b --- /dev/null +++ b/crates/starknet_sierra_compile/src/compile_test.rs @@ -0,0 +1,39 @@ +use std::env; +use std::path::Path; + +use assert_matches::assert_matches; +use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; +use mempool_test_utils::{get_absolute_path, FAULTY_ACCOUNT_CLASS_FILE, TEST_FILES_FOLDER}; + +use crate::compile::{compile_sierra_to_casm, CompilationUtilError}; +use crate::test_utils::contract_class_from_file; + +#[test] +fn test_compile_sierra_to_casm() { + env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Failed to set current dir."); + let sierra_path = Path::new(FAULTY_ACCOUNT_CLASS_FILE); + let expected_casm_contract_length = 72304; + + let contract_class = contract_class_from_file(sierra_path); + let casm_contract = compile_sierra_to_casm(contract_class).unwrap(); + let serialized_casm = serde_json::to_string_pretty(&casm_contract).unwrap().into_bytes(); + + assert_eq!(serialized_casm.len(), expected_casm_contract_length); +} + +// TODO(Arni, 1/5/2024): Add a test for panic result test. +#[test] +fn test_negative_flow_compile_sierra_to_casm() { + env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Failed to set current dir."); + let sierra_path = Path::new(FAULTY_ACCOUNT_CLASS_FILE); + + let mut contract_class = contract_class_from_file(sierra_path); + // Truncate the sierra program to trigger an error. + contract_class.sierra_program = contract_class.sierra_program[..100].to_vec(); + + let result = compile_sierra_to_casm(contract_class); + assert_matches!( + result, + Err(CompilationUtilError::AllowedLibfuncsError(AllowedLibfuncsError::SierraProgramError)) + ); +} diff --git a/crates/starknet_sierra_compile/src/errors.rs b/crates/starknet_sierra_compile/src/errors.rs new file mode 100644 index 00000000000..2d3d2575fa2 --- /dev/null +++ b/crates/starknet_sierra_compile/src/errors.rs @@ -0,0 +1,13 @@ +use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; +use cairo_lang_starknet_classes::casm_contract_class::StarknetSierraCompilationError; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum CompilationUtilError { + #[error(transparent)] + AllowedLibfuncsError(#[from] AllowedLibfuncsError), + #[error(transparent)] + StarknetSierraCompilationError(#[from] StarknetSierraCompilationError), + #[error("Compilation panicked")] + CompilationPanic, +} diff --git a/crates/starknet_sierra_compile/src/lib.rs b/crates/starknet_sierra_compile/src/lib.rs new file mode 100644 index 00000000000..d949f064bd1 --- /dev/null +++ b/crates/starknet_sierra_compile/src/lib.rs @@ -0,0 +1,8 @@ +//! A lib for compiling Sierra into Casm. + +pub mod compile; +pub mod errors; +pub mod utils; + +#[cfg(test)] +pub mod test_utils; diff --git a/crates/starknet_sierra_compile/src/test_utils.rs b/crates/starknet_sierra_compile/src/test_utils.rs new file mode 100644 index 00000000000..39493a09e00 --- /dev/null +++ b/crates/starknet_sierra_compile/src/test_utils.rs @@ -0,0 +1,33 @@ +use std::fs; +use std::path::Path; + +use cairo_lang_starknet_classes::contract_class::{ContractClass, ContractEntryPoints}; +use cairo_lang_utils::bigint::BigUintAsHex; +use serde::Deserialize; + +/// Same as `ContractClass` - but ignores unnecessary fields like `abi` in deserialization. +#[derive(Deserialize)] +struct DeserializedContractClass { + pub sierra_program: Vec, + pub sierra_program_debug_info: Option, + pub contract_class_version: String, + pub entry_points_by_type: ContractEntryPoints, +} + +pub(crate) fn contract_class_from_file>(path: P) -> ContractClass { + let DeserializedContractClass { + sierra_program, + sierra_program_debug_info, + contract_class_version, + entry_points_by_type, + } = serde_json::from_str(&fs::read_to_string(path).expect("Failed to read input file.")) + .expect("deserialization Failed."); + + ContractClass { + sierra_program, + sierra_program_debug_info, + contract_class_version, + entry_points_by_type, + abi: None, + } +} diff --git a/crates/starknet_sierra_compile/src/utils.rs b/crates/starknet_sierra_compile/src/utils.rs new file mode 100644 index 00000000000..5ccdcf9faf0 --- /dev/null +++ b/crates/starknet_sierra_compile/src/utils.rs @@ -0,0 +1,61 @@ +use std::clone::Clone; + +use cairo_lang_starknet_classes::contract_class::{ + ContractClass as CairoLangContractClass, ContractEntryPoint as CairoLangContractEntryPoint, + ContractEntryPoints as CairoLangContractEntryPoints, +}; +use cairo_lang_utils::bigint::BigUintAsHex; +use starknet_api::rpc_transaction::{ + ContractClass as RpcContractClass, EntryPointByType as StarknetApiEntryPointByType, +}; +use starknet_api::state::EntryPoint as StarknetApiEntryPoint; +use starknet_types_core::felt::Felt; + +/// Retruns a [`CairoLangContractClass`] struct ready for Sierra to Casm compilation. Note the `abi` +/// field is None as it is not relevant for the compilation. +pub fn into_contract_class_for_compilation( + rpc_contract_class: &RpcContractClass, +) -> CairoLangContractClass { + let sierra_program = + rpc_contract_class.sierra_program.iter().map(felt_to_big_uint_as_hex).collect(); + let entry_points_by_type = + into_cairo_lang_contract_entry_points(&rpc_contract_class.entry_points_by_type); + + CairoLangContractClass { + sierra_program, + sierra_program_debug_info: None, + contract_class_version: rpc_contract_class.contract_class_version.clone(), + entry_points_by_type, + abi: None, + } +} + +fn into_cairo_lang_contract_entry_points( + entry_points_by_type: &StarknetApiEntryPointByType, +) -> CairoLangContractEntryPoints { + let StarknetApiEntryPointByType { constructor, external, l1handler } = entry_points_by_type; + CairoLangContractEntryPoints { + external: into_cairo_lang_contract_entry_points_vec(external), + l1_handler: into_cairo_lang_contract_entry_points_vec(l1handler), + constructor: into_cairo_lang_contract_entry_points_vec(constructor), + } +} + +fn into_cairo_lang_contract_entry_points_vec( + entry_points: &[StarknetApiEntryPoint], +) -> Vec { + entry_points.iter().map(into_cairo_lang_contract_entry_point).collect() +} + +fn into_cairo_lang_contract_entry_point( + entry_point: &StarknetApiEntryPoint, +) -> CairoLangContractEntryPoint { + CairoLangContractEntryPoint { + selector: entry_point.selector.0.to_biguint(), + function_idx: entry_point.function_idx.0, + } +} + +fn felt_to_big_uint_as_hex(felt: &Felt) -> BigUintAsHex { + BigUintAsHex { value: felt.to_biguint() } +} diff --git a/crates/task_executor/Cargo.toml b/crates/task_executor/Cargo.toml new file mode 100644 index 00000000000..f622c6f95c5 --- /dev/null +++ b/crates/task_executor/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "starknet_task_executor" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[dependencies] +tokio.workspace = true + +[dev-dependencies] +futures.workspace = true +rstest.workspace = true +tokio-test.workspace = true + +[lints] +workspace = true diff --git a/crates/task_executor/src/executor.rs b/crates/task_executor/src/executor.rs new file mode 100644 index 00000000000..e1fb3b4ba78 --- /dev/null +++ b/crates/task_executor/src/executor.rs @@ -0,0 +1,24 @@ +use std::future::Future; + +/// An abstraction for executing tasks, suitable for both CPU-bound and I/O-bound operations. +pub trait TaskExecutor { + type SpawnBlockingError; + type SpawnError; + + /// Offloads a blocking task, _ensuring_ the async event loop remains responsive. + /// It accepts a function that executes a blocking operation and returns a result. + fn spawn_blocking( + &self, + task: F, + ) -> impl Future> + Send + where + F: FnOnce() -> T + Send + 'static, + T: Send + 'static; + + /// Offloads a non-blocking task asynchronously. + /// It accepts a future representing an asynchronous operation and returns a result. + fn spawn(&self, task: F) -> impl Future> + Send + where + F: Future + Send + 'static, + T: Send + 'static; +} diff --git a/crates/task_executor/src/lib.rs b/crates/task_executor/src/lib.rs new file mode 100644 index 00000000000..306d004c59f --- /dev/null +++ b/crates/task_executor/src/lib.rs @@ -0,0 +1,5 @@ +//! This crate contains the async and blocking tasks Executor, which is temporarily placed here. +//! It will likely be moved to `mempool_infra` or some other infra crate in the future. + +pub mod executor; +pub mod tokio_executor; diff --git a/crates/task_executor/src/tokio_executor.rs b/crates/task_executor/src/tokio_executor.rs new file mode 100644 index 00000000000..b77c954b301 --- /dev/null +++ b/crates/task_executor/src/tokio_executor.rs @@ -0,0 +1,131 @@ +use std::future::Future; + +use tokio::runtime::Handle; + +use crate::executor::TaskExecutor; +#[cfg(test)] +#[path = "tokio_executor_test.rs"] +pub mod test; + +#[derive(Clone)] +pub struct TokioExecutor { + // Invariant: the handle must remain private to ensure all tasks spawned via this + // executor originate from the same handle, maintaining control and consistency. + handle: Handle, +} + +impl TokioExecutor { + pub fn new(handle: Handle) -> Self { + Self { handle } + } + + /// Spawns a task and returns a `JoinHandle`. + /// + /// This method is needed to allow tasks to be tracked and managed through a `JoinHandle`, + /// enabling control over task lifecycle such as awaiting completion, cancellation, or checking + /// results. It should be used only when the caller needs to manage the task directly, which is + /// essential both in testing scenarios and in the actual system `main` function. + /// Note: In most cases, where task management is not necessary, the `spawn` or + /// `spawn_blocking` methods should be preferred. + /// + /// # Example + /// ``` + /// use starknet_task_executor::tokio_executor::TokioExecutor; + /// use tokio::runtime::Handle; + /// use tokio::sync::oneshot; + /// + /// #[tokio::main] + /// async fn main() { + /// let runtime = Handle::current(); + /// let executor = TokioExecutor::new(runtime); + /// + /// // Create a oneshot channel to simulate a task waiting for a signal. + /// let (_will_not_send, await_signal_that_wont_come) = oneshot::channel::<()>(); + /// + /// // Spawn a task that waits for the signal (which we will not send). + /// let handle = executor.spawn_with_handle(async move { + /// await_signal_that_wont_come.await.ok(); + /// }); + /// + /// // Abort the task before sending the signal. + /// handle.abort(); + /// + /// assert!(handle.await.unwrap_err().is_cancelled()); + /// } + /// ``` + pub fn spawn_with_handle(&self, future: F) -> tokio::task::JoinHandle + where + F: Future + Send + 'static, + F::Output: Send + 'static, + { + self.handle.spawn(future) + } +} + +impl TaskExecutor for TokioExecutor { + /// Note: `Tokio` catches task panics that returns them as errors, this is a `Tokio`-specific + /// behavior. + type SpawnBlockingError = tokio::task::JoinError; + type SpawnError = tokio::task::JoinError; + + /// Spawns a task that may block, on a dedicated thread, preventing disruption of the async + /// runtime. + + /// # Example + /// + /// ``` + /// use starknet_task_executor::executor::TaskExecutor; + /// use starknet_task_executor::tokio_executor::TokioExecutor; + /// + /// tokio_test::block_on(async { + /// let executor = TokioExecutor::new(tokio::runtime::Handle::current()); + /// let task = || { + /// // Simulate CPU-bound work (sleep/Duration from std and not tokio!). + /// std::thread::sleep(std::time::Duration::from_millis(100)); + /// "FLOOF" + /// }; + /// let result = executor.spawn_blocking(task).await; + /// assert_eq!(result.unwrap(), "FLOOF"); + /// }); + /// ``` + fn spawn_blocking( + &self, + task: F, + ) -> impl Future> + Send + where + F: FnOnce() -> T + Send + 'static, + T: Send + 'static, + { + self.handle.spawn_blocking(task) + } + + /// Executes a async, non-blocking task. + /// + /// Note: If you need to manage the task directly through a `JoinHandle`, use + /// [`Self::spawn_with_handle`] instead. + /// + /// # Example + /// + /// ``` + /// use starknet_task_executor::{ + /// tokio_executor::TokioExecutor, executor::TaskExecutor + /// }; + /// + /// tokio_test::block_on(async { + /// let executor = TokioExecutor::new(tokio::runtime::Handle::current()); + /// let future = async { + /// // Simulate IO-bound work (sleep/Duration from tokio!). + /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + /// "HOPALA" + /// }; + /// let result = executor.spawn(future).await; + /// assert_eq!(result.unwrap(), "HOPALA"); + /// }); + fn spawn(&self, task: F) -> impl Future> + Send + where + F: Future + Send + 'static, + T: Send + 'static, + { + self.handle.spawn(task) + } +} diff --git a/crates/task_executor/src/tokio_executor_test.rs b/crates/task_executor/src/tokio_executor_test.rs new file mode 100644 index 00000000000..1d8bf021299 --- /dev/null +++ b/crates/task_executor/src/tokio_executor_test.rs @@ -0,0 +1,23 @@ +use rstest::{fixture, rstest}; +use tokio::runtime::Handle; + +use crate::executor::TaskExecutor; +use crate::tokio_executor::TokioExecutor; + +#[fixture] +fn executor() -> TokioExecutor { + TokioExecutor::new(Handle::current()) +} + +#[rstest] +#[tokio::test] +async fn test_panic_catching(executor: TokioExecutor) { + // Assert that panic in a task is caught and wrapped in an error. + assert!(executor.spawn_blocking(|| panic!()).await.is_err()); + // Ensure the executor remained usable after the worker thread panicked. + assert!(executor.spawn_blocking(|| "Real tasks don't panic").await.is_ok()); + + // Ditto for async tasks. + assert!(executor.spawn(async { panic!() }).await.is_err()); + assert!(executor.spawn(async { "Real async tasks don't panic" }).await.is_ok()); +} diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml new file mode 100644 index 00000000000..06784baf9b8 --- /dev/null +++ b/crates/test_utils/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "test_utils" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true + +[features] + +[dependencies] +cairo-lang-starknet-classes.workspace = true +cairo-lang-casm.workspace = true +cairo-lang-utils.workspace = true +indexmap = { workspace = true, features = ["serde"] } +primitive-types = { workspace = true, features = ["serde"] } +prometheus-parse.workspace = true +num-bigint.workspace = true +rand.workspace = true +rand_chacha.workspace = true +reqwest = { workspace = true, features = ["json"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["arbitrary_precision"]} +starknet_api = { workspace = true, features = ["testing"] } +starknet-types-core = { workspace = true, features = ["hash"] } + +[dev-dependencies] +pretty_assertions.workspace = true diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs new file mode 100644 index 00000000000..369dafa4d90 --- /dev/null +++ b/crates/test_utils/src/lib.rs @@ -0,0 +1,1064 @@ +#![allow(clippy::unwrap_used)] +#[cfg(test)] +mod precision_test; + +use std::cmp::max; +use std::collections::{BTreeMap, HashMap}; +use std::env; +use std::fs::read_to_string; +use std::hash::Hash; +use std::net::SocketAddr; +use std::num::NonZeroU64; +use std::ops::{Deref, Index}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use cairo_lang_casm::hints::{CoreHint, CoreHintBase, Hint}; +use cairo_lang_casm::operand::{ + BinOpOperand, + CellRef, + DerefOrImmediate, + Operation, + Register, + ResOperand, +}; +use cairo_lang_starknet_classes::casm_contract_class::{ + CasmContractClass, + CasmContractEntryPoint, + CasmContractEntryPoints, +}; +use cairo_lang_starknet_classes::NestedIntList; +use cairo_lang_utils::bigint::BigUintAsHex; +use indexmap::IndexMap; +use num_bigint::BigUint; +use primitive_types::H160; +use prometheus_parse::Value; +use rand::{Rng, RngCore, SeedableRng}; +use rand_chacha::ChaCha8Rng; +use reqwest::Client; +use serde::{Deserialize, Serialize}; +use starknet_api::block::{ + Block, + BlockBody, + BlockHash, + BlockHeader, + BlockNumber, + BlockSignature, + BlockStatus, + BlockTimestamp, + GasPrice, + GasPricePerToken, + StarknetVersion, +}; +use starknet_api::core::{ + ClassHash, + CompiledClassHash, + ContractAddress, + EntryPointSelector, + EthAddress, + EventCommitment, + GlobalRoot, + Nonce, + ReceiptCommitment, + SequencerContractAddress, + StateDiffCommitment, + TransactionCommitment, +}; +use starknet_api::crypto::utils::Signature; +use starknet_api::data_availability::{DataAvailabilityMode, L1DataAvailabilityMode}; +use starknet_api::deprecated_contract_class::{ + ConstructorType, + ContractClass as DeprecatedContractClass, + ContractClassAbiEntry, + EntryPoint as DeprecatedEntryPoint, + EntryPointOffset, + EntryPointType as DeprecatedEntryPointType, + EventAbiEntry, + EventType, + FunctionAbiEntry, + FunctionStateMutability, + FunctionType, + L1HandlerType, + Program, + StructAbiEntry, + StructMember, + StructType, + TypedParameter, +}; +use starknet_api::felt; +use starknet_api::hash::{PoseidonHash, StarkHash}; +use starknet_api::state::{ + ContractClass, + EntryPoint, + EntryPointType, + FunctionIndex, + StateDiff, + StorageKey, + ThinStateDiff, +}; +use starknet_api::transaction::{ + AccountDeploymentData, + Builtin, + Calldata, + ContractAddressSalt, + DeclareTransaction, + DeclareTransactionOutput, + DeclareTransactionV0V1, + DeclareTransactionV2, + DeclareTransactionV3, + DeployAccountTransaction, + DeployAccountTransactionOutput, + DeployAccountTransactionV1, + DeployAccountTransactionV3, + DeployTransaction, + DeployTransactionOutput, + Event, + EventContent, + EventData, + EventIndexInTransactionOutput, + EventKey, + ExecutionResources, + Fee, + GasVector, + InvokeTransaction, + InvokeTransactionOutput, + InvokeTransactionV0, + InvokeTransactionV1, + InvokeTransactionV3, + L1HandlerTransaction, + L1HandlerTransactionOutput, + L1ToL2Payload, + L2ToL1Payload, + MessageToL1, + MessageToL2, + PaymasterData, + Resource, + ResourceBounds, + ResourceBoundsMapping, + RevertedTransactionExecutionStatus, + Tip, + Transaction, + TransactionExecutionStatus, + TransactionHash, + TransactionOffsetInBlock, + TransactionOutput, + TransactionSignature, + TransactionVersion, +}; +use starknet_types_core::felt::Felt; + +////////////////////////////////////////////////////////////////////////// +// GENERIC TEST UTIL FUNCTIONS +////////////////////////////////////////////////////////////////////////// + +pub async fn send_request( + address: SocketAddr, + method: &str, + params: &str, + version: &str, +) -> serde_json::Value { + let client = Client::new(); + let res_str = client + .post(format!("http://{address:?}/rpc/{version}")) + .header("Content-Type", "application/json") + .body(format!(r#"{{"jsonrpc":"2.0","id":"1","method":"{method}","params":[{params}]}}"#)) + .send() + .await + .unwrap() + .text() + .await + .unwrap(); + serde_json::from_str(&res_str).unwrap() +} + +/// Returns the absolute path from the project root. +pub fn get_absolute_path(relative_path: &str) -> PathBuf { + Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../..").join(relative_path) +} + +/// Reads from the directory containing the manifest at run time, same as current working directory. +pub fn read_json_file(path_in_resource_dir: &str) -> serde_json::Value { + let path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("resources") + .join(path_in_resource_dir); + let json_str = read_to_string(path.to_str().unwrap()).unwrap(); + serde_json::from_str(&json_str).unwrap() +} + +pub fn validate_load_and_dump Deserialize<'a>>(path_in_resource_dir: &str) { + let json_value = read_json_file(path_in_resource_dir); + let load_result = serde_json::from_value::(json_value.clone()); + assert!(load_result.is_ok(), "error: {:?}", load_result.err()); + let dump_result = serde_json::to_value(&(load_result.unwrap())); + assert!(dump_result.is_ok(), "error: {:?}", dump_result.err()); + assert_eq!(json_value, dump_result.unwrap()); +} + +/// Used in random test to create a random generator, see for example storage_serde_test. +/// Randomness can be seeded by setting and env variable `SEED` or by the OS (the rust default). +pub fn get_rng() -> ChaCha8Rng { + let seed: u64 = match env::var("SEED") { + Ok(seed_str) => seed_str.parse().unwrap(), + _ => rand::thread_rng().gen(), + }; + // Will be printed if the test failed. + println!("Testing with seed: {seed:?}"); + // Create a new PRNG using a u64 seed. This is a convenience-wrapper around from_seed. + // It is designed such that low Hamming Weight numbers like 0 and 1 can be used and + // should still result in good, independent seeds to the returned PRNG. + // This is not suitable for cryptography purposes. + ChaCha8Rng::seed_from_u64(seed) +} + +/// Use to get the value of a metric by name and labels. +// If the data contains a metric with metric_name and labels returns its value else None. +pub fn prometheus_is_contained( + data: String, + metric_name: &str, + labels: &[(&str, &str)], +) -> Option { + // Converts labels to HashMap. + let labels: HashMap = + labels.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(); + + let lines: Vec<_> = data.lines().map(|s| Ok(s.to_owned())).collect(); + let metrics = prometheus_parse::Scrape::parse(lines.into_iter()).unwrap(); + for s in metrics.samples { + if s.metric == metric_name && s.labels.deref() == &labels { + return Some(s.value); + } + } + None +} + +////////////////////////////////////////////////////////////////////////// +// INTERNAL FUNCTIONS +////////////////////////////////////////////////////////////////////////// + +/// Returns a test block with a variable number of transactions and events. +fn get_rand_test_block_with_events( + rng: &mut ChaCha8Rng, + transaction_count: usize, + events_per_tx: usize, + from_addresses: Option>, + keys: Option>>, +) -> Block { + Block { + header: BlockHeader::default(), + body: get_rand_test_body_with_events( + rng, + transaction_count, + events_per_tx, + from_addresses, + keys, + ), + } +} + +// TODO(Dan, 01/11/2023): Remove this util once v3 tests are ready and transaction generation is +// using randomness more stably. +fn is_v3_transaction(transaction: &Transaction) -> bool { + matches!( + transaction, + Transaction::Declare(DeclareTransaction::V3(_)) + | Transaction::DeployAccount(DeployAccountTransaction::V3(_)) + | Transaction::Invoke(InvokeTransaction::V3(_)) + ) +} + +/// Returns a test block body with a variable number of transactions and events. +fn get_rand_test_body_with_events( + rng: &mut ChaCha8Rng, + transaction_count: usize, + events_per_tx: usize, + from_addresses: Option>, + keys: Option>>, +) -> BlockBody { + let mut transactions = vec![]; + let mut transaction_outputs = vec![]; + let mut transaction_hashes = vec![]; + let mut transaction_execution_statuses = vec![]; + for i in 0..transaction_count { + let mut transaction = Transaction::get_test_instance(rng); + while is_v3_transaction(&transaction) { + transaction = Transaction::get_test_instance(rng); + } + transaction_hashes.push(TransactionHash(StarkHash::from(i as u128))); + let transaction_output = get_test_transaction_output(&transaction); + transactions.push(transaction); + transaction_outputs.push(transaction_output); + transaction_execution_statuses.push(TransactionExecutionStatus::default()); + } + let mut body = BlockBody { transactions, transaction_outputs, transaction_hashes }; + for tx_output in &mut body.transaction_outputs { + let mut events = vec![]; + for _ in 0..events_per_tx { + let from_address = if let Some(ref options) = from_addresses { + *options.index(rng.gen_range(0..options.len())) + } else { + ContractAddress::default() + }; + let final_keys = if let Some(ref options) = keys { + let mut chosen_keys = vec![]; + for options_per_i in options { + let key = options_per_i.index(rng.gen_range(0..options_per_i.len())).clone(); + chosen_keys.push(key); + } + chosen_keys + } else { + vec![EventKey::default()] + }; + events.push(Event { + from_address, + content: EventContent { keys: final_keys, data: EventData::default() }, + }); + } + set_events(tx_output, events); + } + body +} + +fn get_test_transaction_output(transaction: &Transaction) -> TransactionOutput { + let mut rng = get_rng(); + let execution_resources = ExecutionResources::get_test_instance(&mut rng); + let execution_status = TransactionExecutionStatus::get_test_instance(&mut rng); + match transaction { + Transaction::Declare(_) => TransactionOutput::Declare(DeclareTransactionOutput { + execution_resources, + execution_status, + ..Default::default() + }), + Transaction::Deploy(_) => TransactionOutput::Deploy(DeployTransactionOutput { + execution_resources, + execution_status, + ..Default::default() + }), + Transaction::DeployAccount(_) => { + TransactionOutput::DeployAccount(DeployAccountTransactionOutput { + execution_resources, + execution_status, + ..Default::default() + }) + } + Transaction::Invoke(_) => TransactionOutput::Invoke(InvokeTransactionOutput { + execution_resources, + execution_status, + ..Default::default() + }), + Transaction::L1Handler(_) => TransactionOutput::L1Handler(L1HandlerTransactionOutput { + execution_resources, + execution_status, + ..Default::default() + }), + } +} + +fn set_events(tx: &mut TransactionOutput, events: Vec) { + match tx { + TransactionOutput::Declare(tx) => tx.events = events, + TransactionOutput::Deploy(tx) => tx.events = events, + TransactionOutput::DeployAccount(tx) => tx.events = events, + TransactionOutput::Invoke(tx) => tx.events = events, + TransactionOutput::L1Handler(tx) => tx.events = events, + } +} + +////////////////////////////////////////////////////////////////////////// +/// EXTERNAL FUNCTIONS - REMOVE DUPLICATIONS +////////////////////////////////////////////////////////////////////////// + +// Returns a test block with a variable number of transactions and events. +pub fn get_test_block( + transaction_count: usize, + // TODO(shahak): remove unused event-related arguments. + events_per_tx: Option, + from_addresses: Option>, + keys: Option>>, +) -> Block { + let mut rng = get_rng(); + let events_per_tx = events_per_tx.unwrap_or_default(); + get_rand_test_block_with_events( + &mut rng, + transaction_count, + events_per_tx, + from_addresses, + keys, + ) +} + +// Returns a test block body with a variable number of transactions. +pub fn get_test_body( + transaction_count: usize, + events_per_tx: Option, + from_addresses: Option>, + keys: Option>>, +) -> BlockBody { + let mut rng = get_rng(); + let events_per_tx = events_per_tx.unwrap_or_default(); + get_rand_test_body_with_events(&mut rng, transaction_count, events_per_tx, from_addresses, keys) +} + +// Returns a state diff with one item in each IndexMap. +// For a random test state diff call StateDiff::get_test_instance. +pub fn get_test_state_diff() -> StateDiff { + let mut rng = get_rng(); + let mut res = StateDiff::get_test_instance(&mut rng); + // TODO(anatg): fix StateDiff::get_test_instance so the declared_classes will have different + // hashes than the deprecated_contract_classes. + let (_, data) = res.declared_classes.pop().unwrap(); + res.declared_classes.insert(ClassHash(felt!("0x001")), data); + // TODO(yair): Find a way to create replaced classes in a test instance of StateDiff. + res.replaced_classes.clear(); + res +} + +//////////////////////////////////////////////////////////////////////// +// Implementation of GetTestInstance +//////////////////////////////////////////////////////////////////////// + +pub trait GetTestInstance: Sized { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self; +} + +auto_impl_get_test_instance! { + pub struct AccountDeploymentData(pub Vec); + pub struct BlockHash(pub StarkHash); + pub struct BlockHeader { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, + pub n_transactions: usize, + pub n_events: usize, + pub starknet_version: StarknetVersion, + } + pub struct BlockNumber(pub u64); + pub struct BlockSignature(pub Signature); + pub enum BlockStatus { + Pending = 0, + AcceptedOnL2 = 1, + AcceptedOnL1 = 2, + Rejected = 3, + } + pub struct BlockTimestamp(pub u64); + pub enum Builtin { + RangeCheck = 0, + Pedersen = 1, + Poseidon = 2, + EcOp = 3, + Ecdsa = 4, + Bitwise = 5, + Keccak = 6, + SegmentArena = 7, + AddMod = 8, + MulMod = 9, + RangeCheck96 = 10, + } + pub struct StarknetVersion(pub String); + pub struct Calldata(pub Arc>); + pub struct ClassHash(pub StarkHash); + pub struct CompiledClassHash(pub StarkHash); + pub struct ContractAddressSalt(pub StarkHash); + pub struct ContractClass { + pub sierra_program: Vec, + pub entry_points_by_type: HashMap>, + pub abi: String, + } + pub struct DeprecatedContractClass { + pub abi: Option>, + pub program: Program, + pub entry_points_by_type: HashMap>, + } + pub enum ContractClassAbiEntry { + Event(EventAbiEntry) = 0, + Function(FunctionAbiEntry) = 1, + Constructor(FunctionAbiEntry) = 2, + L1Handler(FunctionAbiEntry) = 3, + Struct(StructAbiEntry) = 4, + } + pub enum DataAvailabilityMode { + L1 = 0, + L2 = 1, + } + pub enum DeclareTransaction { + V0(DeclareTransactionV0V1) = 0, + V1(DeclareTransactionV0V1) = 1, + V2(DeclareTransactionV2) = 2, + V3(DeclareTransactionV3) = 3, + } + pub struct DeclareTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + pub struct DeclareTransactionV0V1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub sender_address: ContractAddress, + } + pub struct DeclareTransactionV2 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + } + pub struct DeclareTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + } + pub enum DeployAccountTransaction { + V1(DeployAccountTransactionV1) = 0, + V3(DeployAccountTransactionV3) = 1, + } + pub struct DeployAccountTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + pub struct DeployAccountTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + } + pub struct DeployAccountTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + } + pub struct DeployTransaction { + pub version: TransactionVersion, + pub class_hash: ClassHash, + pub contract_address_salt: ContractAddressSalt, + pub constructor_calldata: Calldata, + } + pub struct DeployTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub contract_address: ContractAddress, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + pub struct DeprecatedEntryPoint { + pub selector: EntryPointSelector, + pub offset: EntryPointOffset, + } + pub enum DeprecatedEntryPointType { + Constructor = 0, + External = 1, + L1Handler = 2, + } + pub struct EntryPoint { + pub function_idx: FunctionIndex, + pub selector: EntryPointSelector, + } + pub struct Event { + pub from_address: ContractAddress, + pub content: EventContent, + } + pub struct EventCommitment(pub StarkHash); + pub struct FunctionIndex(pub usize); + pub struct EntryPointOffset(pub usize); + pub struct EntryPointSelector(pub StarkHash); + pub enum EntryPointType { + Constructor = 0, + External = 1, + L1Handler = 2, + } + pub struct EventAbiEntry { + pub name: String, + pub keys: Vec, + pub data: Vec, + pub r#type: EventType, + } + pub struct EventContent { + pub keys: Vec, + pub data: EventData, + } + pub struct EventData(pub Vec); + pub struct EventIndexInTransactionOutput(pub usize); + pub struct EventKey(pub Felt); + pub enum EventType { + Event = 0, + } + pub struct Fee(pub u128); + pub enum FunctionStateMutability { + View = 0, + } + pub enum FunctionType { + Function = 0, + } + pub struct GasPrice(pub u128); + pub struct GasPricePerToken { + pub price_in_fri: GasPrice, + pub price_in_wei: GasPrice, + } + pub struct GlobalRoot(pub StarkHash); + pub enum InvokeTransaction { + V0(InvokeTransactionV0) = 0, + V1(InvokeTransactionV1) = 1, + V3(InvokeTransactionV3) = 2, + } + pub struct InvokeTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + pub struct InvokeTransactionV0 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub struct InvokeTransactionV1 { + pub max_fee: Fee, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + } + pub struct InvokeTransactionV3 { + pub resource_bounds: ResourceBoundsMapping, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub sender_address: ContractAddress, + pub calldata: Calldata, + pub nonce_data_availability_mode: DataAvailabilityMode, + pub fee_data_availability_mode: DataAvailabilityMode, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + } + pub enum L1DataAvailabilityMode { + Calldata = 0, + Blob = 1, + } + pub struct L1HandlerTransaction { + pub version: TransactionVersion, + pub nonce: Nonce, + pub contract_address: ContractAddress, + pub entry_point_selector: EntryPointSelector, + pub calldata: Calldata, + } + pub struct L1HandlerTransactionOutput { + pub actual_fee: Fee, + pub messages_sent: Vec, + pub events: Vec, + pub execution_status: TransactionExecutionStatus, + pub execution_resources: ExecutionResources, + } + pub struct L1ToL2Payload(pub Vec); + pub struct L2ToL1Payload(pub Vec); + pub struct MessageToL1 { + pub to_address: EthAddress, + pub payload: L2ToL1Payload, + pub from_address: ContractAddress, + } + pub struct MessageToL2 { + pub from_address: EthAddress, + pub payload: L1ToL2Payload, + } + pub struct Nonce(pub Felt); + pub struct TransactionCommitment(pub StarkHash); + pub struct PaymasterData(pub Vec); + pub struct PoseidonHash(pub Felt); + pub struct Program { + pub attributes: serde_json::Value, + pub builtins: serde_json::Value, + pub compiler_version: serde_json::Value, + pub data: serde_json::Value, + pub debug_info: serde_json::Value, + pub hints: serde_json::Value, + pub identifiers: serde_json::Value, + pub main_scope: serde_json::Value, + pub prime: serde_json::Value, + pub reference_manager: serde_json::Value, + } + pub struct ReceiptCommitment(pub StarkHash); + pub enum Resource { + L1Gas = 0, + L2Gas = 1, + } + pub struct ResourceBounds { + pub max_amount: u64, + pub max_price_per_unit: u128, + } + pub struct ResourceBoundsMapping(pub BTreeMap); + pub struct SequencerContractAddress(pub ContractAddress); + pub struct Signature { + pub r: Felt, + pub s: Felt, + } + pub struct StateDiff { + pub deployed_contracts: IndexMap, + pub storage_diffs: IndexMap>, + pub declared_classes: IndexMap, + pub deprecated_declared_classes: IndexMap, + pub nonces: IndexMap, + pub replaced_classes: IndexMap, + } + pub struct StateDiffCommitment(pub PoseidonHash); + pub struct StructMember { + pub name: String, + pub offset: usize, + pub r#type: String, + } + pub enum StructType { + Struct = 0, + } + pub struct ThinStateDiff { + pub deployed_contracts: IndexMap, + pub storage_diffs: IndexMap>, + pub declared_classes: IndexMap, + pub deprecated_declared_classes: Vec, + pub nonces: IndexMap, + pub replaced_classes: IndexMap, + } + pub struct Tip(pub u64); + pub enum Transaction { + Declare(DeclareTransaction) = 0, + Deploy(DeployTransaction) = 1, + DeployAccount(DeployAccountTransaction) = 2, + Invoke(InvokeTransaction) = 3, + L1Handler(L1HandlerTransaction) = 4, + } + pub enum TransactionExecutionStatus { + Succeeded = 0, + Reverted(RevertedTransactionExecutionStatus) = 1, + } + pub struct RevertedTransactionExecutionStatus { + pub revert_reason: String, + } + pub struct TransactionHash(pub StarkHash); + pub struct TransactionOffsetInBlock(pub usize); + pub enum TransactionOutput { + Declare(DeclareTransactionOutput) = 0, + Deploy(DeployTransactionOutput) = 1, + DeployAccount(DeployAccountTransactionOutput) = 2, + Invoke(InvokeTransactionOutput) = 3, + L1Handler(L1HandlerTransactionOutput) = 4, + } + pub struct TransactionSignature(pub Vec); + pub struct TransactionVersion(pub Felt); + pub struct TypedParameter { + pub name: String, + pub r#type: String, + } + + pub struct CasmContractClass { + pub prime: BigUint, + pub compiler_version: String, + pub bytecode: Vec, + pub bytecode_segment_lengths: Option, + pub hints: Vec<(usize, Vec)>, + pub pythonic_hints: Option)>>, + pub entry_points_by_type: CasmContractEntryPoints, + } + + pub struct CasmContractEntryPoints { + pub external: Vec, + pub l1_handler: Vec, + pub constructor: Vec, + } + + pub struct CasmContractEntryPoint { + pub selector: BigUint, + pub offset: usize, + pub builtins: Vec, + } + + pub struct BigUintAsHex { + pub value: BigUint, + } + pub enum NestedIntList { + Leaf(usize) = 0, + Node(Vec) = 1, + } + + binary(bool); + binary(EthAddress); + binary(u8); + binary(u32); + binary(u64); + binary(u128); + binary(usize); + + (BlockNumber, TransactionOffsetInBlock); + (BlockHash, ClassHash); + (ContractAddress, BlockHash); + (ContractAddress, BlockNumber); + (ContractAddress, Nonce); + (ContractAddress, StorageKey, BlockHash); + (ContractAddress, StorageKey, BlockNumber); + (CompiledClassHash, ContractClass); + (usize, Vec); + (usize, Vec); +} + +#[macro_export] +macro_rules! auto_impl_get_test_instance { + () => {}; + // Tuple structs (no names associated with fields) - one field. + ($(pub)? struct $name:ident($(pub)? $ty:ty); $($rest:tt)*) => { + impl GetTestInstance for $name { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self(<$ty>::get_test_instance(rng)) + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // Tuple structs (no names associated with fields) - two fields. + ($(pub)? struct $name:ident($(pub)? $ty0:ty, $(pub)? $ty1:ty) ; $($rest:tt)*) => { + impl GetTestInstance for $name { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self(<$ty0>::get_test_instance(rng), <$ty1>::get_test_instance(rng)) + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // Structs with public fields. + ($(pub)? struct $name:ident { $(pub $field:ident : $ty:ty ,)* } $($rest:tt)*) => { + impl GetTestInstance for $name { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self { + $( + $field: <$ty>::get_test_instance(rng), + )* + } + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // Tuples - two elements. + (($ty0:ty, $ty1:ty) ; $($rest:tt)*) => { + impl GetTestInstance for ($ty0, $ty1) { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + ( + <$ty0>::get_test_instance(rng), + <$ty1>::get_test_instance(rng), + ) + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // Tuples - three elements. + (($ty0:ty, $ty1:ty, $ty2:ty) ; $($rest:tt)*) => { + impl GetTestInstance for ($ty0, $ty1, $ty2) { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + ( + <$ty0>::get_test_instance(rng), + <$ty1>::get_test_instance(rng), + <$ty2>::get_test_instance(rng), + ) + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // enums. + ($(pub)? enum $name:ident { $($variant:ident $( ($ty:ty) )? = $num:expr ,)* } $($rest:tt)*) => { + impl GetTestInstance for $name { + fn get_test_instance(rng: &mut rand_chacha::ChaCha8Rng) -> Self { + use rand::Rng; + let variant = rng.gen_range(0..get_number_of_variants!(enum $name { $($variant $( ($ty) )? = $num ,)* })); + match variant { + $( + $num => { + Self::$variant$((<$ty>::get_test_instance(rng)))? + } + )* + _ => { + panic!("Variant {:?} should match one of the enum {:?} variants.", variant, stringify!($name)); + } + } + } + } + auto_impl_get_test_instance!($($rest)*); + }; + // Binary. + (binary($name:ident); $($rest:tt)*) => { + default_impl_get_test_instance!($name); + auto_impl_get_test_instance!($($rest)*); + } +} + +#[macro_export] +macro_rules! default_impl_get_test_instance { + ($name:path) => { + impl GetTestInstance for $name { + fn get_test_instance(_rng: &mut rand_chacha::ChaCha8Rng) -> Self { + Self::default() + } + } + }; +} + +//////////////////////////////////////////////////////////////////////// +// Implements the [`GetTestInstance`] trait for primitive types. +//////////////////////////////////////////////////////////////////////// +default_impl_get_test_instance!(serde_json::Value); +default_impl_get_test_instance!(String); +impl GetTestInstance for Arc { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + Arc::new(T::get_test_instance(rng)) + } +} +impl GetTestInstance for Option { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + Some(T::get_test_instance(rng)) + } +} +impl GetTestInstance for Vec { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + vec![T::get_test_instance(rng)] + } +} +impl GetTestInstance for HashMap { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + let mut res = HashMap::with_capacity(1); + let k = K::get_test_instance(rng); + let v = V::get_test_instance(rng); + res.insert(k, v); + res + } +} +impl GetTestInstance for IndexMap { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + let mut res = IndexMap::with_capacity(1); + let k = K::get_test_instance(rng); + let v = V::get_test_instance(rng); + res.insert(k, v); + res + } +} +impl GetTestInstance for BTreeMap { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + let mut res = BTreeMap::new(); + let k = K::get_test_instance(rng); + let v = V::get_test_instance(rng); + res.insert(k, v); + res + } +} + +// Counts the number of variants of an enum. +#[macro_export] +macro_rules! get_number_of_variants { + (enum $name:ident { $($variant:ident $( ($ty:ty) )? = $num:expr ,)* }) => { + get_number_of_variants!(@count $($variant),+) + }; + (@count $t1:tt, $($t:tt),+) => { 1 + get_number_of_variants!(@count $($t),+) }; + (@count $t:tt) => { 1 }; +} + +//////////////////////////////////////////////////////////////////////// +// Implements the [`GetTestInstance`] trait for types not supported +// by the macro [`impl_get_test_instance`]. +//////////////////////////////////////////////////////////////////////// +default_impl_get_test_instance!(H160); +default_impl_get_test_instance!(ContractAddress); +default_impl_get_test_instance!(StarkHash); +default_impl_get_test_instance!(StorageKey); +default_impl_get_test_instance!(BigUint); + +impl GetTestInstance for StructAbiEntry { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + Self { + name: String::default(), + size: 1, // Should be minimum 1. + members: Vec::::get_test_instance(rng), + r#type: StructType::Struct, + } + } +} + +impl GetTestInstance for FunctionAbiEntry { + fn get_test_instance(rng: &mut ChaCha8Rng) -> FunctionAbiEntry { + FunctionAbiEntry:: { + name: String::get_test_instance(rng), + inputs: Vec::::get_test_instance(rng), + outputs: Vec::::get_test_instance(rng), + state_mutability: Option::::get_test_instance(rng), + r#type: TYPE::default(), + } + } +} + +// Hint Doesn't implement Default - create instance manually. +impl GetTestInstance for Hint { + fn get_test_instance(_rng: &mut ChaCha8Rng) -> Self { + Self::Core(CoreHintBase::Core(CoreHint::AllocConstantSize { + size: ResOperand::BinOp(BinOpOperand { + op: Operation::Add, + a: CellRef { register: Register::AP, offset: 0 }, + b: DerefOrImmediate::Deref(CellRef { register: Register::AP, offset: 0 }), + }), + dst: CellRef { register: Register::AP, offset: 0 }, + })) + } +} + +impl GetTestInstance for ExecutionResources { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + let builtin = Builtin::get_test_instance(rng); + Self { + steps: NonZeroU64::get_test_instance(rng).into(), + builtin_instance_counter: [(builtin, NonZeroU64::get_test_instance(rng).into())].into(), + memory_holes: NonZeroU64::get_test_instance(rng).into(), + da_gas_consumed: GasVector::get_test_instance(rng), + gas_consumed: GasVector::get_test_instance(rng), + } + } +} + +impl GetTestInstance for GasVector { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + Self { l1_gas: rng.next_u64(), l1_data_gas: rng.next_u64() } + } +} + +impl GetTestInstance for NonZeroU64 { + fn get_test_instance(rng: &mut ChaCha8Rng) -> Self { + max(1, rng.next_u64()).try_into().expect("Failed to convert a non-zero u64 to NonZeroU64") + } +} diff --git a/crates/test_utils/src/precision_test.rs b/crates/test_utils/src/precision_test.rs new file mode 100644 index 00000000000..18138b3f646 --- /dev/null +++ b/crates/test_utils/src/precision_test.rs @@ -0,0 +1,10 @@ +use pretty_assertions::assert_eq; + +#[test] +fn serialization_precision() { + let input = + "{\"value\":244116128358498188146337218061232635775543270890529169229936851982759783745}"; + let serialized = serde_json::from_str::(input).unwrap(); + let deserialized = serde_json::to_string(&serialized).unwrap(); + assert_eq!(input, deserialized); +} diff --git a/crates/tests-integration/Cargo.toml b/crates/tests-integration/Cargo.toml new file mode 100644 index 00000000000..fbebb917b68 --- /dev/null +++ b/crates/tests-integration/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "starknet_mempool_integration_tests" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +axum.workspace = true +blockifier.workspace = true +cairo-lang-starknet-classes.workspace = true +indexmap.workspace = true +itertools.workspace = true +mempool_test_utils = { path = "../mempool_test_utils", version = "0.0" } +papyrus_common.workspace = true +papyrus_rpc.workspace = true +papyrus_storage.workspace = true +reqwest.workspace = true +serde_json.workspace = true +starknet-types-core.workspace = true +starknet_api.workspace = true +starknet_client.workspace = true +starknet_gateway = { path = "../gateway", version = "0.0", features = ["testing"] } +starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } +starknet_mempool_node = { path = "../mempool_node", version = "0.0" } +starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +starknet_task_executor = { path = "../task_executor", version = "0.0" } +strum.workspace = true +tempfile.workspace = true +tokio.workspace = true + +[dev-dependencies] +pretty_assertions.workspace = true +rstest.workspace = true +starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } diff --git a/crates/tests-integration/src/integration_test_setup.rs b/crates/tests-integration/src/integration_test_setup.rs new file mode 100644 index 00000000000..3edc8fe25e3 --- /dev/null +++ b/crates/tests-integration/src/integration_test_setup.rs @@ -0,0 +1,97 @@ +use std::net::SocketAddr; + +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::CairoVersion; +use starknet_api::rpc_transaction::RPCTransaction; +use starknet_api::transaction::TransactionHash; +use starknet_gateway::config::GatewayNetworkConfig; +use starknet_gateway::errors::GatewayError; +use starknet_mempool_infra::trace_util::configure_tracing; +use starknet_mempool_node::communication::{create_node_channels, create_node_clients}; +use starknet_mempool_node::components::create_components; +use starknet_mempool_node::servers::{create_servers, get_server_future}; +use starknet_mempool_types::mempool_types::ThinTransaction; +use starknet_task_executor::tokio_executor::TokioExecutor; +use tokio::runtime::Handle; +use tokio::task::JoinHandle; + +use crate::integration_test_utils::{create_config, GatewayClient}; +use crate::mock_batcher::MockBatcher; +use crate::state_reader::spawn_test_rpc_state_reader; + +pub struct IntegrationTestSetup { + pub task_executor: TokioExecutor, + pub gateway_client: GatewayClient, + pub batcher: MockBatcher, + pub gateway_handle: JoinHandle<()>, + pub mempool_handle: JoinHandle<()>, +} + +impl IntegrationTestSetup { + pub async fn new(n_accounts: usize) -> Self { + let default_account_contract = + FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1); + let accounts = std::iter::repeat(default_account_contract).take(n_accounts); + Self::new_for_account_contracts(accounts).await + } + + pub async fn new_for_account_contracts( + accounts: impl IntoIterator, + ) -> Self { + let handle = Handle::current(); + let task_executor = TokioExecutor::new(handle); + + // Configure and start tracing + configure_tracing(); + + // Spawn a papyrus rpc server for a papyrus storage reader. + let rpc_server_addr = spawn_test_rpc_state_reader(accounts).await; + + // Derive the configuration for the mempool node. + let config = create_config(rpc_server_addr).await; + + // Create the communication network for the mempool node. + let mut channels = create_node_channels(); + + // Create the clients for the mempool node. + let clients = create_node_clients(&config, &mut channels); + + // Create the components for the mempool node. + let components = create_components(&config, &clients); + + // Create the servers for the mempool node. + let servers = create_servers(&config, &mut channels, components); + + let GatewayNetworkConfig { ip, port } = config.gateway_config.network_config; + let gateway_client = GatewayClient::new(SocketAddr::from((ip, port))); + + let gateway_future = get_server_future("Gateway", true, servers.gateway); + let gateway_handle = task_executor.spawn_with_handle(gateway_future); + + // Wait for server to spin up. + // TODO(Gilad): Replace with a persistant Client with a built-in retry mechanism, + // to avoid the sleep and to protect against CI flakiness. + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + + // Build Batcher. + let batcher = MockBatcher::new(clients.get_mempool_client().unwrap()); + + // Build and run mempool. + let mempool_future = get_server_future("Mempool", true, servers.mempool); + let mempool_handle = task_executor.spawn_with_handle(mempool_future); + + Self { task_executor, gateway_client, batcher, gateway_handle, mempool_handle } + } + + pub async fn assert_add_tx_success(&self, tx: &RPCTransaction) -> TransactionHash { + self.gateway_client.assert_add_tx_success(tx).await + } + + pub async fn assert_add_tx_error(&self, tx: &RPCTransaction) -> GatewayError { + self.gateway_client.assert_add_tx_error(tx).await + } + + pub async fn get_txs(&self, n_txs: usize) -> Vec { + self.batcher.get_txs(n_txs).await + } +} diff --git a/crates/tests-integration/src/integration_test_utils.rs b/crates/tests-integration/src/integration_test_utils.rs new file mode 100644 index 00000000000..b9ebcbdb41d --- /dev/null +++ b/crates/tests-integration/src/integration_test_utils.rs @@ -0,0 +1,120 @@ +use std::net::SocketAddr; + +use axum::body::Body; +use blockifier::test_utils::contracts::FeatureContract; +use mempool_test_utils::starknet_api_test_utils::{ + external_tx_to_json, MultiAccountTransactionGenerator, +}; +use reqwest::{Client, Response}; +use starknet_api::rpc_transaction::RPCTransaction; +use starknet_api::transaction::TransactionHash; +use starknet_gateway::config::{ + GatewayConfig, GatewayNetworkConfig, RpcStateReaderConfig, StatefulTransactionValidatorConfig, + StatelessTransactionValidatorConfig, +}; +use starknet_gateway::errors::GatewayError; +use starknet_mempool_node::config::MempoolNodeConfig; +use tokio::net::TcpListener; + +use crate::integration_test_setup::IntegrationTestSetup; + +async fn create_gateway_config() -> GatewayConfig { + let stateless_tx_validator_config = StatelessTransactionValidatorConfig { + validate_non_zero_l1_gas_fee: true, + max_calldata_length: 10, + max_signature_length: 2, + ..Default::default() + }; + + let socket = get_available_socket().await; + let network_config = GatewayNetworkConfig { ip: socket.ip(), port: socket.port() }; + let stateful_tx_validator_config = StatefulTransactionValidatorConfig::create_for_testing(); + let gateway_compiler_config = Default::default(); + + GatewayConfig { + network_config, + stateless_tx_validator_config, + stateful_tx_validator_config, + compiler_config: gateway_compiler_config, + } +} + +pub async fn create_config(rpc_server_addr: SocketAddr) -> MempoolNodeConfig { + let gateway_config = create_gateway_config().await; + let rpc_state_reader_config = test_rpc_state_reader_config(rpc_server_addr); + MempoolNodeConfig { gateway_config, rpc_state_reader_config, ..MempoolNodeConfig::default() } +} + +/// A test utility client for interacting with a gateway server. +pub struct GatewayClient { + socket: SocketAddr, + client: Client, +} + +impl GatewayClient { + pub fn new(socket: SocketAddr) -> Self { + let client = Client::new(); + Self { socket, client } + } + + pub async fn assert_add_tx_success(&self, tx: &RPCTransaction) -> TransactionHash { + let response = self.add_tx(tx).await; + assert!(response.status().is_success()); + + response.json().await.unwrap() + } + + // TODO: implement when usage eventually arises. + pub async fn assert_add_tx_error(&self, _tx: &RPCTransaction) -> GatewayError { + todo!() + } + + // Prefer using assert_add_tx_success or other higher level methods of this client, to ensure + // tests are boilerplate and implementation-detail free. + pub async fn add_tx(&self, tx: &RPCTransaction) -> Response { + let tx_json = external_tx_to_json(tx); + self.client + .post(format!("http://{}/add_tx", self.socket)) + .header("content-type", "application/json") + .body(Body::from(tx_json)) + .send() + .await + .unwrap() + } +} + +fn test_rpc_state_reader_config(rpc_server_addr: SocketAddr) -> RpcStateReaderConfig { + const RPC_SPEC_VERION: &str = "V0_7"; + const JSON_RPC_VERSION: &str = "2.0"; + RpcStateReaderConfig { + url: format!("http://{rpc_server_addr:?}/rpc/{RPC_SPEC_VERION}"), + json_rpc_version: JSON_RPC_VERSION.to_string(), + } +} + +/// Returns a unique IP address and port for testing purposes. +/// +/// Tests run in parallel, so servers (like RPC or web) running on separate tests must have +/// different ports, otherwise the server will fail with "address already in use". +pub async fn get_available_socket() -> SocketAddr { + // Dinamically select port. + // First, set the port to 0 (dynamic port). + TcpListener::bind("127.0.0.1:0") + .await + .expect("Failed to bind to address") + // Then, resolve to the actual selected port. + .local_addr() + .expect("Failed to get local address") +} + +/// Use to create a tx generator with _pre-funded_ accounts, alongside a mocked test setup. +pub async fn setup_with_tx_generation( + accounts: &[FeatureContract], +) -> (IntegrationTestSetup, MultiAccountTransactionGenerator) { + let integration_test_setup = + IntegrationTestSetup::new_for_account_contracts(accounts.iter().copied()).await; + let tx_generator = + MultiAccountTransactionGenerator::new_for_account_contracts(accounts.iter().copied()); + + (integration_test_setup, tx_generator) +} diff --git a/crates/tests-integration/src/lib.rs b/crates/tests-integration/src/lib.rs new file mode 100644 index 00000000000..265c50f21c6 --- /dev/null +++ b/crates/tests-integration/src/lib.rs @@ -0,0 +1,4 @@ +pub mod integration_test_setup; +pub mod integration_test_utils; +pub mod mock_batcher; +pub mod state_reader; diff --git a/crates/tests-integration/src/mock_batcher.rs b/crates/tests-integration/src/mock_batcher.rs new file mode 100644 index 00000000000..15bf0122313 --- /dev/null +++ b/crates/tests-integration/src/mock_batcher.rs @@ -0,0 +1,16 @@ +use starknet_mempool_types::communication::SharedMempoolClient; +use starknet_mempool_types::mempool_types::ThinTransaction; + +pub struct MockBatcher { + mempool_client: SharedMempoolClient, +} + +impl MockBatcher { + pub fn new(mempool_client: SharedMempoolClient) -> Self { + Self { mempool_client } + } + + pub async fn get_txs(&self, n_txs: usize) -> Vec { + self.mempool_client.get_txs(n_txs).await.unwrap() + } +} diff --git a/crates/tests-integration/src/state_reader.rs b/crates/tests-integration/src/state_reader.rs new file mode 100644 index 00000000000..b2526c38ea0 --- /dev/null +++ b/crates/tests-integration/src/state_reader.rs @@ -0,0 +1,295 @@ +use std::net::SocketAddr; +use std::sync::{Arc, OnceLock}; + +use blockifier::abi::abi_utils::get_fee_token_var_address; +use blockifier::context::{BlockContext, ChainInfo}; +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::{ + CairoVersion, BALANCE, CURRENT_BLOCK_TIMESTAMP, DEFAULT_ETH_L1_GAS_PRICE, + DEFAULT_STRK_L1_GAS_PRICE, TEST_SEQUENCER_ADDRESS, +}; +use blockifier::transaction::objects::FeeType; +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use indexmap::{indexmap, IndexMap}; +use itertools::Itertools; +use mempool_test_utils::starknet_api_test_utils::{ + deploy_account_tx, deployed_account_contract_address, +}; +use papyrus_common::pending_classes::PendingClasses; +use papyrus_rpc::{run_server, RpcConfig}; +use papyrus_storage::body::BodyStorageWriter; +use papyrus_storage::class::ClassStorageWriter; +use papyrus_storage::compiled_class::CasmStorageWriter; +use papyrus_storage::header::HeaderStorageWriter; +use papyrus_storage::state::StateStorageWriter; +use papyrus_storage::{open_storage, StorageConfig, StorageReader}; +use starknet_api::block::{ + BlockBody, BlockHeader, BlockNumber, BlockTimestamp, GasPrice, GasPricePerToken, +}; +use starknet_api::core::{ClassHash, ContractAddress, PatriciaKey, SequencerContractAddress}; +use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use starknet_api::state::{StorageKey, ThinStateDiff}; +use starknet_api::{contract_address, felt, patricia_key}; +use starknet_client::reader::PendingData; +use starknet_types_core::felt::Felt; +use strum::IntoEnumIterator; +use tempfile::tempdir; +use tokio::sync::RwLock; + +use crate::integration_test_utils::get_available_socket; + +type ContractClassesMap = + (Vec<(ClassHash, DeprecatedContractClass)>, Vec<(ClassHash, CasmContractClass)>); + +fn deploy_account_tx_contract_address() -> &'static ContractAddress { + static DEPLOY_ACCOUNT_TX_CONTRACT_ADDRESS: OnceLock = OnceLock::new(); + DEPLOY_ACCOUNT_TX_CONTRACT_ADDRESS.get_or_init(|| { + let deploy_tx = deploy_account_tx(); + deployed_account_contract_address(&deploy_tx) + }) +} + +/// StateReader for integration tests. +/// +/// Creates a papyrus storage reader and spawns a papyrus rpc server for it. +/// Returns the address of the rpc server. +/// A variable number of identical accounts and test contracts are initialized and funded. +pub async fn spawn_test_rpc_state_reader( + accounts: impl IntoIterator, +) -> SocketAddr { + let block_context = BlockContext::create_for_testing(); + + // Map feature contracts to their number of instances inside the account array. + let mut account_to_n_instances: IndexMap = + IndexMap::from_iter(accounts.into_iter().counts()); + + // Add essential contracts to contract mapping, if not exist already. + // TODO: can this hard-coding be removed? + for contract in [ + FeatureContract::TestContract(CairoVersion::Cairo0), + FeatureContract::TestContract(CairoVersion::Cairo1), + FeatureContract::ERC20(CairoVersion::Cairo0), + ] { + *account_to_n_instances.entry(contract).or_default() += 1; + } + + let fund_accounts = vec![*deploy_account_tx_contract_address()]; + + let storage_reader = initialize_papyrus_test_state( + block_context.chain_info(), + BALANCE, + account_to_n_instances, + fund_accounts, + ); + run_papyrus_rpc_server(storage_reader).await +} + +fn initialize_papyrus_test_state( + chain_info: &ChainInfo, + initial_balances: u128, + contract_instances: IndexMap, + fund_additional_accounts: Vec, +) -> StorageReader { + let state_diff = prepare_state_diff( + chain_info, + &contract_instances, + initial_balances, + fund_additional_accounts, + ); + + let (cairo0_contract_classes, cairo1_contract_classes) = + prepare_compiled_contract_classes(contract_instances.into_keys()); + + write_state_to_papyrus_storage(state_diff, &cairo0_contract_classes, &cairo1_contract_classes) +} + +fn prepare_state_diff( + chain_info: &ChainInfo, + contract_instances: &IndexMap, + initial_balances: u128, + fund_accounts: Vec, +) -> ThinStateDiff { + let erc20 = FeatureContract::ERC20(CairoVersion::Cairo0); + let erc20_class_hash = erc20.get_class_hash(); + + // Declare and deploy ERC20 contracts. + let mut deployed_contracts = indexmap! { + chain_info.fee_token_address(&FeeType::Eth) => erc20_class_hash, + chain_info.fee_token_address(&FeeType::Strk) => erc20_class_hash + }; + let mut deprecated_declared_classes = Vec::from([erc20.get_class_hash()]); + + let mut storage_diffs = IndexMap::new(); + let mut declared_classes = IndexMap::new(); + for (contract, &n_instances) in contract_instances { + for instance in 0..n_instances { + // Declare and deploy the contracts + match contract.cairo_version() { + CairoVersion::Cairo0 => { + deprecated_declared_classes.push(contract.get_class_hash()); + } + CairoVersion::Cairo1 => { + declared_classes.insert(contract.get_class_hash(), Default::default()); + } + } + let instance = u16::try_from(instance).unwrap(); + deployed_contracts + .insert(contract.get_instance_address(instance), contract.get_class_hash()); + fund_feature_account_contract( + &mut storage_diffs, + contract, + instance, + initial_balances, + chain_info, + ); + } + } + + fund_accounts.iter().for_each(|address| { + fund_account(&mut storage_diffs, address, initial_balances, chain_info) + }); + + ThinStateDiff { + storage_diffs, + deployed_contracts, + declared_classes, + deprecated_declared_classes, + ..Default::default() + } +} + +fn prepare_compiled_contract_classes( + contract_instances: impl Iterator, +) -> ContractClassesMap { + let mut cairo0_contract_classes = Vec::new(); + let mut cairo1_contract_classes = Vec::new(); + for contract in contract_instances { + match contract.cairo_version() { + CairoVersion::Cairo0 => { + cairo0_contract_classes.push(( + contract.get_class_hash(), + serde_json::from_str(&contract.get_raw_class()).unwrap(), + )); + } + CairoVersion::Cairo1 => { + cairo1_contract_classes.push(( + contract.get_class_hash(), + serde_json::from_str(&contract.get_raw_class()).unwrap(), + )); + } + } + } + (cairo0_contract_classes, cairo1_contract_classes) +} + +fn write_state_to_papyrus_storage( + state_diff: ThinStateDiff, + cairo0_contract_classes: &[(ClassHash, DeprecatedContractClass)], + cairo1_contract_classes: &[(ClassHash, CasmContractClass)], +) -> StorageReader { + let block_number = BlockNumber(0); + let block_header = test_block_header(block_number); + + let mut storage_config = StorageConfig::default(); + let tempdir = tempdir().unwrap(); + storage_config.db_config.path_prefix = tempdir.path().to_path_buf(); + let (storage_reader, mut storage_writer) = open_storage(storage_config).unwrap(); + + let cairo0_contract_classes = + cairo0_contract_classes.iter().map(|(x, y)| (*x, y)).collect::>(); + + let mut write_txn = storage_writer.begin_rw_txn().unwrap(); + for (class_hash, casm) in cairo1_contract_classes { + write_txn = write_txn.append_casm(class_hash, casm).unwrap(); + } + write_txn + .append_header(block_number, &block_header) + .unwrap() + .append_body(block_number, BlockBody::default()) + .unwrap() + .append_state_diff(block_number, state_diff) + .unwrap() + .append_classes(block_number, &[], cairo0_contract_classes.as_slice()) + .unwrap() + .commit() + .unwrap(); + + storage_reader +} + +fn test_block_header(block_number: BlockNumber) -> BlockHeader { + BlockHeader { + block_number, + sequencer: SequencerContractAddress(contract_address!(TEST_SEQUENCER_ADDRESS)), + l1_gas_price: GasPricePerToken { + price_in_wei: GasPrice(DEFAULT_ETH_L1_GAS_PRICE), + price_in_fri: GasPrice(DEFAULT_STRK_L1_GAS_PRICE), + }, + l1_data_gas_price: GasPricePerToken { + price_in_wei: GasPrice(DEFAULT_ETH_L1_GAS_PRICE), + price_in_fri: GasPrice(DEFAULT_STRK_L1_GAS_PRICE), + }, + timestamp: BlockTimestamp(CURRENT_BLOCK_TIMESTAMP), + ..Default::default() + } +} + +fn fund_feature_account_contract( + storage_diffs: &mut IndexMap>, + contract: &FeatureContract, + instance: u16, + initial_balances: u128, + chain_info: &ChainInfo, +) { + match contract { + FeatureContract::AccountWithLongValidate(_) + | FeatureContract::AccountWithoutValidations(_) + | FeatureContract::FaultyAccount(_) => { + fund_account( + storage_diffs, + &contract.get_instance_address(instance), + initial_balances, + chain_info, + ); + } + _ => (), + } +} + +fn fund_account( + storage_diffs: &mut IndexMap>, + account_address: &ContractAddress, + initial_balances: u128, + chain_info: &ChainInfo, +) { + let key_value = indexmap! { + get_fee_token_var_address(*account_address) => felt!(initial_balances), + }; + for fee_type in FeeType::iter() { + storage_diffs + .entry(chain_info.fee_token_address(&fee_type)) + .or_default() + .extend(key_value.clone()); + } +} + +async fn run_papyrus_rpc_server(storage_reader: StorageReader) -> SocketAddr { + let rpc_config = RpcConfig { + server_address: get_available_socket().await.to_string(), + ..Default::default() + }; + let (addr, handle) = run_server( + &rpc_config, + Arc::new(RwLock::new(None)), + Arc::new(RwLock::new(PendingData::default())), + Arc::new(RwLock::new(PendingClasses::default())), + storage_reader, + "NODE VERSION", + ) + .await + .unwrap(); + // Spawn the server handle to keep the server running, otherwise the server will stop once the + // handler is out of scope. + tokio::spawn(handle.stopped()); + addr +} diff --git a/crates/tests-integration/tests/end_to_end_test.rs b/crates/tests-integration/tests/end_to_end_test.rs new file mode 100644 index 00000000000..96653769548 --- /dev/null +++ b/crates/tests-integration/tests/end_to_end_test.rs @@ -0,0 +1,47 @@ +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::CairoVersion; +use starknet_api::transaction::TransactionHash; +use starknet_mempool_integration_tests::integration_test_utils::setup_with_tx_generation; + +#[tokio::test] +async fn test_end_to_end() { + // Setup. + let accounts = [ + FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1), + FeatureContract::AccountWithoutValidations(CairoVersion::Cairo0), + ]; + let (mock_running_system, mut tx_generator) = setup_with_tx_generation(&accounts).await; + + let account0_deploy_nonce0 = &tx_generator.account_with_id(0).generate_default_deploy_account(); + let account0_invoke_nonce1 = tx_generator.account_with_id(0).generate_default_invoke(); + let account1_invoke_nonce0 = tx_generator.account_with_id(1).generate_default_invoke(); + let account0_invoke_nonce2 = tx_generator.account_with_id(0).generate_default_invoke(); + + // Test. + + let account0_deploy_nonce0_tx_hash = + mock_running_system.assert_add_tx_success(account0_deploy_nonce0).await; + + mock_running_system.assert_add_tx_success(&account0_invoke_nonce1).await; + + // FIXME: invoke with nonce0 shouldn't be possible, fix it, make this FAIL. + let account1_invoke_nonce0_tx_hash = + mock_running_system.assert_add_tx_success(&account1_invoke_nonce0).await; + + mock_running_system.assert_add_tx_success(&account0_invoke_nonce2).await; + + let mempool_txs = mock_running_system.get_txs(4).await; + + // Assert. + + // Only the transactions with nonce 0 should be returned from the mempool, + // because we haven't merged queue-replenishment yet. + let expected_tx_hashes_from_get_txs = + [account1_invoke_nonce0_tx_hash, account0_deploy_nonce0_tx_hash]; + + // This assert should be replaced with 4 once queue-replenishment is merged, also add a tx hole + // at that point, and ensure the assert doesn't change due to that. + assert_eq!(mempool_txs.len(), 2); + let actual_tx_hashes: Vec = mempool_txs.iter().map(|tx| tx.tx_hash).collect(); + assert_eq!(expected_tx_hashes_from_get_txs, *actual_tx_hashes); +} diff --git a/deployments/papyrus/helm/CI/values.yaml b/deployments/papyrus/helm/CI/values.yaml new file mode 100644 index 00000000000..d60202e9501 --- /dev/null +++ b/deployments/papyrus/helm/CI/values.yaml @@ -0,0 +1,24 @@ +# Default values for a papyrus ci deployment. + +rustLogLevel: "debug" + +deployment: + image: + tag: dev + +pvc: + size: 1Gi + storageClass: standard-rwo +# Configure Ingress. +# ingress: +# enabled: true +# type: gce +# name: ssl-proxy +# pathType: ImplementationSpecific +# annotations: | +# kubernetes.io/ingress.class: nginx +# kubernetes.io/tls-acme: "true" +# nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + +grafanadashboard: + enabled: true diff --git a/deployments/papyrus/helm/Chart.yaml b/deployments/papyrus/helm/Chart.yaml new file mode 100644 index 00000000000..4f53da0c22c --- /dev/null +++ b/deployments/papyrus/helm/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: papyrus +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.2 diff --git a/deployments/papyrus/helm/Monitoring/.gitignore b/deployments/papyrus/helm/Monitoring/.gitignore new file mode 100644 index 00000000000..5e7d2734cfc --- /dev/null +++ b/deployments/papyrus/helm/Monitoring/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/deployments/papyrus/helm/README.md b/deployments/papyrus/helm/README.md new file mode 100644 index 00000000000..aa73e518a1b --- /dev/null +++ b/deployments/papyrus/helm/README.md @@ -0,0 +1,9 @@ +# Papyrus helm chart installation + +## Usage + +```bash +helm upgrade --install `release_name` deployments/helm/ \ +--namespace `namespace_name` --create-namespace \ +--set ingress.host=`ingress_hostname` +``` diff --git a/deployments/papyrus/helm/backup-values.yaml b/deployments/papyrus/helm/backup-values.yaml new file mode 100644 index 00000000000..6c94c11a46f --- /dev/null +++ b/deployments/papyrus/helm/backup-values.yaml @@ -0,0 +1,21 @@ +# Default values for a papyrus-backup deployment. + +# The verbosity level of logs ("debug", "info", "error", etc.) +rustLogLevel: "papyrus=DEBUG" + +# The Docker image (including any tag and repository name) +deployment: + image: + repository: us.gcr.io/starkware-dev/papyrus-backup + tag: 0.2.0 +services: [] +# Persistent volume claim variables for a papyrus pod. +pvc: + size: 1000Gi + storageClass: premium-rwo + +backup: + enabled: true + aws: + s3BucketName: papyrus-backup + s3BucketRegion: us-east-2 diff --git a/deployments/papyrus/helm/files/backup.sh b/deployments/papyrus/helm/files/backup.sh new file mode 100644 index 00000000000..4a016b98111 --- /dev/null +++ b/deployments/papyrus/helm/files/backup.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh +set -x +if [ -z "${ADDITIONAL_HEADER}" ]; then + ADDITIONAL_ARGS="" +else + ADDITIONAL_ARGS="--http_headers=${ADDITIONAL_HEADER}" +fi + +if [ -n "${CONCURRENT_REQUESTS}" ]; then + # temporary workaround for an internal papyrus memory issue + sed -i "s/concurrent_requests: 10/concurrent_requests: $CONCURRENT_REQUESTS/g" /app/config/config.yaml +fi + +RUN_CMD="/app/target/release/papyrus_node --config_file=/app/config/presets/${PRESET} ${ADDITIONAL_ARGS}" + +while true; do + # start papyrus and save the pid + sh -c "$RUN_CMD" & + PAPYRUS_PID="$!" + + sleep "$SLEEP_INTERVAL" + + # stop papyrus + kill -15 "$PAPYRUS_PID" + sleep 5s + + TS=$(date +%s) + if [ "$COMPRESS_BACKUP" = true ]; then + # compress file, upload compressed file and delete the compressed file + cd "/app/data/$CHAIN_ID" || exit 1 + TAR_FILE_NAME="$TS.tar.gz" + tar -czvf "$TAR_FILE_NAME" mdbx.dat + aws s3 cp "$TAR_FILE_NAME" "s3://$S3_BUCKET_NAME/$CHAIN_ID/$PAPYRUS_VERSION/$TAR_FILE_NAME" + rm "$TAR_FILE_NAME" + cd /app || exit 1 + else + # upload db file to s3 + aws s3 cp "/app/data/$CHAIN_ID/mdbx.dat" "s3://$S3_BUCKET_NAME/$CHAIN_ID/$PAPYRUS_VERSION/$TS.dat" + fi +done diff --git a/deployments/papyrus/helm/templates/_helpers.tpl b/deployments/papyrus/helm/templates/_helpers.tpl new file mode 100644 index 00000000000..eef0f98ec6f --- /dev/null +++ b/deployments/papyrus/helm/templates/_helpers.tpl @@ -0,0 +1,76 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "papyrus.name" -}} +{{- default .Release.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "papyrus.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "papyrus.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "papyrus.labels" -}} +helm.sh/chart: {{ include "papyrus.chart" . }} +app: {{ include "papyrus.name" . }} +{{ include "papyrus.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "papyrus.selectorLabels" -}} +app.kubernetes.io/name: {{ include "papyrus.name" . }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "papyrus.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "papyrus.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Build the p2p peer multiaddress string +*/}} +{{- define "p2p.bootstrapPeerMultiaddr" -}} +{{- if and .Values.p2p.enabled (not .Values.p2p.bootstrap) -}} + {{- $ip := .Values.p2p.nodeConfig.bootstrapServer.multiaddrIp -}} + {{- $port := .Values.p2p.nodeConfig.bootstrapServer.multiaddrPort -}} + {{- $uid := .Values.p2p.nodeConfig.bootstrapServer.multiaddrUid -}} + {{- printf "/ip4/%s/tcp/%s/p2p/%s" $ip $port $uid -}} +{{- else -}} + {{- "" -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/deployments/papyrus/helm/templates/aws-creds-secret.yaml b/deployments/papyrus/helm/templates/aws-creds-secret.yaml new file mode 100644 index 00000000000..328f3e0354f --- /dev/null +++ b/deployments/papyrus/helm/templates/aws-creds-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.backup.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "papyrus.name" . }}-aws-creds + labels: + {{- include "papyrus.labels" . | nindent 4 }} +data: + AWS_ACCESS_KEY_ID: {{ .Values.backup.aws.accessKeyId | b64enc }} + AWS_SECRET_ACCESS_KEY: {{ .Values.backup.aws.secretAccessKey | b64enc }} + AWS_DEFAULT_REGION: {{ .Values.backup.aws.s3BucketRegion | b64enc }} +{{- end }} diff --git a/deployments/papyrus/helm/templates/configmap.yaml b/deployments/papyrus/helm/templates/configmap.yaml new file mode 100644 index 00000000000..3cd1c01d0bb --- /dev/null +++ b/deployments/papyrus/helm/templates/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "papyrus.name" . }}-config + labels: + {{- include "papyrus.labels" . | nindent 4 }} +data: + RUST_LOG: {{ .Values.rustLogLevel }} + PRESET: {{ .Values.starknet.preset }} + CONCURRENT_REQUESTS: {{ .Values.node.concurrentFgRequests | quote }} + {{- if .Values.starknet.additionalHeaders }} + ADDITIONAL_HEADER: {{ .Values.starknet.additionalHeaders }} + {{- end }} + {{- if .Values.backup.enabled }} + SLEEP_INTERVAL: {{ .Values.backup.sleepInterval }} + S3_BUCKET_NAME: {{ .Values.backup.aws.s3BucketName }} + PAPYRUS_VERSION: {{ .Values.image.tag | quote }} + COMPRESS_BACKUP: {{ .Values.backup.compress | quote }} + {{- end }} diff --git a/deployments/papyrus/helm/templates/deployment.yaml b/deployments/papyrus/helm/templates/deployment.yaml new file mode 100644 index 00000000000..bb55b3a0445 --- /dev/null +++ b/deployments/papyrus/helm/templates/deployment.yaml @@ -0,0 +1,130 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "papyrus.name" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "papyrus.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "papyrus.selectorLabels" . | nindent 6 }} + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + template: + metadata: + annotations: + {{- if .Values.deployment.annotations }} + {{ toYaml .Values.deployment.annotations | nindent 8 }} + {{- end}} + {{- if .Values.service.ports.monitoring.enabled }} + prometheus.io/scrape: "true" + prometheus.io/path: "/monitoring/metrics" + prometheus.io/port: {{ .Values.service.ports.monitoring.port | quote }} + {{- end }} + labels: + app: papyrus + {{- include "papyrus.selectorLabels" . | nindent 8 }} + spec: + securityContext: + fsGroup: 1000 + volumes: + - name: data + persistentVolumeClaim: + claimName: {{ template "papyrus.name" . }}-data + {{- if .Values.backup.enabled }} + - name: run + configMap: + name: {{ template "papyrus.name" . }}-run + defaultMode: 0777 + {{- end }} + {{- with .Values.deployment.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ template "papyrus.name" . }} + image: "{{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag }}" + imagePullPolicy: {{ .Values.deployment.pullPolicy }} + resources: + limits: + cpu: {{ .Values.deployment.resources.limits.cpu | quote }} + memory: {{ .Values.deployment.resources.limits.memory }} + requests: + cpu: {{ .Values.deployment.resources.requests.cpu | quote}} + memory: {{ .Values.deployment.resources.requests.memory }} + {{- if not .Values.backup.enabled }} + {{- with .Values.deployment.env }} + env: + {{- toYaml . | nindent 10 }} + {{- end }} + args: + - --config_file + - /app/config/presets/{{ .Values.starknet.preset }} + - --base_layer.node_url + - {{ .Values.base_layer_node_url }} + {{- if .Values.p2p.enabled }} + - --network.tcp_port + - {{ .Values.p2p.config.networkTcpPort | quote }} + - --storage.db_config.path_prefix + - {{ .Values.p2p.config.storageDbConfigPathPrefix | quote }} + - --network.#is_none + - {{ .Values.p2p.config.networkIsNone | quote }} + {{- if not .Values.p2p.bootstrap }} + - --network.bootstrap_peer_multiaddr.#is_none + - {{ .Values.p2p.nodeConfig.bootstrapServer.multiaddrIsNone | quote }} + - --network.bootstrap_peer_multiaddr + - {{ include "p2p.bootstrapPeerMultiaddr" . | quote }} + {{- end}} + {{- end }} + {{ range $key, $value := .Values.deployment.extraArgs }} + {{- if $value }} + - --{{ $key }} + - {{ $value | quote }} + {{- else }} + - --{{ $key }} + {{- end }} + {{ end }} + ports: + {{- if .Values.service.ports.rpc.enabled }} + - containerPort: {{ .Values.service.ports.rpc.port }} + name: rpc + {{- end }} + {{- if .Values.service.ports.monitoring.enabled }} + - containerPort: {{ .Values.service.ports.monitoring.port }} + name: monitoring + {{- end }} + {{- if .Values.p2p.enabled }} + - containerPort: {{ .Values.p2p.config.networkTcpPort }} + name: p2p + {{- end }} + volumeMounts: + - name: data + mountPath: /app/data + envFrom: + - configMapRef: + name: {{ template "papyrus.name" . }}-config + {{- else }} + command: + - sh + - -c + - /app/run/backup.sh + volumeMounts: + - name: data + mountPath: /app/data + - name: run + mountPath: /app/run + envFrom: + - configMapRef: + name: {{ template "papyrus.name" . }}-config + - secretRef: + name: {{ template "papyrus.name" . }}-aws-creds + {{- end }} \ No newline at end of file diff --git a/deployments/papyrus/helm/templates/grafana-alerts.yaml b/deployments/papyrus/helm/templates/grafana-alerts.yaml new file mode 100644 index 00000000000..c0342c3aad2 --- /dev/null +++ b/deployments/papyrus/helm/templates/grafana-alerts.yaml @@ -0,0 +1,12 @@ +{{- if .Values.grafanaAlerts.enabled }} +apiVersion: integreatly.org/v1alpha1 +kind: GrafanaDashboard +metadata: + name: {{ .Release.Namespace }}-alerts + namespace: {{ .Release.Namespace | quote }} + labels: + app: grafana-dashboard +spec: + json: | + {{- (.Files.Get "Monitoring/grafana_alerts.json") | nindent 4 }} +{{- end }} diff --git a/deployments/papyrus/helm/templates/grafana-dashboard.yaml b/deployments/papyrus/helm/templates/grafana-dashboard.yaml new file mode 100644 index 00000000000..4a49e0e50e4 --- /dev/null +++ b/deployments/papyrus/helm/templates/grafana-dashboard.yaml @@ -0,0 +1,12 @@ +{{- if .Values.grafanaDashboard.enabled }} +apiVersion: integreatly.org/v1alpha1 +kind: GrafanaDashboard +metadata: + name: {{ .Release.Namespace }}-dashboard + namespace: {{ .Release.Namespace | quote }} + labels: + app: grafana-dashboard +spec: + json: | + {{- (.Files.Get "Monitoring/grafana_dashboard.json") | nindent 4 }} +{{- end }} diff --git a/deployments/papyrus/helm/templates/ingress.yaml b/deployments/papyrus/helm/templates/ingress.yaml new file mode 100644 index 00000000000..d0bf9935cc1 --- /dev/null +++ b/deployments/papyrus/helm/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: "{{ .Values.ingress.name }}-{{ template "papyrus.name" . }}" + namespace: {{ .Release.Namespace }} + labels: + {{- include "papyrus.labels" . | nindent 4 }} +{{- with .Values.ingress.annotations }} + annotations: + {{ toYaml . | nindent 4 }} +{{- end }} +spec: + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - backend: + service: + name: {{ template "papyrus.name" . }}-rpc + port: + number: {{ .Values.services.rpc.port }} + path: /rpc + pathType: {{ .Values.ingress.pathType }} + - backend: + service: + name: {{ template "papyrus.name" . }}-monitoring + port: + number: {{ .Values.services.monitoring.port }} + path: /monitoring + pathType: {{ .Values.ingress.pathType }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.ingress.host }}-ssl-secret +{{- end }} diff --git a/deployments/papyrus/helm/templates/p2p-service.yaml b/deployments/papyrus/helm/templates/p2p-service.yaml new file mode 100644 index 00000000000..f8435115faa --- /dev/null +++ b/deployments/papyrus/helm/templates/p2p-service.yaml @@ -0,0 +1,18 @@ +{{- if and ( not .Values.backup.enabled ) .Values.p2p.service.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "papyrus.name" . }}-p2p + labels: + {{- include "papyrus.labels" . | nindent 4 }} +spec: + selector: + {{- include "papyrus.selectorLabels" . | nindent 6 }} + type: {{ .Values.p2p.service.type }} + ports: + - name: p2p + port: {{ .Values.p2p.service.port }} + protocol: {{ .Values.p2p.service.protocol }} + targetPort: p2p +{{- end }} \ No newline at end of file diff --git a/deployments/papyrus/helm/templates/pvc.yaml b/deployments/papyrus/helm/templates/pvc.yaml new file mode 100644 index 00000000000..d0e2f2d7298 --- /dev/null +++ b/deployments/papyrus/helm/templates/pvc.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "papyrus.name" . }}-data + labels: + {{- include "papyrus.labels" . | nindent 4 }} +spec: + storageClassName: {{ .Values.pvc.storageClass }} + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: {{ .Values.pvc.size | quote }} + {{- if .Values.pvc.restoreFromSnapshot.enabled }} + dataSource: + name: {{ .Values.pvc.restoreFromSnapshot.snapshotName }} + kind: VolumeSnapshot + apiGroup: snapshot.storage.k8s.io + {{- end }} diff --git a/deployments/papyrus/helm/templates/run-configmap.yaml b/deployments/papyrus/helm/templates/run-configmap.yaml new file mode 100644 index 00000000000..8218ceefeab --- /dev/null +++ b/deployments/papyrus/helm/templates/run-configmap.yaml @@ -0,0 +1,11 @@ +{{- if .Values.backup.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "papyrus.name" . }}-run + labels: + {{- include "papyrus.labels" . | nindent 4 }} +data: + backup.sh: | + {{- tpl (.Files.Get "files/backup.sh") . | nindent 4 }} +{{- end }} diff --git a/deployments/papyrus/helm/templates/service.yaml b/deployments/papyrus/helm/templates/service.yaml new file mode 100644 index 00000000000..1b073cf3f0f --- /dev/null +++ b/deployments/papyrus/helm/templates/service.yaml @@ -0,0 +1,26 @@ +{{- if not .Values.backup.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "papyrus.name" . }} + labels: + {{- include "papyrus.labels" . | nindent 4 }} +spec: + selector: + {{- include "papyrus.selectorLabels" . | nindent 6 }} + type: {{ .Values.service.type }} + ports: + {{- if and .Values.service.ports.rpc .Values.service.ports.rpc.enabled }} + - name: rpc + port: {{ .Values.service.ports.rpc.port }} + protocol: {{ .Values.service.ports.rpc.protocol }} + targetPort: rpc + {{- end }} + {{- if and .Values.service.ports.monitoring .Values.service.ports.monitoring.enabled }} + - name: monitoring + port: {{ .Values.service.ports.monitoring.port }} + protocol: {{ .Values.service.ports.monitoring.protocol }} + targetPort: monitoring + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deployments/papyrus/helm/values.yaml b/deployments/papyrus/helm/values.yaml new file mode 100644 index 00000000000..a692b838c34 --- /dev/null +++ b/deployments/papyrus/helm/values.yaml @@ -0,0 +1,137 @@ +# Default values for a papyrus deployment. + +# The verbosity level of logs ("debug", "info", "error", etc.) +rustLogLevel: "info" + +node: + # Number of concurrent requests to the SN feeder gateway + concurrentFgRequests: 50 + +# Ethereum node URL. A value for this variable is mandatory. +base_layer_node_url: + +starknet: + # possible values: "mainnet.json, sepolia_testnet" and "sepolia_integration". + preset: mainnet.json + +p2p: + enabled: false + # Set to true if node act as bootstrap server + bootstrap: false + # General config + config: + # Optional - The node self port to listen + networkTcpPort: 10000 + # Optional - The node data path + storageDbConfigPathPrefix: data + # Optional - network.#is_none flag + networkIsNone: false + # Config to include only if "bootstrap: false" + nodeConfig: + bootstrapServer: + # Mandatory - The network.#is_none flag on the bootsrap server + multiaddrIsNone: + # Mandatory - The bootstrap server ip address. If service is used, use the service address. If not, use the pod address. + multiaddrIp: + # Mandatory - The bootstrap server to connect to, port + multiaddrPort: + # Mandatory - The bootstrap server to connect to, uid + multiaddrUid: + service: + enabled: false + type: ClusterIP + port: 10000 + protocol: TCP + +deployment: + # The container image + image: + repository: ghcr.io/starkware-libs/papyrus + tag: 0.4.0 + # The container's pullPolicy + pullPolicy: Always + # Set pod annotations + annotations: {} + # Set deployment nodeSelector + nodeSelector: {} + # Set deployment tolerations + tolerations: [] + # - key: "key1" + # operator: "Equal" + # value: "value1" + # effect: "NoSchedule" + + # The default resources for a pod. + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 500m + memory: 1Gi + ## Optionally specify extra environment variables to add to papyrus container + env: [] + # - name: FOO + # value: BAR + extraArgs: {} # Optional additional deployment args + # foo: "bar" + +# Service variables for a papyrus pod. +service: + # Specify service type, supported options are ClusterIP, LoadBalancer + type: ClusterIP + ports: + rpc: + enabled: true + port: 8080 + protocol: TCP + monitoring: + enabled: true + port: 8081 + protocol: TCP + +# Persistent volume claim variables for a papyrus pod. +pvc: + # Recommended size is at least 512Gi. + size: 512Gi + # Is is recommended to use an SSD volume (such as GKE premium-rwo). + storageClass: "" + # Use an existing snapshot for the node's data. The kubernetes volumesnapshot object should + # exist in the same namespace as the rest of the resources. + restoreFromSnapshot: + enabled: false + snapshotName: my-snapshot + +# Configure Ingress. +ingress: + # Should an ingress object be created + enabled: false + # Ingress class type. + type: + # Ingress object name in Kubernetes. + name: + # Host name to create Ingress rules. + host: + # Ingress path type. + pathType: + # Annotations to apply to the node ingress. + annotations: {} + +# GrafanaDashboad CRD configuration +# This is relevant for Grafana Operator users https://grafana.github.io/grafana-operator/docs/ +grafanaDashboard: + # Should the GrafanaDashboard object be installed + enabled: false +grafanaAlerts: + enabled: false + +# Backup mode +backup: + enabled: false + sleepInterval: 6h + compress: false + aws: + s3BucketName: my-backup-bucket-name + s3BucketRegion: my-backup-bucket-region + accessKeyId: my aws_access_key_id + secretAccessKey: my aws_secret_access_key diff --git a/deployments/papyrus/install_papyrus.py b/deployments/papyrus/install_papyrus.py new file mode 100644 index 00000000000..69ea8cf3134 --- /dev/null +++ b/deployments/papyrus/install_papyrus.py @@ -0,0 +1,71 @@ +import argparse +import json +import subprocess +import sys + +GRAFANA_DASHBOARD_TEMPLATE_FILE_PATH = "monitoring/templates/grafana_dashboard.json" +GRAFANA_ALERTS_TEMPLATE_FILE_PATH = "monitoring/templates/grafana_alerts.json" +GRAFANA_DASHBOARD_DESTINATION_FILE_PATH = "helm/Monitoring/grafana_dashboard.json" +GRAFANA_ALERTS_DESTINATION_FILE_PATH = "helm/Monitoring/grafana_alerts.json" + +# TODO: Add function to deploy monitoring dashboard. +def parse_command_line_args(): + parser = argparse.ArgumentParser(description="Install Papyrus node.") + parser.add_argument("--release_name", type=str, required=True, help="Name for the helm release.") + parser.add_argument("--namespace", type=str, required=True, help="Target namespace for the Papyrus node.") + parser.add_argument("--create_namespace", action="store_true", default=False, help="Enabling this option will install a new namespace with the given name.") + parser.add_argument("--values_file", action="store", default=None, help="Add additional values file.") + parser.add_argument("--with_alerts", action="store_true", default=False, help="Enabling this option will also deploy a grafana alerts deashboard with the pod.") + parser.add_argument("--prometheus_uid", type=str, required=False, help="UID for prometheus (to use with Grafana).") + parser.add_argument("--old_version", type=str, required=False, help="Represents previous RPC version for the desired env (e.g. v0_3).") + parser.add_argument("--new_version", type=str, required=False, help="Represents current RPC version for the desired env (e.g. v0_4).") + parser.add_argument("--dry_run", action="store_true", default=False, help="Enabling this option will dry run the helm upgrade.",) + parser.add_argument("--helm_deployment_dir", type=str, required=False, default="./deployments/helm/", help="Relative path to the helm deployment directory (default is ./deployments/helm/.") + + return parser.parse_args() + +def generate_grafana_tokens(grafana_namespace: str, prometheus_uid: str, template_path: str, destination_path: str): + grafana_template_lines = open(template_path).readlines() + grafana_dashboard_lines = list() + for line in grafana_template_lines: + grafana_dashboard_lines.append( + line.replace("NAMESPACE", grafana_namespace).replace("${DS_PROMETHEUS}", prometheus_uid)) + grafana_dashboard = "".join(line for line in grafana_dashboard_lines) + grafana_deployment_file = open(destination_path, "a") + # Delete previous file contents. + grafana_deployment_file.truncate(0) + grafana_deployment_file.write(grafana_dashboard) + grafana_deployment_file.flush() + +def main(): + args = parse_command_line_args() + print(args) + # The CMD assumes this script is being run from the root directory. + cmd = f"helm upgrade --install {args.release_name} {args.helm_deployment_dir} --namespace {args.namespace}" + if args.create_namespace: + cmd += " --create-namespace" + if args.values_file: + cmd += f" -f {args.values_file}" + if args.with_alerts: + assert args.prometheus_uid is not None, "Must provide Prometheus UID when deploying with Grafana." + generate_grafana_tokens( + grafana_namespace=args.namespace, + prometheus_uid=args.prometheus_uid, + template_path=GRAFANA_DASHBOARD_TEMPLATE_FILE_PATH, + destination_path=GRAFANA_DASHBOARD_DESTINATION_FILE_PATH + ) + generate_grafana_tokens( + grafana_namespace=args.namespace, + prometheus_uid=args.prometheus_uid, + template_path=GRAFANA_ALERTS_TEMPLATE_FILE_PATH, + destination_path=GRAFANA_ALERTS_DESTINATION_FILE_PATH + ) + + if args.dry_run: + cmd += " --dry-run" + + print(f"running {cmd}...") + subprocess.Popen(cmd, shell=True) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/deployments/papyrus/monitoring/templates/grafana_alerts.json b/deployments/papyrus/monitoring/templates/grafana_alerts.json new file mode 100644 index 00000000000..5c45b36d7b6 --- /dev/null +++ b/deployments/papyrus/monitoring/templates/grafana_alerts.json @@ -0,0 +1,7768 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "panel", + "id": "alertlist", + "name": "Alert list", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph (old)", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 64, + "panels": [], + "title": "Main Alerts", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 27, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 4, + "options": { + "alertName": "(Papyrus)", + "dashboardAlerts": false, + "dashboardTitle": "", + "maxItems": 90, + "showOptions": "current", + "sortOrder": 3, + "stateFilter": { + "alerting": false, + "execution_error": false, + "no_data": false, + "ok": false, + "paused": false, + "pending": false + }, + "tags": [] + }, + "pluginVersion": "8.5.5", + "title": "Alerts Panel", + "type": "alertlist" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "min" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "10m", + "frequency": "1m", + "handler": 1, + "name": "Unsynced headers alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 1 + }, + "hiddenSeries": false, + "id": 67, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"NAMESPACE\"} - papyrus_header_marker{kubernetes_namespace=\"NAMESPACE\"}", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 2, + "visible": true + } + ], + "timeRegions": [], + "title": "Unsynced headers", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "min" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "10m", + "frequency": "1m", + "handler": 1, + "name": "Unsynced bodies alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 68, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"NAMESPACE\"} - papyrus_body_marker{kubernetes_namespace=\"NAMESPACE\"}", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 2, + "visible": true + } + ], + "timeRegions": [], + "title": "Unsynced bodies", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "min" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "10m", + "frequency": "1m", + "handler": 1, + "name": "Unsynced state diffs alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 1 + }, + "hiddenSeries": false, + "id": 69, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"NAMESPACE\"} - papyrus_state_marker{kubernetes_namespace=\"NAMESPACE\"}", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 2, + "visible": true + } + ], + "timeRegions": [], + "title": "Unsynced state diffs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "min" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "10m", + "frequency": "1m", + "handler": 1, + "name": "Unsynced compiled classes alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 10 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"NAMESPACE\"} - papyrus_compiled_class_marker{kubernetes_namespace=\"NAMESPACE\"}", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 2, + "visible": true + } + ], + "timeRegions": [], + "title": "Unsynced compiled classes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 100 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Execution Request Load Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Rate of requests for methods that change Starknet", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 10 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(sum(rpc_incoming_requests{kubernetes_namespace=\"NAMESPACE\", method=~\"addDeclareTransaction|addDeployAccountTransaction|addInvokeTransaction\"})[10m:])", + "legendFormat": "Incoming requests rate (in 10 mins)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 100, + "visible": true + } + ], + "title": "Requests Rate - Execute Functions", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 100 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Call Request Load Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Rate of requests for methods that query Starknet", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 10 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(sum(rpc_incoming_requests{kubernetes_namespace=\"NAMESPACE\", method!~\"addDeclareTransaction|addDeployAccountTransaction|addInvokeTransaction\"})[10m:])", + "legendFormat": "Incoming requests rate (in 10 mins)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 100, + "visible": true + } + ], + "title": "Requests Rate - Call Functions", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0.00001 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "No New Block Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 19 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "max(rate(papyrus_central_block_marker{kubernetes_namespace=\"NAMESPACE\"}[4m])*225)", + "legendFormat": "Number of Blocks", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "lt", + "value": 0.00001, + "visible": true + } + ], + "timeRegions": [], + "title": "Starknet Block Creation Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 52, + "panels": [], + "title": "Latency Alert - Execute Functions", + "type": "row" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addDeclareTransaction OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 29 + }, + "id": 55, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addDeclareTransaction\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addDeclareTransaction OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addDeclareTransaction NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 29 + }, + "id": 54, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addDeclareTransaction\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addDeclareTransaction NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addDeployAccountTransaction OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 29 + }, + "id": 57, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addDeployAccountTransaction\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addDeployAccountTransaction OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addDeployAccountTransaction NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 29 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addDeployAccountTransaction\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addDeployAccountTransaction NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addInvokeTransaction OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 36 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addInvokeTransaction\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addInvokeTransaction OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet addInvokeTransaction NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 36 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"addInvokeTransaction\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "addInvokeTransaction NEW_VERSION Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 60, + "panels": [], + "title": "Latency Alert - Call Functions - Blocks", + "type": "row" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet blockHashAndNumber OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 44 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"blockHashAndNumber\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "blockHashAndNumber OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet blockHashAndNumber NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 44 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"blockHashAndNumber\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "blockHashAndNumber NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet blockNumber OLD_VERSION Latency Alert(Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 44 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"blockNumber\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "blockNumber OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet blockNumber NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 44 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"blockNumber\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "blockNumber NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockTransactionCount OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 51 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockTransactionCount\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockTransactionCount OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockTransactionCount NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 51 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockTransactionCount\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockTransactionCount NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockWithTxHashes OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 51 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockWithTxHashes\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockWithTxHashes OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockWithTxHashes NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 51 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockWithTxHashes\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockWithTxHashes NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockWithTxs OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 58 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockWithTxs\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockWithTxs OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getBlockWithTxs NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 58 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getBlockWithTxs\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getBlockWithTxs NEW_VERSION Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 62, + "panels": [], + "title": "Latency Alert - Call Functions - Transactions", + "type": "row" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionByBlockIdAndIndex OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 66 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionByBlockIdAndIndex\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionByBlockIdAndIndex OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionByBlockIdAndIndex NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 66 + }, + "id": 42, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionByBlockIdAndIndex\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionByBlockIdAndIndex NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionByHash OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 66 + }, + "id": 45, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionByHash\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionByHash OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionByHash NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 66 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionByHash\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionByHash NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionReceipt OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 73 + }, + "id": 47, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionReceipt\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionReceipt OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getTransactionReceipt NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 73 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getTransactionReceipt\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getTransactionReceipt NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet pendingTransactions OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 73 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"pendingTransactions\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "pendingTransactions OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet pendingTransactions NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 73 + }, + "id": 48, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"pendingTransactions\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "pendingTransactions NEW_VERSION Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 80 + }, + "id": 66, + "panels": [], + "title": "Latency Alert - Call Functions - Classes", + "type": "row" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClass OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 81 + }, + "id": 30, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClass\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClass OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClass NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 81 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClass\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClass NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClassAt OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 81 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClassAt\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClassAt OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClassAt NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 81 + }, + "id": 29, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClassAt\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClassAt NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClassHashAt OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 88 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClassHashAt\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClassHashAt OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getClassHashAt NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 88 + }, + "id": 32, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getClassHashAt\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getClassHashAt NEW_VERSION Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 95 + }, + "id": 12, + "panels": [], + "title": "Latency Alert - Call Functions - Others", + "type": "row" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet call OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 96 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"call\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "call OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet call NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 96 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"call\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "call NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet chainId OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 96 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"chainId\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "chainId OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet chainId NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 96 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"chainId\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "chainId NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet estimateFee OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 103 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"estimateFee\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "estimateFee OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet estimateFee NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 103 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"estimateFee\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "estimateFee NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getNonce OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 103 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getNonce\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getNonce OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getNonce NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 103 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getNonce\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getNonce NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getEvents OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 110 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getEvents\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getEvents OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getEvents NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 110 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getEvents\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getEvents NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getStorageAt OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 110 + }, + "id": 41, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getStorageAt\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getStorageAt OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getStorageAt NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 110 + }, + "id": 40, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getStorageAt\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getStorageAt NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getStateUpdate OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 117 + }, + "id": 39, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getStateUpdate\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getStateUpdate OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet getStateUpdate NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 117 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"getStateUpdate\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "getStateUpdate NEW_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet syncing OLD_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 117 + }, + "id": 33, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"syncing\",version=\"OLD_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "syncing OLD_VERSION Latency", + "type": "timeseries" + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Starknet syncing NEW_VERSION Latency Alert (Papyrus)", + "noDataState": "no_data", + "notifications": [] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Latency (seconds)" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 117 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"NAMESPACE\", method=\"syncing\",version=\"NEW_VERSION\",quantile=\"0.95\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "op": "gt", + "value": 1, + "visible": true + } + ], + "title": "syncing NEW_VERSION Latency", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Papyrus-alerts", + "uid": null, + "version": 58, + "weekStart": "" +} diff --git a/deployments/papyrus/monitoring/templates/grafana_dashboard.json b/deployments/papyrus/monitoring/templates/grafana_dashboard.json new file mode 100644 index 00000000000..ecf5224bda1 --- /dev/null +++ b/deployments/papyrus/monitoring/templates/grafana_dashboard.json @@ -0,0 +1,9286 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.5" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "iteration": 1697099323886, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 30, + "panels": [], + "title": "Sync", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference, in seconds, between the time the node received the batch and the batch creation timestamp.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "papyrus_header_latency{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "legendFormat": "Latency (seconds)", + "range": true, + "refId": "A" + } + ], + "title": "Header Latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The Current Starknet block number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Starknet Block Number", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The block number of the last Starknet block that was finalized on L1.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "noValue": "0", + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 15, + "x": 0, + "y": 14 + }, + "id": 15, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_base_layer_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "L1 Block Number", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference between Starknet Block Number and L1 Block Number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "light-blue", + "value": 100 + }, + { + "color": "super-light-orange", + "value": 1000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "red", + "value": 100000 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 9, + "x": 15, + "y": 14 + }, + "id": 69, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} - papyrus_base_layer_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "L1 Block Number Diff", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The current block header marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 19 + }, + "id": 21, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_header_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Block Header", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The current block body marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 19 + }, + "id": 18, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_body_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Block Body", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The current state update marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 19 + }, + "id": 14, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_state_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "State Update", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The current compiled class marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 19 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "papyrus_compiled_class_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Compiled Class (CASM)", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference between the current Starknet block number and the current block header marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "super-light-green", + "value": 1 + }, + { + "color": "super-light-orange", + "value": 5 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 24 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} - papyrus_header_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Block Header Diff", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference between the current Starknet block number and the current block body marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "super-light-green", + "value": 1 + }, + { + "color": "super-light-orange", + "value": 5 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 24 + }, + "id": 66, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} - papyrus_body_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Block Body Diff", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference between the current Starknet block number and the current state update marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "super-light-green", + "value": 1 + }, + { + "color": "super-light-orange", + "value": 5 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 24 + }, + "id": 67, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} - papyrus_state_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "State Update Diff", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The difference between the current Starknet block number and the current compiled class marker.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "super-light-green", + "value": 1 + }, + { + "color": "super-light-orange", + "value": 5 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 24 + }, + "id": 68, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} - papyrus_compiled_class_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"}", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Compiled Class (CASM) Diff", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The percentage of the current block header marker from the current Starknet block number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "super-light-orange", + "value": 0.75 + }, + { + "color": "super-light-green", + "value": 0.9 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 29 + }, + "id": 65, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "floor(papyrus_header_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} / papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} * 10^4) / 10^4", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Block Header %", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The percentage of the current block body marker from the current Starknet block number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "super-light-orange", + "value": 0.75 + }, + { + "color": "super-light-green", + "value": 0.9 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 29 + }, + "id": 17, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "floor(papyrus_body_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} / papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} * 10^4) / 10^4", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Block Body %", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The percentage of the current state update marker from the current Starknet block number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "super-light-orange", + "value": 0.75 + }, + { + "color": "super-light-green", + "value": 0.9 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 29 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "floor(papyrus_state_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} / papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} * 10^4) / 10^4", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "State Update %", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The percentage of the current compiled class marker from the current Starknet block number.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "super-light-orange", + "value": 0.75 + }, + { + "color": "super-light-green", + "value": 0.9 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Central" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 29 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "floor(papyrus_compiled_class_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} / papyrus_central_block_marker{kubernetes_namespace=\"$namespace\", pod=~\"$pod\"} * 10^4) / 10^4", + "hide": false, + "refId": "Head / Central" + } + ], + "title": "Compiled Class (CASM) %", + "transformations": [], + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 34, + "panels": [], + "title": "Resources usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "CPU usage percentage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Percentage", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "percent" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 36, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=~\"$pod\", container!=\"\"}[1m])", + "interval": "", + "legendFormat": "{{container}}", + "range": true, + "refId": "A" + } + ], + "title": "CPU usage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Memory usage in bytes.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 38, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=~\"$pod\", container!=\"\"}) by (container, pod)", + "legendFormat": "{{container}}", + "range": true, + "refId": "A" + } + ], + "title": "Memory usage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Storage usage in bytes.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 3, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 40, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"} - kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}", + "legendFormat": "{{namespace}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage usage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Networking usage.\nTx - Transmitting.\nRx - Receiving.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Bytes / Minute", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Tx" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rx" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 44, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "- sum(rate(container_network_transmit_bytes_total{image!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[1m])) by (container, pod)", + "hide": false, + "legendFormat": "Tx", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(container_network_receive_bytes_total{image!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[1m])) by (container, pod)", + "hide": false, + "legendFormat": "Rx", + "range": true, + "refId": "B" + } + ], + "title": "Networking usage", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 32, + "panels": [], + "title": "Requests and latencies", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 54 + }, + "id": 62, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockNumber\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "blockNumber Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 54 + }, + "id": 70, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockNumber\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "blockNumber Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 54 + }, + "id": 71, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockNumber\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "blockNumber Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 72, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockNumber\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "blockNumber Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 61 + }, + "id": 73, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getNonce\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getNonce Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 61 + }, + "id": 74, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getNonce\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getNonce Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 61 + }, + "id": 75, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getNonce\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getNonce Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 61 + }, + "id": 76, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getNonce\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getNonce Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 68 + }, + "id": 84, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStateUpdate\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getStateUpdate Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 68 + }, + "id": 83, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStateUpdate\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getStateUpdate Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 68 + }, + "id": 82, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStateUpdate\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getStateUpdate Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 68 + }, + "id": 80, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStateUpdate\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getStateUpdate Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 75 + }, + "id": 77, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByHash\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getTransactionByHash Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 75 + }, + "id": 101, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByHash\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getTransactionByHash Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 75 + }, + "id": 79, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByHash\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionByHash Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 75 + }, + "id": 85, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByHash\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionByHash Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 82 + }, + "id": 103, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClass\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getClass Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 82 + }, + "id": 104, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClass\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getClass Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 82 + }, + "id": 105, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClass\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getClass Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 82 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClass\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getClass Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 89 + }, + "id": 106, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getEvents\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getEvents Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 89 + }, + "id": 107, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getEvents\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getEvents Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 89 + }, + "id": 108, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getEvents\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getEvents Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 89 + }, + "id": 86, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getNonce\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getEvents Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 96 + }, + "id": 109, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassAt\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getClassAt Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 96 + }, + "id": 110, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getClassAt Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 96 + }, + "id": 102, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassAt\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getClassAt Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 96 + }, + "id": 87, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getClassAt Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 103 + }, + "id": 112, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassHashAt\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getClassHashAt Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 103 + }, + "id": 113, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassHashAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getClassHashAt Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 103 + }, + "id": 114, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassHashAt\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getClassHashAt Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 103 + }, + "id": 88, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getClassHashAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getClassHashAt Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 110 + }, + "id": 115, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxs\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getBlockWithTxs Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 110 + }, + "id": 116, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxs\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getBlockWithTxs Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 110 + }, + "id": 117, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxs\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getBlockWithTxs Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 110 + }, + "id": 89, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxs\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getBlockWithTxs Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 117 + }, + "id": 118, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStorageAt\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getStorageAt Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 117 + }, + "id": 78, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStorageAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getStorageAt Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 117 + }, + "id": 111, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStorageAt\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getStorageAt Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 117 + }, + "id": 90, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getStorageAt\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getStorageAt Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 124 + }, + "id": 121, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockTransactionCount\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getBlockTransactionCount Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 124 + }, + "id": 122, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockTransactionCount\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getBlockTransactionCount Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 124 + }, + "id": 123, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockTransactionCount\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getBlockTransactionCount Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 124 + }, + "id": 91, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockTransactionCount\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getBlockTransactionCount Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 131 + }, + "id": 124, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionReceipt\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getTransactionReceipt Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 131 + }, + "id": 125, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionReceipt\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getTransactionReceipt Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 131 + }, + "id": 126, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionReceipt\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionReceipt Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 131 + }, + "id": 92, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionReceipt\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionReceipt Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 138 + }, + "id": 127, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxHashes\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getBlockWithTxHashes Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 138 + }, + "id": 128, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxHashes\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getBlockWithTxHashes Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 138 + }, + "id": 129, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxHashes\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getBlockWithTxHashes Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 138 + }, + "id": 93, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getBlockWithTxHashes\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getBlockWithTxHashes Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 145 + }, + "id": 130, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByBlockIdAndIndex\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "getTransactionByBlockIdAndIndex Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 145 + }, + "id": 131, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByBlockIdAndIndex\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "getTransactionByBlockIdAndIndex Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 145 + }, + "id": 132, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByBlockIdAndIndex\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionByBlockIdAndIndex Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 145 + }, + "id": 94, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"getTransactionByBlockIdAndIndex\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "getTransactionByBlockIdAndIndex Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 152 + }, + "id": 133, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "addInvokeTransaction Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 152 + }, + "id": 134, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "addInvokeTransaction Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 152 + }, + "id": 135, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "addInvokeTransaction Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 152 + }, + "id": 95, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "addInvokeTransaction Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 159 + }, + "id": 136, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockHashAndNumber\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "blockHashAndNumber Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 159 + }, + "id": 137, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockHashAndNumber\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "blockHashAndNumber Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 159 + }, + "id": 138, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockHashAndNumber\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "blockHashAndNumber Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 159 + }, + "id": 96, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"blockHashAndNumber\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "blockHashAndNumber Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 166 + }, + "id": 139, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"chainId\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "chainId Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 166 + }, + "id": 140, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"chainId\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "chainId Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 166 + }, + "id": 141, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"chainId\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "chainId Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 166 + }, + "id": 97, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"chainId\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "chainId Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 173 + }, + "id": 142, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"syncing\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "syncing Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 173 + }, + "id": 143, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"syncing\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "syncing Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 173 + }, + "id": 144, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"syncing\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "syncing Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 173 + }, + "id": 98, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"syncing\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "syncing Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 180 + }, + "id": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"call\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "call Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 180 + }, + "id": 119, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"call\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "call Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 180 + }, + "id": 120, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"call\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "call Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 180 + }, + "id": 99, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"call\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "call Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 169 + }, + "id": 153, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"simulateTransactions\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "simulateTransactions Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 169 + }, + "id": 154, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"simulateTransactions\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "simulateTransactions Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 169 + }, + "id": 155, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"simulateTransactions\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "simulateTransactions Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 169 + }, + "id": 156, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"simulateTransactions\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "simulateTransactions Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 176 + }, + "id": 157, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"estimateFee\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "estimateFee Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 176 + }, + "id": 158, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"estimateFee\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "estimateFee Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 176 + }, + "id": 159, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"estimateFee\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "estimateFee Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 176 + }, + "id": 160, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"estimateFee\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "estimateFee Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 183 + }, + "id": 145, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceTransaction\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "traceTransaction Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 183 + }, + "id": 146, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "traceTransaction Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 183 + }, + "id": 147, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceTransaction\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "traceTransaction Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 183 + }, + "id": 148, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "traceTransaction Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 190 + }, + "id": 149, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceBlockTransactions\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "traceBlockTransactions Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 190 + }, + "id": 150, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceBlockTransactions\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "traceBlockTransactions Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 190 + }, + "id": 151, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceBlockTransactions\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "traceBlockTransactions Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 190 + }, + "id": 152, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"traceBlockTransactions\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "traceBlockTransactions Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 197 + }, + "id": 164, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "addInvokeTransaction Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 197 + }, + "id": 163, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "addInvokeTransaction Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 197 + }, + "id": 162, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "addInvokeTransaction Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 197 + }, + "id": 161, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addInvokeTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "addInvokeTransaction Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 204 + }, + "id": 172, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeployAccountTransaction\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "addDeployAccountTransaction Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 204 + }, + "id": 170, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeployAccountTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "addDeployAccountTransaction Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 204 + }, + "id": 167, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeployAccountTransaction\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "addDeployAccountTransaction Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 204 + }, + "id": 166, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeployAccountTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "addDeployAccountTransaction Latencies", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of incoming requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 211 + }, + "id": 171, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_incoming_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeclareTransaction\",version=\"$version\"}", + "legendFormat": "Incoming requests", + "range": true, + "refId": "A" + } + ], + "title": "addDeclareTransaction Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of failed requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 4, + "y": 211 + }, + "id": 169, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_failed_requests{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeclareTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "Failed requests", + "range": true, + "refId": "C" + } + ], + "title": "addDeclareTransaction Failed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latency of the quickest 95% of the requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 8, + "y": 211 + }, + "id": 168, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeclareTransaction\",version=\"$version\",quantile=\"0.95\"}", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "addDeclareTransaction Latency (0.95)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The maximal latencies of different percentages of the quickest requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 10, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 211 + }, + "id": 165, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rpc_request_latency_seconds{kubernetes_namespace=\"$namespace\", pod=~\"$pod\", method=\"addDeclareTransaction\",version=\"$version\"}", + "hide": false, + "legendFormat": "{{quantile}}", + "range": true, + "refId": "B" + } + ], + "title": "addDeclareTransaction Latencies", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(papyrus_header_marker, kubernetes_namespace)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(papyrus_header_marker, kubernetes_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(papyrus_header_marker{kubernetes_namespace=\"$namespace\"}, pod)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "pod", + "options": [], + "query": { + "query": "label_values(papyrus_header_marker{kubernetes_namespace=\"$namespace\"}, pod)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": "V0_5", + "value": "V0_5" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "version", + "options": [ + { + "selected": false, + "text": "V0_4", + "value": "V0_4" + }, + { + "selected": false, + "text": "V0_5", + "value": "V0_5" + } + ], + "query": "V0_4,V0_5", + "queryValue": "None", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Papyrus-node-data", + "uid": null, + "version": 60, + "weekStart": "" +} diff --git a/deployments/papyrus/storage-benchmark/deployment.yaml b/deployments/papyrus/storage-benchmark/deployment.yaml new file mode 100644 index 00000000000..a1e89680a51 --- /dev/null +++ b/deployments/papyrus/storage-benchmark/deployment.yaml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: storage-benchmark + name: storage-benchmark +spec: + replicas: 1 + selector: + matchLabels: + app: storage-benchmark + template: + metadata: + labels: + app: storage-benchmark + spec: + securityContext: + fsGroup: 1000 + initContainers: + - image: us.gcr.io/starkware-dev/papyrus-utils:latest + imagePullPolicy: Always + command: + - "storage_benchmark" + - "--queries_file_path" + - "/app/queries/queries.txt" + - "--db_path" + - "/app/data/" + - "--output_file_path" + - "/tmp/results/output.txt" + - "--chain_id" + - "SN_MAIN" + name: storage-benchmark + volumeMounts: + - mountPath: /app/data + name: data + - mountPath: /app/queries + name: queries + - mountPath: /tmp/results + name: results + containers: + - image: ubuntu + command: + - "sleep" + - "3600" + name: results-export + volumeMounts: + - mountPath: /tmp/results + name: results + volumes: + - name: data + persistentVolumeClaim: + claimName: data + - name: queries + configMap: + name: queries + - name: results + emptyDir: {} diff --git a/deployments/papyrus/storage-benchmark/pvc.yaml b/deployments/papyrus/storage-benchmark/pvc.yaml new file mode 100644 index 00000000000..4c1871b92ed --- /dev/null +++ b/deployments/papyrus/storage-benchmark/pvc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data +spec: + storageClassName: premium-rwo + dataSource: + name: papyrus-db-snapshot + kind: VolumeSnapshot + apiGroup: snapshot.storage.k8s.io + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/deployments/papyrus/storage-benchmark/queries.txt b/deployments/papyrus/storage-benchmark/queries.txt new file mode 100644 index 00000000000..f0c4fe46c64 --- /dev/null +++ b/deployments/papyrus/storage-benchmark/queries.txt @@ -0,0 +1,14 @@ +{"get_nonce_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a69999"]} +{"get_nonce_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a69999"]} +{"get_nonce_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a69999"]} +{"get_nonce_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a69999"]} +{"get_nonce_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_storage_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6","0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c7"]} +{"get_class_hash_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_storage_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6","0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c7"]} +{"get_class_hash_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_storage_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6","0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a62647"]} +{"get_class_hash_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_class_hash_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_class_hash_at":[121,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} +{"get_class_hash_at":[201,"0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6"]} diff --git a/deployments/papyrus/storage-benchmark/run_benchmark.bash b/deployments/papyrus/storage-benchmark/run_benchmark.bash new file mode 100755 index 00000000000..4eb1c09973c --- /dev/null +++ b/deployments/papyrus/storage-benchmark/run_benchmark.bash @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -euxo pipefail + +BASE_PATH="deployments/storage-benchmark" +PVC_FILE="$BASE_PATH/pvc.yaml" +DEPLOYMENT_FILE="$BASE_PATH/deployment.yaml" +CM_FILE="$BASE_PATH/cm.yaml" + +NS="papyrus-storage-benchmark" +DURRATION_TIMEOUT=$1 + +# create a PVC with the benchmarked storage +kubectl --namespace "$NS" apply -f "$PVC_FILE" --wait=true + +# create a configmap with the actions to run +kubectl --namespace "$NS" create configmap queries --from-file "$BASE_PATH/queries.txt" --dry-run=client --output yaml >"$CM_FILE" +kubectl --namespace "$NS" apply -f "$CM_FILE" + +# create the storage-benchmark deployment +kubectl --namespace "$NS" apply -f "$DEPLOYMENT_FILE" --wait=true + +# get the created pod name +POD=$(kubectl get pods -l app=storage-benchmark --namespace "$NS" --no-headers -o custom-columns=":metadata.name") + +# wait for pod to start (since the benchmark is done in an initContainer, when the pod is Ready it +# means the benchmark is done). +kubectl wait --namespace "$NS" --for=condition=ready pod "$POD" --timeout "$DURRATION_TIMEOUT" + +# get the results file +kubectl --namespace "$NS" cp --container results-export "$POD":/tmp/results/output.txt output.txt + +# delete all temp resources from the cluster +kubectl --namespace "$NS" delete -f "$BASE_PATH/*.yaml" --wait=true diff --git a/docs/SECURITY.md b/docs/SECURITY.md deleted file mode 100644 index c297afd72e3..00000000000 --- a/docs/SECURITY.md +++ /dev/null @@ -1,16 +0,0 @@ -# Security policy - -## Reporting a vulnerability - -If there are any vulnerabilities in **Blockifier**, don't hesitate to _report them_. - -1. Use any of the [private contact addresses](https://github.com/starkware-libs/blockifier#support). -2. Describe the vulnerability. - - If you have a fix, that is most welcome -- please attach or summarize it in your message! - -3. We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report. - - Please **do not disclose the vulnerability publicly** until a fix is released! - -4. Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it. diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 14b5d5dcff9..00000000000 --- a/rustfmt.toml +++ /dev/null @@ -1,20 +0,0 @@ -edition = "2021" -newline_style = "Unix" -use_field_init_shorthand = true -use_small_heuristics = "Max" -use_try_shorthand = true -max_width = 100 - -# Unstable features below -unstable_features = true -version = "Two" -comment_width = 100 -format_code_in_doc_comments = true -format_macro_bodies = true -format_macro_matchers = true -format_strings = true -imports_granularity = "Module" -group_imports = "StdExternalCrate" -normalize_comments = true -normalize_doc_attributes = true -wrap_comments = true